From 6d29b9d8d42fc795503b683022fee56241e15af5 Mon Sep 17 00:00:00 2001 From: TudbuT Date: Sat, 16 Apr 2022 18:44:07 +0200 Subject: [PATCH] JIO --- bootstrap/ISBPL.java | 176 +++++++++++++++++++++++++++++++++---------- std.isbpl | 8 ++ stream.isbpl | 11 ++- 3 files changed, 156 insertions(+), 39 deletions(-) diff --git a/bootstrap/ISBPL.java b/bootstrap/ISBPL.java index cbf8048..5553261 100644 --- a/bootstrap/ISBPL.java +++ b/bootstrap/ISBPL.java @@ -1,4 +1,5 @@ import java.io.*; +import java.lang.reflect.*; import java.net.BindException; import java.net.ServerSocket; import java.net.Socket; @@ -17,9 +18,9 @@ import java.util.function.Supplier; public class ISBPL { // TODO: fully implement JIO // public static final boolean ENABLE_JINTEROP = true; - - - static boolean debug = false; + + + static boolean debug = false, printCalls = false; public ISBPLDebugger.IPC debuggerIPC = new ISBPLDebugger.IPC(); ArrayList types = new ArrayList<>(); final ISBPLThreadLocal>> functionStack = ISBPLThreadLocal.withInitial(Stack::new); @@ -131,7 +132,7 @@ public class ISBPL { } return i.get(); }; - case "{": + case "{": return (idx, words, file, stack) -> { AtomicInteger i = new AtomicInteger(idx); ISBPLCallable block = readBlock(i, words, file, false); @@ -167,7 +168,7 @@ public class ISBPL { @SuppressWarnings("RedundantCast") private void addNative(String name) { - ISBPLCallable func = null; + ISBPLCallable func; switch (name) { case "alen": func = (Stack stack) -> { @@ -474,9 +475,7 @@ public class ISBPL { }; break; case "not": - func = (Stack stack) -> { - stack.push(new ISBPLObject(getType("int"), stack.pop().isTruthy() ? 0 : 1)); - }; + func = (Stack stack) -> stack.push(new ISBPLObject(getType("int"), stack.pop().isTruthy() ? 0 : 1)); break; case "neg": func = (Stack stack) -> { @@ -751,7 +750,7 @@ public class ISBPL { }; break; case "pop": - func = (Stack stack) -> stack.pop(); + func = Stack::pop; break; case "swap": func = (Stack stack) -> { @@ -830,9 +829,7 @@ public class ISBPL { }; break; case "stacksize": - func = (Stack stack) -> { - stack.push(new ISBPLObject(getType("int"), stack.size())); - }; + func = (Stack stack) -> stack.push(new ISBPLObject(getType("int"), stack.size())); break; case "fcall": func = (Stack stack) -> { @@ -883,13 +880,108 @@ public class ISBPL { addFunction(t, "=" + s, (stack1) -> t.varget(stack1.pop()).put(var, stack1.pop())); }; 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: func = natives.get(name); break; } 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) { type.methods.put(name, callable); type.methods.put("&" + name, stack -> stack.push(new ISBPLObject(getType("func"), callable))); @@ -1016,12 +1108,12 @@ public class ISBPL { String word = words[i]; if (word.length() == 0) continue; - if(debug) { - String s = ""; + if(printCalls) { + StringBuilder s = new StringBuilder(); 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); if(debuggerIPC.run.get(Thread.currentThread().getId()) < 0) { @@ -1105,7 +1197,7 @@ public class ISBPL { char[] chars = code.toCharArray(); boolean isInString = false; boolean escaping = false; - String word = ""; + StringBuilder word = new StringBuilder(); for (int i = 0 ; i < chars.length ; i++) { char c = chars[i]; if(isInString) { @@ -1115,13 +1207,13 @@ public class ISBPL { continue; } if(c == 'n' && escaping) { - word += '\n'; + word.append('\n'); escaping = false; continue; } if(c == 'r' && escaping) { escaping = false; - word += '\r'; + word.append('\r'); continue; } if(c == '"') { @@ -1133,23 +1225,23 @@ public class ISBPL { continue; } } - word += c; + word.append(c); if(escaping) throw new RuntimeException("Error parsing code: Invalid Escape."); } else if(c == '"' && word.length() == 0) { - word += '"'; + word.append('"'); isInString = true; } else if(c == ' ') { - words.add(word); - word = ""; + words.add(word.toString()); + word = new StringBuilder(); } else { - word += c; + word.append(c); } } - words.add(word); + words.add(word.toString()); return words.toArray(new String[0]); } @@ -1203,6 +1295,7 @@ public class ISBPL { } return bytes.toString(); } + } interface ISBPLKeyword { @@ -1223,7 +1316,7 @@ class ISBPLType { public ISBPLType(String name) { this.name = name; } - + public HashMap varget(ISBPLObject o) { if(!vars.containsKey(o)) { vars.put(o, new HashMap<>()); @@ -1255,7 +1348,7 @@ class ISBPLType { class ISBPLObject { final ISBPLType type; - final Object object; + Object object; public ISBPLObject(ISBPLType type, Object object) { this.type = type; @@ -1294,11 +1387,11 @@ class ISBPLObject { } } - public int checkTypeMulti(ISBPLType... wanted) { + public void checkTypeMulti(ISBPLType... wanted) { int f = -1; - String wantedNames = ""; + StringBuilder wantedNames = new StringBuilder(); for (int i = 0 ; i < wanted.length ; i++) { - wantedNames += " " + wanted[i].name; + wantedNames.append(" ").append(wanted[i].name); if(wanted[i].id == type.id) { f = i; break; @@ -1307,7 +1400,6 @@ class ISBPLObject { if(f == -1) { throw new ISBPLError("IncompatibleTypes", "Incompatible types: " + type.name + " - " + wantedNames.substring(1)); } - return f; } @Override @@ -1414,7 +1506,7 @@ class ISBPLStop extends RuntimeException { } class ISBPLDebugger extends Thread { - private ISBPL isbpl; + private final ISBPL isbpl; int port = -1; long mainID = Thread.currentThread().getId(); @@ -1542,9 +1634,15 @@ class ISBPLDebugger extends Thread { break; case "son": ISBPL.debug = true; + ISBPL.printCalls = true; + break; + case "sonf": + ISBPL.debug = false; + ISBPL.printCalls = true; break; case "soff": ISBPL.debug = false; + ISBPL.printCalls = false; break; case "exit": System.exit(255); @@ -1612,7 +1710,9 @@ class ISBPLStreamer { public static final int CLOSE = 3; public static final int READ = 4; public static final int WRITE = 5; + @SuppressWarnings("unused") public static final int AREAD = 6; + @SuppressWarnings("unused") public static final int AWRITE = 7; public static final int CREATE_SERVER = 9; @@ -1652,7 +1752,7 @@ class ISBPLStreamer { f = new File(isbpl.toJavaString(s)); stream = new ISBPLStream(new FileInputStream(f), new OutputStream() { @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!"); } }); @@ -1665,7 +1765,7 @@ class ISBPLStreamer { f = new File(isbpl.toJavaString(s)); stream = new ISBPLStream(new InputStream() { @Override - public int read() throws IOException { + public int read() { throw new ISBPLError("IllegalArgument", "Can't read a FILE_OUT stream!"); } }, new FileOutputStream(f)); @@ -1695,7 +1795,7 @@ class ISBPLStreamer { } }, new OutputStream() { @Override - public void write(int b) throws IOException { + public void write(int b) { throw new ISBPLError("IllegalArgument", "Can't write to a SERVER stream!"); } }); @@ -1757,7 +1857,7 @@ class ISBPLThreadLocal { return map.get(tid); } - public T set(T t) { - return map.put(Thread.currentThread().getId(), t); + public void set(T t) { + map.put(Thread.currentThread().getId(), t); } } diff --git a/std.isbpl b/std.isbpl index 72aa6c2..44bd6fc 100644 --- a/std.isbpl +++ b/std.isbpl @@ -86,6 +86,14 @@ def TYPE_DOUBLE "double" mktype =TYPE_DOUBLE def TYPE_FUNCTION "func" mktype =TYPE_FUNCTION 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 func _string { def object =object diff --git a/stream.isbpl b/stream.isbpl index 5d7194f..66cba06 100644 --- a/stream.isbpl +++ b/stream.isbpl @@ -21,10 +21,19 @@ func stream.readline { def array 0 anew =array def tmparray 0 anew =tmparray 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 ) } { - id STREAM.read stream =byte array ( ( array alen 1 + anew ) dup =tmparray ) 0 0 ( array alen ) acopy =array 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 }