Example #1
0
 public static void Main(string[] args)
 {
     //                                        check that arguments have been supplied
     if (args.Length != 2) {
       Console.WriteLine("missing args");
       System.Environment.Exit(1);
     }
       //                                        attempt to open data file
     InFile data = new InFile(args[0]);
     if (data.OpenError()) {
       Console.WriteLine("cannot open " + args[0]);
       System.Environment.Exit(1);
     }
       //                                        attempt to open results file
     OutFile results = new OutFile(args[1]);
     if (results.OpenError()) {
       Console.WriteLine("cannot open " + args[1]);
       System.Environment.Exit(1);
     }
       //                                        various initializations
     int total = 0;
     IntSet mySet = new IntSet();
     IntSet smallSet = new IntSet(1, 2, 3, 4, 5);
     string smallSetStr = smallSet.ToString();
       //                                        read and process data file
     int item = data.ReadInt();
     while (!data.NoMoreData()) {
       total = total + item;
       if (item > 0) mySet.Incl(item);
       item = data.ReadInt();
     }
       //                                        write various results to output file
     results.Write("total = ");
     results.WriteLine(total, 5);
     results.WriteLine("unique positive numbers " + mySet.ToString());
     results.WriteLine("union with " + smallSetStr
                    + " = " + mySet.Union(smallSet).ToString());
     results.WriteLine("intersection with " + smallSetStr
                    + " = " + mySet.Intersection(smallSet).ToString());
     results.Close();
 }
Example #2
0
 static void Trace(OutFile results, int pcNow)
 {
     // Simple trace facility for run time debugging
       results.Write(" PC:"); results.Write(pcNow, 5);
       results.Write(" FP:"); results.Write(cpu.fp, 5);
       results.Write(" SP:"); results.Write(cpu.sp, 5);
       results.Write(" HP:"); results.Write(cpu.hp, 5);
       results.Write(" TOS:");
       if (cpu.sp < memSize)
     results.Write(mem[cpu.sp], 5);
       else
     results.Write(" ????");
       results.Write("  " + mnemonics[cpu.ir], -8);
       switch (cpu.ir) {
     case PVM.brn:
     case PVM.bze:
     case PVM.dsp:
     case PVM.lda:
     case PVM.ldc:
     case PVM.prns:
       results.Write(mem[cpu.pc], 7); break;
     default: break;
       }
       results.WriteLine();
 }
Example #3
0
 static void StackDump(OutFile results, int pcNow)
 {
     // Dump local variable and stack area - useful for debugging
       int onLine = 0;
       results.Write("\nStack dump at " + pcNow);
       results.Write(" SP:"); results.Write(cpu.sp, 4);
       results.Write(" FP:"); results.Write(cpu.fp, 4);
       results.Write(" HP:"); results.Write(cpu.hp, 4);
       results.Write(" HB:"); results.WriteLine(heapBase, 4);
       for (int i = stackBase - 1; i >= cpu.sp; i--) {
     results.Write(i, 7); results.Write(mem[i], 5);
     onLine++; if (onLine % 8 == 0) results.WriteLine();
       }
       results.WriteLine();
 }
Example #4
0
 static void PostMortem(OutFile results, int pcNow)
 {
     // Reports run time error and position
       results.WriteLine();
       switch (ps) {
     case badMem:  results.Write("Memory violation"); break;
     case badData: results.Write("Invalid data"); break;
     case noData:  results.Write("No more data"); break;
     case divZero: results.Write("Division by zero"); break;
     case badOp:   results.Write("Illegal opcode"); break;
     case badInd:  results.Write("Subscript out of range"); break;
     case badVal:  results.Write("Value out of range"); break;
     case badAdr:  results.Write("Bad address"); break;
     case badAll:  results.Write("Heap allocation error"); break;
     case nullRef: results.Write("Null reference"); break;
     default:      results.Write("Interpreter error!"); break;
       }
       results.WriteLine(" at " + pcNow);
 }
