origin-or 1.7.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- origin/__init__.py +3 -0
- origin/__main__.py +16 -0
- origin/bc/JavaImplement/BoundMethod.java +11 -0
- origin/bc/JavaImplement/Builtins.java +224 -0
- origin/bc/JavaImplement/HardwareSim.java +93 -0
- origin/bc/JavaImplement/Loader.java +103 -0
- origin/bc/JavaImplement/Main.java +34 -0
- origin/bc/JavaImplement/OpCode.java +79 -0
- origin/bc/JavaImplement/OriginClass.java +16 -0
- origin/bc/JavaImplement/OriginInstance.java +19 -0
- origin/bc/JavaImplement/svm.java +699 -0
- origin/bc/__init__.py +1 -0
- origin/bc/byte_key.py +74 -0
- origin/bc/dump_obc.py +134 -0
- origin/bc/helpers.py +18 -0
- origin/bc/svm.py +509 -0
- origin/bc/to_byte.py +616 -0
- origin/classes.py +525 -0
- origin/errors.py +372 -0
- origin/interpreter.py +446 -0
- origin/lexer.py +96 -0
- origin/lib/__init__.py +1 -0
- origin/lib/calc.or +45 -0
- origin/lib/graph.or +55 -0
- origin/parser.py +968 -0
- origin/runner.py +91 -0
- origin_or-1.7.9.dist-info/METADATA +203 -0
- origin_or-1.7.9.dist-info/RECORD +31 -0
- origin_or-1.7.9.dist-info/WHEEL +5 -0
- origin_or-1.7.9.dist-info/entry_points.txt +2 -0
- origin_or-1.7.9.dist-info/top_level.txt +1 -0
origin/__init__.py
ADDED
origin/__main__.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Entry point for `python -m origin` and the `origin` CLI command."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from .runner import run_origin
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def main():
|
|
8
|
+
if len(sys.argv) < 2:
|
|
9
|
+
print("Origin Programming Language v1.7.9")
|
|
10
|
+
print("Usage: origin <file.or>")
|
|
11
|
+
sys.exit(1)
|
|
12
|
+
run_origin(sys.argv[1])
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
if __name__ == "__main__":
|
|
16
|
+
main()
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
package ORIGIN_CODE.bc.JavaImplement;
|
|
2
|
+
|
|
3
|
+
public final class BoundMethod {
|
|
4
|
+
public final OriginInstance instance;
|
|
5
|
+
public final int funcPc;
|
|
6
|
+
|
|
7
|
+
public BoundMethod(OriginInstance instance, int funcPc) {
|
|
8
|
+
this.instance = instance;
|
|
9
|
+
this.funcPc = funcPc;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
package ORIGIN_CODE.bc.JavaImplement;
|
|
2
|
+
|
|
3
|
+
import java.util.ArrayList;
|
|
4
|
+
import java.util.HashMap;
|
|
5
|
+
import java.util.List;
|
|
6
|
+
import java.util.Map;
|
|
7
|
+
import java.util.Scanner;
|
|
8
|
+
import java.util.concurrent.ThreadLocalRandom;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Registry of built-in callables that the VM exposes to bytecode via CALL.
|
|
12
|
+
* Mirrors the {open, read, write, append, range, ...} dictionary in
|
|
13
|
+
* to_byte.py:18 plus the implicit built-ins handled by the Python branch
|
|
14
|
+
* of CALL at svm.py:333-339.
|
|
15
|
+
*/
|
|
16
|
+
public final class Builtins {
|
|
17
|
+
|
|
18
|
+
@FunctionalInterface
|
|
19
|
+
public interface BuiltinFn {
|
|
20
|
+
Object call(List<Object> args);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private final Map<String, BuiltinFn> registry;
|
|
24
|
+
|
|
25
|
+
public Builtins() {
|
|
26
|
+
this.registry = new HashMap<>();
|
|
27
|
+
registerDefaults();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public BuiltinFn get(String name) {
|
|
31
|
+
return registry.get(name);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public boolean contains(String name) {
|
|
35
|
+
return registry.containsKey(name);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private void registerDefaults() {
|
|
39
|
+
// Compiler builtins (to_byte.py:18-24)
|
|
40
|
+
registry.put("open", args -> new OpenFile(asStr(args, 0), "r"));
|
|
41
|
+
registry.put("read", args -> {
|
|
42
|
+
OpenFile f = asOpenFile(args, 0);
|
|
43
|
+
return f.readAll();
|
|
44
|
+
});
|
|
45
|
+
registry.put("write", args -> {
|
|
46
|
+
Object pathOrFile = args.get(0);
|
|
47
|
+
Object content = args.get(1);
|
|
48
|
+
String contentStr = String.valueOf(content);
|
|
49
|
+
if (pathOrFile instanceof OpenFile) {
|
|
50
|
+
((OpenFile) pathOrFile).writeAll(contentStr);
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
try (java.io.FileWriter w = new java.io.FileWriter(asStr(args, 0))) {
|
|
54
|
+
w.write(contentStr);
|
|
55
|
+
} catch (java.io.IOException e) {
|
|
56
|
+
throw new RuntimeException(e);
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
});
|
|
60
|
+
registry.put("append", args -> {
|
|
61
|
+
Object pathOrFile = args.get(0);
|
|
62
|
+
Object content = args.get(1);
|
|
63
|
+
String contentStr = String.valueOf(content);
|
|
64
|
+
if (pathOrFile instanceof OpenFile) {
|
|
65
|
+
((OpenFile) pathOrFile).appendAll(contentStr);
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
try (java.io.FileWriter w = new java.io.FileWriter(asStr(args, 0), true)) {
|
|
69
|
+
w.write(contentStr);
|
|
70
|
+
} catch (java.io.IOException e) {
|
|
71
|
+
throw new RuntimeException(e);
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
});
|
|
75
|
+
registry.put("range", args -> {
|
|
76
|
+
int n = args.size();
|
|
77
|
+
int start, end;
|
|
78
|
+
if (n == 1) { start = 0; end = asInt(args, 0); }
|
|
79
|
+
else { start = asInt(args, 0); end = asInt(args, 1); }
|
|
80
|
+
List<Object> out = new ArrayList<>();
|
|
81
|
+
for (int i = start; i < end; i++) out.add((long) i);
|
|
82
|
+
return out;
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Implied built-ins called from bytecode (svm.py CALL branch)
|
|
86
|
+
registry.put("str", args -> toStr(args.isEmpty() ? null : args.get(0)));
|
|
87
|
+
registry.put("int", args -> {
|
|
88
|
+
if (args.isEmpty()) return 0L;
|
|
89
|
+
Object v = args.get(0);
|
|
90
|
+
if (v instanceof Long) return v;
|
|
91
|
+
if (v instanceof Double) return ((Double) v).longValue();
|
|
92
|
+
if (v instanceof Boolean) return ((Boolean) v) ? 1L : 0L;
|
|
93
|
+
return Long.parseLong(String.valueOf(v));
|
|
94
|
+
});
|
|
95
|
+
registry.put("float", args -> {
|
|
96
|
+
if (args.isEmpty()) return 0.0;
|
|
97
|
+
Object v = args.get(0);
|
|
98
|
+
if (v instanceof Double) return v;
|
|
99
|
+
if (v instanceof Long) return ((Long) v).doubleValue();
|
|
100
|
+
return Double.parseDouble(String.valueOf(v));
|
|
101
|
+
});
|
|
102
|
+
registry.put("bool", args -> toBool(args.isEmpty() ? null : args.get(0)));
|
|
103
|
+
registry.put("len", args -> (long) lengthOf(args.get(0)));
|
|
104
|
+
registry.put("input", args -> {
|
|
105
|
+
if (args.isEmpty()) return new Scanner(System.in).nextLine();
|
|
106
|
+
System.out.print(args.get(0));
|
|
107
|
+
return new Scanner(System.in).nextLine();
|
|
108
|
+
});
|
|
109
|
+
registry.put("random", args -> {
|
|
110
|
+
// Placeholder; VM handles RAND_NUM directly via ThreadLocalRandom.
|
|
111
|
+
return null;
|
|
112
|
+
});
|
|
113
|
+
registry.put("math", args -> null); // VM handles SQRT directly
|
|
114
|
+
registry.put("print", args -> {
|
|
115
|
+
StringBuilder sb = new StringBuilder();
|
|
116
|
+
for (Object a : args) sb.append(toStr(a));
|
|
117
|
+
System.out.println(sb.toString());
|
|
118
|
+
return null;
|
|
119
|
+
});
|
|
120
|
+
registry.put("list", args -> {
|
|
121
|
+
if (args.isEmpty()) return new ArrayList<>();
|
|
122
|
+
Object v = args.get(0);
|
|
123
|
+
if (v instanceof List) return new ArrayList<>((List<?>) v);
|
|
124
|
+
if (v instanceof String) {
|
|
125
|
+
List<Object> out = new ArrayList<>();
|
|
126
|
+
String s = (String) v;
|
|
127
|
+
for (int i = 0; i < s.length(); i++) out.add(String.valueOf(s.charAt(i)));
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
throw new RuntimeException("object is not iterable");
|
|
131
|
+
});
|
|
132
|
+
registry.put("dict", args -> new HashMap<>());
|
|
133
|
+
registry.put("tuple", args -> new ArrayList<>(args));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// --- helpers used by Builtins and by VM opcode handlers ---
|
|
137
|
+
|
|
138
|
+
public static String toStr(Object v) {
|
|
139
|
+
if (v == null) return "null";
|
|
140
|
+
if (v instanceof OriginInstance) return v.toString();
|
|
141
|
+
return String.valueOf(v);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
public static boolean toBool(Object v) {
|
|
145
|
+
if (v == null) return false;
|
|
146
|
+
if (v instanceof Boolean) return (Boolean) v;
|
|
147
|
+
if (v instanceof Long) return ((Long) v) != 0;
|
|
148
|
+
if (v instanceof Double) return ((Double) v) != 0.0;
|
|
149
|
+
if (v instanceof String) return !((String) v).isEmpty();
|
|
150
|
+
if (v instanceof List) return !((List<?>) v).isEmpty();
|
|
151
|
+
if (v instanceof Map) return !((Map<?, ?>) v).isEmpty();
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public static int asInt(List<Object> args, int i) {
|
|
156
|
+
Object v = args.get(i);
|
|
157
|
+
if (v instanceof Long) return ((Long) v).intValue();
|
|
158
|
+
if (v instanceof Double) return ((Double) v).intValue();
|
|
159
|
+
if (v instanceof Boolean) return ((Boolean) v) ? 1 : 0;
|
|
160
|
+
return Integer.parseInt(String.valueOf(v));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
public static String asStr(List<Object> args, int i) {
|
|
164
|
+
Object v = args.get(i);
|
|
165
|
+
if (v == null) return "null";
|
|
166
|
+
return String.valueOf(v);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
public static long asLong(Object v) {
|
|
170
|
+
if (v instanceof Long) return (Long) v;
|
|
171
|
+
if (v instanceof Double) return ((Double) v).longValue();
|
|
172
|
+
if (v instanceof Boolean) return ((Boolean) v) ? 1L : 0L;
|
|
173
|
+
return Long.parseLong(String.valueOf(v));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
public static double asDouble(Object v) {
|
|
177
|
+
if (v instanceof Double) return (Double) v;
|
|
178
|
+
if (v instanceof Long) return ((Long) v).doubleValue();
|
|
179
|
+
if (v instanceof Boolean) return ((Boolean) v) ? 1.0 : 0.0;
|
|
180
|
+
return Double.parseDouble(String.valueOf(v));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
public static long lengthOf(Object v) {
|
|
184
|
+
if (v instanceof String) return ((String) v).length();
|
|
185
|
+
if (v instanceof List) return ((List<?>) v).size();
|
|
186
|
+
if (v instanceof Map) return ((Map<?, ?>) v).size();
|
|
187
|
+
throw new RuntimeException("object has no len(): " + (v == null ? "null" : v.getClass().getName()));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
public static int randInt(long start, long end) {
|
|
191
|
+
return ThreadLocalRandom.current().nextInt((int) start, (int) end + 1);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** Wrapper for a file handle returned by built-in open(). */
|
|
195
|
+
public static final class OpenFile {
|
|
196
|
+
public final String path;
|
|
197
|
+
public final String mode;
|
|
198
|
+
public OpenFile(String path, String mode) { this.path = path; this.mode = mode; }
|
|
199
|
+
public String readAll() {
|
|
200
|
+
try {
|
|
201
|
+
return new String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get(path)));
|
|
202
|
+
} catch (java.io.IOException e) {
|
|
203
|
+
throw new RuntimeException(e);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
public void writeAll(String content) {
|
|
207
|
+
try (java.io.FileWriter w = new java.io.FileWriter(path)) {
|
|
208
|
+
w.write(content);
|
|
209
|
+
} catch (java.io.IOException e) { throw new RuntimeException(e); }
|
|
210
|
+
}
|
|
211
|
+
public void appendAll(String content) {
|
|
212
|
+
try (java.io.FileWriter w = new java.io.FileWriter(path, true)) {
|
|
213
|
+
w.write(content);
|
|
214
|
+
} catch (java.io.IOException e) { throw new RuntimeException(e); }
|
|
215
|
+
}
|
|
216
|
+
@Override public String toString() { return "<open file '" + path + "' mode='" + mode + "'>"; }
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private static OpenFile asOpenFile(List<Object> args, int i) {
|
|
220
|
+
Object v = args.get(i);
|
|
221
|
+
if (v instanceof OpenFile) return (OpenFile) v;
|
|
222
|
+
return new OpenFile(asStr(args, i), "r");
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
package ORIGIN_CODE.bc.JavaImplement;
|
|
2
|
+
|
|
3
|
+
import java.util.List;
|
|
4
|
+
import java.util.Map;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Hardware-backed operations for SET_PIN, HARDWARE_CALL, SET_SERVO.
|
|
8
|
+
* Mirrors the try-import-then-fallback pattern in svm.py:14-46.
|
|
9
|
+
*
|
|
10
|
+
* The Real backend is intentionally absent — Pi GPIO / smbus2 / adafruit_servokit
|
|
11
|
+
* are not available on the JVM, and adding the JNI/pi4j dependencies is out of
|
|
12
|
+
* scope for this port. Any call to setBackend(Backend.REAL) without the
|
|
13
|
+
* corresponding JNI bridge installed will fall through to simulation.
|
|
14
|
+
*/
|
|
15
|
+
public final class HardwareSim {
|
|
16
|
+
|
|
17
|
+
public enum Backend { SIM, REAL }
|
|
18
|
+
|
|
19
|
+
private static Backend backend = Backend.SIM;
|
|
20
|
+
|
|
21
|
+
public static void setBackend(Backend b) { backend = b; }
|
|
22
|
+
public static Backend getBackend() { return backend; }
|
|
23
|
+
|
|
24
|
+
public static void setPin(long pin, long state) {
|
|
25
|
+
// svm.py:14-21 — only the simulation branch is reachable from the JVM.
|
|
26
|
+
System.out.println("[SIM] Pin " + pin + " set to " + state);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public static Object i2cRead(long addr, long reg, long size) {
|
|
30
|
+
// svm.py:23-29
|
|
31
|
+
return 0L;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public static void i2cWrite(long addr, long reg, Object data) {
|
|
35
|
+
// svm.py:31-38
|
|
36
|
+
// no-op in simulation
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public static void spiWrite(Object data) {
|
|
40
|
+
// svm.py:40-41
|
|
41
|
+
System.out.println("[SIM] SPI write: " + data);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public static Object spiRead(long count) {
|
|
45
|
+
// svm.py:43-45
|
|
46
|
+
System.out.println("[SIM] SPI read: " + count);
|
|
47
|
+
return 0L;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** SET_SERVO dispatcher (svm.py:427-438). Caches the kit globally. */
|
|
51
|
+
public static void setServo(long channel, double angle) {
|
|
52
|
+
// svm.py:432-438 — without adafruit_servokit available on the JVM,
|
|
53
|
+
// we always take the simulation branch.
|
|
54
|
+
System.out.println("[SIM] Servo " + channel + " angle set to " + angle);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** HARDWARE_CALL dispatcher (svm.py:407-425). */
|
|
58
|
+
public static Object hardwareCall(String namespace, String method, List<Object> args) {
|
|
59
|
+
if ("i2c".equals(namespace) && "read".equals(method)) {
|
|
60
|
+
long addr = Builtins.asLong(args.get(0));
|
|
61
|
+
long reg = Builtins.asLong(args.get(1));
|
|
62
|
+
long size = args.size() > 2 ? Builtins.asLong(args.get(2)) : 1L;
|
|
63
|
+
return i2cRead(addr, reg, size);
|
|
64
|
+
}
|
|
65
|
+
if ("i2c".equals(namespace) && "write".equals(method)) {
|
|
66
|
+
long addr = Builtins.asLong(args.get(0));
|
|
67
|
+
long reg = Builtins.asLong(args.get(1));
|
|
68
|
+
i2cWrite(addr, reg, args.get(2));
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
if ("spi".equals(namespace) && "write".equals(method)) {
|
|
72
|
+
spiWrite(args.get(0));
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
if ("spi".equals(namespace) && "read".equals(method)) {
|
|
76
|
+
return spiRead(Builtins.asLong(args.get(0)));
|
|
77
|
+
}
|
|
78
|
+
// svm.py:425 — unknown hardware call gets a generic SIM line
|
|
79
|
+
StringBuilder sb = new StringBuilder("[SIM] ").append(namespace).append(".").append(method).append("(");
|
|
80
|
+
for (int i = 0; i < args.size(); i++) {
|
|
81
|
+
if (i > 0) sb.append(", ");
|
|
82
|
+
sb.append(Builtins.toStr(args.get(i)));
|
|
83
|
+
}
|
|
84
|
+
sb.append(")");
|
|
85
|
+
System.out.println(sb);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** EXEC_PY dispatcher (svm.py:461-463). Simulation: print only. */
|
|
90
|
+
public static void execPy(Object code) {
|
|
91
|
+
System.out.println("[SIM] exec(" + Builtins.toStr(code) + ")");
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
package ORIGIN_CODE.bc.JavaImplement;
|
|
2
|
+
|
|
3
|
+
import java.io.DataInputStream;
|
|
4
|
+
import java.io.IOException;
|
|
5
|
+
import java.io.InputStream;
|
|
6
|
+
import java.nio.ByteBuffer;
|
|
7
|
+
import java.nio.charset.StandardCharsets;
|
|
8
|
+
import java.util.ArrayList;
|
|
9
|
+
import java.util.HashMap;
|
|
10
|
+
import java.util.List;
|
|
11
|
+
import java.util.Map;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Loads an .obc bytecode file into (bytecode, constants[]) for the VM.
|
|
15
|
+
*
|
|
16
|
+
* Format (all big-endian):
|
|
17
|
+
* magic : 4 bytes "OBC1"
|
|
18
|
+
* version : 1 byte (0x01)
|
|
19
|
+
* const_count : 4 bytes int32
|
|
20
|
+
* constants : repeated [typeTag(1) + payload]
|
|
21
|
+
* code_len : 4 bytes int32
|
|
22
|
+
* bytecode : code_len bytes
|
|
23
|
+
*
|
|
24
|
+
* Type tags:
|
|
25
|
+
* 0 = LONG payload = 8 bytes signed
|
|
26
|
+
* 1 = DOUBLE payload = 8 bytes IEEE-754
|
|
27
|
+
* 2 = BOOLEAN payload = 1 byte
|
|
28
|
+
* 3 = STRING payload = int32 len + utf8 bytes
|
|
29
|
+
* 4 = NULL payload = 0 bytes
|
|
30
|
+
* 5 = INT32 payload = 4 bytes signed
|
|
31
|
+
*
|
|
32
|
+
* Origin's bytecode emitter emits integer addresses as ints and small
|
|
33
|
+
* constants as ints; everything else gets LONG. STRING carries names
|
|
34
|
+
* for LOAD_VAR / STORE_VAR and the (ns, method) pair for HARDWARE_CALL
|
|
35
|
+
* (encoded as STRING, STRING).
|
|
36
|
+
*/
|
|
37
|
+
public final class Loader {
|
|
38
|
+
|
|
39
|
+
public static final class Loaded {
|
|
40
|
+
public final byte[] bytecode;
|
|
41
|
+
public final Object[] constants;
|
|
42
|
+
public Loaded(byte[] bytecode, Object[] constants) {
|
|
43
|
+
this.bytecode = bytecode;
|
|
44
|
+
this.constants = constants;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public static Loaded load(InputStream in) throws IOException {
|
|
49
|
+
DataInputStream din = new DataInputStream(in);
|
|
50
|
+
byte[] magic = new byte[4];
|
|
51
|
+
din.readFully(magic);
|
|
52
|
+
if (!new String(magic, StandardCharsets.US_ASCII).equals("OBC1")) {
|
|
53
|
+
throw new IOException("bad magic: " + new String(magic, StandardCharsets.US_ASCII));
|
|
54
|
+
}
|
|
55
|
+
int version = din.readByte() & 0xFF;
|
|
56
|
+
if (version != 1) throw new IOException("unsupported version: " + version);
|
|
57
|
+
|
|
58
|
+
int constCount = din.readInt();
|
|
59
|
+
Object[] consts = new Object[constCount];
|
|
60
|
+
for (int i = 0; i < constCount; i++) {
|
|
61
|
+
consts[i] = readConst(din);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
int codeLen = din.readInt();
|
|
65
|
+
byte[] code = new byte[codeLen];
|
|
66
|
+
din.readFully(code);
|
|
67
|
+
return new Loaded(code, consts);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private static Object readConst(DataInputStream din) throws IOException {
|
|
71
|
+
int tag = din.readByte() & 0xFF;
|
|
72
|
+
switch (tag) {
|
|
73
|
+
case 0: return din.readLong();
|
|
74
|
+
case 1: return din.readDouble();
|
|
75
|
+
case 2: return din.readByte() != 0;
|
|
76
|
+
case 3: {
|
|
77
|
+
int len = din.readInt();
|
|
78
|
+
byte[] b = new byte[len];
|
|
79
|
+
din.readFully(b);
|
|
80
|
+
return new String(b, StandardCharsets.UTF_8);
|
|
81
|
+
}
|
|
82
|
+
case 4: return null;
|
|
83
|
+
case 5: return (long) din.readInt();
|
|
84
|
+
case 6: {
|
|
85
|
+
// TUPLE — emitted by dump_obc.py for both tuple/list literals
|
|
86
|
+
// and for the flat [key, value, ...] representation of dicts
|
|
87
|
+
// used by MAKE_CLASS's methods table.
|
|
88
|
+
int n = din.readInt();
|
|
89
|
+
List<Object> tuple = new ArrayList<>(n);
|
|
90
|
+
for (int i = 0; i < n; i++) tuple.add(readConst(din));
|
|
91
|
+
return tuple;
|
|
92
|
+
}
|
|
93
|
+
default: throw new IOException("bad const tag: " + tag);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Convenience: load from a file path. */
|
|
98
|
+
public static Loaded loadFromFile(String path) throws IOException {
|
|
99
|
+
try (InputStream in = new java.io.FileInputStream(path)) {
|
|
100
|
+
return load(in);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
package ORIGIN_CODE.bc.JavaImplement;
|
|
2
|
+
|
|
3
|
+
import java.io.IOException;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* CLI entry point. Usage:
|
|
7
|
+
* java -cp . ORIGIN_CODE.bc.Main program.obc
|
|
8
|
+
*/
|
|
9
|
+
public final class Main {
|
|
10
|
+
|
|
11
|
+
public static void main(String[] args) {
|
|
12
|
+
if (args.length < 1) {
|
|
13
|
+
System.err.println("usage: java -cp . ORIGIN_CODE.bc.Main <program.obc>");
|
|
14
|
+
System.exit(2);
|
|
15
|
+
}
|
|
16
|
+
String path = args[0];
|
|
17
|
+
|
|
18
|
+
if (args.length >= 2 && "--hw=real".equals(args[1])) {
|
|
19
|
+
HardwareSim.setBackend(HardwareSim.Backend.REAL);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
Loader.Loaded prog = Loader.loadFromFile(path);
|
|
24
|
+
svm vm = new svm(prog.bytecode, prog.constants);
|
|
25
|
+
vm.run();
|
|
26
|
+
} catch (IOException e) {
|
|
27
|
+
System.err.println("load error: " + e.getMessage());
|
|
28
|
+
System.exit(1);
|
|
29
|
+
} catch (RuntimeException e) {
|
|
30
|
+
System.err.println("runtime error: " + e.getMessage());
|
|
31
|
+
System.exit(1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
package ORIGIN_CODE.bc.JavaImplement;
|
|
2
|
+
|
|
3
|
+
public final class OpCode {
|
|
4
|
+
public static final byte PUSH_CONST = 0x01;
|
|
5
|
+
public static final byte LOAD_VAR = 0x02;
|
|
6
|
+
public static final byte STORE_VAR = 0x03;
|
|
7
|
+
public static final byte ADD = 0x04;
|
|
8
|
+
public static final byte SUB = 0x05;
|
|
9
|
+
public static final byte MUL = 0x06;
|
|
10
|
+
public static final byte DIV = 0x07;
|
|
11
|
+
public static final byte MOD = 0x08;
|
|
12
|
+
public static final byte POW = 0x09;
|
|
13
|
+
public static final byte NEGATE = 0x0A;
|
|
14
|
+
public static final byte EQ = 0x0B;
|
|
15
|
+
public static final byte NEQ = 0x0C;
|
|
16
|
+
public static final byte LT = 0x0D;
|
|
17
|
+
public static final byte GT = 0x0E;
|
|
18
|
+
public static final byte LTE = 0x0F;
|
|
19
|
+
public static final byte GTE = 0x10;
|
|
20
|
+
public static final byte AND = 0x11;
|
|
21
|
+
public static final byte OR = 0x12;
|
|
22
|
+
public static final byte NOT = 0x13;
|
|
23
|
+
public static final byte JMP = 0x14;
|
|
24
|
+
public static final byte JMP_IF_FALSE = 0x15;
|
|
25
|
+
public static final byte PRINT = 0x16;
|
|
26
|
+
public static final byte INPUT = 0x17;
|
|
27
|
+
public static final byte LEN = 0x18;
|
|
28
|
+
public static final byte SQRT = 0x19;
|
|
29
|
+
public static final byte RAND_NUM = 0x1A;
|
|
30
|
+
public static final byte LIST_INIT = 0x1B;
|
|
31
|
+
public static final byte DICT_INIT = 0x1C;
|
|
32
|
+
public static final byte INDEX_LOAD = 0x1D;
|
|
33
|
+
public static final byte INDEX_STORE = 0x1E;
|
|
34
|
+
public static final byte HALT = 0x1F;
|
|
35
|
+
public static final byte POP = 0x20;
|
|
36
|
+
public static final byte DUP = 0x21;
|
|
37
|
+
public static final byte CALL = 0x22;
|
|
38
|
+
public static final byte RETURN = 0x23;
|
|
39
|
+
public static final byte LOOP_START = 0x24;
|
|
40
|
+
public static final byte LOOP_END = 0x25;
|
|
41
|
+
public static final byte BREAK = 0x26;
|
|
42
|
+
public static final byte CONTINUE = 0x27;
|
|
43
|
+
public static final byte CAST_STR = 0x28;
|
|
44
|
+
public static final byte CAST_INT = 0x29;
|
|
45
|
+
public static final byte CAST_FLOAT = 0x2A;
|
|
46
|
+
public static final byte GET_ITER = 0x2B;
|
|
47
|
+
public static final byte FOR_ITER = 0x2C;
|
|
48
|
+
public static final byte MAKE_CLASS = 0x2D;
|
|
49
|
+
public static final byte LOAD_ATTR = 0x2E;
|
|
50
|
+
public static final byte STORE_ATTR = 0x2F;
|
|
51
|
+
public static final byte MAKE_CLOSURE = 0x30;
|
|
52
|
+
public static final byte LOAD_UPVALUE = 0x31;
|
|
53
|
+
public static final byte STORE_UPVALUE = 0x32;
|
|
54
|
+
public static final byte SETUP_EXCEPT = 0x33;
|
|
55
|
+
public static final byte POP_EXCEPT = 0x34;
|
|
56
|
+
public static final byte THROW = 0x35;
|
|
57
|
+
public static final byte IMPORT_NAME = 0x36;
|
|
58
|
+
public static final byte IMPORT_FROM = 0x37;
|
|
59
|
+
public static final byte BIT_AND = 0x38;
|
|
60
|
+
public static final byte BIT_OR = 0x39;
|
|
61
|
+
public static final byte BIT_XOR = 0x3A;
|
|
62
|
+
public static final byte BIT_NOT = 0x3B;
|
|
63
|
+
public static final byte LSHIFT = 0x3C;
|
|
64
|
+
public static final byte RSHIFT = 0x3D;
|
|
65
|
+
public static final byte UNPACK_SEQ = 0x3E;
|
|
66
|
+
public static final byte FORMAT_VAL = 0x3F;
|
|
67
|
+
public static final byte BUILD_STR = 0x40;
|
|
68
|
+
public static final byte READ_FILE = 0x41;
|
|
69
|
+
public static final byte WRITE_FILE = 0x42;
|
|
70
|
+
public static final byte APPEND_FILE = 0x43;
|
|
71
|
+
public static final byte HARDWARE_CALL = 0x44;
|
|
72
|
+
public static final byte SET_SERVO = 0x45;
|
|
73
|
+
public static final byte SET_PIN = 0x46;
|
|
74
|
+
public static final byte PARALLEL_START = 0x47;
|
|
75
|
+
public static final byte PARALLEL_END = 0x48;
|
|
76
|
+
public static final byte EXEC_PY = 0x49;
|
|
77
|
+
|
|
78
|
+
private OpCode() {}
|
|
79
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package ORIGIN_CODE.bc.JavaImplement;
|
|
2
|
+
|
|
3
|
+
import java.util.List;
|
|
4
|
+
import java.util.Map;
|
|
5
|
+
|
|
6
|
+
public final class OriginClass {
|
|
7
|
+
public final String name;
|
|
8
|
+
public final List<String> fields;
|
|
9
|
+
public final Map<String, Integer> methods;
|
|
10
|
+
|
|
11
|
+
public OriginClass(String name, List<String> fields, Map<String, Integer> methods) {
|
|
12
|
+
this.name = name;
|
|
13
|
+
this.fields = fields;
|
|
14
|
+
this.methods = methods;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
package ORIGIN_CODE.bc.JavaImplement;
|
|
2
|
+
|
|
3
|
+
import java.util.HashMap;
|
|
4
|
+
import java.util.Map;
|
|
5
|
+
|
|
6
|
+
public final class OriginInstance {
|
|
7
|
+
public final OriginClass originClass;
|
|
8
|
+
public final Map<String, Object> attrs;
|
|
9
|
+
|
|
10
|
+
public OriginInstance(OriginClass originClass) {
|
|
11
|
+
this.originClass = originClass;
|
|
12
|
+
this.attrs = new HashMap<>();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@Override
|
|
16
|
+
public String toString() {
|
|
17
|
+
return "<" + originClass.name + " instance>";
|
|
18
|
+
}
|
|
19
|
+
}
|