Skip to content

Commit

Permalink
Debugger and stream compiler
Browse files Browse the repository at this point in the history
  • Loading branch information
Moderocky committed Jan 31, 2022
1 parent 03c4eed commit bf9ef4d
Show file tree
Hide file tree
Showing 9 changed files with 198 additions and 40 deletions.
8 changes: 7 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>org.byteskript</groupId>
<artifactId>byteskript</artifactId>
<version>1.0.15</version>
<version>1.0.16</version>
<name>ByteSkript</name>
<description>A compiled JVM implementation of the Skript language.</description>

Expand Down Expand Up @@ -89,6 +89,12 @@
<version>5.0.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>mx.kenzie</groupId>
<artifactId>jupiter</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>mx.kenzie</groupId>
<artifactId>autodocs</artifactId>
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/org/byteskript/skript/app/ByteSkriptApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ public static void main(String... args) throws Throwable {
}
new SimpleThrottleController(SKRIPT).run();
} else if (args[0].equalsIgnoreCase("debug")) {
System.out.println(RESET + "This function is currently unavailable." + RESET);
System.out.println(RESET + "Generating a debug report of your current scripts." + RESET);
ScriptDebugger.main();
System.out.println(RESET + "This has been stored in " + CYAN + CYAN_UNDERLINED + "debug.txt" + RESET + ".");
}
}

Expand Down
27 changes: 27 additions & 0 deletions src/main/java/org/byteskript/skript/app/ScriptDebugger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2022 ByteSkript org (Moderocky)
* View the full licence information and permissions:
* https://github.com/Moderocky/ByteSkript/blob/master/LICENSE
*/

package org.byteskript.skript.app;

