=pod

=encoding utf-8

=head1 Name

Zero::Emulator - Assemble and emulate a program in the Zero assembly programming language

=for html
<p><a href="https://github.com/philiprbrenan/zero"><img src="https://github.com/philiprbrenan/zero/workflows/Test/badge.svg"></a>

=head1 Synopsis

Say "hello world":

  Start 1;

  Out "hello World";

  my $e = Execute;

  is_deeply $e->out, ["hello World"];

=head1 Description



Version 20230513.


The following sections describe the methods in each functional area of this
module.  For an alphabetic listing of all methods by name see L<Index|/Index>.



=head1 Execution

=head2 Analysis

=head2 Memory

Access memory

=head2 Execution

Execute assembly code in the emulator

=head3 Start($version)

Start the current assembly using the specified version of the Zero language.  At  the moment only version 1 works..

     Parameter  Description
  1  $version   Version desired - at the moment only 1

B<Example:>


  if (1)                                                                            
  
   {Start 1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Out "hello World";
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["hello World"];
   }
  

=head3 Add($target, $s1, $s2)

Add the source locations together and store in the result in the target area.

     Parameter  Description
  1  $target    Target address
  2  $s1        Source one
  3  $s2        Source two

B<Example:>


  if (1)                                                                          
   {Start 1;
  
    my $a = Add 3, 2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Out  $a;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [5];
   }
  
  if (1)                                                                           
   {Start 1;
    my $a = Subtract 4, 2;
    Out $a;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [2];
   }
  

=head3 Subtract($target, $s1, $s2)

Subtract the second source address from the first and store in the result in the target area.

     Parameter  Description
  1  $target    Target address
  2  $s1        Source one
  3  $s2        Source two

B<Example:>


  if (1)                                                                           
   {Start 1;
  
    my $a = Subtract 4, 2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Out $a;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [2];
   }
  

=head3 Array($name)

Create a new memory area and write its number into the address named by the target operand.

     Parameter  Description
  1  $name      Name of allocation

B<Example:>


  if (1)                                                                            
   {Start 1;
  
    my $a = Array "aaa";  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Mov [$a, 0, "aaa"], 1;
      Mov [$a, 1, "aaa"], 22;
      Mov [$a, 2, "aaa"], 333;
    my $n = ArraySize $a, "aaa";
    Out $n;
  
    ForArray
     {my ($i, $e, $check, $next, $end) = @_;
      IfGt $i, 1,
      Then
       {Trace 1;
       };
      Out $i; Out $e;
     }  $a, "aaa";
  
    Nop;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->memory, {1=>[1, 22, 333]};
  
    is_deeply $e->out,
   [3, 0, 1, 1, 22,
    "Trace: 1",
    "  37    14     1         trace                      
",
    "  38    15     3         label                      
",
    2,
    "  39    16     3           out                      
",
    333,
    "  40    17     3           out                      
",
    "  41    18     3         label                      
",
    "  42    19     3           inc  [0, 3, stackArea] = 3 was 2
",
    "  43    20     3           jmp                      
",
    "  44     9     4         label                      
",
    "  45    10     4           jGe                      
",
    "  46    21     1         label                      
",
    "  47    22     1           nop                      
",
  ];
   }
  

=head3 Free($target, $source)

Free the memory area named by the target operand after confirming that it has the name specified on the source operand.

     Parameter  Description
  1  $target    Target area yielding the id of the area to be freed
  2  $source    Source area yielding the name of the area to be freed

B<Example:>


  if (1)                                                                          
   {Start 1;
    my $a = Array "node";
  
    Free $a, "aaa";  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
  
    is_deeply $e->out, [
    "Wrong name: aaa for array with name: node",
    "    1     2 free",
  ];
   }
  
  if (1)                                                                           
   {Start 1;
    my $a = Array "node";
    Out $a;
    Mov [$a, 1, 'node'], 1;
    Mov [$a, 2, 'node'], 2;
    Mov 1, [$a, \1, 'node'];
    Dump "dddd";
  
    Free $a, "node";  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
  
    is_deeply $e->out, [
    1,
    "dddd",
    "-2=bless([], \"return\")",
    "-1=bless([], \"params\")",
    "0=bless([1, 1], \"stackArea\")",
    "1=bless([undef, 1, 2], \"node\")",
    "Stack trace",
    "    1     6 dump",
  ];
   }
  

=head3 ArraySize($area, $name)

The current size of an array

     Parameter  Description
  1  $area      Location of area
  2  $name      Name of area

B<Example:>


  if (1)                                                                            
   {Start 1;
    my $a = Array "aaa";
      Mov [$a, 0, "aaa"], 1;
      Mov [$a, 1, "aaa"], 22;
      Mov [$a, 2, "aaa"], 333;
  
    my $n = ArraySize $a, "aaa";  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Out $n;
  
    ForArray
     {my ($i, $e, $check, $next, $end) = @_;
      IfGt $i, 1,
      Then
       {Trace 1;
       };
      Out $i; Out $e;
     }  $a, "aaa";
  
    Nop;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->memory, {1=>[1, 22, 333]};
  
    is_deeply $e->out,
   [3, 0, 1, 1, 22,
    "Trace: 1",
    "  37    14     1         trace                      
",
    "  38    15     3         label                      
",
    2,
    "  39    16     3           out                      
",
    333,
    "  40    17     3           out                      
",
    "  41    18     3         label                      
",
    "  42    19     3           inc  [0, 3, stackArea] = 3 was 2
",
    "  43    20     3           jmp                      
",
    "  44     9     4         label                      
",
    "  45    10     4           jGe                      
",
    "  46    21     1         label                      
",
    "  47    22     1           nop                      
",
  ];
   }
  

=head3 ArrayIndex()

Find the 1 based index of the second source operand in the array referenced by the first source operand if it is present in the array else 0 into the target location.  The business of returning -1 leads to the inferno of try catch.


B<Example:>


  if (1)                                                                            
   {Start 1;
    my $a = Array "aaa";
    Mov [$a, 0, "aaa"], 10;
    Mov [$a, 1, "aaa"], 20;
    Mov [$a, 2, "aaa"], 30;
  
  
    Out ArrayIndex $a, 30;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Out ArrayIndex $a, 20;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Out ArrayIndex $a, 10;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Out ArrayIndex $a, 15;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Out ArrayCountLess $a, 35;
    Out ArrayCountLess $a, 25;
    Out ArrayCountLess $a, 15;
    Out ArrayCountLess $a,  5;
  
    Out ArrayCountGreater $a, 35;
    Out ArrayCountGreater $a, 25;
    Out ArrayCountGreater $a, 15;
    Out ArrayCountGreater $a,  5;
  
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [3,2,1,0,  3,2,1,0, 0,1,2,3];
   }
  

=head3 ArrayCountLess()

Count the number of elements in the array specified by the first source operand that are less than the element supplied by the second source operand and place the result in the target location


B<Example:>


  if (1)                                                                            
   {Start 1;
    my $a = Array "aaa";
    Mov [$a, 0, "aaa"], 10;
    Mov [$a, 1, "aaa"], 20;
    Mov [$a, 2, "aaa"], 30;
  
    Out ArrayIndex $a, 30;
    Out ArrayIndex $a, 20;
    Out ArrayIndex $a, 10;
    Out ArrayIndex $a, 15;
  
  
    Out ArrayCountLess $a, 35;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Out ArrayCountLess $a, 25;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Out ArrayCountLess $a, 15;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Out ArrayCountLess $a,  5;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Out ArrayCountGreater $a, 35;
    Out ArrayCountGreater $a, 25;
    Out ArrayCountGreater $a, 15;
    Out ArrayCountGreater $a,  5;
  
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [3,2,1,0,  3,2,1,0, 0,1,2,3];
   }
  

=head3 ArrayCountGreater()

Count the number of elements in the array specified by the first source operand that are greater than the element supplied by the second source operand and place the result in the target location


B<Example:>


  if (1)                                                                            
   {Start 1;
    my $a = Array "aaa";
    Mov [$a, 0, "aaa"], 10;
    Mov [$a, 1, "aaa"], 20;
    Mov [$a, 2, "aaa"], 30;
  
    Out ArrayIndex $a, 30;
    Out ArrayIndex $a, 20;
    Out ArrayIndex $a, 10;
    Out ArrayIndex $a, 15;
  
    Out ArrayCountLess $a, 35;
    Out ArrayCountLess $a, 25;
    Out ArrayCountLess $a, 15;
    Out ArrayCountLess $a,  5;
  
  
    Out ArrayCountGreater $a, 35;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Out ArrayCountGreater $a, 25;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Out ArrayCountGreater $a, 15;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Out ArrayCountGreater $a,  5;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [3,2,1,0,  3,2,1,0, 0,1,2,3];
   }
  

=head3 Call($p)

Call the subroutine at the target address.

     Parameter  Description
  1  $p         Procedure description

