Skip to content

Commit bf9ef4d

Browse files
committed
Debugger and stream compiler
1 parent 03c4eed commit bf9ef4d

File tree

9 files changed

+198
-40
lines changed

9 files changed

+198
-40
lines changed

pom.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>org.byteskript</groupId>
88
<artifactId>byteskript</artifactId>
9-
<version>1.0.15</version>
9+
<version>1.0.16</version>
1010
<name>ByteSkript</name>
1111
<description>A compiled JVM implementation of the Skript language.</description>
1212

@@ -89,6 +89,12 @@
8989
<version>5.0.3</version>
9090
<scope>compile</scope>
9191
</dependency>
92+
<dependency>
93+
<groupId>mx.kenzie</groupId>
94+
<artifactId>jupiter</artifactId>
95+
<version>1.0.0</version>
96+
<scope>compile</scope>
97+
</dependency>
9298
<dependency>
9399
<groupId>mx.kenzie</groupId>
94100
<artifactId>autodocs</artifactId>

src/main/java/org/byteskript/skript/app/ByteSkriptApp.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ public static void main(String... args) throws Throwable {
8585
}
8686
new SimpleThrottleController(SKRIPT).run();
8787
} else if (args[0].equalsIgnoreCase("debug")) {
88-
System.out.println(RESET + "This function is currently unavailable." + RESET);
88+
System.out.println(RESET + "Generating a debug report of your current scripts." + RESET);
89+
ScriptDebugger.main();
90+
System.out.println(RESET + "This has been stored in " + CYAN + CYAN_UNDERLINED + "debug.txt" + RESET + ".");
8991
}
9092
}
9193

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright (c) 2022 ByteSkript org (Moderocky)
3+
* View the full licence information and permissions:
4+
* https://github.com/Moderocky/ByteSkript/blob/master/LICENSE
5+
*/
6+
7+
package org.byteskript.skript.app;
8+
9+
import mx.kenzie.jupiter.stream.Stream;
10+
import org.byteskript.skript.compiler.DebugSkriptCompiler;
11+
import org.byteskript.skript.runtime.Skript;
12+
13+
import java.io.File;
14+
import java.io.FileOutputStream;
15+
import java.io.IOException;
16+
17+
public class ScriptDebugger extends SkriptApp {
18+
19+
public static void main(String... args) throws IOException {
20+
final File file = new File(ROOT, "debug.txt");
21+
try (final FileOutputStream stream = new FileOutputStream(file)) {
22+
final Skript skript = new Skript(new DebugSkriptCompiler(Stream.controller(stream)));
23+
registerLibraries(skript);
24+
skript.compileScripts(SOURCE);
25+
}
26+
}
27+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (c) 2022 ByteSkript org (Moderocky)
3+
* View the full licence information and permissions:
4+
* https://github.com/Moderocky/ByteSkript/blob/master/LICENSE
5+
*/
6+
7+
package org.byteskript.skript.compiler;
8+
9+
import mx.kenzie.foundation.Type;
10+
import mx.kenzie.foundation.language.PostCompileClass;
11+
import mx.kenzie.jupiter.stream.OutputStreamController;
12+
import org.byteskript.skript.api.Library;
13+
14+
import java.io.IOException;
15+
import java.io.InputStream;
16+
import java.util.function.Consumer;
17+
18+
public class DebugSkriptCompiler extends SimpleSkriptCompiler {
19+
final OutputStreamController controller;
20+
21+
public DebugSkriptCompiler(OutputStreamController controller, Library... libraries) {
22+
super(libraries);
23+
this.controller = controller;
24+
}
25+
26+
@Override
27+
protected void compileLine(String line, FileContext context) {
28+
final ElementTree tree = this.parseLine(line, context);
29+
if (tree == null) return;
30+
this.debug(tree, context);
31+
tree.preCompile(context);
32+
tree.compile(context);
33+
for (final Consumer<Context> consumer : context.endOfLine) consumer.accept(context);
34+
context.endOfLine.clear();
35+
context.currentEffect = null;
36+
context.sectionHeader = false;
37+
}
38+
39+
@Override
40+
public PostCompileClass[] compile(InputStream stream, Type path) {
41+
try {
42+
this.controller.write("\n\n");
43+
this.controller.write("--" + path.internalName());
44+
this.controller.write("\n");
45+
} catch (IOException ignored) {}
46+
return super.compile(stream, path);
47+
}
48+
49+
@Override
50+
public PostCompileClass[] compile(String source, Type path) {
51+
try {
52+
this.controller.write("\n\n");
53+
this.controller.write("--" + path.internalName());
54+
this.controller.write("\n");
55+
} catch (IOException ignored) {}
56+
return super.compile(source, path);
57+
}
58+
59+
protected void debug(ElementTree tree, FileContext context) {
60+
try {
61+
this.controller.write("\n");
62+
for (int i = 0; i < context.lineIndent; i++) {
63+
this.controller.write("\t");
64+
}
65+
this.controller.write(tree.toString());
66+
this.controller.write(";");
67+
} catch (IOException ignored) {}
68+
}
69+
70+
}

src/main/java/org/byteskript/skript/compiler/ElementTree.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
import mx.kenzie.foundation.Type;
1010
import org.byteskript.skript.api.HandlerType;
1111
import org.byteskript.skript.api.SyntaxElement;
12+
import org.byteskript.skript.api.syntax.Literal;
1213
import org.byteskript.skript.api.syntax.Section;
1314
import org.byteskript.skript.error.ScriptCompileError;
1415
import org.byteskript.skript.lang.handler.StandardHandlers;
16+
import org.byteskript.skript.lang.syntax.variable.VariableExpression;
1517

1618
import java.util.*;
1719

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

150152
@Override
151153
public String toString() {
152-
return "ElementTree{" +
153-
"current=" + current.name() +
154-
", nested=" + Arrays.toString(nested) +
155-
", compile=" + compile +
156-
'}';
154+
final StringBuilder builder = new StringBuilder();
155+
builder.append(current.getClass().getSimpleName());
156+
builder.append('(');
157+
if (current instanceof Literal<?>) {
158+
builder.append(match.matcher().group());
159+
} else if (current instanceof VariableExpression) {
160+
builder.append(match.matcher().group("name"));
161+
} else {
162+
boolean comma = false;
163+
for (final ElementTree tree : nested) {
164+
if (comma) builder.append(',');
165+
builder.append(tree.toString());
166+
comma = true;
167+
}
168+
}
169+
builder.append(')');
170+
return builder.toString();
157171
}
158172
}

