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);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -1,13 +1,8 @@
|
||||
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.Platform;
|
||||
import it.cavallium.warppi.Platform.ConsoleUtils;
|
||||
import it.cavallium.warppi.Platform.StorageUtils;
|
||||
import it.cavallium.warppi.math.Function;
|
||||
import it.cavallium.warppi.math.MathContext;
|
||||
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.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class RulesManager {
|
||||
|
||||
public static ObjectArrayList<Rule>[] rules;
|
||||
@ -37,18 +36,14 @@ public class RulesManager {
|
||||
|
||||
loadBuiltinRules();
|
||||
|
||||
if (Engine.getPlatform().isJavascript()) {
|
||||
Engine.getPlatform().loadPlatformRules();
|
||||
} else {
|
||||
try {
|
||||
loadDslRules();
|
||||
} catch (IOException | DslFilesException e) {
|
||||
e.printStackTrace();
|
||||
if (e instanceof DslFilesException) {
|
||||
System.err.print(((DslFilesException) e).format());
|
||||
}
|
||||
Engine.getPlatform().exit(1);
|
||||
try {
|
||||
loadDslRules();
|
||||
} catch (IOException | DslFilesException e) {
|
||||
e.printStackTrace();
|
||||
if (e instanceof DslFilesException) {
|
||||
System.err.print(((DslFilesException) e).format());
|
||||
}
|
||||
Engine.getPlatform().exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,33 +66,29 @@ public class RulesManager {
|
||||
}
|
||||
|
||||
private static void loadDslRules() throws IOException, DslFilesException {
|
||||
final StorageUtils storageUtils = Engine.getPlatform().getStorageUtils();
|
||||
final File dslRulesPath = storageUtils.get("rules/dsl/");
|
||||
if (!dslRulesPath.exists()) {
|
||||
return;
|
||||
}
|
||||
final Platform platform = Engine.getPlatform();
|
||||
|
||||
final DslFilesException fileErrors = new DslFilesException();
|
||||
for (final File file : storageUtils.walk(dslRulesPath)) {
|
||||
if (!file.toString().endsWith(".rules")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Engine.getPlatform().getConsoleUtils().out().println(
|
||||
for (final String path : platform.getRuleFilePaths()) {
|
||||
platform.getConsoleUtils().out().println(
|
||||
ConsoleUtils.OUTPUTLEVEL_NODEBUG,
|
||||
"RulesManager",
|
||||
"Found DSL rules file: " + file.getAbsolutePath()
|
||||
"Found DSL rules file: " + path
|
||||
);
|
||||
|
||||
final String source;
|
||||
try (final InputStream resource = storageUtils.getResourceStream(file.toString())) {
|
||||
source = storageUtils.read(resource);
|
||||
try (final InputStream resource = platform.getStorageUtils().getResourceStream(path)) {
|
||||
source = platform.getStorageUtils().read(resource);
|
||||
}
|
||||
|
||||
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) {
|
||||
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 java.io.File;
|
||||
import java.util.ArrayList;
|
||||
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.
|
||||
*
|
||||
* @param file 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 errors The (non-empty) list of errors found in the DSL source file.
|
||||
* @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 errors The (non-empty) list of errors found in the DSL source file.
|
||||
* @throws IllegalArgumentException If the list of errors is empty.
|
||||
*/
|
||||
public void addFileErrors(final File file, final String source, final List<DslError> errors) {
|
||||
filesErrors.add(new FileErrors(file, source, errors));
|
||||
public void addFileErrors(final String filePath, final String source, final List<DslError> 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 java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -11,23 +10,23 @@ import java.util.List;
|
||||
* Also stores the file's path and contents (for error reporting).
|
||||
*/
|
||||
public class FileErrors {
|
||||
private final File file;
|
||||
private final String filePath;
|
||||
private final String source;
|
||||
private final List<DslError> errors;
|
||||
|
||||
/**
|
||||
* 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 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 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 errors The (non-empty) list of errors found in the DSL source file.
|
||||
* @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()) {
|
||||
throw new IllegalArgumentException("The list of errors can't be empty");
|
||||
}
|
||||
this.file = file;
|
||||
this.filePath = filePath;
|
||||
this.source = source;
|
||||
this.errors = errors;
|
||||
}
|
||||
@ -35,8 +34,8 @@ public class FileErrors {
|
||||
/**
|
||||
* @return The path of the DSL source file in which the errors occurred.
|
||||
*/
|
||||
public File getFile() {
|
||||
return file;
|
||||
public String getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,7 +3,6 @@ package it.cavallium.warppi.math.rules.dsl.errorutils;
|
||||
import it.cavallium.warppi.math.rules.dsl.DslError;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
@ -26,7 +25,7 @@ public class FilesErrorsFormatter {
|
||||
*/
|
||||
public String format(final List<FileErrors> filesErrors) {
|
||||
return filesErrors.stream()
|
||||
.sorted(Comparator.comparing(FileErrors::getFile))
|
||||
.sorted(Comparator.comparing(FileErrors::getFilePath))
|
||||
.flatMap(this::formatFileErrors)
|
||||
.collect(Collectors.joining(System.lineSeparator()));
|
||||
}
|
||||
@ -35,17 +34,17 @@ public class FilesErrorsFormatter {
|
||||
final LineMap lines = new LineMap(fileErrors.getSource());
|
||||
return fileErrors.getErrors().stream()
|
||||
.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 List<LineMap.Line> spannedLines = lines.getSpannedLines(error.getPosition(), error.getLength());
|
||||
final LineMap.Line firstLine = spannedLines.get(0);
|
||||
final int column = error.getPosition() - firstLine.getStartPosition() + 1;
|
||||
|
||||
builder.append(file.toString()).append(":")
|
||||
builder.append(filePath).append(":")
|
||||
.append(firstLine.getNumber()).append(":")
|
||||
.append(column).append(":")
|
||||
.append(System.lineSeparator());
|
||||
|
@ -5,7 +5,9 @@ import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
@ -157,8 +159,18 @@ public class DesktopPlatform implements Platform {
|
||||
}
|
||||
|
||||
@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
|
||||
|
@ -1,10 +1,13 @@
|
||||
package it.cavallium.warppi.hardware;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import it.cavallium.warppi.Platform;
|
||||
@ -146,8 +149,18 @@ public class HardwarePlatform implements Platform {
|
||||
}
|
||||
|
||||
@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
|
||||
|
@ -1,7 +1,10 @@
|
||||
package it.cavallium.warppi.teavm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
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.gui.graphicengine.GraphicEngine;
|
||||
import it.cavallium.warppi.gui.graphicengine.html.HtmlEngine;
|
||||
import it.cavallium.warppi.math.rules.RulesManager;
|
||||
import it.cavallium.warppi.util.Error;
|
||||
|
||||
public class TeaVMPlatform implements Platform {
|
||||
@ -140,57 +142,19 @@ public class TeaVMPlatform implements Platform {
|
||||
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
|
||||
public void loadPlatformRules() {
|
||||
RulesManager.addRule(new rules.functions.DivisionRule());
|
||||
RulesManager.addRule(new rules.functions.EmptyNumberRule());
|
||||
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());
|
||||
public List<String> getRuleFilePaths() throws IOException {
|
||||
try (final InputStream listStream = getStorageUtils().getResourceStream("/rules.list")) {
|
||||
return getStorageUtils().readAllLines(listStream);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user