Skip to content

Commit a92f3c3

Browse files
committed
Add simple operator overloading.
1 parent c78e0c5 commit a92f3c3

File tree

11 files changed

+231
-64
lines changed

11 files changed

+231
-64
lines changed

src/main/java/org/byteskript/skript/api/Library.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import mx.kenzie.foundation.language.PostCompileClass;
1313
import org.byteskript.skript.compiler.Context;
1414
import org.byteskript.skript.runtime.type.Converter;
15+
import org.byteskript.skript.runtime.type.OperatorFunction;
1516

1617
import java.util.*;
1718

@@ -83,4 +84,8 @@ default Document[] generateDocumentation() {
8384
return new HashMap<>();
8485
}
8586

87+
default Map<OperatorFunction.Data, OperatorFunction<?, ?>> getOperators() {
88+
return new HashMap<>();
89+
}
90+
8691
}

src/main/java/org/byteskript/skript/api/ModifiableLibrary.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.byteskript.skript.compiler.CompileState;
1616
import org.byteskript.skript.compiler.Context;
1717
import org.byteskript.skript.runtime.type.Converter;
18+
import org.byteskript.skript.runtime.type.OperatorFunction;
1819

1920
import java.lang.reflect.Method;
2021
import java.util.*;
@@ -41,6 +42,8 @@ public class ModifiableLibrary implements SyntaxAnnotationUnwrapper, Library {
4142
protected final String name;
4243
@Ignore
4344
protected final Map<Converter.Data, Converter<?, ?>> converters = new HashMap<>();
45+
@Ignore
46+
protected final Map<OperatorFunction.Data, OperatorFunction<?, ?>> operators = new HashMap<>();
4447

4548
@Description("""
4649
Create a new library instance with the given name.
@@ -125,6 +128,11 @@ public <From, To> void registerConverter(Class<From> from, Class<To> to, Convert
125128
this.converters.put(data, converter);
126129
}
127130

131+
public <First, Second> void registerOperator(OperatorFunction.Type type, Class<First> first, Class<Second> second, OperatorFunction<First, Second> function) {
132+
final OperatorFunction.Data data = new OperatorFunction.Data(type, first, second);
133+
this.operators.put(data, function);
134+
}
135+
128136
@Ignore
129137
public Type registerType(String classPath) {
130138
final Type type = new Type(classPath);
@@ -189,4 +197,9 @@ public SyntaxElement[] getSyntax() {
189197
public Map<Converter.Data, Converter<?, ?>> getConverters() {
190198
return converters;
191199
}
200+
201+
@Override
202+
public Map<OperatorFunction.Data, OperatorFunction<?, ?>> getOperators() {
203+
return operators;
204+
}
192205
}

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ public DebugSkriptCompiler(OutputStreamController controller, Library... librari
2525

2626
@Override
2727
protected void compileLine(String line, FileContext context) {
28+
if (line.isBlank()) {
29+
try {
30+
this.controller.write("\n");
31+
} catch (IOException ignore) {
32+
}
33+
}
2834
final ElementTree tree = this.parseLine(line, context);
2935
if (tree == null) return;
3036
this.debug(tree, context);
@@ -64,12 +70,9 @@ protected FileContext createContext(Type path) {
6470
protected void debug(ElementTree tree, FileContext context) {
6571
try {
6672
this.controller.write("\n");
67-
for (int i = 0; i < context.lineIndent; i++) {
68-
this.controller.write("\t");
69-
}
70-
this.controller.write(tree.toString());
71-
this.controller.write(";");
72-
} catch (IOException ignored) {}
73+
for (int i = 0; i < context.lineIndent; i++) this.controller.write("\t");
74+
this.controller.write(tree.toString(context));
75+
} catch (Throwable ignored) {}
7376
}
7477

7578
}

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

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@
66

77
package org.byteskript.skript.compiler;
88

9+
import mx.kenzie.foundation.MethodErasure;
910
import mx.kenzie.foundation.Type;
1011
import org.byteskript.skript.api.HandlerType;
1112
import org.byteskript.skript.api.SyntaxElement;
1213
import org.byteskript.skript.api.syntax.Literal;
1314
import org.byteskript.skript.api.syntax.Section;
15+
import org.byteskript.skript.api.syntax.TriggerHolder;
1416
import org.byteskript.skript.error.ScriptCompileError;
1517
import org.byteskript.skript.lang.handler.StandardHandlers;
18+
import org.byteskript.skript.lang.syntax.entry.Trigger;
1619
import org.byteskript.skript.lang.syntax.variable.VariableExpression;
1720

1821
import java.util.*;
@@ -172,22 +175,42 @@ public boolean equals(Object obj) {
172175

173176
@Override
174177
public String toString() {
178+
return this.toString(null);
179+
}
180+
181+
public String toString(Context context) {
175182
final StringBuilder builder = new StringBuilder();
176183
builder.append(current.getClass().getSimpleName());
177184
builder.append('(');
178185
if (current instanceof Literal<?>) {
179186
builder.append(match.matcher().group());
180187
} else if (current instanceof VariableExpression) {
181188
builder.append(match.matcher().group("name"));
189+
} else if (current instanceof TriggerHolder && context != null && context.getLine() == this && context.getMethod() != null) {
190+
final MethodErasure erasure = context.getMethod().getErasure();
191+
boolean comma = false;
192+
for (final Type type : erasure.parameterTypes()) {
193+
if (comma) builder.append(", ");
194+
else comma = true;
195+
builder.append(type.getSimpleName());
196+
}
182197
} else {
183198
boolean comma = false;
184199
for (final ElementTree tree : nested) {
185-
if (comma) builder.append(',');
186-
builder.append(tree.toString());
200+
if (comma) builder.append(", ");
201+
builder.append(tree.toString(context));
187202
comma = true;
188203
}
189204
}
190205
builder.append(')');
206+
if (context == null) return builder.toString();
207+
if (context.isSectionHeader() && context.getLine() == this) builder.append(':');
208+
if (current instanceof Trigger && context.getLine() == this && context.getMethod() != null) {
209+
final MethodErasure erasure = context.getMethod().getErasure();
210+
builder.append(" // ");
211+
builder.append(erasure.name());
212+
builder.append(erasure.getDescriptor());
213+
}
191214
return builder.toString();
192215
}
193216
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ public Library[] getLibraries() {
129129
}
130130

131131
protected void compileLine(final String line, final FileContext context) {
132+
if (line.isBlank()) return;
132133
final ElementTree tree = this.parseLine(line, context);
133134
if (tree == null) return;
134135
tree.preCompile(context);
@@ -313,7 +314,6 @@ public PostCompileClass[] compile(InputStream stream, Type path) {
313314
context.lineNumber++;
314315
context.line = null;
315316
final String stripped = this.stripLine(line, comment);
316-
if (stripped.isBlank()) continue;
317317
this.compileLine(context, stripped);
318318
}
319319
context.destroyUnits();
@@ -339,7 +339,6 @@ public PostCompileClass[] compile(String source, Type path) {
339339
context.lineNumber++;
340340
context.line = null;
341341
final String stripped = this.stripLine(line, comment);
342-
if (stripped.isBlank()) continue;
343342
this.compileLine(context, stripped);
344343
}
345344
context.destroyUnits();
@@ -360,7 +359,7 @@ protected FileContext createContext(Type path) {
360359
}
361360

362361
private void compileLine(FileContext context, String stripped) {
363-
if (context.getMethod() != null) {
362+
if (context.getMethod() != null && !stripped.isBlank()) {
364363
context.getMethod().writeCode(WriteInstruction.lineNumber(context.lineNumber));
365364
}
366365
try {

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.byteskript.skript.api.Library;
1313
import org.byteskript.skript.runtime.internal.ModifiableCompiler;
1414
import org.byteskript.skript.runtime.type.Converter;
15+
import org.byteskript.skript.runtime.type.OperatorFunction;
1516

1617
import java.io.InputStream;
1718
import java.util.HashMap;
@@ -43,6 +44,15 @@ public SkriptLangSpec getLanguage() {
4344
return map;
4445
}
4546

47+
@Override
48+
public Map<OperatorFunction.Data, OperatorFunction<?, ?>> getOperators() {
49+
final Map<OperatorFunction.Data, OperatorFunction<?, ?>> map = new HashMap<>();
50+
for (final Library library : this.getLibraries()) {
51+
map.putAll(library.getOperators());
52+
}
53+
return map;
54+
}
55+
4656
public abstract PostCompileClass[] compile(InputStream stream, Type name);
4757

4858
public abstract PostCompileClass[] compile(InputStream file, String path);

src/main/java/org/byteskript/skript/compiler/structure/PreVariable.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,14 @@
1111
import org.byteskript.skript.compiler.CommonTypes;
1212

1313
import java.util.ArrayList;
14-
import java.util.HashSet;
1514
import java.util.List;
16-
import java.util.Set;
1715

1816
public final class PreVariable {
17+
public final List<Type> insight = new ArrayList<>();
1918
private final String name;
2019
public boolean parameter;
2120
public boolean internal;
2221
public boolean atomic;
23-
public final List<Type> insight = new ArrayList<>();
2422

2523
public PreVariable(String name) {
2624
if (name == null) this.name = "EMPTY";

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

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.byteskript.skript.runtime.internal.*;
2525
import org.byteskript.skript.runtime.threading.*;
2626
import org.byteskript.skript.runtime.type.Converter;
27+
import org.byteskript.skript.runtime.type.OperatorFunction;
2728

2829
import java.io.*;
2930
import java.nio.charset.StandardCharsets;
@@ -85,6 +86,8 @@ public final class Skript {
8586
@Ignore
8687
final Map<Converter.Data, Converter<?, ?>> converters;
8788
@Ignore
89+
final Map<OperatorFunction.Data, OperatorFunction<?, ?>> operators;
90+
@Ignore
8891
protected PrintStream out = System.out;
8992

9093
@Description("""
@@ -121,8 +124,12 @@ public Skript(SkriptThreadProvider threadProvider, ModifiableCompiler compiler,
121124
this.processes = new ArrayList<>();
122125
this.events = new HashMap<>();
123126
this.converters = new HashMap<>();
127+
this.operators = new HashMap<>();
124128
skript = this;
125-
if (compiler != null) this.converters.putAll(compiler.getConverters());
129+
if (compiler != null) {
130+
this.converters.putAll(compiler.getConverters());
131+
this.operators.putAll(compiler.getOperators());
132+
}
126133
}
127134

128135
@Description("""
@@ -327,6 +334,25 @@ public <From, To> Converter<From, To> getConverter(Class<From> from, Class<To> t
327334
return null;
328335
}
329336

337+
public <First, Second> OperatorFunction<?, ?> getOperatorFunction(OperatorFunction.Type type,
338+
Class<First> first,
339+
Class<Second> second) {
340+
final OperatorFunction.Data data = new OperatorFunction.Data(type, first, second);
341+
if (operators.containsKey(data)) return operators.get(data);
342+
for (final OperatorFunction.Data found : operators.keySet()) {
343+
if (found.first().isAssignableFrom(first) && found.second().isAssignableFrom(second))
344+
return operators.get(found);
345+
}
346+
for (final OperatorFunction.Data found : operators.keySet()) { // reverse
347+
if (!found.second().isAssignableFrom(first)) continue;
348+
if (!found.first().isAssignableFrom(second)) continue;
349+
final OperatorFunction<?, ?> function = operators.get(found);
350+
if (function.reversible()) return function;
351+
return function.opposite();
352+
}
353+
return null;
354+
}
355+
330356
@Description("""
331357
Gets the parent class-loader attached to this Skript runtime.
332358
This is used to search available libraries and scripts for classes.
@@ -987,6 +1013,7 @@ public Script loadScript(final File source, final String name)
9871013
}
9881014

9891015
//region Output
1016+
9901017
/**
9911018
* Set the current print stream used by the `print` effect.
9921019
* This can be used to redirect output in a particular state.

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.byteskript.skript.api.Library;
1414
import org.byteskript.skript.runtime.Skript;
1515
import org.byteskript.skript.runtime.type.Converter;
16+
import org.byteskript.skript.runtime.type.OperatorFunction;
1617

1718
import java.io.InputStream;
1819
import java.util.*;
@@ -50,6 +51,10 @@ default Document[] generateDocumentation() {
5051
return new HashMap<>();
5152
}
5253

54+
default Map<OperatorFunction.Data, OperatorFunction<?, ?>> getOperators() {
55+
return new HashMap<>();
56+
}
57+
5358
default Promise<PostCompileClass[]> compileAsync(InputStream stream, Type name, Skript skript) {
5459
return this.background(() -> this.compile(stream, name), skript);
5560
}

0 commit comments

Comments
 (0)