Make DSL rule loading work on TeaVM
This commit is contained in:
parent
e5b64ce218
commit
2b9fb97648
@ -60,7 +60,15 @@ public interface Platform {
|
|||||||
|
|
||||||
String[] stacktraceToString(Error e);
|
String[] stacktraceToString(Error e);
|
||||||
|
|
||||||
void loadPlatformRules();
|
/**
|
||||||
|
* Determines the list of files containing DSL rules to load.
|
||||||
|
*
|
||||||
|
* @return a <code>List</code> of paths of files which contain DSL rules.
|
||||||
|
* Each <code>String</code> in the returned <code>List</code> can be passed as an argument to
|
||||||
|
* {@link StorageUtils#getResourceStream(String)} to access the corresponding file's contents.
|
||||||
|
* @throws IOException if an IO error occurs while getting the list of rule file paths.
|
||||||
|
*/
|
||||||
|
List<String> getRuleFilePaths() throws IOException;
|
||||||
|
|
||||||
void zip(String targetPath, String destinationFilePath, String password);
|
void zip(String targetPath, String destinationFilePath, String password);
|
||||||
|
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
package it.cavallium.warppi.math.rules;
|
package it.cavallium.warppi.math.rules;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import it.cavallium.warppi.Engine;
|
import it.cavallium.warppi.Engine;
|
||||||
|
import it.cavallium.warppi.Platform;
|
||||||
import it.cavallium.warppi.Platform.ConsoleUtils;
|
import it.cavallium.warppi.Platform.ConsoleUtils;
|
||||||
import it.cavallium.warppi.Platform.StorageUtils;
|
|
||||||
import it.cavallium.warppi.math.Function;
|
import it.cavallium.warppi.math.Function;
|
||||||
import it.cavallium.warppi.math.MathContext;
|
import it.cavallium.warppi.math.MathContext;
|
||||||
import it.cavallium.warppi.math.functions.Expression;
|
import it.cavallium.warppi.math.functions.Expression;
|
||||||
@ -21,6 +16,10 @@ import it.cavallium.warppi.math.solver.MathSolver;
|
|||||||
import it.cavallium.warppi.util.Error;
|
import it.cavallium.warppi.util.Error;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class RulesManager {
|
public class RulesManager {
|
||||||
|
|
||||||
public static ObjectArrayList<Rule>[] rules;
|
public static ObjectArrayList<Rule>[] rules;
|
||||||
@ -37,9 +36,6 @@ public class RulesManager {
|
|||||||
|
|
||||||
loadBuiltinRules();
|
loadBuiltinRules();
|
||||||
|
|
||||||
if (Engine.getPlatform().isJavascript()) {
|
|
||||||
Engine.getPlatform().loadPlatformRules();
|
|
||||||
} else {
|
|
||||||
try {
|
try {
|
||||||
loadDslRules();
|
loadDslRules();
|
||||||
} catch (IOException | DslFilesException e) {
|
} catch (IOException | DslFilesException e) {
|
||||||
@ -50,7 +46,6 @@ public class RulesManager {
|
|||||||
Engine.getPlatform().exit(1);
|
Engine.getPlatform().exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static void loadBuiltinRules() {
|
private static void loadBuiltinRules() {
|
||||||
Stream.of(
|
Stream.of(
|
||||||
@ -71,33 +66,29 @@ public class RulesManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void loadDslRules() throws IOException, DslFilesException {
|
private static void loadDslRules() throws IOException, DslFilesException {
|
||||||
final StorageUtils storageUtils = Engine.getPlatform().getStorageUtils();
|
final Platform platform = Engine.getPlatform();
|
||||||
final File dslRulesPath = storageUtils.get("rules/dsl/");
|
|
||||||
if (!dslRulesPath.exists()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final DslFilesException fileErrors = new DslFilesException();
|
final DslFilesException fileErrors = new DslFilesException();
|
||||||
for (final File file : storageUtils.walk(dslRulesPath)) {
|
for (final String path : platform.getRuleFilePaths()) {
|
||||||
if (!file.toString().endsWith(".rules")) {
|
platform.getConsoleUtils().out().println(
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Engine.getPlatform().getConsoleUtils().out().println(
|
|
||||||
ConsoleUtils.OUTPUTLEVEL_NODEBUG,
|
ConsoleUtils.OUTPUTLEVEL_NODEBUG,
|
||||||
"RulesManager",
|
"RulesManager",
|
||||||
"Found DSL rules file: " + file.getAbsolutePath()
|
"Found DSL rules file: " + path
|
||||||
);
|
);
|
||||||
|
|
||||||
final String source;
|
final String source;
|
||||||
try (final InputStream resource = storageUtils.getResourceStream(file.toString())) {
|
try (final InputStream resource = platform.getStorageUtils().getResourceStream(path)) {
|
||||||
source = storageUtils.read(resource);
|
source = platform.getStorageUtils().read(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
RulesDsl.makeRules(source).forEach(RulesManager::addRule);
|
// This loop used to be written as RulesDsl.makeRules(source).forEach(RulesManager::addRule),
|
||||||
|
// but the forEach method hangs on TeaVM.
|
||||||
|
for (Rule rule : RulesDsl.makeRules(source)) {
|
||||||
|
addRule(rule);
|
||||||
|
}
|
||||||
} catch (DslAggregateException e) {
|
} catch (DslAggregateException e) {
|
||||||
fileErrors.addFileErrors(file, source, e.getErrors());
|
fileErrors.addFileErrors(path, source, e.getErrors());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ package it.cavallium.warppi.math.rules.dsl.errorutils;
|
|||||||
|
|
||||||
import it.cavallium.warppi.math.rules.dsl.DslError;
|
import it.cavallium.warppi.math.rules.dsl.DslError;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -15,13 +14,13 @@ public class DslFilesException extends Exception {
|
|||||||
/**
|
/**
|
||||||
* Registers errors which have been found in the specified DSL source file.
|
* Registers errors which have been found in the specified DSL source file.
|
||||||
*
|
*
|
||||||
* @param file The path of the DSL source file in which the errors occurred.
|
* @param filePath The path of the DSL source file in which the errors occurred.
|
||||||
* @param source The entire contents of the DSL source file in which the errors occurred.
|
* @param source The entire contents of the DSL source file in which the errors occurred.
|
||||||
* @param errors The (non-empty) list of errors found in the DSL source file.
|
* @param errors The (non-empty) list of errors found in the DSL source file.
|
||||||
* @throws IllegalArgumentException If the list of errors is empty.
|
* @throws IllegalArgumentException If the list of errors is empty.
|
||||||
*/
|
*/
|
||||||
public void addFileErrors(final File file, final String source, final List<DslError> errors) {
|
public void addFileErrors(final String filePath, final String source, final List<DslError> errors) {
|
||||||
filesErrors.add(new FileErrors(file, source, errors));
|
filesErrors.add(new FileErrors(filePath, source, errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,7 +2,6 @@ package it.cavallium.warppi.math.rules.dsl.errorutils;
|
|||||||
|
|
||||||
import it.cavallium.warppi.math.rules.dsl.DslError;
|
import it.cavallium.warppi.math.rules.dsl.DslError;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,23 +10,23 @@ import java.util.List;
|
|||||||
* Also stores the file's path and contents (for error reporting).
|
* Also stores the file's path and contents (for error reporting).
|
||||||
*/
|
*/
|
||||||
public class FileErrors {
|
public class FileErrors {
|
||||||
private final File file;
|
private final String filePath;
|
||||||
private final String source;
|
private final String source;
|
||||||
private final List<DslError> errors;
|
private final List<DslError> errors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a <code>FileErrors</code> instance with the given file and error data.
|
* Constructs a <code>FileErrors</code> instance with the given file and error data.
|
||||||
*
|
*
|
||||||
* @param file The path of the DSL source file in which the errors occurred.
|
* @param filePath The path of the DSL source file in which the errors occurred.
|
||||||
* @param source The entire contents of the DSL source file in which the errors occurred.
|
* @param source The entire contents of the DSL source file in which the errors occurred.
|
||||||
* @param errors The (non-empty) list of errors found in the DSL source file.
|
* @param errors The (non-empty) list of errors found in the DSL source file.
|
||||||
* @throws IllegalArgumentException If the list of errors is empty.
|
* @throws IllegalArgumentException If the list of errors is empty.
|
||||||
*/
|
*/
|
||||||
public FileErrors(final File file, final String source, final List<DslError> errors) {
|
public FileErrors(final String filePath, final String source, final List<DslError> errors) {
|
||||||
if (errors.isEmpty()) {
|
if (errors.isEmpty()) {
|
||||||
throw new IllegalArgumentException("The list of errors can't be empty");
|
throw new IllegalArgumentException("The list of errors can't be empty");
|
||||||
}
|
}
|
||||||
this.file = file;
|
this.filePath = filePath;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.errors = errors;
|
this.errors = errors;
|
||||||
}
|
}
|
||||||
@ -35,8 +34,8 @@ public class FileErrors {
|
|||||||
/**
|
/**
|
||||||
* @return The path of the DSL source file in which the errors occurred.
|
* @return The path of the DSL source file in which the errors occurred.
|
||||||
*/
|
*/
|
||||||
public File getFile() {
|
public String getFilePath() {
|
||||||
return file;
|
return filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,7 +3,6 @@ package it.cavallium.warppi.math.rules.dsl.errorutils;
|
|||||||
import it.cavallium.warppi.math.rules.dsl.DslError;
|
import it.cavallium.warppi.math.rules.dsl.DslError;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -26,7 +25,7 @@ public class FilesErrorsFormatter {
|
|||||||
*/
|
*/
|
||||||
public String format(final List<FileErrors> filesErrors) {
|
public String format(final List<FileErrors> filesErrors) {
|
||||||
return filesErrors.stream()
|
return filesErrors.stream()
|
||||||
.sorted(Comparator.comparing(FileErrors::getFile))
|
.sorted(Comparator.comparing(FileErrors::getFilePath))
|
||||||
.flatMap(this::formatFileErrors)
|
.flatMap(this::formatFileErrors)
|
||||||
.collect(Collectors.joining(System.lineSeparator()));
|
.collect(Collectors.joining(System.lineSeparator()));
|
||||||
}
|
}
|
||||||
@ -35,17 +34,17 @@ public class FilesErrorsFormatter {
|
|||||||
final LineMap lines = new LineMap(fileErrors.getSource());
|
final LineMap lines = new LineMap(fileErrors.getSource());
|
||||||
return fileErrors.getErrors().stream()
|
return fileErrors.getErrors().stream()
|
||||||
.sorted(Comparator.comparing(DslError::getPosition).thenComparing(DslError::getLength))
|
.sorted(Comparator.comparing(DslError::getPosition).thenComparing(DslError::getLength))
|
||||||
.map(error -> formatError(fileErrors.getFile(), lines, error));
|
.map(error -> formatError(fileErrors.getFilePath(), lines, error));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String formatError(final File file, final LineMap lines, final DslError error) {
|
private String formatError(final String filePath, final LineMap lines, final DslError error) {
|
||||||
final StringBuilder builder = new StringBuilder();
|
final StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
final List<LineMap.Line> spannedLines = lines.getSpannedLines(error.getPosition(), error.getLength());
|
final List<LineMap.Line> spannedLines = lines.getSpannedLines(error.getPosition(), error.getLength());
|
||||||
final LineMap.Line firstLine = spannedLines.get(0);
|
final LineMap.Line firstLine = spannedLines.get(0);
|
||||||
final int column = error.getPosition() - firstLine.getStartPosition() + 1;
|
final int column = error.getPosition() - firstLine.getStartPosition() + 1;
|
||||||
|
|
||||||
builder.append(file.toString()).append(":")
|
builder.append(filePath).append(":")
|
||||||
.append(firstLine.getNumber()).append(":")
|
.append(firstLine.getNumber()).append(":")
|
||||||
.append(column).append(":")
|
.append(column).append(":")
|
||||||
.append(System.lineSeparator());
|
.append(System.lineSeparator());
|
||||||
|
@ -5,7 +5,9 @@ import java.io.IOException;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
@ -157,8 +159,18 @@ public class DesktopPlatform implements Platform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadPlatformRules() {
|
public List<String> getRuleFilePaths() throws IOException {
|
||||||
|
final File dslRulesPath = getStorageUtils().get("rules/dsl/");
|
||||||
|
List<String> paths = new ArrayList<>();
|
||||||
|
if (dslRulesPath.exists()) {
|
||||||
|
for (final File file : getStorageUtils().walk(dslRulesPath)) {
|
||||||
|
final String path = file.toString();
|
||||||
|
if (path.endsWith(".rules")) {
|
||||||
|
paths.add(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package it.cavallium.warppi.hardware;
|
package it.cavallium.warppi.hardware;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import it.cavallium.warppi.Platform;
|
import it.cavallium.warppi.Platform;
|
||||||
@ -146,8 +149,18 @@ public class HardwarePlatform implements Platform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadPlatformRules() {
|
public List<String> getRuleFilePaths() throws IOException {
|
||||||
|
final File dslRulesPath = getStorageUtils().get("rules/dsl/");
|
||||||
|
List<String> paths = new ArrayList<>();
|
||||||
|
if (dslRulesPath.exists()) {
|
||||||
|
for (final File file : getStorageUtils().walk(dslRulesPath)) {
|
||||||
|
final String path = file.toString();
|
||||||
|
if (path.endsWith(".rules")) {
|
||||||
|
paths.add(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package it.cavallium.warppi.teavm;
|
package it.cavallium.warppi.teavm;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.teavm.jso.browser.Window;
|
import org.teavm.jso.browser.Window;
|
||||||
@ -10,7 +13,6 @@ import org.teavm.jso.dom.html.HTMLDocument;
|
|||||||
import it.cavallium.warppi.Platform;
|
import it.cavallium.warppi.Platform;
|
||||||
import it.cavallium.warppi.gui.graphicengine.GraphicEngine;
|
import it.cavallium.warppi.gui.graphicengine.GraphicEngine;
|
||||||
import it.cavallium.warppi.gui.graphicengine.html.HtmlEngine;
|
import it.cavallium.warppi.gui.graphicengine.html.HtmlEngine;
|
||||||
import it.cavallium.warppi.math.rules.RulesManager;
|
|
||||||
import it.cavallium.warppi.util.Error;
|
import it.cavallium.warppi.util.Error;
|
||||||
|
|
||||||
public class TeaVMPlatform implements Platform {
|
public class TeaVMPlatform implements Platform {
|
||||||
@ -140,57 +142,19 @@ public class TeaVMPlatform implements Platform {
|
|||||||
return e.getMessage().toUpperCase().replace("\r", "").split("\n");
|
return e.getMessage().toUpperCase().replace("\r", "").split("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the list of resource files containing DSL rules to load from the <code>/rules.list</code> resource on the server.
|
||||||
|
* <p>
|
||||||
|
* The <code>/rules.list</code> resource must exist and be a text file with zero or more lines.
|
||||||
|
* Each line specifies the name of another resource containing DSL source code.
|
||||||
|
* Blank lines aren't allowed, and resource names are interpreted exactly as written (without stripping
|
||||||
|
* leading/trailing spaces, etc.)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void loadPlatformRules() {
|
public List<String> getRuleFilePaths() throws IOException {
|
||||||
RulesManager.addRule(new rules.functions.DivisionRule());
|
try (final InputStream listStream = getStorageUtils().getResourceStream("/rules.list")) {
|
||||||
RulesManager.addRule(new rules.functions.EmptyNumberRule());
|
return getStorageUtils().readAllLines(listStream);
|
||||||
RulesManager.addRule(new rules.functions.ExpressionRule());
|
}
|
||||||
RulesManager.addRule(new rules.functions.JokeRule());
|
|
||||||
RulesManager.addRule(new rules.functions.MultiplicationRule());
|
|
||||||
RulesManager.addRule(new rules.functions.NegativeRule());
|
|
||||||
RulesManager.addRule(new rules.functions.NumberRule());
|
|
||||||
RulesManager.addRule(new rules.functions.PowerRule());
|
|
||||||
RulesManager.addRule(new rules.functions.RootRule());
|
|
||||||
RulesManager.addRule(new rules.functions.SubtractionRule());
|
|
||||||
RulesManager.addRule(new rules.functions.SumRule());
|
|
||||||
RulesManager.addRule(new rules.functions.SumSubtractionRule());
|
|
||||||
RulesManager.addRule(new rules.functions.VariableRule());
|
|
||||||
RulesManager.addRule(new rules.ExpandRule1());
|
|
||||||
RulesManager.addRule(new rules.ExpandRule2());
|
|
||||||
RulesManager.addRule(new rules.ExpandRule5());
|
|
||||||
RulesManager.addRule(new rules.ExponentRule1());
|
|
||||||
RulesManager.addRule(new rules.ExponentRule2());
|
|
||||||
RulesManager.addRule(new rules.ExponentRule3());
|
|
||||||
RulesManager.addRule(new rules.ExponentRule4());
|
|
||||||
RulesManager.addRule(new rules.ExponentRule8());
|
|
||||||
RulesManager.addRule(new rules.ExponentRule9());
|
|
||||||
RulesManager.addRule(new rules.ExponentRule15());
|
|
||||||
RulesManager.addRule(new rules.ExponentRule16());
|
|
||||||
RulesManager.addRule(new rules.ExponentRule17());
|
|
||||||
RulesManager.addRule(new rules.FractionsRule1());
|
|
||||||
RulesManager.addRule(new rules.FractionsRule2());
|
|
||||||
RulesManager.addRule(new rules.FractionsRule3());
|
|
||||||
RulesManager.addRule(new rules.FractionsRule4());
|
|
||||||
RulesManager.addRule(new rules.FractionsRule5());
|
|
||||||
RulesManager.addRule(new rules.FractionsRule6());
|
|
||||||
RulesManager.addRule(new rules.FractionsRule7());
|
|
||||||
RulesManager.addRule(new rules.FractionsRule8());
|
|
||||||
RulesManager.addRule(new rules.FractionsRule9());
|
|
||||||
RulesManager.addRule(new rules.FractionsRule10());
|
|
||||||
RulesManager.addRule(new rules.FractionsRule11());
|
|
||||||
RulesManager.addRule(new rules.FractionsRule12());
|
|
||||||
RulesManager.addRule(new rules.FractionsRule14());
|
|
||||||
RulesManager.addRule(new rules.NumberRule1());
|
|
||||||
RulesManager.addRule(new rules.NumberRule2());
|
|
||||||
RulesManager.addRule(new rules.NumberRule3());
|
|
||||||
RulesManager.addRule(new rules.NumberRule4());
|
|
||||||
RulesManager.addRule(new rules.NumberRule5());
|
|
||||||
RulesManager.addRule(new rules.NumberRule7());
|
|
||||||
RulesManager.addRule(new rules.UndefinedRule1());
|
|
||||||
RulesManager.addRule(new rules.UndefinedRule2());
|
|
||||||
RulesManager.addRule(new rules.VariableRule1());
|
|
||||||
RulesManager.addRule(new rules.VariableRule2());
|
|
||||||
RulesManager.addRule(new rules.VariableRule3());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user