Skip to content

Commit e0dfb05

Browse files
committed
Test mode and inline effect.
1 parent 5c673e4 commit e0dfb05

File tree

11 files changed

+217
-26
lines changed

11 files changed

+217
-26
lines changed

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

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import mx.kenzie.foundation.language.PostCompileClass;
1010
import org.byteskript.skript.runtime.Skript;
11+
import org.byteskript.skript.runtime.internal.ExtractedSyntaxCalls;
1112

1213
import java.io.File;
1314
import java.io.FileInputStream;
@@ -25,13 +26,17 @@ public static void main(String... args) throws Throwable {
2526
makeFiles();
2627
System.out.println(RESET + "Welcome to " + BRIGHT_PURPLE + "ByteSkript" + RESET + "!");
2728
System.out.println(RESET + "Available arguments:");
28-
System.out.println(RESET + "\trun | " + CYAN + "Run scripts in the " + CYAN_UNDERLINED + "skripts/" + CYAN + " directory.");
29-
System.out.println(RESET + "\trun <file> | " + CYAN + "Run a single script in isolation.");
30-
System.out.println(RESET + "\tcompile | " + CYAN + "Compile library class files for all scripts.");
31-
System.out.println(RESET + "\t | " + CYAN + "Syntax-providing classes can be moved to the " + CYAN_UNDERLINED + "libraries/" + CYAN + " folder.");
32-
System.out.println(RESET + "\tjar <name> | " + CYAN + "Build a Jar file in " + CYAN_UNDERLINED + "compiled/" + CYAN + " from all your scripts.");
33-
System.out.println(RESET + "\t | " + CYAN + "This will include files in " + CYAN_UNDERLINED + "resources/" + CYAN);
34-
System.out.println(RESET + "\tclean | " + CYAN + "Cleans the " + CYAN_UNDERLINED + "compiled/" + CYAN + " folder.");
29+
System.out.println(RESET + "\trun <file> | " + CYAN + "Run scripts in the " + CYAN_UNDERLINED + "skripts/" + CYAN + " directory.");
30+
System.out.println(RESET + "\t | " + CYAN + "If a file-arg is given, only this script will be run.");
31+
System.out.println(RESET + "\tcompile | " + CYAN + "Compile library class files for all scripts.");
32+
System.out.println(RESET + "\t | " + CYAN + "Syntax-providing classes can be moved to the " + CYAN_UNDERLINED + "libraries/" + CYAN + " folder.");
33+
System.out.println(RESET + "\tjar <name> | " + CYAN + "Build a Jar file in " + CYAN_UNDERLINED + "compiled/" + CYAN + " from all your scripts.");
34+
System.out.println(RESET + "\t | " + CYAN + "This will include files in " + CYAN_UNDERLINED + "resources/" + CYAN);
35+
System.out.println(RESET + "\tclean | " + CYAN + "Cleans the " + CYAN_UNDERLINED + "compiled/" + CYAN + " folder.");
36+
System.out.println(RESET + "\ttest <file> | " + CYAN + "Runs available scripts in test mode.");
37+
System.out.println(RESET + "\t | " + CYAN + "Test-only features will be available here.");
38+
System.out.println(RESET + "\t | " + CYAN + "If a file-arg is given, only this script will be tested.");
39+
System.out.println(RESET + "\tdebug | " + CYAN + "Generates a debug information file (for bug reports!)");
3540
System.out.print(RESET);
3641
System.out.println("Visit https://docs.byteskript.org for help and tutorials.");
3742
} else if (args[0].equalsIgnoreCase("clean")) {
@@ -64,6 +69,23 @@ public static void main(String... args) throws Throwable {
6469
ScriptJarBuilder.main(arguments);
6570
} else if (args[0].equalsIgnoreCase("compile")) {
6671
ScriptCompiler.main();
72+
} else if (args[0].equalsIgnoreCase("test") && args.length < 2) {
73+
ExtractedSyntaxCalls.setTest(true);
74+
ScriptLoader.main();
75+
} else if (args[0].equalsIgnoreCase("test")) {
76+
ExtractedSyntaxCalls.setTest(true);
77+
final String name = args[1];
78+
final File file = new File(name);
79+
registerLibraries(SKRIPT);
80+
try (final InputStream stream = new FileInputStream(file)) {
81+
final PostCompileClass[] classes = SKRIPT.compileComplexScript(stream, "skript." + file.getName());
82+
for (final PostCompileClass type : classes) {
83+
SKRIPT.loadScript(type);
84+
}
85+
}
86+
new SimpleThrottleController(SKRIPT).run();
87+
} else if (args[0].equalsIgnoreCase("debug")) {
88+
System.out.println(RESET + "This function is currently unavailable." + RESET);
6789
}
6890
}
6991

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ public void createTree(ProgrammaticSplitTree tree) {
262262

263263
@Override
264264
public <Tree extends ProgrammaticSplitTree> Tree findTree(Class<Tree> type) {
265-
for (ProgrammaticSplitTree tree : this.trees) {
265+
for (final ProgrammaticSplitTree tree : this.trees) {
266266
if (type.isInstance(tree)) return (Tree) tree;
267267
}
268268
return null;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ public ElementTree assembleExpression(String expression, final Type expected, fi
241241
final Type[] types = match.expected();
242242
final String[] inputs = match.groups();
243243
if (inputs.length < types.length) continue;
244+
context.setState(handler.getSubState()); // anticipate inner-effect state change
244245
details.expressionMatched = handler;
245246
inner:
246247
for (int i = 0; i < types.length; i++) {

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

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import org.byteskript.skript.lang.syntax.map.MapCreator;
6060
import org.byteskript.skript.lang.syntax.maths.*;
6161
import org.byteskript.skript.lang.syntax.script.*;
62+
import org.byteskript.skript.lang.syntax.test.TestEffect;
6263
import org.byteskript.skript.lang.syntax.timing.*;
6364
import org.byteskript.skript.lang.syntax.type.*;
6465
import org.byteskript.skript.lang.syntax.type.property.FinalEntry;
@@ -172,6 +173,7 @@ private SkriptLangSpec() {
172173
new ContinueEffect(),
173174
new BreakIfEffect(),
174175
new BreakEffect(),
176+
new TestEffect(),
175177
new TryEffect(),
176178
new ClearList(),
177179
new LoadScriptEffect(),
@@ -181,14 +183,21 @@ private SkriptLangSpec() {
181183
);
182184
registerSyntax(CompileState.STATEMENT,
183185
new NoneLiteral(),
184-
new ImplicitArrayCreator(),
185-
new BracketExpression(),
186-
new BooleanLiteral(),
187-
new ThisThingExpression(),
186+
new StringLiteral(),
187+
new RegexLiteral(),
188+
new IntegerLiteral(),
189+
new LongLiteral(),
190+
new FloatLiteral(),
191+
new DoubleLiteral(),
192+
new DoubleLiteral()
193+
);
194+
registerSyntax(CompileState.STATEMENT,
188195
new ThreadVariableExpression(),
189196
new AtomicVariableExpression(),
190197
new GlobalVariableExpression(),
191-
new VariableExpression(),
198+
new VariableExpression()
199+
);
200+
registerSyntax(CompileState.STATEMENT,
192201
new IsArray(),
193202
new IsOfType(),
194203
new Exists(),
@@ -199,11 +208,21 @@ private SkriptLangSpec() {
199208
new NotEqual(),
200209
new IsEqual(),
201210
new Contains(),
202-
new Matches(),
211+
new Matches()
212+
);
213+
registerSyntax(CompileState.STATEMENT,
214+
new ThreadVariableExpression(),
215+
new AtomicVariableExpression(),
216+
new GlobalVariableExpression(),
217+
new VariableExpression()
218+
);
219+
registerSyntax(CompileState.STATEMENT,
220+
new ImplicitArrayCreator(),
221+
new BracketExpression(),
222+
new BooleanLiteral(),
223+
new ThisThingExpression(),
203224
new TernaryOtherwiseExpression(),
204225
new BinaryOtherwiseExpression(),
205-
new StringLiteral(),
206-
new RegexLiteral(),
207226
new SupplierSection(),
208227
new RunnableSection(),
209228
new ThreadExpression(),
@@ -235,11 +254,6 @@ private SkriptLangSpec() {
235254
new WeeksExpression(),
236255
new MonthsExpression(),
237256
new YearsExpression(),
238-
new IntegerLiteral(),
239-
new LongLiteral(),
240-
new FloatLiteral(),
241-
new DoubleLiteral(),
242-
new DoubleLiteral(),
243257
new MapCreator(),
244258
new ListCreator(),
245259
new IndexOfList(),

src/main/java/org/byteskript/skript/lang/syntax/flow/error/TryEffect.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public void compile(Context context, Pattern.Match match) throws Throwable {
6565
visitor.visitLabel(next);
6666
}));
6767
method.writeCode(WriteInstruction.pop());
68+
tree.close(context);
6869
context.setState(CompileState.CODE_BODY);
6970
}
7071

src/main/java/org/byteskript/skript/lang/syntax/script/UnloadScriptEffect.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
import org.byteskript.skript.runtime.Script;
1616
import org.byteskript.skript.runtime.Skript;
1717

18-
import java.io.IOException;
19-
2018
@Documentation(
2119
name = "Unload Script",
2220
description = """
@@ -38,7 +36,7 @@ public UnloadScriptEffect() {
3836
}
3937

4038
@ForceExtract
41-
public static void unloadScript(Object object) throws IOException {
39+
public static void unloadScript(Object object) {
4240
if (object instanceof Class main)
4341
Skript.localInstance().unloadScript(main);
4442
else if (object instanceof Script script)
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright (c) 2021 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.lang.syntax.test;
8+
9+
import mx.kenzie.foundation.MethodBuilder;
10+
import mx.kenzie.foundation.WriteInstruction;
11+
import org.byteskript.skript.api.note.Documentation;
12+
import org.byteskript.skript.api.syntax.Effect;
13+
import org.byteskript.skript.compiler.CompileState;
14+
import org.byteskript.skript.compiler.Context;
15+
import org.byteskript.skript.compiler.Pattern;
16+
import org.byteskript.skript.compiler.SkriptLangSpec;
17+
import org.byteskript.skript.compiler.structure.MultiLabel;
18+
import org.byteskript.skript.compiler.structure.TryCatchTree;
19+
import org.byteskript.skript.error.ScriptCompileError;
20+
import org.byteskript.skript.lang.element.StandardElements;
21+
import org.byteskript.skript.runtime.internal.ExtractedSyntaxCalls;
22+
import org.objectweb.asm.Label;
23+
import org.objectweb.asm.Opcodes;
24+
25+
@Documentation(
26+
name = "Inline Test",
27+
description = """
28+
Attempts the following effect only during a `test` phase.
29+
Errors caused by side-effects from the test will be ignored outside the test phase.
30+
31+
This is a meta-effect and follows an unusual pattern.
32+
""",
33+
examples = {
34+
"""
35+
test: print "hello!"
36+
"""
37+
}
38+
)
39+
public class TestEffect extends Effect {
40+
41+
public TestEffect() {
42+
super(SkriptLangSpec.LIBRARY, StandardElements.EFFECT, "test: %Effect%");
43+
}
44+
45+
@Override
46+
public CompileState getSubState() {
47+
return CompileState.CODE_BODY; // need to run an effect inside this!
48+
}
49+
50+
@Override
51+
public void preCompile(Context context, Pattern.Match match) throws Throwable {
52+
final TryCatchTree tree = new TryCatchTree(context.getSection(1), new MultiLabel());
53+
context.createTree(tree);
54+
tree.start(context);
55+
final MethodBuilder method = context.getMethod();
56+
final Label label = tree.getEnd().use();
57+
method.writeCode(WriteInstruction.invoke(ExtractedSyntaxCalls.class.getMethod("isTest")));
58+
method.writeCode((writer, visitor) -> visitor.visitJumpInsn(153, label));
59+
super.preCompile(context, match);
60+
}
61+
62+
@Override
63+
public void compile(Context context, Pattern.Match match) throws Throwable {
64+
final TryCatchTree tree = context.findTree(TryCatchTree.class);
65+
final Label label = tree.getEnd().use();
66+
final Label next = tree.getStartCatch();
67+
final MethodBuilder method = context.getMethod();
68+
if (method == null) throw new ScriptCompileError(context.lineNumber(), "Test effect used outside method.");
69+
context.getMethod().writeCode(((writer, visitor) -> {
70+
visitor.visitJumpInsn(Opcodes.GOTO, label);
71+
visitor.visitLabel(next);
72+
}));
73+
method.writeCode(WriteInstruction.invoke(ExtractedSyntaxCalls.class.getMethod("handleTestError", Throwable.class)));
74+
tree.close(context);
75+
context.setState(CompileState.CODE_BODY);
76+
}
77+
78+
@Override
79+
public Pattern.Match match(String thing, Context context) {
80+
if (!thing.startsWith("test: ")) return null;
81+
if (thing.endsWith(":")) {
82+
context.getError().addHint(this, "Section headers cannot be used in the 'test' effect.");
83+
return null;
84+
}
85+
return super.match(thing, context);
86+
}
87+
88+
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@
1717

1818
@SuppressWarnings({"removal"})
1919
@Ignore
20+
public
2021
class UnsafeAccessor {
2122

22-
private static final Unsafe UNSAFE;
23+
protected static final Unsafe UNSAFE;
2324

2425
static {
2526
try {

src/main/java/org/byteskript/skript/runtime/internal/ExtractedSyntaxCalls.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.byteskript.skript.error.ScriptRuntimeError;
1212
import org.byteskript.skript.runtime.Script;
1313
import org.byteskript.skript.runtime.Skript;
14+
import org.byteskript.skript.runtime.UnsafeAccessor;
1415
import org.byteskript.skript.runtime.threading.ScriptThread;
1516
import org.byteskript.skript.runtime.type.DataList;
1617

@@ -23,7 +24,7 @@
2324
import java.util.function.Supplier;
2425

2526
@Ignore
26-
public class ExtractedSyntaxCalls {
27+
public class ExtractedSyntaxCalls extends UnsafeAccessor {
2728

2829
public static ModifiableCompiler getCompiler() {
2930
return findInstance().getCompiler();
@@ -35,6 +36,18 @@ private static Skript findInstance() {
3536
return thread.skript;
3637
}
3738

39+
public static void handleTestError(Throwable throwable) {
40+
if (isTest()) UNSAFE.throwException(throwable);
41+
}
42+
43+
public static boolean isTest() {
44+
return "true".equals(System.getProperty("skript.test_mode"));
45+
}
46+
47+
public static void setTest(boolean boo) {
48+
System.setProperty("skript.test_mode", boo + "");
49+
}
50+
3851
public static DataList getLoadedScripts() {
3952
final DataList list = new DataList();
4053
for (final Script script : findInstance().getScripts()) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright (c) 2021 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.test;
8+
9+
import mx.kenzie.foundation.language.PostCompileClass;
10+
import org.byteskript.skript.runtime.Script;
11+
import org.byteskript.skript.runtime.Skript;
12+
import org.byteskript.skript.runtime.internal.ExtractedSyntaxCalls;
13+
import org.byteskript.skript.runtime.internal.Member;
14+
import org.junit.BeforeClass;
15+
import org.junit.Test;
16+
17+
public class TestTest extends SkriptTest {
18+
19+
private static final Skript skript = new Skript();
20+
private static Script script;
21+
22+
@BeforeClass
23+
public static void start() throws Throwable {
24+
final PostCompileClass cls = skript.compileScript(SectionsTest.class.getClassLoader()
25+
.getResourceAsStream("test.bsk"), "skript.test");
26+
script = skript.loadScript(cls);
27+
}
28+
29+
@Test
30+
public void nonTest() throws Throwable {
31+
ExtractedSyntaxCalls.setTest(false);
32+
final Member function = script.getFunction("test_func");
33+
assert function != null;
34+
assert (int) function.invoke() == 10;
35+
}
36+
37+
@Test
38+
public void inTest() throws Throwable {
39+
ExtractedSyntaxCalls.setTest(true);
40+
final Member function = script.getFunction("test_func");
41+
assert function != null;
42+
assert (int) function.invoke() == 5;
43+
ExtractedSyntaxCalls.setTest(false);
44+
}
45+
46+
}

src/test/resources/test.bsk

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
function test_func:
3+
trigger:
4+
set {var} to 10
5+
assert {var} is 10
6+
test: set {var} to 5
7+
return {var}

0 commit comments

Comments
 (0)