Example #5
0
 static void HeapDump(OutFile results, int pcNow)
 {
     // Dump heap area - useful for debugging
       int onLine = 0;
       results.Write("\nHeap dump at " + pcNow);
       results.Write(" SP:"); results.Write(cpu.sp, 4);
       results.Write(" FP:"); results.Write(cpu.fp, 4);
       results.Write(" HP:"); results.Write(cpu.hp, 4);
       results.Write(" HB:"); results.WriteLine(heapBase, 4);
       for (int i = heapBase; i < cpu.hp; i++) {
     results.Write(i, 7); results.Write(mem[i], 5);
     onLine++; if (onLine % 8 == 0) results.WriteLine();
       }
       results.WriteLine();
 }
Example #6
0
 public static void QuickInterpret(int codeLen, int initSP)
 {
     // Interprets the codeLen instructions stored in mem, with stack pointer
     // initialized to initSP.  Use StdIn and StdOut without asking
       Console.WriteLine("\nHit <Enter> to start");
       Console.ReadLine();
       bool tracing = false;
       InFile data = new InFile("");
       OutFile results = new OutFile("");
       Emulator(0, codeLen, initSP, data, results, tracing);
 }
Example #7
0
        public static void ListCode(string fileName, int codeLen)
        {
            // Lists the codeLen instructions stored in mem on a named output file
              int i, j, n;

              if (fileName == null) return;
              OutFile codeFile = new OutFile(fileName);

              /* ------------- The following may be useful for debugging the interpreter
              i = 0;
              while (i < codeLen) {
            codeFile.Write(mem[i], 5);
            if ((i + 1) % 15 == 0) codeFile.WriteLine();
            i++;
              }
              codeFile.WriteLine();

              ------------- */

              i = 0;
              codeFile.WriteLine("ASSEM\nBEGIN");
              while (i < codeLen) {
            int o = mem[i] % (PVM.nul + 1); // force in range
            codeFile.Write("  {");
            codeFile.Write(i, 5);
            codeFile.Write(" } ");
            codeFile.Write(mnemonics[o], -8);
            switch (o) {
              case PVM.brn:
              case PVM.bze:
              case PVM.dsp:
              case PVM.lda:
              case PVM.ldc:
            i = (i + 1) % memSize; codeFile.Write(mem[i]);
            break;

              case PVM.prns:
            i = (i + 1) % memSize;
            j = mem[i]; codeFile.Write(" \"");
            while (mem[j] != 0) {
              switch (mem[j]) {
                case '\\' : codeFile.Write("\\\\"); break;
                case '\"' : codeFile.Write("\\\""); break;
                case '\'' : codeFile.Write("\\\'"); break;
                case '\b' : codeFile.Write("\\b"); break;
                case '\t' : codeFile.Write("\\t"); break;
                case '\n' : codeFile.Write("\\n"); break;
                case '\f' : codeFile.Write("\\f"); break;
                case '\r' : codeFile.Write("\\r"); break;
                default   : codeFile.Write((char) mem[j]); break;
              }
              j--;
            }
            codeFile.Write("\"");
            break;
            }
            i = (i + 1) % memSize;
            codeFile.WriteLine();
              }
              codeFile.WriteLine("END.");
              codeFile.Close();
        }
Example #8
0
 public static void Interpret(int codeLen, int initSP)
 {
     // Interactively opens data and results files.  Then interprets the codeLen
     // instructions stored in mem, with stack pointer initialized to initSP
       Console.Write("\nTrace execution (y/N/q)? ");
       char reply = (Console.ReadLine() + " ").ToUpper()[0];
       if (reply != 'Q') {
     bool tracing = reply == 'Y';
     Console.Write("\nData file [STDIN] ? ");
     InFile data = new InFile(Console.ReadLine());
     Console.Write("\nResults file [STDOUT] ? ");
     OutFile results = new OutFile(Console.ReadLine());
     Emulator(0, codeLen, initSP, data, results, tracing);
     results.Close();
     data.Close();
       }
 }
