Viewing file: soen229/tsim.pl | Back to directory listing
Author: Loren Segal | Last modified: February 20 2006 07:00 pm | Download

#! /usr/bin/perl 
 
# this program simulates a hypothetical stack based machine
 
@instructions = <STDIN>; #load instructions into computer
chomp(@instructions);
 
$pc =0; #pc is machine's program counter
@stack; #stack is current function stack
# in our case our whole program is one big function so only 1 stack for 
#whole program
%memory; # hypothetical computer memory
 
# note down labels position
for($i=0;$i<($#instructions+1);$i++) { 
	@inst = split(/ +/,$instructions[$i]);
	if( $inst[0] eq "label"){ 
		$labels{$inst[1]} = $i;
	}
}
 
# execute machine instructions one by one
while(1) {
	execute ($instructions[$pc]);
	$pc++;
	if( $pc > $#instructions) {
		print "illegal memory access\n";
		exit();
	}
}
 
sub execute () {
	my($line) = @_;
	my(@inst);
	@inst = split(" ",$line);
 
	if($inst[0] eq "push") {
		push(@stack,$inst[1]);
 
	} elsif($inst[0] eq "rvalue") {
		push(@stack,$memory{$inst[1]});
 
	}elsif($inst[0] eq "lvalue") {
		$memory{$inst[1]} = 0;
		push(@stack,$inst[1]);
 
	}elsif($inst[0] eq "pop") {
		pop(@stack);
 
	}elsif($inst[0] eq "assign") {
		my($val1,$val2);
		$val1 = pop(@stack);
		$val2 = pop(@stack);
		$memory{$val1} = $val2;
		push(@stack,$val2);	
 
	} elsif($inst[0] eq "label") {
		#ignore as we have already noted label positions
 
	} elsif ($inst[0] eq "goto") {
		$pc = $labels{$inst[1]};
#		print "modifying pc: new value: $pc\n";
 
	} elsif($inst[0] eq "gotrue") {
		$top = pop(@stack);
		if($top != 0) {
			$pc = $labels{$inst[1]};
		}	
 
	} elsif($inst[0] eq "gofalse") {
		$top = pop(@stack);
		if($top == 0) {
			$pc = $labels{$inst[1]};
#			print "modifying pc: new value: $pc\n";
		}	
 
	} elsif($inst[0] eq "add") {
		my($val1,$val2);
		$val2 = pop(@stack);
		$val1 = pop(@stack);
		push(@stack,$val1+$val2);
 
	} elsif($inst[0] eq "sub") {
		my($val1,$val2);
		$val2 = pop(@stack);
		$val1 = pop(@stack);
		push(@stack,$val1-$val2);
	
	} elsif($inst[0] eq "mul") {
		my($val1,$val2);
		$val2 = pop(@stack);
		$val1 = pop(@stack);
		push(@stack,$val1*$val2);
 
	} elsif($inst[0] eq "div") {
		my($val1,$val2);
		$val2 = pop(@stack);
		$val1 = pop(@stack);
		push(@stack,$val1/$val2);
	
	} elsif($inst[0] eq "print") {
		print $stack[$#stack];
		print "\n";
	}elsif($inst[0] eq "copy") {
		push(@stack,$stack[$#stack]);
	}
	 elsif($inst[0] eq "halt") {
		print "halting machine\n";
		exit();
	}
}