B<Example:>


  if (1)                                                                           
   {Start 1;
    my $w = Procedure 'write', sub
     {Out 'aaa';
      Return;
     };
  
    Call $w;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["aaa"];
   }
  
  if (1)                                                                          
   {Start 1;
    my $w = Procedure 'write', sub
     {my $a = ParamsGet 0;
      Out $a;
      Return;
     };
    ParamsPut 0, 'bbb';
  
    Call $w;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["bbb"];
   }
  
  if (1)                                                                            
   {Start 1;
    my $w = Procedure 'write', sub
     {ReturnPut 0, "ccc";
      Return;
     };
  
    Call $w;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ReturnGet \0, 0;
    Out \0;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["ccc"];
   }
  
  if (1)                                                                            
   {Start 1;
    my $a = Array "aaa";
    Dump "dddd";
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [
    "dddd",
    "-2=bless([], \"return\")",
    "-1=bless([], \"params\")",
    "0=bless([1], \"stackArea\")",
    "1=bless([], \"aaa\")",
    "Stack trace",
    "    1     2 dump",
  ];
   }
  
  if (1)                                                                              
   {Start 1;
    my $a = Array "aaa";
    my $i = Mov 1;
    my $v = Mov 11;
    ParamsPut 0, $a;
    ParamsPut 1, $i;
    ParamsPut 2, $v;
    my $set = Procedure 'set', sub
     {my $a = ParamsGet 0;
      my $i = ParamsGet 1;
      my $v = ParamsGet 2;
      Mov [$a, \$i, 'aaa'], $v;
      Return;
     };
  
    Call $set;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $V = Mov [$a, \$i, 'aaa'];
    AssertEq $v, $V;
    Out [$a, \$i, 'aaa'];
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [11];
   }
  
  if (1)                                                                            
   {Start 1;
    my $set = Procedure 'set', sub
     {my $a = ParamsGet 0;
     };
    ParamsPut 0, 1;
  
    Call $set;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ParamsPut 0, 1;
  
    Call $set;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [];
   }
  

=head3 Confess()

Confess.


B<Example:>


  if (1)                                                                          
   {Start 1;
    my $c = Procedure 'confess', sub
  
     {Confess;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     };
    Call $c;
    my $e = Execute(suppressOutput=>1);
  
    is_deeply $e->out, ["Confess at:", "    2     3 confess", "    1     6 call"];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   }
  

=head3 Dump($title)

Dump memory.

     Parameter  Description
  1  $title     Title

B<Example:>


  if (1)                                                                           
   {Start 1;
    my $a = Array "node";
    Out $a;
    Mov [$a, 1, 'node'], 1;
    Mov [$a, 2, 'node'], 2;
    Mov 1, [$a, \1, 'node'];
  
    Dump "dddd";  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Free $a, "node";
    my $e = Execute(suppressOutput=>1);
  
    is_deeply $e->out, [
    1,
    "dddd",
    "-2=bless([], \"return\")",
    "-1=bless([], \"params\")",
    "0=bless([1, 1], \"stackArea\")",
    "1=bless([undef, 1, 2], \"node\")",
    "Stack trace",
    "    1     6 dump",
  ];
   }
  

=head3 DumpArray($target, $title)

Dump an array.

     Parameter  Description
  1  $target    Array to dump
  2  $title     Title of dump

B<Example:>


  if (1)                                                                           
   {Start 1;
    my $a = Array "aaa";
      Mov [$a, 0, "aaa"], 1;
      Mov [$a, 1, "aaa"], 22;
      Mov [$a, 2, "aaa"], 333;
  
    DumpArray $a, "AAAA";  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
  
    is_deeply $e->out,
   ["AAAA",
    "bless([1, 22, 333], \"aaa\")",
    "Stack trace",
    "    1     5 dumpArray",
  ];
   }
  

=head3 Trace($source)

Trace.

     Parameter  Description
  1  $source    Trace setting

B<Example:>


  if (1)                                                                            
   {Start 1;
  
    Trace 1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfEq 1, 2,
    Then
     {Mov 1, 1;
      Mov 2, 1;
     },
    Else
     {Mov 3, 3;
      Mov 4, 4;
     };
    IfEq 2, 2,
    Then
     {Mov 1, 1;
      Mov 2, 1;
     },
    Else
     {Mov 3, 3;
      Mov 4, 4;
     };
    my $e = Execute(suppressOutput=>1);
    is_deeply scalar($e->out->@*), 14;
   }
  

=head3 TracePoints($source)

Enable trace points.

     Parameter  Description
  1  $source    Trace points if true

B<Example:>


  if (1)                                                                          
   {my $N = 5;
    Start 1;
  
    TracePoints 1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    For
     {my $a = Mov 1;
      Inc $a;
     } $N;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [
  
    "TracePoints: 1",  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    "Trace",
    "    1     6 tracePoint",
    "Trace",
    "    1     6 tracePoint",
    "Trace",
    "    1     6 tracePoint",
    "Trace",
    "    1     6 tracePoint",
    "Trace",
    "    1     6 tracePoint",
  ];
   }
  

=head3 Dec($target)

Decrement the target.

     Parameter  Description
  1  $target    Target address

B<Example:>


  if (1)                                                                          
   {Start 1;
    my $a = Mov 3;
  
    Dec $a;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Out $a;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [2];
   }
  

=head3 Inc($target)

Increment the target.

     Parameter  Description
  1  $target    Target address

B<Example:>


  if (1)                                                                          
   {Start 1;
    my $a = Mov 3;
  
    Inc $a;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Out $a;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [4];
   }
  

=head3 Jmp($target)

Jump to a label.

     Parameter  Description
  1  $target    Target address

B<Example:>


  if (1)                                                                          
   {Start 1;
  
    Jmp (my $a = label);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Out  1;
  
      Jmp (my $b = label);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    setLabel($a);
      Out  2;
    setLabel($b);
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [2];
   }
  

=head3 Jle($target, $source, $source2)

Jump to a target label if the first source field is less than or equal to the second source field.

     Parameter  Description
  1  $target    Target label
  2  $source    Source to test
  3  $source2

B<Example:>


  if (1)                                                                                 
   {Start 1;
    my $a = Array "aaa";
    my $b = Array "bbb";
    Mov [$a, 0, 'aaa'], $b;
    Mov [$b, 0, 'bbb'], 99;
    For
     {my ($i, $check, $next, $end) = @_;
      my $c = Mov [$a, \0, 'aaa'];
      my $d = Mov [$c, \0, 'bbb'];
      Jeq $next, $d, $d;
      Jne $next, $d, $d;
  
      Jle $next, $d, $d;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Jlt $next, $d, $d;
      Jge $next, $d, $d;
      Jgt $next, $d, $d;
     } 3;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->analyzeExecutionResults(doubleWrite=>3), "#       24 instructions executed";
    is_deeply $e->memory, { 1=>  bless([2], "aaa"), 2=>  bless([99], "bbb") };
   }
  

=head3 Jlt($target, $source, $source2)

Jump to a target label if the first source field is less than the second source field.

     Parameter  Description
  1  $target    Target label
  2  $source    Source to test
  3  $source2

B<Example:>


  if (1)                                                                                 
   {Start 1;
    my $a = Array "aaa";
    my $b = Array "bbb";
    Mov [$a, 0, 'aaa'], $b;
    Mov [$b, 0, 'bbb'], 99;
    For
     {my ($i, $check, $next, $end) = @_;
      my $c = Mov [$a, \0, 'aaa'];
      my $d = Mov [$c, \0, 'bbb'];
      Jeq $next, $d, $d;
      Jne $next, $d, $d;
      Jle $next, $d, $d;
  
      Jlt $next, $d, $d;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Jge $next, $d, $d;
      Jgt $next, $d, $d;
     } 3;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->analyzeExecutionResults(doubleWrite=>3), "#       24 instructions executed";
    is_deeply $e->memory, { 1=>  bless([2], "aaa"), 2=>  bless([99], "bbb") };
   }
  

=head3 Jge($target, $source, $source2)

Jump to a target label if the first source field is greater than or equal to the second source field.

     Parameter  Description
  1  $target    Target label
  2  $source    Source to test
  3  $source2

B<Example:>


  if (1)                                                                                 
   {Start 1;
    my $a = Array "aaa";
    my $b = Array "bbb";
    Mov [$a, 0, 'aaa'], $b;
    Mov [$b, 0, 'bbb'], 99;
    For
     {my ($i, $check, $next, $end) = @_;
      my $c = Mov [$a, \0, 'aaa'];
      my $d = Mov [$c, \0, 'bbb'];
      Jeq $next, $d, $d;
      Jne $next, $d, $d;
      Jle $next, $d, $d;
      Jlt $next, $d, $d;
  
      Jge $next, $d, $d;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Jgt $next, $d, $d;
     } 3;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->analyzeExecutionResults(doubleWrite=>3), "#       24 instructions executed";
    is_deeply $e->memory, { 1=>  bless([2], "aaa"), 2=>  bless([99], "bbb") };
   }
  

=head3 Jgt($target, $source, $source2)

Jump to a target label if the first source field is greater than the second source field.

     Parameter  Description
  1  $target    Target label
  2  $source    Source to test
  3  $source2

B<Example:>


  if (1)                                                                                 
   {Start 1;
    my $a = Array "aaa";
    my $b = Array "bbb";
    Mov [$a, 0, 'aaa'], $b;
    Mov [$b, 0, 'bbb'], 99;
    For
     {my ($i, $check, $next, $end) = @_;
      my $c = Mov [$a, \0, 'aaa'];
      my $d = Mov [$c, \0, 'bbb'];
      Jeq $next, $d, $d;
      Jne $next, $d, $d;
      Jle $next, $d, $d;
      Jlt $next, $d, $d;
      Jge $next, $d, $d;
  
      Jgt $next, $d, $d;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     } 3;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->analyzeExecutionResults(doubleWrite=>3), "#       24 instructions executed";
    is_deeply $e->memory, { 1=>  bless([2], "aaa"), 2=>  bless([99], "bbb") };
   }
  

=head3 Jeq($target, $source, $source2)