Example #9
0
        public static void Emulator(int initPC, int codeLen, int initSP,
                                InFile data, OutFile results, bool tracing)
        {
            // Emulates action of the codeLen instructions stored in mem[0 .. codeLen-1], with
            // program counter initialized to initPC, stack pointer initialized to initSP.
            // data and results are used for I/O.  Tracing at the code level may be requested

              int pcNow;                  // current program counter
              int loop;                   // internal loops
              int tos, sos;               // value popped from stack
              int adr;                    // effective address for memory accesses
              stackBase = initSP;
              heapBase = codeLen;         // initialize boundaries
              cpu.hp = heapBase;          // initialize registers
              cpu.sp = stackBase;
              cpu.gp = stackBase;
              cpu.mp = stackBase;
              cpu.fp = stackBase;
              cpu.pc = initPC;            // initialize program counter
              ps = running;               // prepare to execute
              int ops = 0;
              timer.Start();
              do {
            ops++;
            pcNow = cpu.pc;           // retain for tracing/postmortem
            if (cpu.pc < 0 || cpu.pc >= codeLen) {
              ps = badAdr;
              break;
            }
            cpu.ir = Next();          // fetch
            if (tracing) Trace(results, pcNow);
            switch (cpu.ir) {         // execute
              case PVM.nop:           // no operation
            break;
              case PVM.dsp:           // decrement stack pointer (allocate space for variables)
            int localSpace = Next();
            cpu.sp -= localSpace;
            if (InBounds(cpu.sp)) // initialize
              for (loop = 0; loop < localSpace; loop++)
                mem[cpu.sp + loop] = 0;
            break;
              case PVM.ldc:           // push constant value
            Push(Next());
            break;
              case PVM.lda:           // push local address
            adr = cpu.fp - 1 - Next();
            if (InBounds(adr)) Push(adr);
            break;
              case PVM.ldv:           // dereference
            Push(mem[Pop()]);
            break;
              case PVM.sto:           // store
            tos = Pop(); adr = Pop();
            if (InBounds(adr)) mem[adr] = tos;
            break;
              case PVM.ldxa:          // heap array indexing
            adr = Pop();
            int heapPtr = Pop();
            if (heapPtr == 0) ps = nullRef;
            else if (heapPtr < heapBase || heapPtr >= cpu.hp) ps = badMem;
            else if (adr < 0 || adr >= mem[heapPtr]) ps = badInd;
            else Push(heapPtr + adr + 1);
            break;
              case PVM.inpi:          // integer input
            adr = Pop();
            if (InBounds(adr)) {
              mem[adr] = data.ReadInt();
              if (data.Error()) ps = badData;
            }
            break;
              case PVM.prni:          // integer output
            if (tracing) results.Write(padding);
            results.Write(Pop(), 0);
            if (tracing) results.WriteLine();
            break;
              case PVM.inpb:          // boolean input
            adr = Pop();
            if (InBounds(adr)) {
              mem[adr] = data.ReadBool() ? 1 : 0;
              if (data.Error()) ps = badData;
            }
            break;
              case PVM.prnb:          // boolean output
            if (tracing) results.Write(padding);
            if (Pop() != 0) results.Write(" true  "); else results.Write(" false ");
            if (tracing) results.WriteLine();
            break;
              case PVM.prns:          // string output
            if (tracing) results.Write(padding);
            loop = Next();
            while (ps == running && mem[loop] != 0) {
              results.Write((char) mem[loop]); loop--;
              if (loop < stackBase) ps = badMem;
            }
            if (tracing) results.WriteLine();
            break;
              case PVM.prnl:          // newline
            results.WriteLine();
            break;
              case PVM.neg:           // integer negation
            Push(-Pop());
            break;
              case PVM.add:           // integer addition
            tos = Pop(); Push(Pop() + tos);
            break;
              case PVM.sub:           // integer subtraction
            tos = Pop(); Push(Pop() - tos);
            break;
              case PVM.mul:           // integer multiplication
            tos = Pop(); Push(Pop() * tos);
            break;
              case PVM.div:           // integer division (quotient)
            tos = Pop(); Push(Pop() / tos);
            break;
              case PVM.rem:           // integer division (remainder)
            tos = Pop(); Push(Pop() % tos);
            break;
              case PVM.not:           // logical negation
            Push(Pop() == 0 ? 1 : 0);
            break;
              case PVM.and:           // logical and
            tos = Pop(); Push(Pop() & tos);
            break;
              case PVM.or:            // logical or
            tos = Pop(); Push(Pop() | tos);
            break;
              case PVM.ceq:           // logical equality
            tos = Pop(); Push(Pop() == tos ? 1 : 0);
            break;
              case PVM.cne:           // logical inequality
            tos = Pop(); Push(Pop() != tos ? 1 : 0);
            break;
              case PVM.clt:           // logical less
            tos = Pop(); Push(Pop() <  tos ? 1 : 0);
            break;
              case PVM.cle:           // logical less or equal
            tos = Pop(); Push(Pop() <= tos ? 1 : 0);
            break;
              case PVM.cgt:           // logical greater
            tos = Pop(); Push(Pop() >  tos ? 1 : 0);
            break;
              case PVM.cge:           // logical greater or equal
            tos = Pop(); Push(Pop() >= tos ? 1 : 0);
            break;
              case PVM.brn:           // unconditional branch
            cpu.pc = Next();
            if (cpu.pc < 0 || cpu.pc >= codeLen) ps = badAdr;
            break;
              case PVM.bze:           // pop top of stack, branch if false
            int target = Next();
            if (Pop() == 0) {
              cpu.pc = target;
              if (cpu.pc < 0 || cpu.pc >= codeLen) ps = badAdr;
            }
            break;
              case PVM.anew:          // heap array allocation
            int size = Pop();
            if (size <= 0 || size + 1 > cpu.sp - cpu.hp - 2)
              ps = badAll;
            else {
              mem[cpu.hp] = size;
              Push(cpu.hp);
              cpu.hp += size + 1;
            }
            break;
              case PVM.halt:          // halt
            ps = finished;
            break;
              case PVM.stk:           // stack dump (debugging)
            StackDump(results, pcNow);
            break;
              case PVM.heap:           // heap dump (debugging)
            HeapDump(results, pcNow);
            break;
              case PVM.ldc_0:         // push constant 0
              case PVM.ldc_1:         // push constant 1
              case PVM.ldc_2:         // push constant 2
              case PVM.ldc_3:         // push constant 3
              case PVM.lda_0:         // push local address 0
              case PVM.lda_1:         // push local address 1
              case PVM.lda_2:         // push local address 2
              case PVM.lda_3:         // push local address 3
              case PVM.ldl:           // push local value
              case PVM.ldl_0:         // push value of local variable 0
              case PVM.ldl_1:         // push value of local variable 1
              case PVM.ldl_2:         // push value of local variable 2
              case PVM.ldl_3:         // push value of local variable 3
              case PVM.stl:           // store local value
              case PVM.stlc:          // store local value
              case PVM.stl_0:         // pop to local variable 0
              case PVM.stl_1:         // pop to local variable 1
              case PVM.stl_2:         // pop to local variable 2
              case PVM.stl_3:         // pop to local variable 3
              case PVM.stoc:          // character checked store
              case PVM.inpc:          // character input
              case PVM.prnc:          // character output
              case PVM.low:           // toLowerCase
              case PVM.islet:         // isLetter
              case PVM.inc:           // ++
              case PVM.dec:           // --
              default:              // unrecognized opcode
            ps = badOp;
            break;
            }
              } while (ps == running);
              TimeSpan ts = timer.Elapsed;

              // Format and display the TimeSpan value.
              string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
              ts.Hours, ts.Minutes, ts.Seconds,
              ts.Milliseconds / 10);
              Console.WriteLine("\n\n" + ops + " operations.  Run Time " + elapsedTime + "\n\n");
              if (ps != finished) PostMortem(results, pcNow);
              timer.Reset();
              timer.Stop();
        }
