This commit is contained in:
Daniella / Tove 2022-04-16 18:44:07 +02:00
parent 07c0ddcff0
commit 6d29b9d8d4
3 changed files with 156 additions and 39 deletions

View file

@ -1,4 +1,5 @@
import java.io.*; import java.io.*;
import java.lang.reflect.*;
import java.net.BindException; import java.net.BindException;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
@ -17,9 +18,9 @@ import java.util.function.Supplier;
public class ISBPL { public class ISBPL {
// TODO: fully implement JIO // TODO: fully implement JIO
// public static final boolean ENABLE_JINTEROP = true; // public static final boolean ENABLE_JINTEROP = true;
static boolean debug = false; static boolean debug = false, printCalls = false;
public ISBPLDebugger.IPC debuggerIPC = new ISBPLDebugger.IPC(); public ISBPLDebugger.IPC debuggerIPC = new ISBPLDebugger.IPC();
ArrayList<ISBPLType> types = new ArrayList<>(); ArrayList<ISBPLType> types = new ArrayList<>();
final ISBPLThreadLocal<Stack<HashMap<String, ISBPLCallable>>> functionStack = ISBPLThreadLocal.withInitial(Stack::new); final ISBPLThreadLocal<Stack<HashMap<String, ISBPLCallable>>> functionStack = ISBPLThreadLocal.withInitial(Stack::new);
@ -131,7 +132,7 @@ public class ISBPL {
} }
return i.get(); return i.get();
}; };
case "{": case "{":
return (idx, words, file, stack) -> { return (idx, words, file, stack) -> {
AtomicInteger i = new AtomicInteger(idx); AtomicInteger i = new AtomicInteger(idx);
ISBPLCallable block = readBlock(i, words, file, false); ISBPLCallable block = readBlock(i, words, file, false);
@ -167,7 +168,7 @@ public class ISBPL {
@SuppressWarnings("RedundantCast") @SuppressWarnings("RedundantCast")
private void addNative(String name) { private void addNative(String name) {
ISBPLCallable func = null; ISBPLCallable func;
switch (name) { switch (name) {
case "alen": case "alen":
func = (Stack<ISBPLObject> stack) -> { func = (Stack<ISBPLObject> stack) -> {
@ -474,9 +475,7 @@ public class ISBPL {
}; };
break; break;
case "not": case "not":
func = (Stack<ISBPLObject> stack) -> { func = (Stack<ISBPLObject> stack) -> stack.push(new ISBPLObject(getType("int"), stack.pop().isTruthy() ? 0 : 1));
stack.push(new ISBPLObject(getType("int"), stack.pop().isTruthy() ? 0 : 1));
};
break; break;
case "neg": case "neg":
func = (Stack<ISBPLObject> stack) -> { func = (Stack<ISBPLObject> stack) -> {
@ -751,7 +750,7 @@ public class ISBPL {
}; };
break; break;
case "pop": case "pop":
func = (Stack<ISBPLObject> stack) -> stack.pop(); func = Stack::pop;
break; break;
case "swap": case "swap":
func = (Stack<ISBPLObject> stack) -> { func = (Stack<ISBPLObject> stack) -> {
@ -830,9 +829,7 @@ public class ISBPL {
}; };
break; break;
case "stacksize": case "stacksize":
func = (Stack<ISBPLObject> stack) -> { func = (Stack<ISBPLObject> stack) -> stack.push(new ISBPLObject(getType("int"), stack.size()));
stack.push(new ISBPLObject(getType("int"), stack.size()));
};
break; break;
case "fcall": case "fcall":
func = (Stack<ISBPLObject> stack) -> { func = (Stack<ISBPLObject> stack) -> {
@ -883,13 +880,108 @@ public class ISBPL {
addFunction(t, "=" + s, (stack1) -> t.varget(stack1.pop()).put(var, stack1.pop())); addFunction(t, "=" + s, (stack1) -> t.varget(stack1.pop()).put(var, stack1.pop()));
}; };
break; break;
case "jio.class":
func = (stack) -> {
ISBPLObject str = stack.pop();
String s = toJavaString(str);
try {
stack.push(toISBPL(Class.forName(s)));
}
catch (ClassNotFoundException e) {
throw new ISBPLError("JIO", "Class not found");
}
};
break;
default: default:
func = natives.get(name); func = natives.get(name);
break; break;
} }
addFunction(name, func); addFunction(name, func);
} }
public ISBPLObject toISBPL(Class<?> clazz) {
ISBPLType type = getType(clazz.getName());
if(type == null) {
type = registerType(clazz.getName());
for (Field field : clazz.getDeclaredFields()) {
addFunction(type, field.getName(), stack -> {
field.setAccessible(true);
if(debug)
System.err.println("Java Get: " + field);
try {
stack.push(toISBPL(field.get(stack.pop().object)));
}
catch (IllegalAccessException ignored) {
}
});
addFunction(type, "=" + field.getName(), stack -> {
field.setAccessible(true);
if(debug)
System.err.println("Java Set: " + field);
try {
field.set(stack.pop().object, fromISBPL(stack.pop()));
}
catch (IllegalAccessException ignored) {
}
});
}
for (Method method : clazz.getDeclaredMethods()) {
addFunction(type, method.getName() + method.getParameterCount(), stack -> {
method.setAccessible(true);
Object o = stack.pop().object;
Object[] params = new Object[method.getParameterCount()];
for (int i = params.length - 1 ; i >= 0 ; i--) {
params[i] = fromISBPL(stack.pop());
}
if(debug)
System.err.println("Java Call: " + method + " - " + Arrays.toString(params));
try {
Object r = method.invoke(o, params);
if(method.getReturnType() != void.class)
stack.push(toISBPL(r));
}
catch (IllegalAccessException ignored) { }
catch (InvocationTargetException e) {
stack.push(toISBPL(e));
throw new ISBPLError("Java", "Java error");
}
});
}
}
return new ISBPLObject(type, null);
}
private Object fromISBPL(ISBPLObject o) {
ISBPLType type = o.type;
if (type.equals(getType("string")))
return toJavaString(o);
if (type.equals(getType("array"))) {
ISBPLObject[] isbplArray = ((ISBPLObject[]) o.object);
Object[] array = new Object[isbplArray.length];
for (int i = 0 ; i < array.length ; i++) {
array[i] = fromISBPL(isbplArray[i]);
}
return array;
}
return o.object;
}
public ISBPLObject toISBPL(Object object) {
ISBPLObject o = toISBPL(object.getClass());
if (object instanceof String) {
object = toISBPLString(((String) object));
}
if (object.getClass().isArray()) {
ISBPLObject[] isbplArray = new ISBPLObject[Array.getLength(object)];
for (int i = 0 ; i < isbplArray.length ; i++) {
isbplArray[i] = toISBPL(Array.get(object, i));
}
object = isbplArray;
}
o.object = object;
return o;
}
public void addFunction(ISBPLType type, String name, ISBPLCallable callable) { public void addFunction(ISBPLType type, String name, ISBPLCallable callable) {
type.methods.put(name, callable); type.methods.put(name, callable);
type.methods.put("&" + name, stack -> stack.push(new ISBPLObject(getType("func"), callable))); type.methods.put("&" + name, stack -> stack.push(new ISBPLObject(getType("func"), callable)));
@ -1016,12 +1108,12 @@ public class ISBPL {
String word = words[i]; String word = words[i];
if (word.length() == 0) if (word.length() == 0)
continue; continue;
if(debug) { if(printCalls) {
String s = ""; StringBuilder s = new StringBuilder();
for (int x = 0 ; x < functionStack.get().size() ; x++) { for (int x = 0 ; x < functionStack.get().size() ; x++) {
s += "\t"; s.append("\t");
} }
System.err.println(s + word + "\t\t" + stack); System.err.println(s + word + "\t\t" + (debug ? stack : ""));
} }
while (debuggerIPC.run.get(Thread.currentThread().getId()) == 0) Thread.sleep(1); while (debuggerIPC.run.get(Thread.currentThread().getId()) == 0) Thread.sleep(1);
if(debuggerIPC.run.get(Thread.currentThread().getId()) < 0) { if(debuggerIPC.run.get(Thread.currentThread().getId()) < 0) {
@ -1105,7 +1197,7 @@ public class ISBPL {
char[] chars = code.toCharArray(); char[] chars = code.toCharArray();
boolean isInString = false; boolean isInString = false;
boolean escaping = false; boolean escaping = false;
String word = ""; StringBuilder word = new StringBuilder();
for (int i = 0 ; i < chars.length ; i++) { for (int i = 0 ; i < chars.length ; i++) {
char c = chars[i]; char c = chars[i];
if(isInString) { if(isInString) {
@ -1115,13 +1207,13 @@ public class ISBPL {
continue; continue;
} }
if(c == 'n' && escaping) { if(c == 'n' && escaping) {
word += '\n'; word.append('\n');
escaping = false; escaping = false;
continue; continue;
} }
if(c == 'r' && escaping) { if(c == 'r' && escaping) {
escaping = false; escaping = false;
word += '\r'; word.append('\r');
continue; continue;
} }
if(c == '"') { if(c == '"') {
@ -1133,23 +1225,23 @@ public class ISBPL {
continue; continue;
} }
} }
word += c; word.append(c);
if(escaping) if(escaping)
throw new RuntimeException("Error parsing code: Invalid Escape."); throw new RuntimeException("Error parsing code: Invalid Escape.");
} }
else if(c == '"' && word.length() == 0) { else if(c == '"' && word.length() == 0) {
word += '"'; word.append('"');
isInString = true; isInString = true;
} }
else if(c == ' ') { else if(c == ' ') {
words.add(word); words.add(word.toString());
word = ""; word = new StringBuilder();
} }
else { else {
word += c; word.append(c);
} }
} }
words.add(word); words.add(word.toString());
return words.toArray(new String[0]); return words.toArray(new String[0]);
} }
@ -1203,6 +1295,7 @@ public class ISBPL {
} }
return bytes.toString(); return bytes.toString();
} }
} }
interface ISBPLKeyword { interface ISBPLKeyword {
@ -1223,7 +1316,7 @@ class ISBPLType {
public ISBPLType(String name) { public ISBPLType(String name) {
this.name = name; this.name = name;
} }
public HashMap<Object, ISBPLObject> varget(ISBPLObject o) { public HashMap<Object, ISBPLObject> varget(ISBPLObject o) {
if(!vars.containsKey(o)) { if(!vars.containsKey(o)) {
vars.put(o, new HashMap<>()); vars.put(o, new HashMap<>());
@ -1255,7 +1348,7 @@ class ISBPLType {
class ISBPLObject { class ISBPLObject {
final ISBPLType type; final ISBPLType type;
final Object object; Object object;
public ISBPLObject(ISBPLType type, Object object) { public ISBPLObject(ISBPLType type, Object object) {
this.type = type; this.type = type;
@ -1294,11 +1387,11 @@ class ISBPLObject {
} }
} }
public int checkTypeMulti(ISBPLType... wanted) { public void checkTypeMulti(ISBPLType... wanted) {
int f = -1; int f = -1;
String wantedNames = ""; StringBuilder wantedNames = new StringBuilder();
for (int i = 0 ; i < wanted.length ; i++) { for (int i = 0 ; i < wanted.length ; i++) {
wantedNames += " " + wanted[i].name; wantedNames.append(" ").append(wanted[i].name);
if(wanted[i].id == type.id) { if(wanted[i].id == type.id) {
f = i; f = i;
break; break;
@ -1307,7 +1400,6 @@ class ISBPLObject {
if(f == -1) { if(f == -1) {
throw new ISBPLError("IncompatibleTypes", "Incompatible types: " + type.name + " - " + wantedNames.substring(1)); throw new ISBPLError("IncompatibleTypes", "Incompatible types: " + type.name + " - " + wantedNames.substring(1));
} }
return f;
} }
@Override @Override
@ -1414,7 +1506,7 @@ class ISBPLStop extends RuntimeException {
} }
class ISBPLDebugger extends Thread { class ISBPLDebugger extends Thread {
private ISBPL isbpl; private final ISBPL isbpl;
int port = -1; int port = -1;
long mainID = Thread.currentThread().getId(); long mainID = Thread.currentThread().getId();
@ -1542,9 +1634,15 @@ class ISBPLDebugger extends Thread {
break; break;
case "son": case "son":
ISBPL.debug = true; ISBPL.debug = true;
ISBPL.printCalls = true;
break;
case "sonf":
ISBPL.debug = false;
ISBPL.printCalls = true;
break; break;
case "soff": case "soff":
ISBPL.debug = false; ISBPL.debug = false;
ISBPL.printCalls = false;
break; break;
case "exit": case "exit":
System.exit(255); System.exit(255);
@ -1612,7 +1710,9 @@ class ISBPLStreamer {
public static final int CLOSE = 3; public static final int CLOSE = 3;
public static final int READ = 4; public static final int READ = 4;
public static final int WRITE = 5; public static final int WRITE = 5;
@SuppressWarnings("unused")
public static final int AREAD = 6; public static final int AREAD = 6;
@SuppressWarnings("unused")
public static final int AWRITE = 7; public static final int AWRITE = 7;
public static final int CREATE_SERVER = 9; public static final int CREATE_SERVER = 9;
@ -1652,7 +1752,7 @@ class ISBPLStreamer {
f = new File(isbpl.toJavaString(s)); f = new File(isbpl.toJavaString(s));
stream = new ISBPLStream(new FileInputStream(f), new OutputStream() { stream = new ISBPLStream(new FileInputStream(f), new OutputStream() {
@Override @Override
public void write(int b) throws IOException { public void write(int b) {
throw new ISBPLError("IllegalArgument", "Can't write to a FILE_IN stream!"); throw new ISBPLError("IllegalArgument", "Can't write to a FILE_IN stream!");
} }
}); });
@ -1665,7 +1765,7 @@ class ISBPLStreamer {
f = new File(isbpl.toJavaString(s)); f = new File(isbpl.toJavaString(s));
stream = new ISBPLStream(new InputStream() { stream = new ISBPLStream(new InputStream() {
@Override @Override
public int read() throws IOException { public int read() {
throw new ISBPLError("IllegalArgument", "Can't read a FILE_OUT stream!"); throw new ISBPLError("IllegalArgument", "Can't read a FILE_OUT stream!");
} }
}, new FileOutputStream(f)); }, new FileOutputStream(f));
@ -1695,7 +1795,7 @@ class ISBPLStreamer {
} }
}, new OutputStream() { }, new OutputStream() {
@Override @Override
public void write(int b) throws IOException { public void write(int b) {
throw new ISBPLError("IllegalArgument", "Can't write to a SERVER stream!"); throw new ISBPLError("IllegalArgument", "Can't write to a SERVER stream!");
} }
}); });
@ -1757,7 +1857,7 @@ class ISBPLThreadLocal<T> {
return map.get(tid); return map.get(tid);
} }
public T set(T t) { public void set(T t) {
return map.put(Thread.currentThread().getId(), t); map.put(Thread.currentThread().getId(), t);
} }
} }

View file

@ -86,6 +86,14 @@ def TYPE_DOUBLE "double" mktype =TYPE_DOUBLE
def TYPE_FUNCTION "func" mktype =TYPE_FUNCTION def TYPE_FUNCTION "func" mktype =TYPE_FUNCTION
def TYPE_ARRAY "array" mktype =TYPE_ARRAY def TYPE_ARRAY "array" mktype =TYPE_ARRAY
def TYPE_JIO "jio" mktype =TYPE_JIO
"class" {
pop
native jio.class
jio.class
} TYPE_JIO defmethod
def JIO 0 TYPE_JIO settype =JIO
def TYPE_STRING "string" mktype =TYPE_STRING def TYPE_STRING "string" mktype =TYPE_STRING
func _string { func _string {
def object =object def object =object

View file

@ -21,10 +21,19 @@ func stream.readline {
def array 0 anew =array def array 0 anew =array
def tmparray 0 anew =tmparray def tmparray 0 anew =tmparray
def i 1 neg =i def i 1 neg =i
id STREAM.read stream =byte
byte -1 eq if {
-1
2 stop
}
while { ( i 1 + =i ) ( byte 10 eq not ) } { while { ( i 1 + =i ) ( byte 10 eq not ) } {
id STREAM.read stream =byte
array ( ( array alen 1 + anew ) dup =tmparray ) 0 0 ( array alen ) acopy =array array ( ( array alen 1 + anew ) dup =tmparray ) 0 0 ( array alen ) acopy =array
array dup alen 1 - byte _char aput array dup alen 1 - byte _char aput
id STREAM.read stream =byte
}
array alen 0 eq if {
array _string
2 stop
} }
array ( ( array alen 1 - anew ) dup =tmparray 0 0 ) ( tmparray alen ) acopy _string array ( ( array alen 1 - anew ) dup =tmparray 0 0 ) ( tmparray alen ) acopy _string
} }