JIO
This commit is contained in:
parent
07c0ddcff0
commit
6d29b9d8d4
3 changed files with 156 additions and 39 deletions
|
@ -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;
|
||||||
|
@ -19,7 +20,7 @@ public class ISBPL {
|
||||||
// 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);
|
||||||
|
@ -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,6 +880,18 @@ 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;
|
||||||
|
@ -890,6 +899,89 @@ public class ISBPL {
|
||||||
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 {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
11
stream.isbpl
11
stream.isbpl
|
@ -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
|
||||||
while { ( i 1 + =i ) ( byte 10 eq not ) } {
|
|
||||||
id STREAM.read stream =byte
|
id STREAM.read stream =byte
|
||||||
|
byte -1 eq if {
|
||||||
|
-1
|
||||||
|
2 stop
|
||||||
|
}
|
||||||
|
while { ( i 1 + =i ) ( byte 10 eq not ) } {
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue