Skip to content

Commit 0a40474

Browse files
committed
Debugging.
1 parent 1bc545b commit 0a40474

File tree

6 files changed

+163
-63
lines changed

6 files changed

+163
-63
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
target
2+
/nbproject/

pom.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,18 @@
1111
<exec.mainClass>io.github.coderodde.simple.stack.machine.SimpleStackMachine</exec.mainClass>
1212
</properties>
1313
<name>SimpleStackMachine.java</name>
14+
<dependencies>
15+
<dependency>
16+
<groupId>junit</groupId>
17+
<artifactId>junit</artifactId>
18+
<version>4.13.2</version>
19+
<scope>test</scope>
20+
</dependency>
21+
<dependency>
22+
<groupId>org.hamcrest</groupId>
23+
<artifactId>hamcrest-core</artifactId>
24+
<version>1.3</version>
25+
<scope>test</scope>
26+
</dependency>
27+
</dependencies>
1428
</project>

src/main/java/io/github/coderodde/simple/stack/machine/MachineLanguageSpecification.java

Lines changed: 42 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ public void execute(final SimpleStackMachine machine) {
2424

2525
@Override
2626
public void execute(final SimpleStackMachine machine) {
27-
machine.checkTapeReserve(1 + Long.BYTES);
27+
machine.checkTapeReserve(1 + Integer.BYTES);
2828
machine.advanceInstructionPointer();
2929

3030
final int number =
3131
machine.readWordFromTape(machine.getInstructionPointer());
3232

33+
machine.advanceInstructionPointer(Integer.BYTES);
3334
machine.push(number);
3435
}
3536
}
@@ -508,13 +509,13 @@ public void execute(final SimpleStackMachine machine) {
508509
}
509510
}
510511

511-
public static final class PrintNumberInstructionImplementation
512+
public static final class PrintStringInstructionImplementation
512513
implements InstructionImplementation {
513514

514515
@Override
515516
public void execute(final SimpleStackMachine machine) {
516517
machine.checkTapeReserve(1);
517-
machine.requireStackSize(1);
518+
machine.requireStackSize(2);
518519
machine.advanceInstructionPointer();
519520

520521
final int stringLength = machine.pop();
@@ -530,87 +531,76 @@ private static String processStringPrint(final SimpleStackMachine machine,
530531
final int stringLength,
531532
final int startAddress) {
532533
final int numberOfWords =
533-
stringLength * Character.BYTES +
534+
stringLength / Character.BYTES +
534535
(stringLength % 2 == 0 ? 0 : 1);
535536

536537
final int[] words = new int[numberOfWords];
537538

538539
for (int i = 0; i < words.length; i++) {
539-
words[i] = machine.readWordFromTape(startAddress + i);
540+
words[i] =
541+
machine.readWordFromTape(startAddress + Integer.BYTES * i);
540542
}
541543

542544
final char[] characterData = new char[stringLength];
543545

546+
int currentWordIndex = 0;
547+
544548
for (int i = 0; i < characterData.length; ++i) {
545-
final int word = words[i / Character.BYTES];
546-
final int diffIndex = i % Character.BYTES == 0 ? 0 : 1;
547-
characterData[i] = (char)(words[i / 2 + diffIndex]);
549+
final int currentWord = words[currentWordIndex];
550+
final int characterIndex = i == 0 ? 0 : 1;
551+
552+
if (characterIndex == 0) {
553+
characterData[i] = (char)(currentWord & 0xff);
554+
} else {
555+
characterData[i] = (char)((currentWord >> Byte.SIZE) & 0xff);
556+
}
557+
558+
if (i % Character.BYTES == 1) {
559+
currentWordIndex++;
560+
}
548561
}
549562

550563
return new String(characterData);
551564
}
552565

553-
public static final class PrintStringInstructionImplementation
566+
public static final class PrintNumberInstructionImplementation
554567
implements InstructionImplementation {
555568

556569
@Override
557570
public void execute(final SimpleStackMachine machine) {
558571
machine.checkTapeReserve(1);
559-
machine.requireStackSize(2);
572+
machine.requireStackSize(1);
560573
machine.advanceInstructionPointer();
561574

562-
final int numberOfChars = (int) machine.pop();
563-
final int stringStartIndex = (int) machine.pop();
564-
final int numberOfNumbers =
565-
(int)(numberOfChars / Long.BYTES
566-
+ (numberOfChars % Long.BYTES == 0 ? 0 : 1));
567-
568-
final long[] stringData = new long[numberOfNumbers];
569-
570-
for (int p = stringStartIndex, i = 0; i < numberOfNumbers; ++i) {
571-
stringData[i] = machine.readNumber();
572-
machine.advanceInstructionPointer(Long.BYTES);
573-
}
574-
575-
final byte[] asciiString = new byte[numberOfChars];
576-
577-
for (int byteIndex = 0; byteIndex < numberOfChars; ++byteIndex) {
578-
final long textChunk = stringData[byteIndex / Long.BYTES];
579-
final byte byteChar =
580-
(byte)(((textChunk) >>>
581-
Byte.SIZE * (byteIndex % Long.BYTES)) & 0xff);
582-
583-
asciiString[byteIndex] = byteChar;
584-
}
585-
586-
final StringBuilder sb = new StringBuilder(numberOfChars);
587-
588-
for (int i = 0; i < asciiString.length; ++i) {
589-
sb.append((char)(asciiString[i]));
590-
}
591-
592-
System.out.println(sb.toString());
575+
System.out.println(machine.pop());
593576
}
594577
}
595578

596579
public static final class ReadStringInstructionImplementation
597580
implements InstructionImplementation {
598581

599-
@Override
600-
public void execute(SimpleStackMachine machine) {
601-
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
602-
}
603-
}
604-
605-
public static final class ReadNumberInstructionImplementation
606-
implements InstructionImplementation {
607-
608582
@Override
609583
public void execute(SimpleStackMachine machine) {
610584
machine.checkTapeReserve(1);
611-
machine.requireStackSize(1);
585+
machine.requireStackSize(2);
612586
machine.advanceInstructionPointer();
613-
machine.readNumber();
587+
588+
final int stringLength = machine.pop();
589+
final int stringAddress = machine.pop();
590+
591+
614592
}
615593
}
594+
595+
// public static final class ReadNumberInstructionImplementation
596+
// implements InstructionImplementation {
597+
//
598+
// @Override
599+
// public void execute(SimpleStackMachine machine) {
600+
// machine.checkTapeReserve(1);
601+
// machine.requireStackSize(1);
602+
// machine.advanceInstructionPointer();
603+
// machine.readNumber();
604+
// }
605+
// }
616606
}

src/main/java/io/github/coderodde/simple/stack/machine/Operation.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,23 +82,45 @@ public enum Operation {
8282
private static final Map<String, Operation> mapOperationNameToOperationEnum
8383
= new HashMap<>();
8484

85+
private static final Map<Byte, Operation> mapOperationByteToOperatoinEnum =
86+
new HashMap<>();
87+
88+
private final String opcodeName;
8589
private final byte opcodeByte;
8690
private final InstructionImplementation impl;
8791

88-
private Operation(final String name,
92+
private Operation(final String opcodeName,
8993
final byte opcodeByte,
9094
final InstructionImplementation impl) {
95+
this.opcodeName = opcodeName;
9196
this.opcodeByte = opcodeByte;
9297
this.impl = impl;
9398
}
9499

95-
public Operation getOperation(final String operationName) {
100+
public InstructionImplementation getImpl() {
101+
return this.impl;
102+
}
103+
104+
public String getOperationName() {
105+
return opcodeName;
106+
}
107+
108+
public byte getOpcodeByte() {
109+
return this.opcodeByte;
110+
}
111+
112+
public static Operation getOperation(final String operationName) {
96113
return mapOperationNameToOperationEnum.get(operationName);
97114
}
98115

116+
public static Operation getOperation(final byte opcode) {
117+
return mapOperationByteToOperatoinEnum.get(opcode);
118+
}
119+
99120
static {
100121
for (final Operation o : Operation.values()) {
101122
mapOperationNameToOperationEnum.put(o.name(), o);
123+
mapOperationByteToOperatoinEnum.put(o.opcodeByte, o);
102124
}
103125
}
104126
}

src/main/java/io/github/coderodde/simple/stack/machine/SimpleStackMachine.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,10 @@ public void execute(final byte[] programBytes) {
195195

196196
private void executeImpl() {
197197
final byte opcode = tape[instructionPointer];
198-
// final InstructionImplementation impl = Operation.
198+
final Operation operation = Operation.getOperation(opcode);
199+
final InstructionImplementation impl = operation.getImpl();
200+
201+
impl.execute(this);
199202
}
200203

201204
public static void main(String[] args) {
@@ -225,15 +228,15 @@ int readWordFromTape(final int address) {
225228
throw new StackMachineException(exceptionMessage);
226229
}
227230

228-
final int nb0 = Byte.toUnsignedInt(tape[address]);
229-
final int nb1 = Byte.toUnsignedInt(tape[address + 1]) << 8;
230-
final int nb2 = Byte.toUnsignedInt(tape[address + 2]) << 16;
231-
final int nb3 = Byte.toUnsignedInt(tape[address + 3]) << 24;
231+
final int word0 = Byte.toUnsignedInt(tape[address + 0]) << 0;
232+
final int word1 = Byte.toUnsignedInt(tape[address + 1]) << 8;
233+
final int word2 = Byte.toUnsignedInt(tape[address + 2]) << 16;
234+
final int word3 = Byte.toUnsignedInt(tape[address + 3]) << 24;
232235

233-
return nb0 |
234-
nb1 |
235-
nb2 |
236-
nb3;
236+
return word0 |
237+
word1 |
238+
word2 |
239+
word3;
237240
}
238241

239242
void writeWordToTape(final int address, int word) {
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package io.github.coderodde.simple.stack.machine;
2+
3+
import org.junit.Test;
4+
5+
public class MachineLanguageSpecificationTest {
6+
7+
@Test
8+
public void printString() {
9+
final SimpleStackMachine machine = new SimpleStackMachine();
10+
final CodeBuilder cb = new CodeBuilder(1000);
11+
12+
cb.emit(Operation.PUSH.getOpcodeByte());
13+
cb.emit(6);
14+
cb.emit(Operation.PUSH.getOpcodeByte());
15+
cb.emit(900);
16+
cb.emit(Operation.PRINT_STRING.getOpcodeByte());
17+
cb.emit(Operation.HALT.getOpcodeByte());
18+
cb.emit("Hello!", 900);
19+
20+
machine.execute(cb.toByteArray());
21+
}
22+
23+
private static class CodeBuilder {
24+
private final byte[] code;
25+
private int pointer = 0;
26+
27+
CodeBuilder(int capacity) {
28+
this.code = new byte[capacity];
29+
}
30+
31+
void emit(byte b) {
32+
code[pointer++] = b;
33+
}
34+
35+
void emit(int word) {
36+
for (final byte b : intToBytes(word)) {
37+
emit(b);
38+
}
39+
}
40+
41+
void emit(String str) {
42+
byte[] stringBytes = str.getBytes();
43+
44+
for (final byte b : stringBytes) {
45+
emit(b);
46+
}
47+
}
48+
49+
void emit(String str, int startIndex) {
50+
byte[] stringBytes = str.getBytes();
51+
52+
for (int i = 0; i < stringBytes.length; ++i) {
53+
code[startIndex + i] = stringBytes[i];
54+
}
55+
}
56+
57+
byte[] toByteArray() {
58+
return code;
59+
}
60+
61+
static byte[] intToBytes(int value) {
62+
return new byte[] {
63+
(byte)(value >>> 24), // highest byte (big-endian)
64+
(byte)(value >>> 16),
65+
(byte)(value >>> 8),
66+
(byte)value
67+
};
68+
}
69+
}
70+
}

0 commit comments

Comments
 (0)