Example #10
0
        // The interpreters and utility methods
        public static void Emulator(int initPC, int codeLen, int initSP,
                                InFile data, OutFile results, bool tracing)
        {
            // Emulates action of the codeLen instructions stored in mem[0 .. codeLen-1], with
            // program counter initialized to initPC, stack pointer initialized to initSP.
            // data and results are used for I/O.  Tracing at the code level may be requested

              int pcNow;                  // current program counter
              int loop;                   // internal loops
              int tos, sos;               // value popped from stack
              stackBase = initSP;
              heapBase = codeLen;         // initialize boundaries
              cpu.hp = heapBase;          // initialize registers
              cpu.sp = stackBase;
              cpu.gp = stackBase;
              cpu.mp = stackBase;
              cpu.fp = stackBase;
              cpu.pc = initPC;            // initialize program counter
              ps = running;               // prepare to execute
              int ops = 0;
              timer.Start();
              do {
            ops++;
            pcNow = cpu.pc;           // retain for tracing/postmortem
            cpu.ir = mem[cpu.pc++];          // fetch
            //        if (tracing) Trace(results, pcNow);
            switch (cpu.ir) {         // execute
              case PVM.nop:           // no operation
            break;
              case PVM.dsp:           // decrement stack pointer (allocate space for variables)
            cpu.sp -= mem[cpu.pc++];
            break;
              case PVM.ldc:           // push constant value
            mem[--cpu.sp] = mem[cpu.pc++];
            break;
              case PVM.lda:           // push local address
            mem[--cpu.sp] = cpu.fp - 1 - mem[cpu.pc++];
            break;
              case PVM.ldv:           // dereference
            mem[cpu.sp] = mem[mem[cpu.sp]];
            break;
              case PVM.sto:           // store
            tos = mem[cpu.sp++]; mem[mem[cpu.sp++]] = tos;
            break;
              case PVM.ldxa:          // heap array indexing
            tos = mem[cpu.sp++]; mem[cpu.sp] = mem[cpu.sp] + tos;
            break;
              case PVM.inpi:          // integer input
            mem[mem[cpu.sp++]] = data.ReadInt();
            break;
              case PVM.prni:          // integer output
            //            if (tracing) results.Write(padding);
            results.Write(mem[cpu.sp++], 0);
            //            if (tracing) results.WriteLine();
            break;
              case PVM.inpb:          // boolean input
            mem[mem[cpu.sp++]] = data.ReadBool() ? 1 : 0;
            break;
              case PVM.prnb:          // boolean output
            //            if (tracing) results.Write(padding);
            if (mem[cpu.sp++] != 0) results.Write(" true  "); else results.Write(" false ");
            //            if (tracing) results.WriteLine();
            break;
              case PVM.prns:          // string output
            //            if (tracing) results.Write(padding);
            loop = mem[cpu.pc++];
            while (mem[loop] != 0) {
              results.Write((char) mem[loop]); loop--;
            }
            //            if (tracing) results.WriteLine();
            break;
              case PVM.prnl:          // newline
            results.WriteLine();
            break;
              case PVM.neg:           // integer negation
            mem[cpu.sp] = -mem[cpu.sp];
            break;
              case PVM.add:           // integer addition
            tos = mem[cpu.sp++]; mem[cpu.sp] += tos;
            break;
              case PVM.sub:           // integer subtraction
            tos = mem[cpu.sp++]; mem[cpu.sp] -= tos;
            break;
              case PVM.mul:           // integer multiplication
            tos = mem[cpu.sp++]; mem[cpu.sp] *= tos;
            break;
              case PVM.div:           // integer division (quotient)
            tos = mem[cpu.sp++]; mem[cpu.sp] /= tos;
            break;
              case PVM.rem:           // integer division (remainder)
            tos = mem[cpu.sp++]; mem[cpu.sp] %= tos;
            break;
              case PVM.not:           // logical negation
            mem[cpu.sp] = mem[cpu.sp] == 0 ? 1 : 0;
            break;
              case PVM.and:           // logical and
            tos = mem[cpu.sp++]; mem[cpu.sp] &= tos;
            break;
              case PVM.or:            // logical or
            tos = mem[cpu.sp++]; mem[cpu.sp] |= tos;
            break;
              case PVM.ceq:           // logical equality
            tos = mem[cpu.sp++]; mem[cpu.sp] = mem[cpu.sp] == tos ? 1 : 0;
            break;
              case PVM.cne:           // logical inequality
            tos = mem[cpu.sp++]; mem[cpu.sp] = mem[cpu.sp] != tos ? 1 : 0;
            break;
              case PVM.clt:           // logical less
            tos = mem[cpu.sp++]; mem[cpu.sp] = mem[cpu.sp] <  tos ? 1 : 0;
            break;
              case PVM.cle:           // logical less or equal
            tos = mem[cpu.sp++]; mem[cpu.sp] = mem[cpu.sp] <= tos ? 1 : 0;
            break;
              case PVM.cgt:           // logical greater
            tos = mem[cpu.sp++]; mem[cpu.sp] = mem[cpu.sp] >  tos ? 1 : 0;
            break;
              case PVM.cge:           // logical greater or equal
            tos = mem[cpu.sp++]; mem[cpu.sp] = mem[cpu.sp] >= tos ? 1 : 0;
            break;
              case PVM.brn:           // unconditional branch
            cpu.pc = mem[cpu.pc++];
            break;
              case PVM.bze:           // pop top of stack, branch if false
            int target = mem[cpu.pc++];
            if (mem[cpu.sp++] == 0) cpu.pc = target;
            break;
              case PVM.anew:          // heap array allocation
            int size = mem[cpu.sp];
            mem[cpu.sp] = cpu.hp;
            cpu.hp += size;
            break;
              case PVM.halt:          // halt
            ps = finished;
            break;
              case PVM.stk:           // stack dump (debugging)
            StackDump(results, pcNow);
            break;
              case PVM.heap:           // heap dump (debugging)
            HeapDump(results, pcNow);
            break;
              case PVM.ldc_0:         // push constant 0
              case PVM.ldc_1:         // push constant 1
              case PVM.ldc_2:         // push constant 2
              case PVM.ldc_3:         // push constant 3
              case PVM.lda_0:         // push local address 0
              case PVM.lda_1:         // push local address 1
              case PVM.lda_2:         // push local address 2
              case PVM.lda_3:         // push local address 3
              case PVM.ldl:           // push local value
              case PVM.ldl_0:         // push value of local variable 0
              case PVM.ldl_1:         // push value of local variable 1
              case PVM.ldl_2:         // push value of local variable 2
              case PVM.ldl_3:         // push value of local variable 3
              case PVM.stl:           // store local value
              case PVM.stlc:          // store local value
              case PVM.stl_0:         // pop to local variable 0
              case PVM.stl_1:         // pop to local variable 1
              case PVM.stl_2:         // pop to local variable 2
              case PVM.stl_3:         // pop to local variable 3
              case PVM.stoc:          // character checked store
              case PVM.inpc:          // character input
              case PVM.prnc:          // character output
              case PVM.low:           // toLowerCase
              case PVM.islet:         // isLetter
              case PVM.inc:           // ++
              case PVM.dec:           // --
              default:                // unrecognized opcode
            ps = badOp;
            break;
            }
              } while (ps == running);
              TimeSpan ts = timer.Elapsed;

              // Format and display the TimeSpan value.
              string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
              ts.Hours, ts.Minutes, ts.Seconds,
              ts.Milliseconds / 10);
              Console.WriteLine("\n\n" + ops + " operations.  Run Time " + elapsedTime + "\n\n");
              if (ps != finished) PostMortem(results, pcNow);
              timer.Reset();
              timer.Stop();
        }