import mx.kenzie.jupiter.stream.Stream;
import org.byteskript.skript.compiler.DebugSkriptCompiler;
import org.byteskript.skript.runtime.Skript;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class ScriptDebugger extends SkriptApp {

public static void main(String... args) throws IOException {
final File file = new File(ROOT, "debug.txt");
try (final FileOutputStream stream = new FileOutputStream(file)) {
final Skript skript = new Skript(new DebugSkriptCompiler(Stream.controller(stream)));
registerLibraries(skript);
skript.compileScripts(SOURCE);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2022 ByteSkript org (Moderocky)
* View the full licence information and permissions:
* https://github.com/Moderocky/ByteSkript/blob/master/LICENSE
*/

package org.byteskript.skript.compiler;

import mx.kenzie.foundation.Type;
import mx.kenzie.foundation.language.PostCompileClass;
import mx.kenzie.jupiter.stream.OutputStreamController;
import org.byteskript.skript.api.Library;

import java.io.IOException;
import java.io.InputStream;
import java.util.function.Consumer;

public class DebugSkriptCompiler extends SimpleSkriptCompiler {
final OutputStreamController controller;

public DebugSkriptCompiler(OutputStreamController controller, Library... libraries) {
super(libraries);
this.controller = controller;
}

@Override
protected void compileLine(String line, FileContext context) {
final ElementTree tree = this.parseLine(line, context);
if (tree == null) return;
this.debug(tree, context);
tree.preCompile(context);
tree.compile(context);
for (final Consumer<Context> consumer : context.endOfLine) consumer.accept(context);
context.endOfLine.clear();
context.currentEffect = null;
context.sectionHeader = false;
}

@Override
public PostCompileClass[] compile(InputStream stream, Type path) {
try {
this.controller.write("\n\n");
this.controller.write("--" + path.internalName());
this.controller.write("\n");
} catch (IOException ignored) {}
return super.compile(stream, path);
}

@Override
public PostCompileClass[] compile(String source, Type path) {
try {
this.controller.write("\n\n");
this.controller.write("--" + path.internalName());
this.controller.write("\n");
} catch (IOException ignored) {}
return super.compile(source, path);
}

protected void debug(ElementTree tree, FileContext context) {
try {
this.controller.write("\n");
for (int i = 0; i < context.lineIndent; i++) {
this.controller.write("\t");
}
this.controller.write(tree.toString());
this.controller.write(";");
} catch (IOException ignored) {}
}

}
24 changes: 19 additions & 5 deletions src/main/java/org/byteskript/skript/compiler/ElementTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import mx.kenzie.foundation.Type;
import org.byteskript.skript.api.HandlerType;
import org.byteskript.skript.api.SyntaxElement;
import org.byteskript.skript.api.syntax.Literal;
import org.byteskript.skript.api.syntax.Section;
import org.byteskript.skript.error.ScriptCompileError;
import org.byteskript.skript.lang.handler.StandardHandlers;
import org.byteskript.skript.lang.syntax.variable.VariableExpression;

import java.util.*;

Expand Down Expand Up @@ -149,10 +151,22 @@ public boolean equals(Object obj) {

@Override
public String toString() {
return "ElementTree{" +
"current=" + current.name() +
", nested=" + Arrays.toString(nested) +
", compile=" + compile +
'}';
final StringBuilder builder = new StringBuilder();
builder.append(current.getClass().getSimpleName());
builder.append('(');
if (current instanceof Literal<?>) {
builder.append(match.matcher().group());
} else if (current instanceof VariableExpression) {
builder.append(match.matcher().group("name"));
} else {
boolean comma = false;
for (final ElementTree tree : nested) {
if (comma) builder.append(',');
builder.append(tree.toString());
comma = true;
}
}
builder.append(')');
return builder.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class FileContext extends Context {
final Map<HandlerType, List<PropertyAccessGenerator>> usedProperties = new HashMap<>();
final List<ClassBuilder> suppressedClasses = new ArrayList<>();
final List<Flag> flags = new ArrayList<>();
public int indent, lineNumber, lambdaIndex, indexShift;
public int indent, lineIndent, lineNumber, lambdaIndex, indexShift;
public boolean sectionHeader;
public ElementTree line;
public ElementTree current;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import mx.kenzie.foundation.Type;
import mx.kenzie.foundation.WriteInstruction;
import mx.kenzie.foundation.language.PostCompileClass;
import mx.kenzie.jupiter.stream.Stream;
import org.byteskript.skript.api.Library;
import org.byteskript.skript.api.SyntaxElement;
import org.byteskript.skript.api.syntax.InnerModifyExpression;
Expand All @@ -24,13 +25,15 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.regex.Matcher;

public class SimpleSkriptCompiler extends SkriptCompiler implements SkriptParser {
private static volatile int anonymous = 0;
protected final List<Library> libraries = new ArrayList<>();
protected final java.util.regex.Pattern whitespace = java.util.regex.Pattern.compile("(?<=^)[\\t ]+(?=\\S)");
private final String regex = "\\s+$";

public SimpleSkriptCompiler(final Library... libraries) {
this.libraries.addAll(List.of(libraries));
Expand Down Expand Up @@ -80,21 +83,20 @@ private String unstream(InputStream stream) {
protected List<String> removeComments(final String string) {
final List<String> original = string.lines().toList(); // stream of sadness :(
final List<String> lines = new ArrayList<>();
final String regex = "\\s+$";
boolean inComment = false;
boolean comment = false;
for (final String old : original) {
String line = old;
if (inComment) {
if (comment) {
if (line.contains("*/")) {
line = line.substring(line.indexOf("*/") + 2); // keep last part of line
inComment = false;
comment = false;
} else {
line = ""; // inside a commented block
}
} else {
if (line.contains("//")) line = line.substring(0, line.indexOf("//")); // keep first part of line
if (line.contains("/*")) {
inComment = true;
comment = true;
line = line.substring(0, line.indexOf("/*")); // first part of line not in comment
}
}
Expand All @@ -104,19 +106,35 @@ protected List<String> removeComments(final String string) {
return lines;
}

protected String stripLine(final String old, AtomicBoolean comment) {
String line = old;
if (comment.get()) {
if (line.contains("*/")) {
line = line.substring(line.indexOf("*/") + 2); // keep last part of line
comment.set(false);
} else line = ""; // inside a commented block
} else {
if (line.contains("//")) line = line.substring(0, line.indexOf("//")); // keep first part of line
if (line.contains("/*")) {
comment.set(true);
line = line.substring(0, line.indexOf("/*")); // first part of line not in comment
}
}
return line.replaceAll(regex, ""); // trim trailing whitespace

}

@Override
public Library[] getLibraries() {
return libraries.toArray(new Library[0]);
}

protected void compileLine(final String line, final FileContext context) {
final ElementTree tree = parseLine(line, context);
final ElementTree tree = this.parseLine(line, context);
if (tree == null) return;
tree.preCompile(context);
tree.compile(context);
for (Consumer<Context> consumer : context.endOfLine) {
consumer.accept(context);
}
for (final Consumer<Context> consumer : context.endOfLine) consumer.accept(context);
context.endOfLine.clear();
context.currentEffect = null;
context.sectionHeader = false;
Expand Down Expand Up @@ -177,6 +195,7 @@ public ElementTree parseLine(final String line, final FileContext context) {
context.setIndentUnit(unit);
}
final int actual = this.trueIndent(line, context.indentUnit());
context.lineIndent = actual;
if (actual < expected) {
for (int i = 0; i < (expected - actual); i++) {
context.destroySection();
Expand Down Expand Up @@ -280,36 +299,45 @@ public boolean removeLibrary(Library library) {
}

@Override
public PostCompileClass[] compile(InputStream stream, Type name) {
return compile(unstream(stream), name);
public PostCompileClass[] compile(InputStream stream, Type path) {
final FileContext context = new FileContext(path);
context.libraries.addAll(libraries);
for (final Library library : libraries) {
for (final Type type : library.getTypes()) context.registerType(type);
}
final AtomicBoolean comment = new AtomicBoolean(false);
for (final String line : Stream.controller(stream).lines()) {
context.lineNumber++;
context.line = null;
final String stripped = this.stripLine(line, comment);
if (stripped.isBlank()) continue;
this.compileLine(context, stripped);
}
context.destroyUnits();
context.destroySections();
return context.compile();
}

@Override
public PostCompileClass[] compile(InputStream source, String path) {
if (path == null) return this.compile(source);
return compile(unstream(source), new Type(path));
return compile(source, new Type(path));
}

@Override
public PostCompileClass[] compile(String source, Type path) {
final FileContext context = new FileContext(path);
context.libraries.addAll(libraries);
for (final Library library : libraries) {
for (final Type type : library.getTypes()) context.registerType(type);
}
final List<String> lines = this.removeComments(source);
for (final String line : lines) {
final AtomicBoolean comment = new AtomicBoolean(false);
for (final String line : source.lines().toList()) {
context.lineNumber++;
context.line = null;
if (line.isBlank()) continue;
if (context.getMethod() != null) {
context.getMethod().writeCode(WriteInstruction.lineNumber(context.lineNumber));
}
try {
this.compileLine(line, context);
} catch (ScriptParseError | ScriptCompileError ex) {
throw ex;
} catch (Throwable ex) {
throw new ScriptCompileError(context.lineNumber, "Unknown error during compilation:", ex);
}
final String stripped = this.stripLine(line, comment);
if (stripped.isBlank()) continue;
this.compileLine(context, stripped);
}
context.destroyUnits();
context.destroySections();
Expand All @@ -324,6 +352,19 @@ public SimpleSkriptCompiler clone() {
return compiler;
}

private void compileLine(FileContext context, String stripped) {
if (context.getMethod() != null) {
context.getMethod().writeCode(WriteInstruction.lineNumber(context.lineNumber));
}
try {
this.compileLine(stripped, context);
} catch (ScriptParseError | ScriptCompileError ex) {
throw ex;
} catch (Throwable ex) {
throw new ScriptCompileError(context.lineNumber, "Unknown error during compilation:", ex);
}
}

int trueIndent(final String line, final String unit) {
if (unit == null) return 0;
int indent = 0, offset = 0;
Expand Down
10 changes: 4 additions & 6 deletions src/main/java/org/byteskript/skript/runtime/Skript.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,7 @@ public Skript() {
@ThreadSpecific
public static RuntimeClassLoader localLoader() {
final Thread current = Thread.currentThread();
if (!(current instanceof ScriptThread thread))
throw new ScriptRuntimeError("Not running on a script thread.");
if (!(current instanceof ScriptThread thread)) throw new ScriptRuntimeError("Not running on a script thread.");
return thread.skript.parent;
}

Expand Down Expand Up @@ -183,8 +182,7 @@ public static GlobalVariableMap getVariables() {
@ThreadSpecific
public static Skript localInstance() {
final Thread current = Thread.currentThread();
if (!(current instanceof ScriptThread thread))
throw new ScriptRuntimeError("Not running on a script thread.");
if (!(current instanceof ScriptThread thread)) throw new ScriptRuntimeError("Not running on a script thread.");
return thread.skript;
}

Expand Down Expand Up @@ -441,9 +439,9 @@ public Class<?> defineClass(String name, byte[] bytes) {
compiler.addLibrary(library);
}

private static String getClassName(InputStream is)
private static String getClassName(InputStream input)
throws IOException {
final DataInputStream stream = new DataInputStream(is);
final DataInputStream stream = new DataInputStream(input);
stream.readLong();
final int paths = (stream.readShort() & 0xffff) - 1;
final int[] classes = new int[paths];
Expand Down
Loading

0 comments on commit bf9ef4d

Please sign in to comment.