src/main/java/org/byteskript/skript/compiler/FileContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public class FileContext extends Context {
3333
final Map<HandlerType, List<PropertyAccessGenerator>> usedProperties = new HashMap<>();
3434
final List<ClassBuilder> suppressedClasses = new ArrayList<>();
3535
final List<Flag> flags = new ArrayList<>();
36-
public int indent, lineNumber, lambdaIndex, indexShift;
36+
public int indent, lineIndent, lineNumber, lambdaIndex, indexShift;
3737
public boolean sectionHeader;
3838
public ElementTree line;
3939
public ElementTree current;

src/main/java/org/byteskript/skript/compiler/SimpleSkriptCompiler.java

Lines changed: 66 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import mx.kenzie.foundation.Type;
1010
import mx.kenzie.foundation.WriteInstruction;
1111
import mx.kenzie.foundation.language.PostCompileClass;
12+
import mx.kenzie.jupiter.stream.Stream;
1213
import org.byteskript.skript.api.Library;
1314
import org.byteskript.skript.api.SyntaxElement;
1415
import org.byteskript.skript.api.syntax.InnerModifyExpression;
@@ -24,13 +25,15 @@
2425
import java.nio.charset.StandardCharsets;
2526
import java.util.ArrayList;
2627
import java.util.List;
28+
import java.util.concurrent.atomic.AtomicBoolean;
2729
import java.util.function.Consumer;
2830
import java.util.regex.Matcher;
2931

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

3538
public SimpleSkriptCompiler(final Library... libraries) {
3639
this.libraries.addAll(List.of(libraries));
@@ -80,21 +83,20 @@ private String unstream(InputStream stream) {
8083
protected List<String> removeComments(final String string) {
8184
final List<String> original = string.lines().toList(); // stream of sadness :(
8285
final List<String> lines = new ArrayList<>();
83-
final String regex = "\\s+$";
84-
boolean inComment = false;
86+
boolean comment = false;
8587
for (final String old : original) {
8688
String line = old;
87-
if (inComment) {
89+
if (comment) {
8890
if (line.contains("*/")) {
8991
line = line.substring(line.indexOf("*/") + 2); // keep last part of line
90-
inComment = false;
92+
comment = false;
9193
} else {
9294
line = ""; // inside a commented block
9395
}
9496
} else {
9597
if (line.contains("//")) line = line.substring(0, line.indexOf("//")); // keep first part of line
9698
if (line.contains("/*")) {
97-
inComment = true;
99+
comment = true;
98100
line = line.substring(0, line.indexOf("/*")); // first part of line not in comment
99101
}
100102
}
@@ -104,19 +106,35 @@ protected List<String> removeComments(final String string) {
104106
return lines;
105107
}
106108

109+
protected String stripLine(final String old, AtomicBoolean comment) {
110+
String line = old;
111+
if (comment.get()) {
112+
if (line.contains("*/")) {
113+
line = line.substring(line.indexOf("*/") + 2); // keep last part of line
114+
comment.set(false);
115+
} else line = ""; // inside a commented block
116+
} else {
117+
if (line.contains("//")) line = line.substring(0, line.indexOf("//")); // keep first part of line
118+
if (line.contains("/*")) {
119+
comment.set(true);
120+
line = line.substring(0, line.indexOf("/*")); // first part of line not in comment
121+
}
122+
}
123+
return line.replaceAll(regex, ""); // trim trailing whitespace
124+
125+
}
126+
107127
@Override
108128
public Library[] getLibraries() {
109129
return libraries.toArray(new Library[0]);
110130
}
111131

112132
protected void compileLine(final String line, final FileContext context) {
113-
final ElementTree tree = parseLine(line, context);
133+
final ElementTree tree = this.parseLine(line, context);
114134
if (tree == null) return;
115135
tree.preCompile(context);
116136
tree.compile(context);
117-
for (Consumer<Context> consumer : context.endOfLine) {
118-
consumer.accept(context);
119-
}
137+
for (final Consumer<Context> consumer : context.endOfLine) consumer.accept(context);
120138
context.endOfLine.clear();
121139
context.currentEffect = null;
122140
context.sectionHeader = false;
@@ -177,6 +195,7 @@ public ElementTree parseLine(final String line, final FileContext context) {
177195
context.setIndentUnit(unit);
178196
}
179197
final int actual = this.trueIndent(line, context.indentUnit());
198+
context.lineIndent = actual;
180199
if (actual < expected) {
181200
for (int i = 0; i < (expected - actual); i++) {
182201
context.destroySection();
@@ -280,36 +299,45 @@ public boolean removeLibrary(Library library) {
280299
}
281300

282301
@Override
283-
public PostCompileClass[] compile(InputStream stream, Type name) {
284-
return compile(unstream(stream), name);
302+
public PostCompileClass[] compile(InputStream stream, Type path) {
303+
final FileContext context = new FileContext(path);
304+
context.libraries.addAll(libraries);
305+
for (final Library library : libraries) {
306+
for (final Type type : library.getTypes()) context.registerType(type);
307+
}
308+
final AtomicBoolean comment = new AtomicBoolean(false);
309+
for (final String line : Stream.controller(stream).lines()) {
310+
context.lineNumber++;
311+
context.line = null;
312+
final String stripped = this.stripLine(line, comment);
313+
if (stripped.isBlank()) continue;
314+
this.compileLine(context, stripped);
315+
}
316+
context.destroyUnits();
317+
context.destroySections();
318+
return context.compile();
285319
}
286320

321+
@Override
287322
public PostCompileClass[] compile(InputStream source, String path) {
288323
if (path == null) return this.compile(source);
289-
return compile(unstream(source), new Type(path));
324+
return compile(source, new Type(path));
290325
}
291326

327+
@Override
292328
public PostCompileClass[] compile(String source, Type path) {
293329
final FileContext context = new FileContext(path);
294330
context.libraries.addAll(libraries);
295331
for (final Library library : libraries) {
296332
for (final Type type : library.getTypes()) context.registerType(type);
297333
}
298-
final List<String> lines = this.removeComments(source);
299-
for (final String line : lines) {
334+
final AtomicBoolean comment = new AtomicBoolean(false);
335+
for (final String line : source.lines().toList()) {
300336
context.lineNumber++;
301337
context.line = null;
302-
if (line.isBlank()) continue;
303-
if (context.getMethod() != null) {
304-
context.getMethod().writeCode(WriteInstruction.lineNumber(context.lineNumber));
305-
}
306-
try {
307-
this.compileLine(line, context);
308-
} catch (ScriptParseError | ScriptCompileError ex) {
309-
throw ex;
310-
} catch (Throwable ex) {
311-
throw new ScriptCompileError(context.lineNumber, "Unknown error during compilation:", ex);
312-
}
338+
final String stripped = this.stripLine(line, comment);
339+
if (stripped.isBlank()) continue;
340+
this.compileLine(context, stripped);
313341
}
314342
context.destroyUnits();
315343
context.destroySections();
@@ -324,6 +352,19 @@ public SimpleSkriptCompiler clone() {
324352
return compiler;
325353
}
326354

355+
private void compileLine(FileContext context, String stripped) {
356+
if (context.getMethod() != null) {
357+
context.getMethod().writeCode(WriteInstruction.lineNumber(context.lineNumber));
358+
}
359+
try {
360+
this.compileLine(stripped, context);
361+
} catch (ScriptParseError | ScriptCompileError ex) {
362+
throw ex;
363+
} catch (Throwable ex) {
364+
throw new ScriptCompileError(context.lineNumber, "Unknown error during compilation:", ex);
365+
}
366+
}
367+
327368
int trueIndent(final String line, final String unit) {
328369
if (unit == null) return 0;
329370
int indent = 0, offset = 0;

src/main/java/org/byteskript/skript/runtime/Skript.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,7 @@ public Skript() {
131131
@ThreadSpecific
132132
public static RuntimeClassLoader localLoader() {
133133
final Thread current = Thread.currentThread();
134-
if (!(current instanceof ScriptThread thread))
135-
throw new ScriptRuntimeError("Not running on a script thread.");
134+
if (!(current instanceof ScriptThread thread)) throw new ScriptRuntimeError("Not running on a script thread.");
136135
return thread.skript.parent;
137136
}
138137

@@ -183,8 +182,7 @@ public static GlobalVariableMap getVariables() {
183182
@ThreadSpecific
184183
public static Skript localInstance() {
185184
final Thread current = Thread.currentThread();
186-
if (!(current instanceof ScriptThread thread))
187-
throw new ScriptRuntimeError("Not running on a script thread.");
185+
if (!(current instanceof ScriptThread thread)) throw new ScriptRuntimeError("Not running on a script thread.");
188186
return thread.skript;
189187
}
190188

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

444-
private static String getClassName(InputStream is)
442+
private static String getClassName(InputStream input)
445443
throws IOException {
446-
final DataInputStream stream = new DataInputStream(is);
444+
final DataInputStream stream = new DataInputStream(input);
447445
stream.readLong();
448446
final int paths = (stream.readShort() & 0xffff) - 1;
449447
final int[] classes = new int[paths];

0 commit comments

Comments
 (0)