#! /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();
}
}
Powered by
GeSHi Syntax Highlighting software.
Author of all (other) material unless otherwise specified:
Loren Segal. Copyright 2005.