package de.danielkullmann.hackvm;
import java.util.Observable;
import java.util.Observer;
import de.danielkullmann.hackvm.HackVM.Trace;
public class Hack implements Observer {
/**
* @param args
*/
public static void main(String[] args) {
new Hack(args);
}
private int limit = -1;
public Hack(String[] args ) {
int index = 0;
String program = null;
String stack = null;
String memory = null;
boolean trace = false;
for ( ; index < args.length ; index++ ) {
if ( args[index].equals( "-s" ) ) {
index++;
stack = args[index];
}
else if ( args[index].equals( "-m" ) ) {
index++;
memory = args[index];
}
else if ( args[index].equals( "-l" ) ) {
index++;
limit = Integer.parseInt( args[index] );
}
else if ( args[index].equals( "-t" ) ) {
trace = true;
}
else if ( args[index].equals( "-h" ) ) {
help();
System.exit(1);
}
else {
if ( program == null ) program = args[index];
else program = program + " " + args[index];
}
}
if ( program.equals("") ) {
System.err.println( "Usage: java Hack [-s stack] [-m memory] <program text>" );
System.exit(1);
}
HackVM vm = new HackVM();
if ( trace ) {
vm.addObserver( this );
}
VMState result = vm.execute(program, stack, memory);
if ( result.getError() != null && ! result.getError().equals("") ) {
System.out.println( "Error: " + result.getError() );
}
System.out.println( "Output: " + result.getOutput() );
}
private static void help() {
String help =
" Instruction Description:\n" +
" ' ' Do Nothing\n" +
" 'p' Print S0 interpreted as an integer\n" +
" 'P' Print S0 interpreted as an ASCII character (only the least significant 7 bits of the value are used)\n" +
" '0' Push the value 0 on the stack\n" +
" '1' Push the value 1 on the stack\n" +
" '2' Push the value 2 on the stack\n" +
" '3' Push the value 3 on the stack\n" +
" '4' Push the value 4 on the stack\n" +
" '5' Push the value 5 on the stack\n" +
" '6' Push the value 6 on the stack\n" +
" '7' Push the value 7 on the stack\n" +
" '8' Push the value 8 on the stack\n" +
" '9' Push the value 9 on the stack\n" +
" '+' Push S1+S0\n" +
" '-' Push S1-S0\n" +
" '*' Push S1*S0\n" +
" '/' Push S1/S0\n" +
" ':' Push -1 if S1<S0, 0 if S1=S0, or 1 S1>S0\n" +
" 'g' Add S0 to the program counter\n" +
" '?' Add S0 to the program counter if S1 is 0\n" +
" 'c' Push the program counter on the call stack and set the program counter to S0\n" +
" '$' Set the program counter to the value pop'ed from the call stack\n" +
" '<' Push the value of memory cell S0\n" +
" '>' Store S1 into memory cell S0\n" +
" '^' Push a copy of S<S0+1> (ex: 0^ duplicates S0)\n" +
" 'v' Remove S<S0+1> from the stack and push it on top (ex: 1v swaps S0 and S1)\n" +
" 'd' Drop S0\n" +
" '!' Terminate the program\n";
System.out.println( help );
}
@Override
public void update(Observable obs, Object st) {
VMState state = (VMState) st;
Trace trace = state.getExecutionTrace().get( state.getExecutionTrace().size()-1 );
System.out.println( trace );
if ( limit > 0 && state.getTicks() > limit ) {
System.exit(1);
}
}
}