#!/usr/bin/perl

###############################################
# IBM 650 ASSEMBLER AND BYTE CODE INTERPRETER #
# WRITTEN BY ERVIN RUCI, MARCH 22, 1998.      #
# LANGUAGE USED : MACPERL		      #
# COURSE CS 3711. PROGRAMMING LANGUAGES.      #
# PROF. ART MILLER.			      #
###############################################

#you can't put comments inside a loop. makes life easier for me
########### CONSTANTS ########################
$output_file="out.650";		#BYTECODE WILL GO HERE BY DEFAULT
$output_file1="out.ibm";	#ASSEMBLER CODE WRITTEN TO THIS FILE

#	DECLARE A COUPLE OF CONSTANTS
%reserved_words = ("VAR",  "+0", "MOVE", "+0",
         	   "ADD" , "+1", "SUB",  "-1",
         	   "MULT", "+2", "DIV",  "-2",
                   "SQR" , "+3", "SQRT", "-3",
                   "EQ"  , "+4", "NEQ",  "-4",
	           "GTEQ", "+5", "LT",   "-5",
	           "GETA", "+6", "PUTA", "-6",
	           "LOOP", "+7", "LABL", "-7",
	           "READ", "+8", "PRNT", "-8",
	           "STOP", "+9");

%jumps = ("EQ","+4","NEQ","-4","GTEQ","+5","LT","-5","LOOP","+7");

%arithmetic =("ADD","+1","SUB","-1","MULT","+2","DIV","-2");

################################################