Jump to a target label if the first source field is equal to the second source field.

     Parameter  Description
  1  $target    Target label
  2  $source    Source to test
  3  $source2

B<Example:>


  if (1)                                                                                 
   {Start 1;
    my $a = Array "aaa";
    my $b = Array "bbb";
    Mov [$a, 0, 'aaa'], $b;
    Mov [$b, 0, 'bbb'], 99;
    For
     {my ($i, $check, $next, $end) = @_;
      my $c = Mov [$a, \0, 'aaa'];
      my $d = Mov [$c, \0, 'bbb'];
  
      Jeq $next, $d, $d;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Jne $next, $d, $d;
      Jle $next, $d, $d;
      Jlt $next, $d, $d;
      Jge $next, $d, $d;
      Jgt $next, $d, $d;
     } 3;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->analyzeExecutionResults(doubleWrite=>3), "#       24 instructions executed";
    is_deeply $e->memory, { 1=>  bless([2], "aaa"), 2=>  bless([99], "bbb") };
   }
  

=head3 Jne($target, $source, $source2)

Jump to a target label if the first source field is not equal to the second source field.

     Parameter  Description
  1  $target    Target label
  2  $source    Source to test
  3  $source2

B<Example:>


  if (1)                                                                                 
   {Start 1;
    my $a = Array "aaa";
    my $b = Array "bbb";
    Mov [$a, 0, 'aaa'], $b;
    Mov [$b, 0, 'bbb'], 99;
    For
     {my ($i, $check, $next, $end) = @_;
      my $c = Mov [$a, \0, 'aaa'];
      my $d = Mov [$c, \0, 'bbb'];
      Jeq $next, $d, $d;
  
      Jne $next, $d, $d;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Jle $next, $d, $d;
      Jlt $next, $d, $d;
      Jge $next, $d, $d;
      Jgt $next, $d, $d;
     } 3;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->analyzeExecutionResults(doubleWrite=>3), "#       24 instructions executed";
    is_deeply $e->memory, { 1=>  bless([2], "aaa"), 2=>  bless([99], "bbb") };
   }
  

=head3 JFalse($target, $source)

Jump to a target label if the first source field is equal to zero

     Parameter  Description
  1  $target    Target label
  2  $source    Source to test

B<Example:>


  if (1)                                                                           
   {Start 1;
    my $a = Mov 1;
    Block
     {my ($start, $good, $bad, $end) = @_;
      JTrue $end, $a;
      Out 1;
     };
    Block
     {my ($start, $good, $bad, $end) = @_;
  
      JFalse $end, $a;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Out 2;
     };
    Mov $a, 0;
    Block
     {my ($start, $good, $bad, $end) = @_;
      JTrue $end, $a;
      Out 3;
     };
    Block
     {my ($start, $good, $bad, $end) = @_;
  
      JFalse $end, $a;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Out 4;
     };
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [2, 3];
   }
  

=head3 JTrue($target, $source)

Jump to a target label if the first source field is not equal to zero

     Parameter  Description
  1  $target    Target label
  2  $source    Source to test

B<Example:>


  if (1)                                                                           
   {Start 1;
    my $a = Mov 1;
    Block
     {my ($start, $good, $bad, $end) = @_;
  
      JTrue $end, $a;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Out 1;
     };
    Block
     {my ($start, $good, $bad, $end) = @_;
      JFalse $end, $a;
      Out 2;
     };
    Mov $a, 0;
    Block
     {my ($start, $good, $bad, $end) = @_;
  
      JTrue $end, $a;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Out 3;
     };
    Block
     {my ($start, $good, $bad, $end) = @_;
      JFalse $end, $a;
      Out 4;
     };
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [2, 3];
   }
  

=head3 Label($source)

Create a label..

     Parameter  Description
  1  $source    Name of label

B<Example:>


  if (1)                                                                           
   {Start 1;
    Mov 0, 1;
    Jlt ((my $a = label), \0, 2);
      Out  1;
      Jmp (my $b = label);
    setLabel($a);
      Out  2;
    setLabel($b);
  
    Jgt ((my $c = label), \0, 3);
      Out  1;
      Jmp (my $d = label);
    setLabel($c);
      Out  2;
    setLabel($d);
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [2,1];
   }
  
  if (1)                                                                          
   {Start 1;
    Mov 0, 0;
    my $a = setLabel;
      Out \0;
      Inc \0;
    Jlt $a, \0, 10;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [0..9];
   }
  

=head3 Clear($target)

Clear the first bytes of an area.  The area is specified by the first element of the address, the number of locations to clear is specified by the second element of the target address..

     Parameter  Description
  1  $target    Target address

B<Example:>


  if (1)                                                                           
   {Start 1;
    my $a = Array "aaa";
  
    Clear [$a, 10, 'aaa'];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->memory->{1}, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
   }
  

=head3 LeAddress()

Load the address component.


B<Example:>


  if (1)                                                                           
   {Start 1;
    my $a = Array "array";
    my $b = Mov 2;
    my $c = Mov 5;
  
    my $d = LeAddress $c;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $f = LeArea    [$a, \0, 'array'];
    Out $d;
    Out $f;
    Mov [$a, \$b, 'array'], 22;
    Mov [$a, \$c, 'array'], 33;
    Mov [$f, \$d, 'array'], 44;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out,    [2,1];
    is_deeply $e->memory, {1=>[undef, undef, 44, undef, undef, 33]};
   }
  

=head3 LeArea()

Load the address component.


B<Example:>


  if (1)                                                                           
   {Start 1;
    my $a = Array "array";
    my $b = Mov 2;
    my $c = Mov 5;
    my $d = LeAddress $c;
  
    my $f = LeArea    [$a, \0, 'array'];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Out $d;
    Out $f;
    Mov [$a, \$b, 'array'], 22;
    Mov [$a, \$c, 'array'], 33;
    Mov [$f, \$d, 'array'], 44;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out,    [2,1];
    is_deeply $e->memory, {1=>[undef, undef, 44, undef, undef, 33]};
   }
  

=head3 Mov()

Copy a constant or memory address to the target address.


