#!/usr/bin/awk -f function printin(){ for(i = 1; i <= NR; ++i) print input[i] } function splitarg() { split($3, arg, ",") } function complain(s) { bad[Enolabel] = sprintf("%d missing label at line", pc) bad[Enoinst] = sprintf("%d unknown instruction: %s", pc, $2) bad[Enoprob] = sprintf("%d no such complaint", pc) bad[Eemptyinst] = sprintf("%d no instruction given", NR) # if this happens, things are really bad if(bad[s] == "") complain(Noprob) print bad[s] exit 1 } function puts(){ s = $3 for(i = 4; i <= NF; ++i) s = s " " $i print s } function newlabel(s) { labels[s] = NR } function havelabel(s) { return labels[s] } function decimal(n){ if(n ~ /^0x/){ n = substr(n, 3) } } # TODO # sets, use US="|" # stacks BEGIN{ FS = "[\t ]*" label = 1 inst = 2 args = 3 labels["BEGIN"] = "BEGIN" labels["END"] = "END" # error codes for complain() Enoprob = 0 Enolabel = 1 Enoinst = 2 Eemptyinst = 3 # errstr Eshredder = "this isn't a paper shredder! (ERROR: empty file given)" # for functions that require arguments nargs["as"] = 2 nargs["cmp"] = 2 nargs["vcmp"] = 2 nargs["carry"] = 1 nargs["mod"] = 1 nargs["mov"] = 2 # accumulator acm = 0 type["jmp"] = type["jnz"] = type["jz"] = "branch" # stage 1; read input, get labels, remove comments while(getline){ if($0 == "-" || $0 == "eof"){ --NR break } gsub(";.*", "") # skip empty lines if($0 == ""){ NR-- continue } input[NR] = $0 if($1 != "" && labels[$1] == "") labels[$1] = NR-1 } if(!NR) print Eshredder # stage 2; exection. the jury was rigged. debugging = 0 if(debugging) printf "read %d lines\n", NR for(pc = 1; pc <= NR; ++pc){ $0 = input[pc] # might be a problem depending on awk implementations. if(debugging) printf "%s\t---\tpc=%d, i=%d, z=%d\n", input[pc], pc, var["i"], zero if(nargs[$2]) splitarg() # instructions if ($2 == "") { complain(Enoinst) } # VERY BAD else if($2 == "as") { var[arg[1]] = arg[2] } else if($2 == "cmp") { zero = var[arg[1]] == arg[2] } else if($2 == "vcmp") { zero = var[arg[1]] == var[arg[2]] } else if($2 == "put") { printf "var[%s] = %d\n", $3, var[$3] } # else if($2 == "puts") { print $3 } else if($2 == "puts") { puts() } else if($2 == "puta") { print "A " acm } else if($2 == "inc") { var[$3]++ } else if($2 == "jmp") { pc = labels[$3] } else if($2 == "jz") { if(zero) pc = labels[$3] } else if($2 == "jnz") { if(!zero) pc = labels[$3] } else if($2 == "push") { stack[++nstk] = $3 } else if($2 == "call") { callstack[++ncall] = pc+1; pc = labels[$3] } else if($2 == "cnz") { if(!zero) callstack[++ncall] = pc+1; pc = labels[$3] } else if($2 == "ret") { pc = callstack[ncall--]-1 } else if($2 == "add") { acm += $3 } else if($2 == "sub") { acm -= $3 } else if($2 == "mul") { acm *= $3 } else if($2 == "div") { acm /= $3 } else if($2 == "exp") { acm ^= $3 } else if($2 == "abs") { acm = acm < 0 ? -acm : acm } else if($2 == "carry") { if(arg[1] > 0) print (carry = acm >= 2^arg[1]-1) } else if($2 == "zero") { print zero ? zero : "0" } else if($2 == "halt") { exit i } else if($2 == "read") { printf "input: "; getline; acm = $0; print acm } else if($2 == "mod") { carry = !(acm % arg[1]) } else if($2 == "cbit") { print carry } else if($2 == "mova") { acm = var[$3] } else if($2 == "mov") { var[arg[1]] = var[arg[2]] } } if(debugging) printf "%s ; pc=%d, i=%d, z=%d\n", input[i], i, var["i"], zero # for(i in labels) # need to lex this # printf "labels[%s] = %s\n", i, labels[i] # for(i in var) # need to lex this # printf "var[%s] = %s\n", i, var[i] # printin() }