#	GET THE FILE FROM THE COMMAND LINE
if ($#ARGV <0) {die "Usage:  $0 inputfile outputfile(optional)\n";}
   ($infile) = @ARGV;
   if (! -r $infile){die "Can't read input $infile\n";}
   if (! -f $infile){die "Input $infile is not a plain file\n";}
   if ($#ARGV >0){$output_file=$ARGV[1];}

#	see if it is byte code or assembler
$t=substr($infile,length($infile)-3,length($infile));
if ($t eq 'ibm'){$t=1}
elsif ($t eq '650'){$t=0}
else {print "Error :$t. Legal File names are filename.ibm or filename.650\n\n";}

if (($t eq 1) || ($t eq 0)){
open(FILE,"$infile");	  @FILE1 = ;	close(FILE);

if ($t eq 1){ #this means that we are dealing with assembler code

#initialize the variables
$op1=100; $op2=300; $op3=600; $index=0; $i=0; $comment=1; $stop= 'STOP';
$it_is_over=0; $initialize=1; $num_of_lines=0; $skip=0; $sto=0; $iold=0;
$ii=0;	$jump=0; $check=0;	$read=0;

####################################
#the variables are always declared at the top so i dont need to priori 
#collect them into an array. i need to have the data though.
#see if there are any data given in the end of code down

$dstop=0;	$lines=0;
foreach $FILE1(@FILE1)
{
chomp($FILE1); #remove line ending

if ($FILE1 eq 'STOP'){$dstop++; if ($dstop eq 2){$num_of_lines=$lines+1}}
else	{
if ($dstop eq 2){push(@data,$FILE1)}#this is the data array
	}
$lines++;
}#foreach 

######################end of preparing the data and code arrays ###

#	Here starts the whole fun...

while ($i+$skip<$num_of_lines)
{
	$FILE=$FILE1[$i+$skip];
	
	$first_char=substr($FILE,0,1);
	if ($first_char ne '#') 	#	SEE IF THE LINE IS A COMMENT
 {
	$i++;		$ii++;		$comment=0;	@vars = (); 
	$count = ($FILE =~ tr/ / /);
		if ($count eq 0){$vars[0]=$FILE}
		else	{@vars=split(/ /,$FILE);}
	while (($pseudo, $machine) = each(%reserved_words))
  {	
	if ($vars[0] eq $pseudo) 
    {
	$previous=$pseudo;		$comment=1;
	if ($initialize eq 0)	{
	$k=$i-1; print "Error: $prev_variable Un-Initialized Line $k, compilation aborted\n";
	$i=$num_of_lines+1;
				}
   	else
      {
	if ($pseudo eq 'LABL')
	{
	$index=0;
	foreach $label (@label){$index++}
	$label[$index]="$vars[1]##$i";
	$c="$machine $i 000 000\n";
	}
		
	elsif ($pseudo eq 'VAR')
	{
	$offset=0;
	$address=$op1;
	while ($offset<$vars[2])
	{
	$variab="$vars[1]##$offset##$op1";
	push(@variable,$variab); 
	$offset++;
	$op1++;
	}
	$initialize=0;
	$prev_variable=$vars[1];
	$c="$machine 000 $vars[2] $address\n";
	}#END OF VAR
			

else	{	# IT IS NEITHER VAR NOR LABEL. LOOK FOR INSTRUCTIONS


	if ($pseudo eq "STOP")
	{
	$c=("+9 999 999 999\n");	$it_is_over++;
	}


if (($pseudo eq 'MOVE') || ($pseudo eq 'SQR') || ($pseudo eq 'SQRT')){

&find;_var(@variable);	#THIS PROCEDURE FINDS THE VARIABLES IN THE TABLE

if ($xf eq '-1') {print "Error $pseudo: Variable $vars[1] Undeclared at Line $i\n";}
if ($yf eq '-1') {print "Error $pseudo: Variable $vars[2] Undeclared at Line $i\n";}
if (($xf ne '-1') && ($yf ne '-1')) {
@three_opsx=split(/##/,$variable[$xxxi]);	@three_opsz=split(/##/,$variable[$yyyi]);
	$c=("$machine $xxx $zzz $yyy\n");	#print the machine code
	if ($vars[0] eq 'MOVE'){$three_opsz[3]=$three_opsx[3];}
	if ($vars[0] eq 'SQR'){$three_opsz[3]=$three_opsx[3]*$three_opsx[3];}
	if ($vars[0] eq 'SQRT'){$three_opsz[3]=sqrt($three_ops[3]);}
$variable[$yyyi]="$three_opsz[0]##$three_opsz[1]##$three_opsz[2]##$three_opsz[3]";
			}#if $xxx ne -1 and $zzz ne -1
} #	END OF MOVE , SQR , SQRT
	


#now lets perform the array operations. will include range checking
#GETA x[y]->z
#PUTA x->y[z]
#if the variable x say has been declared of length 2 and y is 3
#then this is a syntax error trying to access elements outside the range

	if (($pseudo eq 'GETA') || ($pseudo eq 'PUTA')) {

&find;_var(@variable);

if ($xf eq '-1'){print "Error $pseudo: Variable $vars[1] Undeclared at Line $i\n";}
if ($yf eq '-1'){print "Error $pseudo: Variable $vars[2] Undeclared at Line $i\n";}
if ($zf eq '-1'){print "Error $pseudo: Variable $vars[3] Undeclared at Line $i\n";}
	if (($xf ne '-1') && ($zf ne '-1') && ($yf ne '-1')) {
@three_opsx=split(/##/,$variable[$xxxi]);
@three_opsz=split(/##/,$variable[$zzzi]);
	$c=("$machine $xxx $yyy $zzz\n");#print the machine code
$xxx=$xxa;
$zzz=$zza;
$yyy=$yya;
		if ($pseudo eq 'GETA'){	#GETA x[y]->z	
		if ($yyy>$length_x){print "ERROR: $vars[1] [$yyy] out of range";}
		else 	{
	$xxxi=$xxxi-$length_x+$yyy;		$xxx=$three_opsx[3];
$variable[$zzzi]="$three_opsz[0]##$three_opsz[1]##$three_opsz[2]##$xxx";
			}#else
		}#if GETA

		if ($pseudo eq 'PUTA'){#PUTA x->y[z]
		if ($zzz>$length_y){print "ERROR: $vars[2] [$zzz] out of range";}
		else	{
	$yyyi=$yyyi-$length_y+$zzz;		$xxx=$three_opsx[3];
	@three_opsy=split(/##/,$variable[$yyyi]);		
$variable[$yyyi]="$three_opsy[0]##$three_opsy[1]##$three_opsy[2]##$xxx";
			}#else
		}#if PUTA

	}#if
	
} #end of array routine




#now lets see about input/output operations
#YOU CAN NOT READ AN ARRAY VARIABLE!
if (($pseudo eq 'READ') || ($pseudo eq 'PRNT')){

&find;_var(@variable);

if ($xf eq '-1'){print "Error $pseudo: Variable $vars[1] Undeclared at Line $i\n";}
else {
	@three_opsz=split(/##/,$variable[$xxxi]);
if ($pseudo eq 'READ') {

#read input card. if there is nothing at the end of code read from keyboard
if ($read>$#data){	$zz=;	chomp($zz);	}
else	{$zz=$data[$read]; $read++;}

$variable[$xxxi]="$three_opsz[0]##$three_opsz[1]##$three_opsz[2]##$zz";
$c=("$machine $yyy $zzz $xxx\n");#print the machine code
						}
elsif ($pseudo eq 'PRNT') {
	print "$three_opsz[3]\n";

	$c=("$machine $xxx $yyy $zzz\n");#print the machine code
						}
}
	} #	END OF READ PRNT.
	


#now check the arithmetic operations
while (($pseudo, $machine) = each(%arithmetic))
{
	if ($FILE =~/$pseudo/) {

&find;_var(@variable);

if ($xf eq '-1'){print "Error $pseudo: $vars[1] Undeclared. Line $i\n";}
if ($yf eq '-1'){print "Error $pseudo: $vars[2] Undeclared. Line $i\n";}
if ($zf eq '-1'){print "Error $pseudo: $vars[3] Undeclared. Line $i\n";}
	
	if (($xf ne '-1') && ($zf ne '-1') && ($yf ne '-1')) 
	{
	$c=("$machine $xxx $yyy $zzz\n");#print the machine code
@three_opsz=split(/##/,$variable[$zzzi]);	$z=$three_opsz[3];
@three_opsy=split(/##/,$variable[$yyyi]);	$y=$three_opsy[3];
@three_opsx=split(/##/,$variable[$xxxi]);	$x=$three_opsx[3];
	
	if    ($pseudo eq 'ADD')	{$z=$x+$y;}
	elsif ($pseudo eq 'SUB') 	{$z=$x-$y;}
	elsif ($pseudo eq 'MULT')	{$z=$x*$y;}
	else {	if ($y ne 0){$z=$x/$y;}
		else {print "Error $pseudo: Division by Zero on line $i";}
	     }
$variable[$zzzi]="$three_opsz[0]##$three_opsz[1]##$three_opsz[2]##$z";
	}#if
	}#if
	}#while


#now lets deal with the logical involving labels and jumps operations
while (($pseudo, $machine) = each(%jumps))
{
	if ($vars[0] eq $pseudo) {

&find;_var(@variable);

if (substr($zzz,0,1) eq 0){	$zzz=substr($zzz,1);}
$index=0;
	foreach $label (@label)	{
	@two_ops=split(/##/,$label);
		if ($vars[3] =~/$two_ops[0]/)	{
		$zzz=$two_ops[1];
		$zzzi=$index;	
        					}
		$index++;
				}#foreach
if ($xf eq '-1'){print "Error $pseudo: Variable $vars[1] Undeclared at Line $i\n";}
if ($yf eq '-1'){print "Error $pseudo: Variable $vars[2] Undeclared at Line $i\n";}
if ($zzz eq '000'){print "Error $pseudo: Label $vars[3] Undeclared at Line $i\n";}
	
if (($xf ne '-1') && ($zzz ne '000') && ($yf ne '-1')) 
	{
	$c=("$machine $xxx $yyy $zzz\n");#print the machine code
if ($prev_labl ne $vars[3]){$jump=0}#make sure the byte code is written once
$jump++; #count how many jumps. need to wite correct byte code
if ($jump eq 1){getcode($c);}

@three_opsx=split(/##/,$variable[$xxxi]);	$x=$three_opsx[3];
@three_opsy=split(/##/,$variable[$yyyi]);	$y=$three_opsy[3];
@three_opsz=split(/##/,$label[$zzzi]);		$z=$three_opsz[1];

if ($pseudo eq 'EQ')	{if ($x eq $y){$iold=$i;$i=$z;}			}
if ($pseudo eq 'NEQ')	{if ($x ne $y){$iold=$i;$i=$z;}			}
if ($pseudo eq 'GTEQ')	{if ($x >= $y){$iold=$i;$i=$z;}			}
if ($pseudo eq 'LT')	{if ($x < $y){$iold=$i;$i=$z;}			}
if ($pseudo eq 'LOOP')	{
$x++;if ($x<=$y){$iold=$i;$i=$z;} @three_opsx=split(/##/,$variable[$xxxi]);
$variable[$xxxi]="$three_opsx[0]##$three_opsx[1]##$three_opsx[2]##$x";
			}#end of loop
	}#if
	$prev_labl=$vars[3];
	$check++;

	if ($check eq 200)	{
	$i=$num_of_lines+1;
	print "Run Time Error: Infinite loop. ABORTING..\n";
				}
	}#if
	}#while

}#else it is not var or labl
}#else start checking the code
}#if $var eq $pseudo
}#while

	
if ($comment eq 0) {
	if ($previous eq 'VAR')
	{
$index = $#variable;	$c= "+0 000 000 $FILE\n";	&getcode1;($c);
@three=split(/##/,$variable[$index]);	$first=$three[0];    $check=1;

	while (($check eq 1) && ($index>=0)){
	$variable[$index]="$variable[$index]##$FILE";			
	$index=$index-1;
	@three=split(/##/,$variable[$index]);
	if ($three[0] ne $first){$check=0}
	}
	$initialize=1;
	}#if $previous eq 'VAR'
	
else	{
	print "Can Not Interpret this :-> $FILE: Error on line $i\n";
	$i=$num_of_lines+1; print "ABORTING...\n";
	}#else
	}#if comment eq 0
	
	else	{#	this means that we are ok. new valid instruction
# 	NEED THIS TO MAKE SURE THAT BYTE CODE IS WRITTEN ONLY ONCE.
	if ($i eq $ii)			{	getcode($c);	}
	else			        {	$ii=$iold;	}
		}#else

####################
}#if it is not a comment
else {$skip++;}#	the line is a comment, skip it, interpret next line

}#while, the whole messy loop ends here

#now print the result to the file
foreach $data(@data){&getcode1;($data);}	#	PUT THE DATA BACK IN
open(output, ">$output_file");	print output @code; 	close(output);
print "The Intermediate machine code is in : $output_file\n";

}#	End of dealing with assembler code...
















else {
######################################
###	Byte Code Saga Starts Here  ##
######################################

#	Re initialize the variables

$index=0; $i=0; $comment=1;$it_is_over=0; $initialize=1; $num_of_lines=0; 
$skip=0; $sto=0; $iold=0; $ii=0; $jump=0; $check=0;	$read=0;
%reserved_words = ("MOVE", "+0",
         	   "ADD" , "+1", "SUB",  "-1",
         	   "MULT", "+2", "DIV",  "-2",
                   "SQR" , "+3", "SQRT", "-3",
                   "EQ"  , "+4", "NEQ",  "-4",
	           "GTEQ", "+5", "LT",   "-5",
	           "GETA", "+6", "PUTA", "-6",
	           "LOOP", "+7", "LABL", "-7",
	           "READ", "+8", "PRNT", "-8",
	           "STOP", "+9");

$dstop=0;	$lines=0; @data=();
#prepare the data array
foreach $FILE1(@FILE1)
{	#THIS WILL CREATE A DATA ARRAY AND A SEPARATE CODE ARRAY
	chomp($FILE1); #remove line ending
	if ($FILE1 eq '+9 999 999 999'){$dstop++; 
	if ($dstop eq 2){$num_of_lines=$lines+1}}
	else	{
	if ($dstop eq 2){push(@data,$FILE1); }#this is the data array
		}
	$lines++; #this counts how many lines of code the program has
}#foreach 

######################end of preparing the data and code arrays ###

#	Here starts the REAL fun...

while ($i<$num_of_lines)
{
	$FILE=$FILE1[$i];                                 
	$i++;		$ii++;		$comment=0;	@vars = (); 
	@vars=split(/ /,$FILE);	#split the input string into operators

#initialize the variable declared previously (IF IT IS NOT ALREADY)
if ($initialize eq 0)	{
$index = $#variable; 			$c= "$vars[3]\n";
@three=split(/##/,$variable[$index]);	$first=$three[2]; 

#this is needed to initialize the entries of an array.
#split the varuable entry then go back and initialize with the same value
#all the other entries of a given variable
   $check=1;$go=1;
#$index looks after the size of the array variable

	while (($check eq 1) && ($index>=0))	{
	$variable[$index]="$variable[$index]##$vars[3]";			
	$index=$index-1;	$go++;
	@three=split(/##/,$variable[$index]);
#this will successfully initialize all entries in a array variable
	if ($three[1] =~/$go/) {$check=1}else {$check=0;}
						}#end of while
	$initialize=1;	# Now everything has been initialized
		}#if the variable was un-initialized. now it is
	
if (($vars[0] eq '+0') && ($vars[1] eq '000') && ($vars[2] ne '000'))
	{	#	THIS MEANS THAT it is a variable
	$namev=$vars[3];	$sizev=$vars[2];
	while ($sizev>0){
	$variab="variable##$sizev##$namev";
	push(@variable,$variab);
	$sizev=$sizev-1;
	$namev=$namev+1;
	}#this will have put all entries of the variable into the table 
	$initialize=0; #it is not initialized
	$prev_variable=$vars[3]; #previous variable
	$c="VAR $vars[3] $vars[2]\n";	#Assembler pseudocode
	$comment=1;#this means that the line was interpreted
	}


else	{#	this means that it is not a variable declaration.

	while (($pseudo, $machine) = each(%reserved_words))
  {	
$bajge="$vars[0]$vars[1]$vars[2]";
$b="$vars[0]$vars[1]";
#make sure it is not a variable initialization or declaration
#NOT ABSOLUTELY NECESSARY BUT WORKS BETTER THIS WAY
if (($vars[0] eq $machine) && ($bajge ne '+0000000') && ($b ne '+0000'))
    {
	$previous=$machine;		$comment=1;

	if ($machine eq '-7')	# 	if it is a label
	{			#	build the label table
	if (substr($vars[1],0,1) eq 0){
	$place=substr($vars[1],1);}
	$lab="$vars[0]##$place";
	push(@label,$lab);
	$c="$pseudo $vars[1]\n";#	write the pseudocode
	}

	if ($machine eq "+9")	#	if it is a stop instruction
	{
	$c=("STOP\n");
	}

if (($pseudo eq 'MOVE') || ($pseudo eq 'SQR') || ($pseudo eq 'SQRT')){
$index=0;$xxx='-1';$yyy='000';$zzz='-1';

foreach $variable(@variable)	{
@ops=split(/##/,$variable);
if ($ops[2] eq $vars[1]){$xxx=$ops[3];$xxxi=$index;}
if ($ops[2] eq $vars[3]){$zzz=$ops[3];$zzzi=$index;}
$index++
				}#	prepare the variables for work
if ($xxx eq '-1') 
{print "Error! $machine: Variable $vars[1] Undeclared at Line $i\n";}
if ($zzz eq '-1') 
{print "Error! $machine: Variable $vars[3] Undeclared at Line $i\n";} 

if (($xxx ne '-1') && ($zzz ne '-1')) {

	@three_opsx=split(/##/,$variable[$xxxi]);	
	@three_opsz=split(/##/,$variable[$zzzi]);
	$c=("$pseudo $vars[1] $vars[3]\n");	#print the machine code
	if ($vars[0] eq '+0'){$three_opsz[3]=$three_opsx[3];}
	if ($vars[0] eq '+3'){$three_opsz[3]=$three_opsx[3]*$three_opsx[3];}
	if ($vars[0] eq '-3'){$three_opsz[3]=sqrt($three_opsx[3]);}
$variable[$zzzi]="$three_opsz[0]##$three_opsz[1]##$three_opsz[2]##$three_opsz[3]";
					}#if $xxx ne -1 and $zzz ne -1
} #end of MOVE SQR SQRT
	
###################################################################
#now lets perform the array operations. will include range checking
#GETA x[y]->z
#PUTA x->y[z]
#if the variable x say has been declared of length 2 and y is 3
#then this is a syntax error trying to access elements outside the range

if (($pseudo eq 'GETA') || ($pseudo eq 'PUTA')) {
	$index=0;$xxx='-1';$yyy='-1';$zzz='-1';
	foreach $variable(@variable)	{
	@ops=split(/##/,$variable);
if ($ops[2] eq $vars[1]){$xxx=$ops[3];$xxxi=$index;$lengthx=$ops[2]}
if ($ops[2] eq $vars[2]){$yyy=$ops[3];$yyyi=$index;$lengthy=$ops[2]}
if ($ops[2] eq $vars[3]){$zzz=$ops[3];$zzzi=$index;}
$index++
					}#	prepare the variables
if ($xxx eq '-1'){print "Error $machine: Variable $vars[1] Undeclared at Line $i\n";}
if ($yyy eq '-1'){print "Error $machine: Variable $vars[2] Undeclared at Line $i\n";}
if ($zzz eq '-1'){print "Error $machine: Variable $vars[3] Undeclared at Line $i\n";}
	
if (($xxx ne '-1') && ($zzz ne '-1') && ($yyy ne '-1')) {

	@three_opsx=split(/##/,$variable[$xxxi]);
	@three_opsz=split(/##/,$variable[$zzzi]);
	$c=("$pseudo $vars[1] $vars[2] $vars[3]\n");#print the machine code

	if ($machine eq 'GETA')	{	#GETA x[y]->z	
	if ($yyy>$lengthx){print "ERROR: $vars[1] [$yyy] out of range\n";}
	else 	{
	$xxxi=$xxxi-$lengthx+$yyy;
	@three_opsx=split(/##/,$variable[$xxxi]);
	$xxx=$three_opsx[3];
$variable[$zzzi]="$three_opsz[0]##$three_opsz[1]##$three_opsz[2]##$xxx";
		}#else
				}#if GETA

	if ($machine eq 'PUTA')	{	#PUTA x->y[z]
	if ($zzz>$lengthy){print "ERROR: $vars[2] [$zzz] out of range\n";}
		else	{
	$yyyi=$yyyi-$lengthy+$zzz;		$xxx=$three_opsx[3];
@three_opsy=split(/##/,$variable[$yyyi]);		
$variable[$yyyi]="$three_opsy[0]##$three_opsy[1]##$three_opsy[2]##$xxx";
			}#else
				}#if PUTA
	}#if
	
} #end of array routine


#now lets see about input/output operations
#YOU CAN NOT READ AN ARRAY AT A TIME!
if (($machine eq '+8') || ($machine eq '-8')){
$index=0;$xxx='-1';$yyy='-1';$zzz='-1';#INITIALIZE
	foreach $variable(@variable)	{
	@ops=split(/##/,$variable);
	if ($ops[2] eq $vars[1]){$xxx=$ops[3];$xxxi=$index;}
	if ($ops[2] eq $vars[2]){$yyy=$ops[3];$yyyi=$index;}
	if ($ops[2] eq $vars[3]){$zzz=$ops[3];$zzzi=$index;}
	$index++
					}#FOREACH
if ($machine eq '+8') {	#READ
	if ($zzz eq '-1')	{
	print "Error $machine: Variable $vars[3] Undeclared at Line $i\n";
				}
else {
	@three_opsz=split(/##/,$variable[$zzzi]);
#read input card. if there is nothing at the end of code read from keyboard

if ($read>$#data){	$zz=;	chomp($zz);	}

else	{$zz=$data[$read]; $read++;} #read data at the bottom of code.
       				     #if nothing sits there read STDIN
$variable[$zzzi]="$three_opsz[0]##$three_opsz[1]##$three_opsz[2]##$zz";

$c=("$pseudo $vars[3]\n");#print the machine code
					}
}

elsif ($machine eq '-8') {#PRINT

	if ($xxx eq '-1')	{
print "Error $machine: Variable $vars[1] Undeclared at Line $i\n";
				}
else 	{
	@three_opsz=split(/##/,$variable[$xxxi]);
	print "$three_opsz[3]\n";
	$c=("$pseudo $vars[1]\n");#print the machine code
	}
			}#IF MACHINE EQ -8
	} #end of READ/PRINT ROUTINE
	

#now check the arithmetic operations
while (($pseudo, $machine) = each(%arithmetic))
{
	if ($vars[0] eq $machine) {

	$index=0;$xxx='-1';$yyy='-1';$zzz='-1';
foreach $variable(@variable)	{
	@ops=split(/##/,$variable);
	if ($ops[2] eq $vars[1]){$xxx=$ops[3];$xxxi=$index;}
	if ($ops[2] eq $vars[2]){$yyy=$ops[3];$yyyi=$index;}
	if ($ops[2] eq $vars[3]){$zzz=$ops[3];$zzzi=$index;}
$index++
				}#	prepare the variables for work
if ($xxx eq '-1'){print "Error $machine: $vars[1] Undeclared. Line $i\n";}
if ($yyy eq '-1'){print "Error $machine: $vars[2] Undeclared. Line $i\n";}
if ($zzz eq '-1'){print "Error $machine: $vars[3] Undeclared. Line $i\n";}
	
	if (($xxx ne '-1') && ($zzz ne '-1') && ($yyy ne '-1')) 
	{
$c=("$pseudo $vars[1] $vars[2] $vars[3]\n");#print the machine code

	if    ($pseudo eq 'ADD')	{$zzz=$xxx+$yyy;}
	elsif ($pseudo eq 'SUB') 	{$zzz=$xxx-$yyy;}
	elsif ($pseudo eq 'MULT')	{$zzz=$xxx*$yyy;}
	else {	if ($yyy ne 0){$zzz=$xxx/$yyy;}
		else {print "Error $machine: Division by Zero on line $i";}
	     }
@three_opsz=split(/##/,$variable[$zzzi]);
$variable[$zzzi]="$three_opsz[0]##$three_opsz[1]##$three_opsz[2]##$zzz";
	}#if
	}#if
	}#while

#now lets deal with the logical involving labels and jumps operations
while (($pseudo, $machine) = each(%jumps))
{
	if ($vars[0] eq $machine) {
$index=0;$xxx='-1';$yyy='-1';$z=$vars[3];

foreach $variable(@variable)	{
	@ops=split(/##/,$variable);
	if ($ops[2] eq $vars[1]){$xxx=$ops[3];$xxxi=$index;}
	if ($ops[2] eq $vars[2]){$yyy=$ops[3];$yyyi=$index;}
	$index++;
				}#	prepare the variables for work
		
if ($xxx eq '-1'){print "Error $machine: Variable $vars[1] Undeclared at Line $i\n";}
if ($yyy eq '-1'){print "Error $machine: Variable $vars[2] Undeclared at Line $i\n";}
	
if (($xxx ne '-1') && ($zzz ne 0) && ($yyy ne '-1')) 

#********************************************************


	{
	$c=("$pseudo $vars[1] $vars[2] $vars[3]\n");#print the machine code

if ($prev_labl ne $vars[3]){$jump=0}#make sure the byte code is written once
$jump++; #count how many jumps. need to write correct code
if ($jump eq 1){getcode($c);}

@three_opsx=split(/##/,$variable[$xxxi]);	$x=$three_opsx[3];
@three_opsy=split(/##/,$variable[$yyyi]);	$y=$three_opsy[3];

if ($pseudo eq 'EQ')	{if ($x eq $y){$iold=$i;$i=$z;}			}
if ($pseudo eq 'NEQ')	{if ($x ne $y){$iold=$i;$i=$z;}			}
if ($pseudo eq 'GTEQ')	{if ($x >= $y){$iold=$i;$i=$z;}			}
if ($pseudo eq 'LT')	{if ($x < $y){$iold=$i;$i=$z;}			}
if ($pseudo eq 'LOOP')	{
$x++;if ($x<=$y){$iold=$i;$i=$z;} 
@three_opsx=split(/##/,$variable[$xxxi]);
$variable[$xxxi]="$three_opsx[0]##$three_opsx[1]##$three_opsx[2]##$x";
			}#end of loop
	}#if
	$prev_labl=$vars[3];
	$check++;
	if ($check eq 300){$i=$old; print "Run Time Error: Infinite loop";}
	}#if
	}#while




}	#	start checking the code
}	#	while
}	#	else	





#this is just beacause of the array operations

	if ($i eq $ii)			{	getcode($c);		}
	else			        {	$ii=$iold;		}







}#while, the whole messy loop ends here


#now print the result to the file

foreach $data(@data){&getcode1;($data);}
open(output, ">$output_file1");	print output @code; 	close(output);

#print "\n";	print "These are the variables you used\n";
#foreach $variable(@variable){print "$variable\n";}
#print "the data\n";
#foreach $data(@data){print "$data\n"}
#
#print "the labels\n";
#
#foreach $label(@label){print "$label\n"}
#
print "The Intermediate machine code is in : $output_file1\n";


	} #	end of working with byte code

}#if $t eq 1 or 0


sub three_digit
{
if (length($_[0]) eq 1)
{
$_[0]="00$_[0]";
}
elsif (length($_[0]) eq 2)
{
$_[0]="0$_[0]";
}
else
{
$_[0];
}
$_[0];
}


sub trim
{
if (substr($_[0],0,1) eq '+'){

$_[0]=substr($_[0],1);

}#if
else    {
$_[0];
	}
$_[0];
}


sub getcode
{
@s=split(/ /,$_[0]);
$op=$s[0];
foreach $s(@s){&three;_digit($s)}
$first = shift(@s); 
$li=join(' ',@s);
$line="$op $li";
$pos=0;
foreach $code (@code){$pos++}
$code[$pos]=$line;
}



sub getcode1
{
$pos=0;
foreach $code (@code){$pos++}
$code[$pos]=$_[0];

}

sub find_var
{
$xxx='000'; $yyy='000'; $zzz='000'; 
$xf='-1';   $yf='-1';   $zf='-1';	
#print "$vars[1]:$vars[2]:$vars[3]\n";
	$index=0;
	foreach $_ (@_){
		@three_ops=split(/##/,$_);
#print ":$three_ops[0]:\n";
if ($vars[1] eq $three_ops[0]){$xxa=$three_ops[3];$xf=1;$xxx=$three_ops[2];$xxxi=$index;$length_x=$three_ops[1];}
if ($vars[2] eq $three_ops[0]){$yya=$three_ops[3];$yf=1;$yyy=$three_ops[2];$yyyi=$index;$length_y=$three_ops[1];}
if ($vars[3] eq $three_ops[0]){$zza=$three_ops[3];$zf=1;$zzz=$three_ops[2];$zzzi=$index;}
#print "$xxx|$yyy\n";
			$index++;
			}#foreach
}



sub fix
{
$cc=0;$finished=0;
$l=length($_[0]);
while (($cc < $l) && ($finished eq 0)){
$cc1=$cc+1;
$v=substr($_[0],$cc,$cc1);

if ($v eq 0)
{
$_[0]=substr($_[0],$cc1);
}
else{$finished=1}
$cc++;
}

}#fix