B<Example:>


  if (1)                                                                          
   {Start 1;
  
    my $a = Mov 2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Out $a;
  
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [2];
   }
  
   {Start 1;                                                                      
  
  if (1)                                                                          
   {Start 1;
    my $a = Array "aaa";
  
    Mov     [$a,  1, "aaa"],  11;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Mov  1, [$a, \1, "aaa"];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Out \1;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [11];
   }
  
  if (1)                                                                           
   {Start 1;
    my $a = Array "alloc";
  
    my $b = Mov 99;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    my $c = Mov $a;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Mov [$a, 0, 'alloc'], $b;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Mov [$c, 1, 'alloc'], 2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok Execute(memory=>  { 1=>  bless([99, 2], "alloc") });
   }
  
  if (1)                                                                            
   {Start 1;
    my $a = Array "aaa";
    Dump "dddd";
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [
    "dddd",
    "-2=bless([], \"return\")",
    "-1=bless([], \"params\")",
    "0=bless([1], \"stackArea\")",
    "1=bless([], \"aaa\")",
    "Stack trace",
    "    1     2 dump",
  ];
   }
  
  if (1)                                                                              
   {Start 1;
    my $a = Array "aaa";
  
    my $i = Mov 1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    my $v = Mov 11;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ParamsPut 0, $a;
    ParamsPut 1, $i;
    ParamsPut 2, $v;
    my $set = Procedure 'set', sub
     {my $a = ParamsGet 0;
      my $i = ParamsGet 1;
      my $v = ParamsGet 2;
  
      Mov [$a, \$i, 'aaa'], $v;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Return;
     };
    Call $set;
  
    my $V = Mov [$a, \$i, 'aaa'];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    AssertEq $v, $V;
    Out [$a, \$i, 'aaa'];
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [11];
   }
  
  if (1)                                                                            
   {Start 1;
    my $set = Procedure 'set', sub
     {my $a = ParamsGet 0;
     };
    ParamsPut 0, 1;
    Call $set;
    ParamsPut 0, 1;
    Call $set;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [];
   }
  
  if (1)                                                                                 
   {Start 1;
    my $a = Array "aaa";
    my $b = Array "bbb";
  
    Mov [$a, 0, 'aaa'], $b;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Mov [$b, 0, 'bbb'], 99;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    For
     {my ($i, $check, $next, $end) = @_;
  
      my $c = Mov [$a, \0, 'aaa'];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
      my $d = Mov [$c, \0, 'bbb'];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Jeq $next, $d, $d;
      Jne $next, $d, $d;
      Jle $next, $d, $d;
      Jlt $next, $d, $d;
      Jge $next, $d, $d;
      Jgt $next, $d, $d;
     } 3;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->analyzeExecutionResults(doubleWrite=>3), "#       24 instructions executed";
    is_deeply $e->memory, { 1=>  bless([2], "aaa"), 2=>  bless([99], "bbb") };
   }
  
  if (1)                                                                           
   {Start 1;
    my $a = Array 'aaa';
  
    my $b = Mov 2;                                                                # Location to move to in a  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    For
     {my ($i, $check, $next, $end) = @_;
  
      Mov [$a, \$b, 'aaa'], 1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Jeq $next, [$a, \$b, 'aaa'], 1;
     } 3;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->analyzeExecutionResults(doubleWrite=>3), "#       19 instructions executed";
    is_deeply $e->memory, {1=>  bless([undef, undef, 1], "aaa")};
   }
  
  if (1)                                                                           
   {Start 1;
    my $a = Array "aaa";
  
      Mov [$a, 0, "aaa"], 1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
      Mov [$a, 1, "aaa"], 22;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
      Mov [$a, 2, "aaa"], 333;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    DumpArray $a, "AAAA";
    my $e = Execute(suppressOutput=>1);
  
    is_deeply $e->out,
   ["AAAA",
    "bless([1, 22, 333], \"aaa\")",
    "Stack trace",
    "    1     5 dumpArray",
  ];
   }
  

=head3 Not()

Move and not.


B<Example:>


  if (1)                                                                          
   {Start 1;
    my $a = Mov 3;
  
    my $b = Not $a;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    my $c = Not $b;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Out $a;
    Out $b;
    Out $c;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [3, "", 1];
   }
  

=head3 Nop()

Do nothing (but do it well!).


B<Example:>


  if (1)                                                                          
   {Start 1;
  
    Nop;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok Execute(out=>[]);
   }
  

=head3 Out($source)

Write memory contents to out.

     Parameter  Description
  1  $source    Either a scalar constant or memory address to output

B<Example:>


  if (1)                                                                            
   {Start 1;
  
    Out "hello World";  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["hello World"];
   }
  

=head3 Procedure($name, $source)

Define a procedure.

     Parameter  Description
  1  $name      Name of procedure
  2  $source    Source code as a subroutine# $assembly->instruction(action=>"procedure"

B<Example:>


  if (1)                                                                          
   {Start 1;
  
    my $add = Procedure 'add2', sub  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {my $a = ParamsGet 0;
      my $b = Add $a, 2;
      ReturnPut 0, $b;
      Return;
     };
    ParamsPut 0, 2;
    Call $add;
    my $c = ReturnGet 0;
    Out $c;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [4];
   }
  
  if (1)                                                                          
   {Start 1;
    for my $i(1..10)
     {Out $i;
     };
    IfTrue 0,
    Then
     {Out 99;
     };
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [1..10];
   }
  

=head3 ParamsGet()

Get a word from the parameters in the previous frame and store it in the current frame.


B<Example:>


  if (1)                                                                              
   {Start 1;
    my $a = Array "aaa";
    my $i = Mov 1;
    my $v = Mov 11;
    ParamsPut 0, $a;
    ParamsPut 1, $i;
    ParamsPut 2, $v;
    my $set = Procedure 'set', sub
  
     {my $a = ParamsGet 0;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
      my $i = ParamsGet 1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
      my $v = ParamsGet 2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Mov [$a, \$i, 'aaa'], $v;
      Return;
     };
    Call $set;
    my $V = Mov [$a, \$i, 'aaa'];
    AssertEq $v, $V;
    Out [$a, \$i, 'aaa'];
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [11];
   }
  

=head3 ParamsPut($target, $source)

Put a word into the parameters list to make it visible in a called procedure.

     Parameter  Description
  1  $target    Parameter number
  2  $source    Address to fetch parameter from

B<Example:>


  if (1)                                                                              
   {Start 1;
    my $a = Array "aaa";
    my $i = Mov 1;
    my $v = Mov 11;
  
    ParamsPut 0, $a;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    ParamsPut 1, $i;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    ParamsPut 2, $v;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $set = Procedure 'set', sub
     {my $a = ParamsGet 0;
      my $i = ParamsGet 1;
      my $v = ParamsGet 2;
      Mov [$a, \$i, 'aaa'], $v;
      Return;
     };
    Call $set;
    my $V = Mov [$a, \$i, 'aaa'];
    AssertEq $v, $V;
    Out [$a, \$i, 'aaa'];
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [11];
   }
  

=head3 Return()

Return from a procedure via the call stack.


B<Example:>


  if (1)                                                                           
   {Start 1;
    my $w = Procedure 'write', sub
     {Out 'aaa';
  
      Return;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     };
    Call $w;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["aaa"];
   }
  

=head3 ReturnGet(if (@_ == 1))

Get a word from the return area and save it.

     Parameter     Description
  1  if (@_ == 1)  Create a variable

B<Example:>


  if (1)                                                                            
   {Start 1;
    my $w = Procedure 'write', sub
     {ReturnPut 0, "ccc";
      Return;
     };
    Call $w;
  
    ReturnGet \0, 0;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Out \0;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["ccc"];
   }
  

=head3 ReturnPut($target, $source)

Put a word into the return area.

     Parameter  Description
  1  $target    Offset in return area to write to
  2  $source    Memory address whose contents are to be placed in the return area

B<Example:>


  if (1)                                                                            
   {Start 1;
    my $w = Procedure 'write', sub
  
     {ReturnPut 0, "ccc";  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Return;
     };
    Call $w;
    ReturnGet \0, 0;
    Out \0;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["ccc"];
   }
  

=head3 Resize($target, $source)

Resize the target area to the source size.

     Parameter  Description
  1  $target    Target address
  2  $source    Source address

B<Example:>


  if (1)                                                                          
   {Start 1;
    my $a = Array 'aaa';
    Mov [$a, 0, 'aaa'], 1;
    Mov [$a, 1, 'aaa'], 2;
    Mov [$a, 2, 'aaa'], 3;
  
    Resize $a, 2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->memory, {1=>  [1, 2]};
   }
  

=head3 Pop(if (@_ == 0))

Pop the memory area specified by the source operand into the memory address specified by the target operand.

     Parameter     Description
  1  if (@_ == 0)  Pop current stack frame into a local variable

B<Example:>


  if (1)                                                                           
   {Start 1;
    my $a = Array "aaa";
    Push $a, 1;
    Push $a, 2;
  
    my $c = Pop $a;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    my $d = Pop $a;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Out $c;
    Out $d;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out,    [2, 1];
    is_deeply $e->memory, { 1=>  []};
   }
  

=head3 Push()

Push the value in the current stack frame specified by the source operand onto the memory area identified by the target operand..


B<Example:>


  if (1)                                                                           
   {Start 1;
    my $a = Array "aaa";
  
    Push $a, 1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Push $a, 2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $c = Pop $a;
    my $d = Pop $a;
  
    Out $c;
    Out $d;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out,    [2, 1];
    is_deeply $e->memory, { 1=>  []};
   }
  

=head3 ShiftLeft(my ($target, $source)

Shift left within an element.

     Parameter    Description
  1  my ($target  Target to shift
  2  $source      Amount to shift

B<Example:>


  if (1)                                                                          
   {Start 1;
    my $a = Mov 1;
  
    ShiftLeft $a, $a;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Out $a;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [2];
   }
  

=head3 ShiftRight(my ($target, $source)

Shift right with an element.

     Parameter    Description
  1  my ($target  Target to shift
  2  $source      Amount to shift

B<Example:>


  if (1)                                                                          
   {Start 1;
    my $a = Mov 4;
  
    ShiftRight $a, 1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Out $a;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [2];
   }
  

=head3 ShiftUp($target, $source)

Shift an element up one in an area.

     Parameter  Description
  1  $target    Target to shift
  2  $source    Amount to shift

B<Example:>


  if (1)                                                                          
   {Start 1;
    my $a = Array "array";
    Mov [$a, 0, 'array'], 0;
    Mov [$a, 1, 'array'], 1;
    Mov [$a, 2, 'array'], 2;
  
    ShiftUp [$a, 1, 'array'], 99;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->memory, {1=>[0, 99, 1, 2]};
   }
  

=head3 ShiftDown(if (@_ == 1))

Shift an element down one in an area.

     Parameter     Description
  1  if (@_ == 1)  Create a variable

B<Example:>


  if (1)                                                                          
   {Start 1;
    my $a = Array "array";
    Mov [$a, 0, 'array'], 0;
    Mov [$a, 1, 'array'], 99;
    Mov [$a, 2, 'array'], 2;
  
    my $b = ShiftDown [$a, \1, 'array'];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Out $b;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->memory, {1=>[0, 2]};
    is_deeply $e->out,    [99];
   }
  

=head3 Watch($target)

Shift an element down one in an area.

     Parameter  Description
  1  $target    Memory address to watch

B<Example:>


  if (1)                                                                          
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    my $c = Mov 3;
  
    Watch $b;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Mov $a, 4;
    Mov $b, 5;
    Mov $c, 6;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out,
  [
    "Change at watched area: 0 (stackArea), address: 1
",
    "    1     6 mov",
    "Current value: 2",
    "New     value: 5",
    "-2=bless([], \"return\")",
    "-1=bless([], \"params\")",
    "0=bless([4, 2, 3], \"stackArea\")",
  ];
   }
  

=head3 Tally($source)

Counts instructions when enabled.

     Parameter  Description
  1  $source    Tally instructions when true

B<Example:>


  if (1)                                                                           
   {my $N = 5;
    Start 1;
    For
  
     {Tally 1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      my $a = Mov 1;
  
      Tally 2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Inc $a;
  
      Tally 0;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     } $N;
    my $e = Execute;
  
    is_deeply $e->tallyCount, 2 * $N;
    is_deeply $e->tallyCounts,{ 1 => {mov => $N}, 2 => {inc => $N}};
   }
  

=head3 Then($t)

Then block.

     Parameter  Description
  1  $t         Then block subroutine

B<Example:>


  if (1)                                                                            
   {Start 1;
    Trace 1;
    IfEq 1, 2,
  
    Then  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {Mov 1, 1;
      Mov 2, 1;
     },
    Else
     {Mov 3, 3;
      Mov 4, 4;
     };
    IfEq 2, 2,
  
    Then  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {Mov 1, 1;
      Mov 2, 1;
     },
    Else
     {Mov 3, 3;
      Mov 4, 4;
     };
    my $e = Execute(suppressOutput=>1);
    is_deeply scalar($e->out->@*), 14;
   }
  

=head3 Else($e)

Else block.

     Parameter  Description
  1  $e         Else block subroutine

B<Example:>


  if (1)                                                                            
   {Start 1;
    Trace 1;
    IfEq 1, 2,
    Then
     {Mov 1, 1;
      Mov 2, 1;
     },
  
    Else  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {Mov 3, 3;
      Mov 4, 4;
     };
    IfEq 2, 2,
    Then
     {Mov 1, 1;
      Mov 2, 1;
     },
  
    Else  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {Mov 3, 3;
      Mov 4, 4;
     };
    my $e = Execute(suppressOutput=>1);
    is_deeply scalar($e->out->@*), 14;
   }
  

=head3 IfFalse($a, %options)

Execute then clause if the specified memory address is zero representing false.

     Parameter  Description
  1  $a         Memory address
  2  %options   Then block

B<Example:>


  if (1)                                                                            
   {Start 1;
  
    IfFalse 1,  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Then
     {Out 1
     },
    Else
     {Out 0
     };
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [0];
   }
  

=head3 IfTrue($a, %options)

Execute then clause if the specified memory address is not zero representing true.

     Parameter  Description
  1  $a         Memory address
  2  %options   Then block

B<Example:>


  if (1)                                                                          
   {Start 1;
  
    IfTrue 1,  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Then
     {Out 1
     },
    Else
     {Out 0
     };
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [1];
   }
  

=head3 IfEq($a, $b, %options)

Execute then or else clause depending on whether two memory locations are equal..

     Parameter  Description
  1  $a         First memory address
  2  $b         Second memory address
  3  %options   Then block

B<Example:>


  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
  
    IfEq $a, $a, Then {Out "Eq"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfNe $a, $a, Then {Out "Ne"};
    IfLe $a, $a, Then {Out "Le"};
    IfLt $a, $a, Then {Out "Lt"};
    IfGe $a, $a, Then {Out "Ge"};
    IfGt $a, $a, Then {Out "Gt"};
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Eq", "Le", "Ge"];
   }
  
  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
  
    IfEq $a, $b, Then {Out "Eq"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfNe $a, $b, Then {Out "Ne"};
    IfLe $a, $b, Then {Out "Le"};
    IfLt $a, $b, Then {Out "Lt"};
    IfGe $a, $b, Then {Out "Ge"};
    IfGt $a, $b, Then {Out "Gt"};
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Ne", "Le", "Lt"];
   }
  
  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
  
    IfEq $b, $a, Then {Out "Eq"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfNe $b, $a, Then {Out "Ne"};
    IfLe $b, $a, Then {Out "Le"};
    IfLt $b, $a, Then {Out "Lt"};
    IfGe $b, $a, Then {Out "Ge"};
    IfGt $b, $a, Then {Out "Gt"};
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Ne", "Ge", "Gt"];
   }
  

=head3 IfNe($a, $b, %options)

Execute then or else clause depending on whether two memory locations are not equal..

     Parameter  Description
  1  $a         First memory address
  2  $b         Second memory address
  3  %options   Then block

B<Example:>


  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    IfEq $a, $a, Then {Out "Eq"};
  
    IfNe $a, $a, Then {Out "Ne"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfLe $a, $a, Then {Out "Le"};
    IfLt $a, $a, Then {Out "Lt"};
    IfGe $a, $a, Then {Out "Ge"};
    IfGt $a, $a, Then {Out "Gt"};
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Eq", "Le", "Ge"];
   }
  
  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    IfEq $a, $b, Then {Out "Eq"};
  
    IfNe $a, $b, Then {Out "Ne"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfLe $a, $b, Then {Out "Le"};
    IfLt $a, $b, Then {Out "Lt"};
    IfGe $a, $b, Then {Out "Ge"};
    IfGt $a, $b, Then {Out "Gt"};
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Ne", "Le", "Lt"];
   }
  
  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    IfEq $b, $a, Then {Out "Eq"};
  
    IfNe $b, $a, Then {Out "Ne"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfLe $b, $a, Then {Out "Le"};
    IfLt $b, $a, Then {Out "Lt"};
    IfGe $b, $a, Then {Out "Ge"};
    IfGt $b, $a, Then {Out "Gt"};
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Ne", "Ge", "Gt"];
   }
  

=head3 IfLt($a, $b, %options)

Execute then or else clause depending on whether two memory locations are less than..

     Parameter  Description
  1  $a         First memory address
  2  $b         Second memory address
  3  %options   Then block

B<Example:>


  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    IfEq $a, $a, Then {Out "Eq"};
    IfNe $a, $a, Then {Out "Ne"};
    IfLe $a, $a, Then {Out "Le"};
  
    IfLt $a, $a, Then {Out "Lt"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfGe $a, $a, Then {Out "Ge"};
    IfGt $a, $a, Then {Out "Gt"};
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Eq", "Le", "Ge"];
   }
  
  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    IfEq $a, $b, Then {Out "Eq"};
    IfNe $a, $b, Then {Out "Ne"};
    IfLe $a, $b, Then {Out "Le"};
  
    IfLt $a, $b, Then {Out "Lt"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfGe $a, $b, Then {Out "Ge"};
    IfGt $a, $b, Then {Out "Gt"};
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Ne", "Le", "Lt"];
   }
  
  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    IfEq $b, $a, Then {Out "Eq"};
    IfNe $b, $a, Then {Out "Ne"};
    IfLe $b, $a, Then {Out "Le"};
  
    IfLt $b, $a, Then {Out "Lt"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfGe $b, $a, Then {Out "Ge"};
    IfGt $b, $a, Then {Out "Gt"};
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Ne", "Ge", "Gt"];
   }
  

=head3 IfLe($a, $b, %options)

Execute then or else clause depending on whether two memory locations are less than or equal..

     Parameter  Description
  1  $a         First memory address
  2  $b         Second memory address
  3  %options   Then block

B<Example:>


  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    IfEq $a, $a, Then {Out "Eq"};
    IfNe $a, $a, Then {Out "Ne"};
  
    IfLe $a, $a, Then {Out "Le"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfLt $a, $a, Then {Out "Lt"};
    IfGe $a, $a, Then {Out "Ge"};
    IfGt $a, $a, Then {Out "Gt"};
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Eq", "Le", "Ge"];
   }
  
  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    IfEq $a, $b, Then {Out "Eq"};
    IfNe $a, $b, Then {Out "Ne"};
  
    IfLe $a, $b, Then {Out "Le"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfLt $a, $b, Then {Out "Lt"};
    IfGe $a, $b, Then {Out "Ge"};
    IfGt $a, $b, Then {Out "Gt"};
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Ne", "Le", "Lt"];
   }
  
  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    IfEq $b, $a, Then {Out "Eq"};
    IfNe $b, $a, Then {Out "Ne"};
  
    IfLe $b, $a, Then {Out "Le"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfLt $b, $a, Then {Out "Lt"};
    IfGe $b, $a, Then {Out "Ge"};
    IfGt $b, $a, Then {Out "Gt"};
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Ne", "Ge", "Gt"];
   }
  

=head3 IfGt($a, $b, %options)

Execute then or else clause depending on whether two memory locations are greater than..

     Parameter  Description
  1  $a         First memory address
  2  $b         Second memory address
  3  %options   Then block

B<Example:>


  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    IfEq $a, $a, Then {Out "Eq"};
    IfNe $a, $a, Then {Out "Ne"};
    IfLe $a, $a, Then {Out "Le"};
    IfLt $a, $a, Then {Out "Lt"};
    IfGe $a, $a, Then {Out "Ge"};
  
    IfGt $a, $a, Then {Out "Gt"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Eq", "Le", "Ge"];
   }
  
  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    IfEq $a, $b, Then {Out "Eq"};
    IfNe $a, $b, Then {Out "Ne"};
    IfLe $a, $b, Then {Out "Le"};
    IfLt $a, $b, Then {Out "Lt"};
    IfGe $a, $b, Then {Out "Ge"};
  
    IfGt $a, $b, Then {Out "Gt"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Ne", "Le", "Lt"];
   }
  
  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    IfEq $b, $a, Then {Out "Eq"};
    IfNe $b, $a, Then {Out "Ne"};
    IfLe $b, $a, Then {Out "Le"};
    IfLt $b, $a, Then {Out "Lt"};
    IfGe $b, $a, Then {Out "Ge"};
  
    IfGt $b, $a, Then {Out "Gt"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Ne", "Ge", "Gt"];
   }
  

=head3 IfGe($a, $b, %options)

Execute then or else clause depending on whether two memory locations are greater than or equal..

     Parameter  Description
  1  $a         First memory address
  2  $b         Second memory address
  3  %options   Then block

B<Example:>


  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    IfEq $a, $a, Then {Out "Eq"};
    IfNe $a, $a, Then {Out "Ne"};
    IfLe $a, $a, Then {Out "Le"};
    IfLt $a, $a, Then {Out "Lt"};
  
    IfGe $a, $a, Then {Out "Ge"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfGt $a, $a, Then {Out "Gt"};
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Eq", "Le", "Ge"];
   }
  
  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    IfEq $a, $b, Then {Out "Eq"};
    IfNe $a, $b, Then {Out "Ne"};
    IfLe $a, $b, Then {Out "Le"};
    IfLt $a, $b, Then {Out "Lt"};
  
    IfGe $a, $b, Then {Out "Ge"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfGt $a, $b, Then {Out "Gt"};
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Ne", "Le", "Lt"];
   }
  
  if (1)                                                                                   
   {Start 1;
    my $a = Mov 1;
    my $b = Mov 2;
    IfEq $b, $a, Then {Out "Eq"};
    IfNe $b, $a, Then {Out "Ne"};
    IfLe $b, $a, Then {Out "Le"};
    IfLt $b, $a, Then {Out "Lt"};
  
    IfGe $b, $a, Then {Out "Ge"};  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    IfGt $b, $a, Then {Out "Gt"};
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Ne", "Ge", "Gt"];
   }
  

=head3 Assert(%options)

Assert regardless.

     Parameter  Description
  1  %options   Options

B<Example:>


  if (1)                                                                          
   {Start 1;
  
    Assert;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
  
    is_deeply $e->out, ["Assert failed", "    1     1 assert"];  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   }
  

=head3 AssertEq($a, $b, %options)

Assert two memory locations are equal..

     Parameter  Description
  1  $a         First memory address
  2  $b         Second memory address
  3  %options

B<Example:>


  if (1)                                                                          
   {Start 1;
    Mov 0, 1;
  
    AssertEq \0, 2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Assert 1 == 2 failed", "    1     2 assertEq"];
   }
  

=head3 AssertNe($a, $b, %options)

Assert two memory locations are not equal..

     Parameter  Description
  1  $a         First memory address
  2  $b         Second memory address
  3  %options

B<Example:>


  if (1)                                                                          
   {Start 1;
    Mov 0, 1;
  
    AssertNe \0, 1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Assert 1 != 1 failed", "    1     2 assertNe"];
   }
  

=head3 AssertLt($a, $b, %options)

Assert two memory locations are less than..

     Parameter  Description
  1  $a         First memory address
  2  $b         Second memory address
  3  %options

B<Example:>


  if (1)                                                                          
   {Start 1;
    Mov 0, 1;
  
    AssertLt \0, 0;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Assert 1 <  0 failed", "    1     2 assertLt"];
   }
  

=head3 AssertLe($a, $b, %options)

Assert two memory locations are less than or equal..

     Parameter  Description
  1  $a         First memory address
  2  $b         Second memory address
  3  %options

B<Example:>


  if (1)                                                                          
   {Start 1;
    Mov 0, 1;
  
    AssertLe \0, 0;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Assert 1 <= 0 failed", "    1     2 assertLe"];
   }
  

=head3 AssertGt($a, $b, %options)

Assert two memory locations are greater than..

     Parameter  Description
  1  $a         First memory address
  2  $b         Second memory address
  3  %options

B<Example:>


  if (1)                                                                          
   {Start 1;
    Mov 0, 1;
  
    AssertGt \0, 2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Assert 1 >  2 failed", "    1     2 assertGt"];
   }
  

=head3 AssertGe($a, $b, %options)

Assert are greater than or equal..

     Parameter  Description
  1  $a         First memory address
  2  $b         Second memory address
  3  %options

B<Example:>


  if (1)                                                                          
   {Start 1;
    Mov 0, 1;
  
    AssertGe \0, 2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, ["Assert 1 >= 2 failed", "    1     2 assertGe"];
   }
  

=head3 AssertTrue($a, %options)

Assert true

     Parameter  Description
  1  $a         Source operand
  2  %options

B<Example:>


  if (1)                                                                          
   {Start 1;
    AssertFalse 0;
  
    AssertTrue  0;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1, trace=>1);
    is_deeply $e->out,
  [ "   1     0     1   assertFalse                      
",
  
    "AssertTrue 0 failed",  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    "    1     2 assertTrue",
    "   2     1     1    assertTrue                      
"];
   }
  

=head3 AssertFalse($a, %options)

Assert false

     Parameter  Description
  1  $a         Source operand
  2  %options

B<Example:>


  if (1)                                                                          
   {Start 1;
    AssertTrue  1;
  
    AssertFalse 1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $e = Execute(suppressOutput=>1, trace=>1);
    is_deeply $e->out,
  [ "   1     0     1    assertTrue                      
",
  
    "AssertFalse 1 failed",  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    "    1     2 assertFalse",
    "   2     1     1   assertFalse                      
"];
  
   }
  

=head3 For($block, $range, %options)

For loop 0..range-1 or in reverse.

     Parameter  Description
  1  $block     Block
  2  $range     Limit
  3  %options   Options

B<Example:>


  if (1)                                                                           
   {my $N = 5;
    Start 1;
  
    For  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {Tally 1;
      my $a = Mov 1;
      Tally 2;
      Inc $a;
      Tally 0;
     } $N;
    my $e = Execute;
  
    is_deeply $e->tallyCount, 2 * $N;
    is_deeply $e->tallyCounts,{ 1 => {mov => $N}, 2 => {inc => $N}};
   }
  

=head3 ForArray($block, $area, $name, %options)

For loop to process each element of the named area.

     Parameter  Description
  1  $block     Block of code
  2  $area      Area
  3  $name      Area name
  4  %options   Options

B<Example:>


  if (1)                                                                            
   {Start 1;
    my $a = Array "aaa";
      Mov [$a, 0, "aaa"], 1;
      Mov [$a, 1, "aaa"], 22;
      Mov [$a, 2, "aaa"], 333;
    my $n = ArraySize $a, "aaa";
    Out $n;
  
  
    ForArray  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {my ($i, $e, $check, $next, $end) = @_;
      IfGt $i, 1,
      Then
       {Trace 1;
       };
      Out $i; Out $e;
     }  $a, "aaa";
  
    Nop;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->memory, {1=>[1, 22, 333]};
  
    is_deeply $e->out,
   [3, 0, 1, 1, 22,
    "Trace: 1",
    "  37    14     1         trace                      
",
    "  38    15     3         label                      
",
    2,
    "  39    16     3           out                      
",
    333,
    "  40    17     3           out                      
",
    "  41    18     3         label                      
",
    "  42    19     3           inc  [0, 3, stackArea] = 3 was 2
",
    "  43    20     3           jmp                      
",
    "  44     9     4         label                      
",
    "  45    10     4           jGe                      
",
    "  46    21     1         label                      
",
    "  47    22     1           nop                      
",
  ];
   }
  

=head3 Good($good)

A good ending.

     Parameter  Description
  1  $good      What to do on a good ending

B<Example:>


  if (1)                                                                            
   {Start 1;
    Block
     {my ($start, $good, $bad, $end) = @_;
      Out 1;
      Jmp $good;
     }
  
    Good  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {Out 2;
     },
    Bad
     {Out 3;
     };
    Out 4;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [1,2,4];
   }
  

=head3 Bad($bad)

A bad ending.

     Parameter  Description
  1  $bad       What to do on a bad ending

B<Example:>


  if (1)                                                                            
   {Start 1;
    Block
     {my ($start, $good, $bad, $end) = @_;
      Out 1;
      Jmp $good;
     }
    Good
     {Out 2;
     },
  
    Bad  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {Out 3;
     };
    Out 4;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [1,2,4];
   }
  

=head3 Block($block, %options)

Block of code that can either be restarted or come to a good or a bad ending.

     Parameter  Description
  1  $block     Block
  2  %options   Options

B<Example:>


  if (1)                                                                            
   {Start 1;
  
    Block  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {my ($start, $good, $bad, $end) = @_;
      Out 1;
      Jmp $good;
     }
    Good
     {Out 2;
     },
    Bad
     {Out 3;
     };
    Out 4;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [1,2,4];
   }
  
  if (1)                                                                          
   {Start 1;
  
    Block  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {my ($start, $good, $bad, $end) = @_;
      Out 1;
      Jmp $bad;
     }
    Good
     {Out 2;
     },
    Bad
     {Out 3;
     };
    Out 4;
    my $e = Execute(suppressOutput=>1);
    is_deeply $e->out, [1,3,4];
   }
  

=head3 Execute(%options)

Execute the current assembly.

     Parameter  Description
  1  %options   Options

B<Example:>


  if (1)                                                                            
   {Start 1;
    Out "hello World";
  
    my $e = Execute(suppressOutput=>1);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    is_deeply $e->out, ["hello World"];
   }
  

=head1 Tests

=head1 Examples


=head1 Private Methods

=head2 Zero::Emulator::Execution::areaContent($exec, $address)

Content of an area containing a address in memory in the specified execution.

     Parameter  Description
  1  $exec      Execution environment
  2  $address   Address specification

=head2 Zero::Emulator::Execution::dumpMemory($exec)

Dump memory.

     Parameter  Description
  1  $exec      Execution environment

=head2 Zero::Emulator::Execution::analyzeExecutionResultsLeast($exec, %options)

Analyze execution results for least used code.

     Parameter  Description
  1  $exec      Execution results
  2  %options   Options

=head2 Zero::Emulator::Execution::analyzeExecutionResultsMost($exec, %options)

Analyze execution results for most used code.

     Parameter  Description
  1  $exec      Execution results
  2  %options   Options

=head2 Zero::Emulator::Execution::analyzeExecutionNotRead($exec, %options)

Analyze execution results for variables never read.

     Parameter  Description
  1  $exec      Execution results
  2  %options   Options

=head2 Zero::Emulator::Execution::analyzeExecutionResultsDoubleWrite($exec, %options)

Analyze execution results - double writes.

     Parameter  Description
  1  $exec      Execution results
  2  %options   Options

=head2 Zero::Emulator::Execution::analyzeExecutionResults($exec, %options)

Analyze execution results.

     Parameter  Description
  1  $exec      Execution results
  2  %options   Options

=head2 Zero::Emulator::Execution::check($exec, $area, $name)

Check that a user area access is valid.

     Parameter  Description
  1  $exec      Execution environment
  2  $area      Area
  3  $name      Expected area name

=head2 Zero::Emulator::Execution::getMemory($exec, $area, $address, $name, %options)

Get from memory.

     Parameter  Description
  1  $exec      Execution environment
  2  $area      Area
  3  $address   Address
  4  $name      Expected name of area
  5  %options   Options

=head2 Zero::Emulator::Execution::get($exec, $area, $address)

Get from memory.

     Parameter  Description
  1  $exec      Execution environment
  2  $area      Area
  3  $address   Address

=head2 Zero::Emulator::Execution::set($exec, $address, $value)

Set the value of an address at the specified address in memory in the current execution environment.

     Parameter  Description
  1  $exec      Execution environment
  2  $address   Address specification
  3  $value     Value

=head2 Zero::Emulator::Execution::stackArea($exec)

Current stack frame.

     Parameter  Description
  1  $exec      Execution environment

=head2 Zero::Emulator::Execution::address($exec, $area, $address, $name)

Record a reference to memory.

     Parameter  Description
  1  $exec      Execution environment
  2  $area      Area
  3  $address   Address in area
  4  $name      Memory

=head2 Zero::Emulator::Execution::stackTrace($exec, $title)

Create a stack trace.

     Parameter  Description
  1  $exec      Execution environment
  2  $title     Title

=head2 Zero::Emulator::Execution::stackTraceAndExit($exec, $title, %options)

Create a stack trace and exit from the emulated program.

     Parameter  Description
  1  $exec      Execution environment
  2  $title     Title
  3  %options   Options

=head2 Zero::Emulator::Execution::allocMemory($exec, $name, $stacked)

Create the name of a new memory area.

     Parameter  Description
  1  $exec      Execution environment
  2  $name      Name of allocation
  3  $stacked   Stacked if true

=head2 Zero::Emulator::Execution::setMemoryType($exec, $area, $name)

Set the type of a memory area - a name that can be used to confirm the validity of reads and writes to that array represented by that area.

     Parameter  Description
  1  $exec      Execution environment
  2  $area      Area name
  3  $name      Name of allocation

=head2 Zero::Emulator::Execution::notRead()

Record the unused memory locations in the current stack frame.


=head2 Zero::Emulator::Execution::rwWrite($exec, $area, $address)

Observe write to memory.

     Parameter  Description
  1  $exec      Area in memory
  2  $area      Address within area
  3  $address

=head2 Zero::Emulator::Execution::markAsRead($exec, $area, $address)

Mark a memory address as having been read from.

     Parameter  Description
  1  $exec      Area in memory
  2  $area      Address within area
  3  $address

=head2 Zero::Emulator::Execution::rwRead($exec, $area, $address)

Observe read from memory.

     Parameter  Description
  1  $exec      Area in memory
  2  $area      Address within area
  3  $address

=head2 Zero::Emulator::Execution::left($exec, $ref, $extra)

Address a memory address.

     Parameter  Description
  1  $exec      Reference
  2  $ref       An optional extra offset to add or subtract to the final memory address
  3  $extra

=head2 Zero::Emulator::Execution::leftSuppress($exec, $ref)

Indicate that a memory address has been read.

     Parameter  Description
  1  $exec      Execution environment
  2  $ref       Reference

=head2 Zero::Emulator::Execution::right($exec, $ref)

Get a constant or a memory address.

     Parameter  Description
  1  $exec      Location
  2  $ref       Optional area

=head2 Zero::Emulator::Execution::jumpOp($exec, $i, $check)

Jump to the target address if the tested memory area if the condition is matched.

     Parameter  Description
  1  $exec      Execution environment
  2  $i         Instruction
  3  $check     Check

=head2 Zero::Emulator::Execution::assert1($exec, $test, $sub)

Assert true or false

     Parameter  Description
  1  $exec      Execution environment
  2  $test      Text of test
  3  $sub       Subroutine of test

=head2 Zero::Emulator::Execution::assert($exec, $test, $sub)

Assert generically.

     Parameter  Description
  1  $exec      Execution environment
  2  $test      Text of test
  3  $sub       Subroutine of test

=head2 Zero::Emulator::Execution::assign($exec, $target, $value)

Assign - check for pointless assignments.

     Parameter  Description
  1  $exec      Execution environment
  2  $target    Target of assign
  3  $value     Value to assign

=head2 Zero::Emulator::Execution::allocateSystemAreas($exec)

Allocate system areas for a new stack frame.

     Parameter  Description
  1  $exec      Execution environment

=head2 Zero::Emulator::Execution::freeSystemAreas($exec, $c)

Free system areas for the specified stack frame.

     Parameter  Description
  1  $exec      Execution environment
  2  $c         Stack frame

=head2 Zero::Emulator::Execution::currentInstruction($exec)

Locate current instruction.

     Parameter  Description
  1  $exec      Execution environment

=head2 Zero::Emulator::Execution::createInitialStackEntry($exec)

Create the initial stack frame.

     Parameter  Description
  1  $exec      Execution environment

=head2 Zero::Emulator::Execution::checkArrayName($exec, $area, $name)

Check the name of an array

     Parameter  Description
  1  $exec      Execution environment
  2  $area      Array
  3  $name      Array name

=head2 Zero::Emulator::Execution::locateAreaElement($exec, $area, $op)

Locate an element in an array

     Parameter  Description
  1  $exec      Execution environment
  2  $area      Array
  3  $op        Operation

=head2 Zero::Emulator::Execution::countAreaElement($exec, $area, $op)

Count the number of elements in array that meet some specification

     Parameter  Description
  1  $exec      Execution environment
  2  $area      Array
  3  $op        Operation

=head2 Zero::Emulator::Code::execute($block, %options)

Execute a block of code.

     Parameter  Description
  1  $block     Block of code
  2  %options   Execution options

=head2 Zero::Emulator::Execution::formatTrace($exec)

Describe last memory assignment.

     Parameter  Description
  1  $exec      Execution

=head2 TracePoint(%options)

Trace point - a point in the code where the flow of execution might change.

     Parameter  Description
  1  %options   Parameters

=head2 Ifx($cmp, $a, $b, %options)

Execute then or else clause depending on whether two memory locations are equal..

     Parameter  Description
  1  $cmp       Comparison
  2  $a         First memory address
  3  $b         Second memory address
  4  %options   Then block

=head2 Assert1($op, $a)

Assert operation.

     Parameter  Description
  1  $op        Operation
  2  $a         Source operand

=head2 Assert2($op, $a, $b)

Assert operation.

     Parameter  Description
  1  $op        Operation
  2  $a         First memory address
  3  $b         Second memory address

=head2 Var($value)

Create a variable initialized to the specified value.

     Parameter  Description
  1  $value     Value


=head1 Index


1 L<Add|/Add> - Add the source locations together and store in the result in the target area.

2 L<Array|/Array> - Create a new memory area and write its number into the address named by the target operand.

3 L<ArrayCountGreater|/ArrayCountGreater> - Count the number of elements in the array specified by the first source operand that are greater than the element supplied by the second source operand and place the result in the target location

4 L<ArrayCountLess|/ArrayCountLess> - Count the number of elements in the array specified by the first source operand that are less than the element supplied by the second source operand and place the result in the target location

5 L<ArrayIndex|/ArrayIndex> - Find the 1 based index of the second source operand in the array referenced by the first source operand if it is present in the array else 0 into the target location.

6 L<ArraySize|/ArraySize> - The current size of an array

7 L<Assert|/Assert> - Assert regardless.

8 L<Assert1|/Assert1> - Assert operation.

9 L<Assert2|/Assert2> - Assert operation.

10 L<AssertEq|/AssertEq> - Assert two memory locations are equal.

11 L<AssertFalse|/AssertFalse> - Assert false

12 L<AssertGe|/AssertGe> - Assert are greater than or equal.

13 L<AssertGt|/AssertGt> - Assert two memory locations are greater than.

14 L<AssertLe|/AssertLe> - Assert two memory locations are less than or equal.

15 L<AssertLt|/AssertLt> - Assert two memory locations are less than.

16 L<AssertNe|/AssertNe> - Assert two memory locations are not equal.

17 L<AssertTrue|/AssertTrue> - Assert true

18 L<Bad|/Bad> - A bad ending.

19 L<Block|/Block> - Block of code that can either be restarted or come to a good or a bad ending.

20 L<Call|/Call> - Call the subroutine at the target address.

21 L<Clear|/Clear> - Clear the first bytes of an area.

22 L<Confess|/Confess> - Confess.

23 L<Dec|/Dec> - Decrement the target.

24 L<Dump|/Dump> - Dump memory.

25 L<DumpArray|/DumpArray> - Dump an array.

26 L<Else|/Else> - Else block.

27 L<Execute|/Execute> - Execute the current assembly.

28 L<For|/For> - For loop 0.

29 L<ForArray|/ForArray> - For loop to process each element of the named area.

30 L<Free|/Free> - Free the memory area named by the target operand after confirming that it has the name specified on the source operand.

31 L<Good|/Good> - A good ending.

32 L<IfEq|/IfEq> - Execute then or else clause depending on whether two memory locations are equal.

33 L<IfFalse|/IfFalse> - Execute then clause if the specified memory address is zero representing false.

34 L<IfGe|/IfGe> - Execute then or else clause depending on whether two memory locations are greater than or equal.

35 L<IfGt|/IfGt> - Execute then or else clause depending on whether two memory locations are greater than.

36 L<IfLe|/IfLe> - Execute then or else clause depending on whether two memory locations are less than or equal.

37 L<IfLt|/IfLt> - Execute then or else clause depending on whether two memory locations are less than.

38 L<IfNe|/IfNe> - Execute then or else clause depending on whether two memory locations are not equal.

39 L<IfTrue|/IfTrue> - Execute then clause if the specified memory address is not zero representing true.

40 L<Ifx|/Ifx> - Execute then or else clause depending on whether two memory locations are equal.

41 L<Inc|/Inc> - Increment the target.

42 L<Jeq|/Jeq> - Jump to a target label if the first source field is equal to the second source field.

43 L<JFalse|/JFalse> - Jump to a target label if the first source field is equal to zero

44 L<Jge|/Jge> - Jump to a target label if the first source field is greater than or equal to the second source field.

45 L<Jgt|/Jgt> - Jump to a target label if the first source field is greater than the second source field.

46 L<Jle|/Jle> - Jump to a target label if the first source field is less than or equal to the second source field.

47 L<Jlt|/Jlt> - Jump to a target label if the first source field is less than the second source field.

48 L<Jmp|/Jmp> - Jump to a label.

49 L<Jne|/Jne> - Jump to a target label if the first source field is not equal to the second source field.

50 L<JTrue|/JTrue> - Jump to a target label if the first source field is not equal to zero

51 L<Label|/Label> - Create a label.

52 L<LeAddress|/LeAddress> - Load the address component.

53 L<LeArea|/LeArea> - Load the address component.

54 L<Mov|/Mov> - Copy a constant or memory address to the target address.

55 L<Nop|/Nop> - Do nothing (but do it well!).

56 L<Not|/Not> - Move and not.

57 L<Out|/Out> - Write memory contents to out.

58 L<ParamsGet|/ParamsGet> - Get a word from the parameters in the previous frame and store it in the current frame.

59 L<ParamsPut|/ParamsPut> - Put a word into the parameters list to make it visible in a called procedure.

60 L<Pop|/Pop> - Pop the memory area specified by the source operand into the memory address specified by the target operand.

61 L<Procedure|/Procedure> - Define a procedure.

62 L<Push|/Push> - Push the value in the current stack frame specified by the source operand onto the memory area identified by the target operand.

63 L<Resize|/Resize> - Resize the target area to the source size.

64 L<Return|/Return> - Return from a procedure via the call stack.

65 L<ReturnGet|/ReturnGet> - Get a word from the return area and save it.

66 L<ReturnPut|/ReturnPut> - Put a word into the return area.

67 L<ShiftDown|/ShiftDown> - Shift an element down one in an area.

68 L<ShiftLeft|/ShiftLeft> - Shift left within an element.

69 L<ShiftRight|/ShiftRight> - Shift right with an element.

70 L<ShiftUp|/ShiftUp> - Shift an element up one in an area.

71 L<Start|/Start> - Start the current assembly using the specified version of the Zero language.

72 L<Subtract|/Subtract> - Subtract the second source address from the first and store in the result in the target area.

73 L<Tally|/Tally> - Counts instructions when enabled.

74 L<Then|/Then> - Then block.

75 L<Trace|/Trace> - Trace.

76 L<TracePoint|/TracePoint> - Trace point - a point in the code where the flow of execution might change.

77 L<TracePoints|/TracePoints> - Enable trace points.

78 L<Var|/Var> - Create a variable initialized to the specified value.

79 L<Watch|/Watch> - Shift an element down one in an area.

80 L<Zero::Emulator::Code::execute|/Zero::Emulator::Code::execute> - Execute a block of code.

81 L<Zero::Emulator::Execution::address|/Zero::Emulator::Execution::address> - Record a reference to memory.

82 L<Zero::Emulator::Execution::allocateSystemAreas|/Zero::Emulator::Execution::allocateSystemAreas> - Allocate system areas for a new stack frame.

83 L<Zero::Emulator::Execution::allocMemory|/Zero::Emulator::Execution::allocMemory> - Create the name of a new memory area.

84 L<Zero::Emulator::Execution::analyzeExecutionNotRead|/Zero::Emulator::Execution::analyzeExecutionNotRead> - Analyze execution results for variables never read.

85 L<Zero::Emulator::Execution::analyzeExecutionResults|/Zero::Emulator::Execution::analyzeExecutionResults> - Analyze execution results.

86 L<Zero::Emulator::Execution::analyzeExecutionResultsDoubleWrite|/Zero::Emulator::Execution::analyzeExecutionResultsDoubleWrite> - Analyze execution results - double writes.

87 L<Zero::Emulator::Execution::analyzeExecutionResultsLeast|/Zero::Emulator::Execution::analyzeExecutionResultsLeast> - Analyze execution results for least used code.

88 L<Zero::Emulator::Execution::analyzeExecutionResultsMost|/Zero::Emulator::Execution::analyzeExecutionResultsMost> - Analyze execution results for most used code.

89 L<Zero::Emulator::Execution::areaContent|/Zero::Emulator::Execution::areaContent> - Content of an area containing a address in memory in the specified execution.

90 L<Zero::Emulator::Execution::assert|/Zero::Emulator::Execution::assert> - Assert generically.

91 L<Zero::Emulator::Execution::assert1|/Zero::Emulator::Execution::assert1> - Assert true or false

92 L<Zero::Emulator::Execution::assign|/Zero::Emulator::Execution::assign> - Assign - check for pointless assignments.

93 L<Zero::Emulator::Execution::check|/Zero::Emulator::Execution::check> - Check that a user area access is valid.

94 L<Zero::Emulator::Execution::checkArrayName|/Zero::Emulator::Execution::checkArrayName> - Check the name of an array

95 L<Zero::Emulator::Execution::countAreaElement|/Zero::Emulator::Execution::countAreaElement> - Count the number of elements in array that meet some specification

96 L<Zero::Emulator::Execution::createInitialStackEntry|/Zero::Emulator::Execution::createInitialStackEntry> - Create the initial stack frame.

97 L<Zero::Emulator::Execution::currentInstruction|/Zero::Emulator::Execution::currentInstruction> - Locate current instruction.

98 L<Zero::Emulator::Execution::dumpMemory|/Zero::Emulator::Execution::dumpMemory> - Dump memory.

99 L<Zero::Emulator::Execution::formatTrace|/Zero::Emulator::Execution::formatTrace> - Describe last memory assignment.

100 L<Zero::Emulator::Execution::freeSystemAreas|/Zero::Emulator::Execution::freeSystemAreas> - Free system areas for the specified stack frame.

101 L<Zero::Emulator::Execution::get|/Zero::Emulator::Execution::get> - Get from memory.

102 L<Zero::Emulator::Execution::getMemory|/Zero::Emulator::Execution::getMemory> - Get from memory.

103 L<Zero::Emulator::Execution::jumpOp|/Zero::Emulator::Execution::jumpOp> - Jump to the target address if the tested memory area if the condition is matched.

104 L<Zero::Emulator::Execution::left|/Zero::Emulator::Execution::left> - Address a memory address.

105 L<Zero::Emulator::Execution::leftSuppress|/Zero::Emulator::Execution::leftSuppress> - Indicate that a memory address has been read.

106 L<Zero::Emulator::Execution::locateAreaElement|/Zero::Emulator::Execution::locateAreaElement> - Locate an element in an array

107 L<Zero::Emulator::Execution::markAsRead|/Zero::Emulator::Execution::markAsRead> - Mark a memory address as having been read from.

108 L<Zero::Emulator::Execution::notRead|/Zero::Emulator::Execution::notRead> - Record the unused memory locations in the current stack frame.

109 L<Zero::Emulator::Execution::right|/Zero::Emulator::Execution::right> - Get a constant or a memory address.

110 L<Zero::Emulator::Execution::rwRead|/Zero::Emulator::Execution::rwRead> - Observe read from memory.

111 L<Zero::Emulator::Execution::rwWrite|/Zero::Emulator::Execution::rwWrite> - Observe write to memory.

112 L<Zero::Emulator::Execution::set|/Zero::Emulator::Execution::set> - Set the value of an address at the specified address in memory in the current execution environment.

113 L<Zero::Emulator::Execution::setMemoryType|/Zero::Emulator::Execution::setMemoryType> - Set the type of a memory area - a name that can be used to confirm the validity of reads and writes to that array represented by that area.

114 L<Zero::Emulator::Execution::stackArea|/Zero::Emulator::Execution::stackArea> - Current stack frame.

115 L<Zero::Emulator::Execution::stackTrace|/Zero::Emulator::Execution::stackTrace> - Create a stack trace.

116 L<Zero::Emulator::Execution::stackTraceAndExit|/Zero::Emulator::Execution::stackTraceAndExit> - Create a stack trace and exit from the emulated program.

=head1 Installation

This module is written in 100% Pure Perl and, thus, it is easy to read,
comprehend, use, modify and install via B<cpan>:

  sudo cpan install Zero::Emulator

=head1 Author

L<philiprbrenan@gmail.com|mailto:philiprbrenan@gmail.com>

L<http://www.appaapps.com|http://www.appaapps.com>

=head1 Copyright

Copyright (c) 2016-2023 Philip R Brenan.

This module is free software. It may be used, redistributed and/or modified
under the same terms as Perl itself.

=cut
