From 97c7f42400d515d7d021cde95ed95f93bf9fda97 Mon Sep 17 00:00:00 2001 From: Stan Hebben Date: Tue, 10 Jun 2014 21:12:55 +0200 Subject: [PATCH] - Added documentation to some classes - Created script provider system - Did some refactoring to improve the API --- .../main/java/minetweaker/MineTweakerAPI.java | 57 ++++++++ .../src/main/java/minetweaker/Tweaker.java | 50 ------- .../minecraft/util/CloseablePriorityList.java | 81 +++++++++++ .../minetweaker/minecraft/util/FileUtil.java | 27 ++++ .../{ => runtime}/GlobalFunctions.java | 4 +- .../{ => runtime}/GlobalRegistry.java | 105 +++++++++++++-- .../minetweaker/{ => runtime}/ILogger.java | 2 +- .../{ => runtime}/IMineTweaker.java | 14 +- .../minetweaker/runtime/IScriptIterator.java | 24 ++++ .../minetweaker/runtime/IScriptProvider.java | 10 +- .../java/minetweaker/runtime/Tweaker.java | 125 +++++++++++++++++ .../providers/ScriptIteratorDirectory.java | 73 ++++++++++ .../providers/ScriptIteratorSingle.java | 52 +++++++ .../runtime/providers/ScriptIteratorZip.java | 70 ++++++++++ .../providers/ScriptProviderDirectory.java | 47 +++++++ .../providers/ScriptProviderMemory.java | 106 +++++++++++++++ .../minetweaker/mc172/MineTweakerCommand.java | 3 +- .../minetweaker/mc172/MineTweakerMod.java | 4 - ZenScript/build.gradle | 1 + .../stanhebben/zenscript/IZenErrorLogger.java | 24 ++-- .../stanhebben/zenscript/TypeExpansion.java | 127 ++++++++++++++++-- .../java/stanhebben/zenscript/ZenModule.java | 101 +++++++++++--- .../stanhebben/zenscript/ZenParsedFile.java | 84 ++++++++---- .../zenscript/ZenRuntimeException.java | 13 +- .../{ZenParser.java => ZenTokener.java} | 35 ++++- .../zenscript/annotations/CompareType.java | 12 +- .../zenscript/annotations/IterableList.java | 6 - .../zenscript/annotations/IterableMap.java | 6 - .../zenscript/annotations/IterableSimple.java | 11 +- .../zenscript/annotations/NotNull.java | 11 +- .../zenscript/annotations/OperatorType.java | 11 +- .../zenscript/annotations/Optional.java | 6 - .../zenscript/annotations/ZenCaster.java | 10 +- .../zenscript/annotations/ZenClass.java | 12 +- .../zenscript/annotations/ZenExpansion.java | 28 ++-- .../zenscript/annotations/ZenGetter.java | 14 +- .../annotations/ZenMemberGetter.java | 17 +-- .../annotations/ZenMemberSetter.java | 17 +-- .../zenscript/annotations/ZenMethod.java | 20 +-- .../annotations/ZenMethodStatic.java | 11 +- .../zenscript/annotations/ZenOperator.java | 16 +-- .../zenscript/annotations/ZenSetter.java | 20 +-- .../compiler/IEnvironmentGlobal.java | 2 - .../zenscript/definitions/ParsedFunction.java | 8 +- .../zenscript/docs/ZenScriptDoclet.java | 26 ++++ .../zenscript/expression/Expression.java | 4 +- .../stanhebben/zenscript/package-info.java | 40 ++++++ .../parser/expression/ParsedExpression.java | 34 ++--- .../zenscript/statements/Statement.java | 6 +- .../stanhebben/zenscript/type/ZenType.java | 42 +++--- 50 files changed, 1311 insertions(+), 318 deletions(-) delete mode 100644 MineTweaker3-API/src/main/java/minetweaker/Tweaker.java create mode 100644 MineTweaker3-API/src/main/java/minetweaker/minecraft/util/CloseablePriorityList.java create mode 100644 MineTweaker3-API/src/main/java/minetweaker/minecraft/util/FileUtil.java rename MineTweaker3-API/src/main/java/minetweaker/{ => runtime}/GlobalFunctions.java (84%) rename MineTweaker3-API/src/main/java/minetweaker/{ => runtime}/GlobalRegistry.java (66%) rename MineTweaker3-API/src/main/java/minetweaker/{ => runtime}/ILogger.java (93%) rename MineTweaker3-API/src/main/java/minetweaker/{ => runtime}/IMineTweaker.java (80%) create mode 100644 MineTweaker3-API/src/main/java/minetweaker/runtime/IScriptIterator.java rename ZenScript/src/main/java/stanhebben/zenscript/ZenParsedModule.java => MineTweaker3-API/src/main/java/minetweaker/runtime/IScriptProvider.java (56%) create mode 100644 MineTweaker3-API/src/main/java/minetweaker/runtime/Tweaker.java create mode 100644 MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptIteratorDirectory.java create mode 100644 MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptIteratorSingle.java create mode 100644 MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptIteratorZip.java create mode 100644 MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptProviderDirectory.java create mode 100644 MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptProviderMemory.java rename ZenScript/src/main/java/stanhebben/zenscript/{ZenParser.java => ZenTokener.java} (86%) create mode 100644 ZenScript/src/main/java/stanhebben/zenscript/docs/ZenScriptDoclet.java create mode 100644 ZenScript/src/main/java/stanhebben/zenscript/package-info.java diff --git a/MineTweaker3-API/src/main/java/minetweaker/MineTweakerAPI.java b/MineTweaker3-API/src/main/java/minetweaker/MineTweakerAPI.java index 9b4dcc9..f20c64d 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/MineTweakerAPI.java +++ b/MineTweaker3-API/src/main/java/minetweaker/MineTweakerAPI.java @@ -1,8 +1,16 @@ package minetweaker; +import java.lang.annotation.Annotation; +import minetweaker.runtime.IMineTweaker; +import minetweaker.runtime.ILogger; +import minetweaker.runtime.Tweaker; import minetweaker.minecraft.recipes.IRecipeManager; import minetweaker.minecraft.oredict.IOreDict; import minetweaker.minecraft.recipes.IFurnaceManager; +import minetweaker.runtime.GlobalRegistry; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenExpansion; +import stanhebben.zenscript.symbols.IZenSymbol; /** * Provides access to the MineTweaker API. @@ -50,4 +58,53 @@ public class MineTweakerAPI { * Access point to the furnace manager. */ public static IFurnaceManager furnace = null; + + /** + * Registers an annotated class. A class is annotated with either @ZenClass + * or @ZenExpansion. Classes not annotated with either of these will be + * ignored. + * + * @param annotatedClass + */ + public static void registerClass(Class annotatedClass) { + for (Annotation annotation : annotatedClass.getAnnotations()) { + if (annotation instanceof ZenExpansion) { + GlobalRegistry.registerExpansion(annotatedClass); + } else if (annotation instanceof ZenClass) { + GlobalRegistry.registerNativeClass(annotatedClass); + } + } + } + + /** + * Registers a global symbol. Global symbols are immediately accessible from + * anywhere in the scripts. + * + * @param name + * @param symbol + */ + public static void registerGlobalSymbol(String name, IZenSymbol symbol) { + GlobalRegistry.registerGlobal(name, symbol); + } + + /** + * Registers a recipe remover. Removers are called when the global + * minetweaker.remove() function is called. + * + * @param remover recipe remover + */ + public static void registerRemover(IRecipeRemover remover) { + GlobalRegistry.registerRemover(remover); + } + + /** + * Registers a bracket handler. Is capable of converting the bracket syntax + * to an actual value. This new handler will be added last - it can thus + * not intercept values that are already handled by the system. + * + * @param handler bracket handler to be added + */ + public static void registerBracketHandler(IBracketHandler handler) { + GlobalRegistry.registerBracketHandler(handler); + } } diff --git a/MineTweaker3-API/src/main/java/minetweaker/Tweaker.java b/MineTweaker3-API/src/main/java/minetweaker/Tweaker.java deleted file mode 100644 index dca257d..0000000 --- a/MineTweaker3-API/src/main/java/minetweaker/Tweaker.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - -package minetweaker; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import minetweaker.minecraft.item.IIngredient; - -/** - * - * - * @author Stan Hebben - */ -public class Tweaker implements IMineTweaker { - List actions = new ArrayList(); - Set wereStuck = new HashSet(); - - @Override - public void apply(IUndoableAction action) { - MineTweakerAPI.logger.logInfo(action.describe()); - action.apply(); - } - - @Override - public void remove(IIngredient items) { - GlobalRegistry.remove(items); - } - - @Override - public List rollback() { - List stuck = new ArrayList(); - for (int i = actions.size() - 1; i >= 0; i--) { - IUndoableAction action = actions.get(i); - if (action.canUndo()) { - MineTweakerAPI.logger.logInfo(action.describeUndo()); - action.undo(); - } else { - stuck.add(0, action); - wereStuck.add(action); - } - } - return stuck; - } -} diff --git a/MineTweaker3-API/src/main/java/minetweaker/minecraft/util/CloseablePriorityList.java b/MineTweaker3-API/src/main/java/minetweaker/minecraft/util/CloseablePriorityList.java new file mode 100644 index 0000000..0f91de1 --- /dev/null +++ b/MineTweaker3-API/src/main/java/minetweaker/minecraft/util/CloseablePriorityList.java @@ -0,0 +1,81 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.minecraft.util; + +import java.io.Closeable; +import java.io.IOException; +import java.util.Iterator; + +/** + * + * @author Stan + */ +public class CloseablePriorityList implements Iterable { + private CloseableEntry first; + + /** + * Adds a new item to the list. The new item will be inserted at the head of + * the list. + * + * @param value + * @return + */ + public Closeable add(T value) { + if (first == null) { + first = new CloseableEntry(value); + } else { + CloseableEntry entry = new CloseableEntry(value); + entry.next = first; + first.prev = entry; + first = entry; + } + + return first; + } + + @Override + public Iterator iterator() { + return new MyIterator(); + } + + private class MyIterator implements Iterator { + private CloseableEntry current = null; + + @Override + public boolean hasNext() { + return current == null || current.next != null; + } + + @Override + public T next() { + current = current == null ? first : current.next; + return current.value; + } + } + + private class CloseableEntry implements Closeable { + private final T value; + private CloseableEntry next; + private CloseableEntry prev; + + public CloseableEntry(T value) { + this.value = value; + } + + @Override + public void close() throws IOException { + if (next != null) { + next.prev = prev; + } + if (prev == null) { + first = next; + } else { + prev.next = next; + } + } + } +} diff --git a/MineTweaker3-API/src/main/java/minetweaker/minecraft/util/FileUtil.java b/MineTweaker3-API/src/main/java/minetweaker/minecraft/util/FileUtil.java new file mode 100644 index 0000000..ae242ac --- /dev/null +++ b/MineTweaker3-API/src/main/java/minetweaker/minecraft/util/FileUtil.java @@ -0,0 +1,27 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.minecraft.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * + * @author Stan + */ +public class FileUtil { + public static final byte[] read(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + byte[] buffer = new byte[65536]; + while (input.available() > 0) { + int bytesRead = input.read(buffer); + output.write(buffer, 0, bytesRead); + } + return output.toByteArray(); + } +} diff --git a/MineTweaker3-API/src/main/java/minetweaker/GlobalFunctions.java b/MineTweaker3-API/src/main/java/minetweaker/runtime/GlobalFunctions.java similarity index 84% rename from MineTweaker3-API/src/main/java/minetweaker/GlobalFunctions.java rename to MineTweaker3-API/src/main/java/minetweaker/runtime/GlobalFunctions.java index 1de8e6b..c6f5714 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/GlobalFunctions.java +++ b/MineTweaker3-API/src/main/java/minetweaker/runtime/GlobalFunctions.java @@ -4,7 +4,9 @@ * and open the template in the editor. */ -package minetweaker; +package minetweaker.runtime; + +import minetweaker.MineTweakerAPI; /** * diff --git a/MineTweaker3-API/src/main/java/minetweaker/GlobalRegistry.java b/MineTweaker3-API/src/main/java/minetweaker/runtime/GlobalRegistry.java similarity index 66% rename from MineTweaker3-API/src/main/java/minetweaker/GlobalRegistry.java rename to MineTweaker3-API/src/main/java/minetweaker/runtime/GlobalRegistry.java index d63bc9d..04bd411 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/GlobalRegistry.java +++ b/MineTweaker3-API/src/main/java/minetweaker/runtime/GlobalRegistry.java @@ -4,27 +4,35 @@ * and open the template in the editor. */ -package minetweaker; +package minetweaker.runtime; import java.lang.annotation.Annotation; import java.lang.reflect.Field; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import minetweaker.IBracketHandler; +import minetweaker.IRecipeRemover; +import minetweaker.MineTweakerAPI; import minetweaker.minecraft.item.IIngredient; import stanhebben.zenscript.IZenErrorLogger; import stanhebben.zenscript.TypeExpansion; import stanhebben.zenscript.annotations.ZenExpansion; +import stanhebben.zenscript.compiler.ClassNameGenerator; +import stanhebben.zenscript.compiler.IEnvironmentGlobal; import stanhebben.zenscript.compiler.TypeRegistry; +import stanhebben.zenscript.expression.partial.IPartialExpression; import stanhebben.zenscript.parser.Token; import stanhebben.zenscript.symbols.IZenCompileEnvironment; import stanhebben.zenscript.symbols.IZenSymbol; import stanhebben.zenscript.symbols.SymbolJavaStaticField; import stanhebben.zenscript.symbols.SymbolJavaStaticMethod; import stanhebben.zenscript.symbols.SymbolPackage; +import stanhebben.zenscript.type.ZenType; import stanhebben.zenscript.type.ZenTypeNative; import stanhebben.zenscript.type.natives.JavaMethod; import stanhebben.zenscript.util.ZenPosition; @@ -44,15 +52,15 @@ public class GlobalRegistry { private static final Map expansions = new HashMap(); static { - register("print", getStaticFunction(GlobalFunctions.class, "print", String.class)); - register("max", getStaticFunction(Math.class, "max", int.class, int.class)); - register("min", getStaticFunction(Math.class, "min", int.class, int.class)); + registerGlobal("print", getStaticFunction(GlobalFunctions.class, "print", String.class)); + registerGlobal("max", getStaticFunction(Math.class, "max", int.class, int.class)); + registerGlobal("min", getStaticFunction(Math.class, "min", int.class, int.class)); - register("logger", getStaticField(MineTweakerAPI.class, "logger")); - register("minetweaker", getStaticField(MineTweakerAPI.class, "tweaker")); - register("recipes", getStaticField(MineTweakerAPI.class, "recipes")); - register("furnace", getStaticField(MineTweakerAPI.class, "furnace")); - register("oreDict", getStaticField(MineTweakerAPI.class, "oreDict")); + registerGlobal("logger", getStaticField(MineTweakerAPI.class, "logger")); + registerGlobal("minetweaker", getStaticField(MineTweakerAPI.class, "tweaker")); + registerGlobal("recipes", getStaticField(MineTweakerAPI.class, "recipes")); + registerGlobal("furnace", getStaticField(MineTweakerAPI.class, "furnace")); + registerGlobal("oreDict", getStaticField(MineTweakerAPI.class, "oreDict")); /*registerExpansion(ExpandAnyArray.class); registerExpansion(ExpandAnyDict.class); @@ -88,7 +96,7 @@ public class GlobalRegistry { private GlobalRegistry() {} - public static void register(String name, IZenSymbol symbol) { + public static void registerGlobal(String name, IZenSymbol symbol) { if (globals.containsKey(name)) { throw new IllegalArgumentException("symbol already exists: " + name); } @@ -161,6 +169,10 @@ public class GlobalRegistry { } } + public static IEnvironmentGlobal makeGlobalEnvironment(Map classes) { + return new MyGlobalEnvironment(classes); + } + private static class MyErrorLogger implements IZenErrorLogger { @Override public void error(ZenPosition position, String message) { @@ -208,4 +220,77 @@ public class GlobalRegistry { return expansions.get(type); } } + + private static class MyGlobalEnvironment implements IEnvironmentGlobal { + private final Map classes; + private final Map symbols; + private final ClassNameGenerator generator; + + public MyGlobalEnvironment(Map classes) { + this.classes = classes; + symbols = new HashMap(); + generator = new ClassNameGenerator(); + } + + @Override + public IZenCompileEnvironment getEnvironment() { + return environment; + } + + @Override + public TypeExpansion getExpansion(String name) { + return expansions.get(name); + } + + @Override + public String makeClassName() { + return generator.generate(); + } + + @Override + public boolean containsClass(String name) { + return classes.containsKey(name); + } + + @Override + public void putClass(String name, byte[] data) { + classes.put(name, data); + } + + @Override + public IPartialExpression getValue(String name, ZenPosition position) { + if (symbols.containsKey(name)) { + return symbols.get(name).instance(position); + } else if (globals.containsKey(name)) { + return globals.get(name).instance(position); + } else { + IZenSymbol pkg = root.get(name); + if (pkg == null) { + return null; + } else { + return pkg.instance(position); + } + } + } + + @Override + public void putValue(String name, IZenSymbol value) { + symbols.put(name, value); + } + + @Override + public ZenType getType(Type type) { + return types.getType(type); + } + + @Override + public void error(ZenPosition position, String message) { + MineTweakerAPI.logger.logError("[" + position.getFile() + ":" + position.getLine() + "] Error: " + message); + } + + @Override + public void warning(ZenPosition position, String message) { + MineTweakerAPI.logger.logWarning("[" + position.getFile() + ":" + position.getLine() + "] Warning: " + message); + } + } } diff --git a/MineTweaker3-API/src/main/java/minetweaker/ILogger.java b/MineTweaker3-API/src/main/java/minetweaker/runtime/ILogger.java similarity index 93% rename from MineTweaker3-API/src/main/java/minetweaker/ILogger.java rename to MineTweaker3-API/src/main/java/minetweaker/runtime/ILogger.java index feb2688..afa7841 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/ILogger.java +++ b/MineTweaker3-API/src/main/java/minetweaker/runtime/ILogger.java @@ -4,7 +4,7 @@ * and open the template in the editor. */ -package minetweaker; +package minetweaker.runtime; import stanhebben.zenscript.annotations.ZenMethod; diff --git a/MineTweaker3-API/src/main/java/minetweaker/IMineTweaker.java b/MineTweaker3-API/src/main/java/minetweaker/runtime/IMineTweaker.java similarity index 80% rename from MineTweaker3-API/src/main/java/minetweaker/IMineTweaker.java rename to MineTweaker3-API/src/main/java/minetweaker/runtime/IMineTweaker.java index a1ba5a5..79f46de 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/IMineTweaker.java +++ b/MineTweaker3-API/src/main/java/minetweaker/runtime/IMineTweaker.java @@ -4,9 +4,11 @@ * and open the template in the editor. */ -package minetweaker; +package minetweaker.runtime; +import java.io.Closeable; import java.util.List; +import minetweaker.IUndoableAction; import minetweaker.minecraft.item.IIngredient; import stanhebben.zenscript.annotations.ZenClass; import stanhebben.zenscript.annotations.ZenMethod; @@ -41,4 +43,14 @@ public interface IMineTweaker { * @return stuck action list */ public List rollback(); + + /** + * Registers a script provider. + * + * @param provider + * @return + */ + public Closeable registerScriptProvider(IScriptProvider provider); + + public void load(); } diff --git a/MineTweaker3-API/src/main/java/minetweaker/runtime/IScriptIterator.java b/MineTweaker3-API/src/main/java/minetweaker/runtime/IScriptIterator.java new file mode 100644 index 0000000..6dac8a0 --- /dev/null +++ b/MineTweaker3-API/src/main/java/minetweaker/runtime/IScriptIterator.java @@ -0,0 +1,24 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.runtime; + +import java.io.IOException; +import java.io.InputStream; + +/** + * + * @author Stan + */ +public interface IScriptIterator { + public String getGroupName(); + + public boolean next(); + + public String getName(); + + public InputStream open() throws IOException; +} diff --git a/ZenScript/src/main/java/stanhebben/zenscript/ZenParsedModule.java b/MineTweaker3-API/src/main/java/minetweaker/runtime/IScriptProvider.java similarity index 56% rename from ZenScript/src/main/java/stanhebben/zenscript/ZenParsedModule.java rename to MineTweaker3-API/src/main/java/minetweaker/runtime/IScriptProvider.java index a248860..46418ea 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/ZenParsedModule.java +++ b/MineTweaker3-API/src/main/java/minetweaker/runtime/IScriptProvider.java @@ -4,14 +4,14 @@ * and open the template in the editor. */ -package stanhebben.zenscript; +package minetweaker.runtime; -import java.util.List; +import java.util.Iterator; /** * - * @author Stanneke + * @author Stan */ -public class ZenParsedModule { - private List files; +public interface IScriptProvider { + public Iterator getScripts(); } diff --git a/MineTweaker3-API/src/main/java/minetweaker/runtime/Tweaker.java b/MineTweaker3-API/src/main/java/minetweaker/runtime/Tweaker.java new file mode 100644 index 0000000..06ac5dc --- /dev/null +++ b/MineTweaker3-API/src/main/java/minetweaker/runtime/Tweaker.java @@ -0,0 +1,125 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.runtime; + +import java.io.BufferedInputStream; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.minecraft.item.IIngredient; +import minetweaker.minecraft.util.CloseablePriorityList; +import stanhebben.zenscript.ZenModule; +import static stanhebben.zenscript.ZenModule.compileScripts; +import static stanhebben.zenscript.ZenModule.extractClassName; +import stanhebben.zenscript.ZenParsedFile; +import stanhebben.zenscript.ZenTokener; +import stanhebben.zenscript.compiler.IEnvironmentGlobal; + +/** + * + * + * @author Stan Hebben + */ +public class Tweaker implements IMineTweaker { + private final CloseablePriorityList scriptProviders = new CloseablePriorityList(); + private final List actions = new ArrayList(); + private final Set wereStuck = new HashSet(); + + @Override + public void apply(IUndoableAction action) { + MineTweakerAPI.logger.logInfo(action.describe()); + action.apply(); + } + + @Override + public void remove(IIngredient items) { + GlobalRegistry.remove(items); + } + + @Override + public List rollback() { + List stuck = new ArrayList(); + for (int i = actions.size() - 1; i >= 0; i--) { + IUndoableAction action = actions.get(i); + if (action.canUndo()) { + MineTweakerAPI.logger.logInfo(action.describeUndo()); + action.undo(); + } else { + stuck.add(0, action); + wereStuck.add(action); + } + } + actions.clear(); + return stuck; + } + + @Override + public Closeable registerScriptProvider(IScriptProvider provider) { + return scriptProviders.add(provider); + } + + @Override + public void load() { + Set executed = new HashSet(); + + for (IScriptProvider provider : scriptProviders) { + Iterator scripts = provider.getScripts(); + while (scripts.hasNext()) { + IScriptIterator script = scripts.next(); + + if (!executed.contains(script.getGroupName())) { + executed.add(script.getGroupName()); + + Map classes = new HashMap(); + IEnvironmentGlobal environmentGlobal = GlobalRegistry.makeGlobalEnvironment(classes); + + List files = new ArrayList(); + + while (script.next()) { + try { + String filename = script.getName(); + + String className = extractClassName(filename); + + Reader reader = new InputStreamReader(new BufferedInputStream(script.open())); + ZenTokener parser = new ZenTokener(reader, environmentGlobal.getEnvironment()); + ZenParsedFile pfile = new ZenParsedFile(filename, className, parser, environmentGlobal); + files.add(pfile); + reader.close(); + } catch (IOException ex) { + MineTweakerAPI.logger.logError("Could not load script " + script.getName() + ": " + ex.getMessage()); + } + } + + String filename = script.getGroupName(); + compileScripts(filename, files, environmentGlobal); + + // execute scripts + ZenModule module = new ZenModule(classes); + module.getMain().run(); + } + } + } + + if (wereStuck.size() > 0) { + MineTweakerAPI.logger.logWarning(Integer.toString(wereStuck.size()) + " modifications were stuck"); + for (IUndoableAction action : wereStuck) { + MineTweakerAPI.logger.logInfo("Stuck: " + action.describe()); + } + } + } +} diff --git a/MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptIteratorDirectory.java b/MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptIteratorDirectory.java new file mode 100644 index 0000000..ba8db00 --- /dev/null +++ b/MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptIteratorDirectory.java @@ -0,0 +1,73 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.runtime.providers; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import minetweaker.runtime.IScriptIterator; + +/** + * + * @author Stan + */ +public class ScriptIteratorDirectory implements IScriptIterator { + private final File directory; + private Iterator contents; + private File current; + + public ScriptIteratorDirectory(File directory) { + this.directory = directory; + + File scriptDir = new File(directory, "scripts"); + List contentsList = new ArrayList(); + if (scriptDir.exists()) { + iterate(scriptDir, contentsList); + } + contents = contentsList.iterator(); + } + + @Override + public String getGroupName() { + return directory.getName(); + } + + @Override + public boolean next() { + if (contents.hasNext()) { + current = contents.next(); + return true; + } else { + return false; + } + } + + @Override + public String getName() { + return current.getAbsolutePath().substring(directory.getAbsolutePath().length()); + } + + @Override + public InputStream open() throws IOException { + return new BufferedInputStream(new FileInputStream(current)); + } + + private static void iterate(File directory, List contentsList) { + for (File file : directory.listFiles()) { + if (file.isDirectory()) { + iterate(file, contentsList); + } else if (file.isFile() && file.getName().endsWith(".zs")) { + contentsList.add(file); + } + } + } +} diff --git a/MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptIteratorSingle.java b/MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptIteratorSingle.java new file mode 100644 index 0000000..75e9089 --- /dev/null +++ b/MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptIteratorSingle.java @@ -0,0 +1,52 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.runtime.providers; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import minetweaker.runtime.IScriptIterator; + +/** + * + * @author Stan + */ +public class ScriptIteratorSingle implements IScriptIterator { + private final File file; + private boolean first = true; + + public ScriptIteratorSingle(File file) { + this.file = file; + } + + @Override + public String getGroupName() { + return file.getName(); + } + + @Override + public boolean next() { + if (first) { + first = false; + return true; + } else { + return false; + } + } + + @Override + public String getName() { + return file.getName(); + } + + @Override + public InputStream open() throws IOException { + return new BufferedInputStream(new FileInputStream(file)); + } +} diff --git a/MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptIteratorZip.java b/MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptIteratorZip.java new file mode 100644 index 0000000..13feb4a --- /dev/null +++ b/MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptIteratorZip.java @@ -0,0 +1,70 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.runtime.providers; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import minetweaker.runtime.IScriptIterator; + +/** + * + * @author Stan + */ +public class ScriptIteratorZip implements IScriptIterator { + private final File file; + private final ZipFile zipFile; + private final Iterator entries; + private ZipEntry current; + + public ScriptIteratorZip(File file) throws IOException { + this.file = file; + + zipFile = new ZipFile(file); + List entriesList = new ArrayList(); + Enumeration original = zipFile.entries(); + while (original.hasMoreElements()) { + ZipEntry entry = original.nextElement(); + if (entry.getName().startsWith("scripts/") && entry.getName().endsWith(".zs")) { + entriesList.add(entry); + } + } + + entries = entriesList.iterator(); + } + + @Override + public String getGroupName() { + return file.getName().substring(0, file.getName().lastIndexOf('.')); + } + + @Override + public boolean next() { + if (entries.hasNext()) { + current = entries.next(); + return true; + } else { + return false; + } + } + + @Override + public String getName() { + return current.getName().substring("scripts/".length()); + } + + @Override + public InputStream open() throws IOException { + return zipFile.getInputStream(current); + } +} diff --git a/MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptProviderDirectory.java b/MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptProviderDirectory.java new file mode 100644 index 0000000..61ec9aa --- /dev/null +++ b/MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptProviderDirectory.java @@ -0,0 +1,47 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.runtime.providers; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import minetweaker.MineTweakerAPI; +import minetweaker.runtime.IScriptIterator; +import minetweaker.runtime.IScriptProvider; + +/** + * + * @author Stan + */ +public class ScriptProviderDirectory implements IScriptProvider { + private final File directory; + + public ScriptProviderDirectory(File directory) { + this.directory = directory; + } + + @Override + public Iterator getScripts() { + List scripts = new ArrayList(); + for (File file : directory.listFiles()) { + if (file.isDirectory()) { + scripts.add(new ScriptIteratorDirectory(file)); + } else if (file.getName().endsWith(".zs")) { + scripts.add(new ScriptIteratorSingle(file)); + } else if (file.getName().endsWith(".zip")) { + try { + scripts.add(new ScriptIteratorZip(file)); + } catch (IOException ex) { + MineTweakerAPI.logger.logError("Could not load " + file.getName() + ": " + ex.getMessage()); + } + } + } + return scripts.iterator(); + } +} diff --git a/MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptProviderMemory.java b/MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptProviderMemory.java new file mode 100644 index 0000000..3267e3d --- /dev/null +++ b/MineTweaker3-API/src/main/java/minetweaker/runtime/providers/ScriptProviderMemory.java @@ -0,0 +1,106 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.runtime.providers; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.InflaterInputStream; +import minetweaker.MineTweakerAPI; +import minetweaker.minecraft.util.FileUtil; +import minetweaker.runtime.IScriptIterator; +import minetweaker.runtime.IScriptProvider; + +/** + * + * @author Stan + */ +public class ScriptProviderMemory { + public static byte[] collect(Iterable providers) { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + try { + DeflaterOutputStream deflater = new DeflaterOutputStream(output); + DataOutputStream deflaterData = new DataOutputStream(deflater); + Set executed = new HashSet(); + + for (IScriptProvider provider : providers) { + Iterator scripts = provider.getScripts(); + while (scripts.hasNext()) { + IScriptIterator script = scripts.next(); + + if (!executed.contains(script.getGroupName())) { + executed.add(script.getGroupName()); + + deflaterData.writeUTF(script.getGroupName()); + + while (script.next()) { + String name = script.getName(); + byte[] data = FileUtil.read(script.open()); + deflaterData.writeUTF(name); + deflaterData.writeInt(data.length); + deflaterData.write(data); + } + + deflaterData.writeUTF(""); + } + } + } + + deflaterData.writeUTF(""); + + deflater.close(); + } catch (IOException ex) { + MineTweakerAPI.logger.logError("Could not collect scripts: " + ex.getMessage()); + } + return output.toByteArray(); + } + + public ScriptProviderMemory(byte[] scripts) { + try { + InflaterInputStream inflater = new InflaterInputStream(new ByteArrayInputStream(scripts)); + DataInputStream inflaterData = new DataInputStream(inflater); + + String moduleName = inflaterData.readUTF(); + while (moduleName.length() > 0) { + List files = new ArrayList(); + + String fileName = inflaterData.readUTF(); + while (fileName.length() > 0) { + byte[] data = new byte[inflaterData.readInt()]; + inflaterData.readFully(data); + files.add(new MemoryFile(fileName, data)); + + fileName = inflaterData.readUTF(); + } + + moduleName = inflaterData.readUTF(); + } + + inflaterData.close(); + } catch (IOException ex) { + MineTweakerAPI.logger.logError("Could not load transmitted scripts: " + ex.getMessage()); + } + } + + private class MemoryFile { + private final String name; + private final byte[] data; + + public MemoryFile(String name, byte[] data) { + this.name = name; + this.data = data; + } + } +} diff --git a/MineTweaker3-MC17-Main/src/main/java/minetweaker/mc172/MineTweakerCommand.java b/MineTweaker3-MC17-Main/src/main/java/minetweaker/mc172/MineTweakerCommand.java index 23c6b28..ad49214 100644 --- a/MineTweaker3-MC17-Main/src/main/java/minetweaker/mc172/MineTweakerCommand.java +++ b/MineTweaker3-MC17-Main/src/main/java/minetweaker/mc172/MineTweakerCommand.java @@ -2,6 +2,7 @@ package minetweaker.mc172; import java.util.Arrays; import java.util.List; +import minetweaker.MineTweakerAPI; import net.minecraft.command.ICommand; import net.minecraft.command.ICommandSender; @@ -82,7 +83,7 @@ public class MineTweakerCommand implements ICommand { } if (arguments[0].equals("reload")) { - MineTweakerMod.instance.reloadScripts(); + MineTweakerAPI.tweaker.load(); } /*if (arguments[0].equals("name")) { diff --git a/MineTweaker3-MC17-Main/src/main/java/minetweaker/mc172/MineTweakerMod.java b/MineTweaker3-MC17-Main/src/main/java/minetweaker/mc172/MineTweakerMod.java index 2e9200f..fa4978f 100644 --- a/MineTweaker3-MC17-Main/src/main/java/minetweaker/mc172/MineTweakerMod.java +++ b/MineTweaker3-MC17-Main/src/main/java/minetweaker/mc172/MineTweakerMod.java @@ -28,8 +28,4 @@ public class MineTweakerMod { MineTweakerAPI.oreDict = new OreDict(); MineTweakerAPI.recipes = new MTRecipeManager(); } - - public void reloadScripts() { - // TODO: implements - } } diff --git a/ZenScript/build.gradle b/ZenScript/build.gradle index d362f62..6aafb36 100644 --- a/ZenScript/build.gradle +++ b/ZenScript/build.gradle @@ -3,4 +3,5 @@ apply plugin: 'java' dependencies { compile group: 'org.ow2.asm', name: 'asm', version:'4.2' compile group: 'org.ow2.asm', name: 'asm-commons', version:'4.2' + compile files("${System.properties['java.home']}/../lib/tools.jar") } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/IZenErrorLogger.java b/ZenScript/src/main/java/stanhebben/zenscript/IZenErrorLogger.java index d57613b..9fbe5e6 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/IZenErrorLogger.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/IZenErrorLogger.java @@ -1,19 +1,27 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript; import stanhebben.zenscript.util.ZenPosition; /** - * - * @author Stanneke + * Error logger. Implementations can forward errors to their own error logging + * system. + * + * @author Stan Hebben */ public interface IZenErrorLogger { + /** + * Called when an error is detected during compilation. + * + * @param position error position + * @param message error message + */ public void error(ZenPosition position, String message); + /** + * Called when a warning is generated during compilation. + * + * @param position warning position + * @param message warning message + */ public void warning(ZenPosition position, String message); } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/TypeExpansion.java b/ZenScript/src/main/java/stanhebben/zenscript/TypeExpansion.java index a2eb48a..848ecc1 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/TypeExpansion.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/TypeExpansion.java @@ -1,9 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript; import java.lang.annotation.Annotation; @@ -23,7 +17,6 @@ import stanhebben.zenscript.annotations.ZenSetter; import stanhebben.zenscript.compiler.IEnvironmentGlobal; import stanhebben.zenscript.compiler.ITypeRegistry; import stanhebben.zenscript.expression.Expression; -import stanhebben.zenscript.expression.ExpressionString; import stanhebben.zenscript.expression.partial.IPartialExpression; import stanhebben.zenscript.type.ZenType; import stanhebben.zenscript.type.expand.ZenExpandCaster; @@ -33,8 +26,11 @@ import stanhebben.zenscript.type.natives.ZenNativeOperator; import stanhebben.zenscript.util.ZenPosition; /** - * - * @author Stanneke + * Type expansions provide additional members for existing types. They can + * add members, casters or operators and these will be available to all compiling + * scripts. + * + * @author Stan Hebben */ public class TypeExpansion { private final Map members; @@ -44,6 +40,10 @@ public class TypeExpansion { private final List binaryOperators; private final List unaryOperators; + /** + * Creates an empty type expansion. Use the expand method to register the + * actual expansions. + */ public TypeExpansion() { members = new HashMap(); staticMembers = new HashMap(); @@ -53,6 +53,15 @@ public class TypeExpansion { unaryOperators = new ArrayList(); } + /** + * Added a native type expansion. The provided class must contain the proper + * annotations for the required expansions, else nothing will happen. Each + * expansion method must be static and accept the expanded type as first + * argument. + * + * @param cls expanding class + * @param types type registry + */ public void expand(Class cls, ITypeRegistry types) { for (Method method : cls.getMethods()) { String methodName = method.getName(); @@ -149,7 +158,17 @@ public class TypeExpansion { } } - public ZenExpandCaster getCaster(ZenType type, IEnvironmentGlobal environment) { + /** + * Retrieves a caster from this expansion. May return null if no suitable + * caster was available. + * + * @param type target type + * @param environment compilation environment + * @return caster, or null if there is no suitable caster + */ + public ZenExpandCaster getCaster( + ZenType type, + IEnvironmentGlobal environment) { for (ZenExpandCaster caster : casters) { if (caster.getTarget().equals(type)) { return caster; @@ -164,7 +183,21 @@ public class TypeExpansion { return null; } - public Expression unary(ZenPosition position, IEnvironmentGlobal environment, Expression value, OperatorType operator) { + /** + * Retrieves a unary operator from this expansion. May return null if no + * suitable operator was available. + * + * @param position calling position + * @param environment compile environment + * @param value argument value + * @param operator unary operator + * @return the resulting expression, or null if no operator was available + */ + public Expression unary( + ZenPosition position, + IEnvironmentGlobal environment, + Expression value, + OperatorType operator) { for (ZenNativeOperator op : unaryOperators) { if (op.getOperator() == operator) { return op.getMethod().callStatic(position, environment, value); @@ -174,7 +207,23 @@ public class TypeExpansion { return null; } - public Expression binary(ZenPosition position, IEnvironmentGlobal environment, Expression left, Expression right, OperatorType operator) { + /** + * Retrieves a binary operator from this expansion. May return null if no + * suitable operator was available. + * + * @param position calling position + * @param environment compile environment + * @param left first argument value (left side) + * @param right second argument value (right side) + * @param operator binary operator + * @return the resulting expression, or null if no operator was available + */ + public Expression binary( + ZenPosition position, + IEnvironmentGlobal environment, + Expression left, + Expression right, + OperatorType operator) { for (ZenNativeOperator op : binaryOperators) { if (op.getOperator() == operator) { return op.getMethod().callStatic(position, environment, left, right); @@ -184,7 +233,25 @@ public class TypeExpansion { return null; } - public Expression trinary(ZenPosition position, IEnvironmentGlobal environment, Expression first, Expression second, Expression third, OperatorType operator) { + /** + * Retrieves a ternary operator from this expansion. May return null if no + * suitable operator was available. + * + * @param position calling position + * @param environment compile environment + * @param first first argument value + * @param second second argument value + * @param third third arugment value + * @param operator ternary operator + * @return the resulting expression, or null if no operator was available + */ + public Expression ternary( + ZenPosition position, + IEnvironmentGlobal environment, + Expression first, + Expression second, + Expression third, + OperatorType operator) { for (ZenNativeOperator op : trinaryOperators) { if (op.getOperator() == operator) { return op.getMethod().callStatic(position, environment, first, second, third); @@ -194,7 +261,21 @@ public class TypeExpansion { return null; } - public IPartialExpression member(ZenPosition position, IEnvironmentGlobal environment, Expression value, String member) { + /** + * Retrieves an instance member from this expansion. May return null if no + * suitable member was available. + * + * @param position calling position + * @param environment compile environment + * @param value instance value + * @param member member name + * @return resulting member expression, or null if no such member was available + */ + public IPartialExpression instanceMember( + ZenPosition position, + IEnvironmentGlobal environment, + Expression value, + String member) { if (members.containsKey(member)) { return members.get(member).instance(position, environment, value); } @@ -202,6 +283,15 @@ public class TypeExpansion { return null; } + /** + * Retrieves a static member from this expansion. May return null if no + * suitable member was available. + * + * @param position calling position + * @param environment compile environment + * @param member member name + * @return resulting static member expression, or null if no such member was available + */ public IPartialExpression staticMember(ZenPosition position, IEnvironmentGlobal environment, String member) { if (staticMembers.containsKey(member)) { return staticMembers.get(member).instance(position, environment); @@ -210,6 +300,15 @@ public class TypeExpansion { return null; } + // ####################### + // ### Private methods ### + // ####################### + + /** + * Checks if the given method is static. Throws an exception if not. + * + * @param method metod to validate + */ private void checkStatic(Method method) { if ((method.getModifiers() & Modifier.STATIC) == 0) { throw new RuntimeException("Expansion method " + method.getName() + " must be static"); diff --git a/ZenScript/src/main/java/stanhebben/zenscript/ZenModule.java b/ZenScript/src/main/java/stanhebben/zenscript/ZenModule.java index 90a4ebd..8ae4221 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/ZenModule.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/ZenModule.java @@ -39,13 +39,26 @@ import stanhebben.zenscript.util.StringUtil; import static stanhebben.zenscript.util.ZenTypeUtil.internal; /** - * - * @author Stanneke + * Main module class. Contains a compiled module. The static methods of this + * class can be used to compile a specific file or files. + * + * Modules may contain statements in their source, or define functions. Functions + * in different scripts within the same module are accessible to each other, but + * not to other modules. + * + * @author Stan Hebben */ public class ZenModule { - public static void compileScripts(String mainclass, String mainFileName, List scripts, IEnvironmentGlobal environmentGlobal) { + /** + * Compiles a set of parsed files into a module. + * + * @param mainFileName main filename (used for debug info) + * @param scripts scripts to compile + * @param environmentGlobal global compile environment + */ + public static void compileScripts(String mainFileName, List scripts, IEnvironmentGlobal environmentGlobal) { ClassWriter clsMain = new ClassWriter(ClassWriter.COMPUTE_MAXS); - clsMain.visitSource(mainclass, null); + clsMain.visitSource(mainFileName, null); clsMain.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, "__ZenMain__", null, internal(Object.class), new String[] {internal(Runnable.class)}); MethodOutput mainRun = new MethodOutput(clsMain, Opcodes.ACC_PUBLIC, "run", "()V", null, null); @@ -159,6 +172,14 @@ public class ZenModule { environmentGlobal.putClass("__ZenMain__", clsMain.toByteArray()); } + /** + * Compiles a single script file. + * + * @param single file to be compiled + * @param environment compile environment + * @return compiled module + * @throws IOException if the file could not be read + */ public static ZenModule compileScriptFile(File single, IZenCompileEnvironment environment) throws IOException { Map classes = new HashMap(); ClassNameGenerator nameGen = new ClassNameGenerator(); @@ -173,14 +194,14 @@ public class ZenModule { FileInputStream input = new FileInputStream(single); Reader reader = new InputStreamReader(new BufferedInputStream(input)); - ZenParser parser = new ZenParser(reader, environment); + ZenTokener parser = new ZenTokener(reader, environment); ZenParsedFile file = new ZenParsedFile(filename, className, parser, environmentGlobal); reader.close(); List files = new ArrayList(); files.add(file); - compileScripts(className, filename, files, environmentGlobal); + compileScripts(filename, files, environmentGlobal); // debug: output classes File outputDir = new File("generated"); @@ -196,6 +217,16 @@ public class ZenModule { return new ZenModule(classes); } + /** + * Compiles a zip file as module. All containing files (inside the given + * subdirectory) will be compiled. + * + * @param file zip file + * @param subdir subdirectory (use empty string to compile all) + * @param environment compile environment + * @return compiled module + * @throws IOException if the file could not be read properly + */ public static ZenModule compileZip(File file, String subdir, IZenCompileEnvironment environment) throws IOException { Map classes = new HashMap(); ClassNameGenerator nameGen = new ClassNameGenerator(); @@ -217,7 +248,7 @@ public class ZenModule { String className = extractClassName(filename); Reader reader = new InputStreamReader(new BufferedInputStream(zipFile.getInputStream(entry))); - ZenParser parser = new ZenParser(reader, environment); + ZenTokener parser = new ZenTokener(reader, environment); ZenParsedFile pfile = new ZenParsedFile(filename, className, parser, environmentGlobal); files.add(pfile); reader.close(); @@ -225,8 +256,7 @@ public class ZenModule { } String filename = file.getName(); - String className = extractClassName(filename); - compileScripts(className, filename, files, environmentGlobal); + compileScripts(filename, files, environmentGlobal); // debug: output classes File outputDir = new File("generated"); @@ -245,11 +275,23 @@ public class ZenModule { private final Map classes; private final MyClassLoader classLoader; - private ZenModule(Map classes) { + /** + * Constructs a module for the given set of classes. Mostly intended for + * internal use. + * + * @param classes + */ + public ZenModule(Map classes) { this.classes = classes; classLoader = new MyClassLoader(); } + /** + * Retrieves the main runnable. Running this runnable will execute the content + * of the given module. + * + * @return main runnable + */ public Runnable getMain() { try { return (Runnable) classLoader.loadClass("__ZenMain__").newInstance(); @@ -262,18 +304,17 @@ public class ZenModule { } } - private class MyClassLoader extends ClassLoader { - @Override - public Class findClass(String name) throws ClassNotFoundException { - if (classes.containsKey(name)) { - return this.defineClass(name, classes.get(name), 0, classes.get(name).length); - } - - return super.findClass(name); - } - } + // ###################### + // ### Static methods ### + // ###################### - private static String extractClassName(String filename) { + /** + * Converts a filename into a class name. + * + * @param filename filename to convert + * @return class name + */ + public static String extractClassName(String filename) { filename = filename.replace('\\', '/'); if (filename.startsWith("/")) filename = filename.substring(1); @@ -291,4 +332,22 @@ public class ZenModule { return filename.substring(0, 1).toUpperCase() + filename.substring(1); } } + + // ############################# + // ### Private inner classes ### + // ############################# + + /** + * Custom class loader. Loads classes from this module. + */ + private class MyClassLoader extends ClassLoader { + @Override + public Class findClass(String name) throws ClassNotFoundException { + if (classes.containsKey(name)) { + return this.defineClass(name, classes.get(name), 0, classes.get(name).length); + } + + return super.findClass(name); + } + } } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/ZenParsedFile.java b/ZenScript/src/main/java/stanhebben/zenscript/ZenParsedFile.java index 8db60d6..e84b667 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/ZenParsedFile.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/ZenParsedFile.java @@ -1,16 +1,10 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import static stanhebben.zenscript.ZenParser.*; +import static stanhebben.zenscript.ZenTokener.*; import stanhebben.zenscript.compiler.IEnvironmentGlobal; import stanhebben.zenscript.definitions.Import; import stanhebben.zenscript.definitions.ParsedFunction; @@ -18,8 +12,19 @@ import stanhebben.zenscript.parser.Token; import stanhebben.zenscript.statements.Statement; /** - * - * @author Stanneke + * Contains a parsed file. + * + * A parsed file contains: + *
    + *
  • A set of imports
  • + *
  • A set of parsed functions
  • + *
  • A set of statuments
  • + *
+ * + * This parsed file cannot be executed by itself, but it can be compiled into + * a module, possibly together with other files. + * + * @author Stan Hebben */ public class ZenParsedFile { private final String filename; @@ -28,7 +33,15 @@ public class ZenParsedFile { private final Map functions; private final List statements; - public ZenParsedFile(String filename, String classname, ZenParser parser, IEnvironmentGlobal environment) { + /** + * Constructs and parses a given file. + * + * @param filename parsed filename + * @param classname output class name + * @param tokener input tokener + * @param environment compile environment + */ + public ZenParsedFile(String filename, String classname, ZenTokener tokener, IEnvironmentGlobal environment) { this.filename = filename; this.classname = classname; @@ -36,61 +49,86 @@ public class ZenParsedFile { functions = new HashMap(); statements = new ArrayList(); - parser.setFile(this); + tokener.setFile(this); - while (parser.peek() != null && parser.peek().getType() == T_IMPORT) { - Token start = parser.next(); + while (tokener.peek() != null && tokener.peek().getType() == T_IMPORT) { + Token start = tokener.next(); List importName = new ArrayList(); - Token tName = parser.required(T_ID, "identifier expected"); + Token tName = tokener.required(T_ID, "identifier expected"); importName.add(tName.getValue()); - while (parser.optional(T_DOT) != null) { - Token tNamePart = parser.required(T_ID, "identifier expected"); + while (tokener.optional(T_DOT) != null) { + Token tNamePart = tokener.required(T_ID, "identifier expected"); importName.add(tNamePart.getValue()); } String rename = null; - if (parser.optional(T_AS) != null) { - Token tRename = parser.required(T_ID, "identifier expected"); + if (tokener.optional(T_AS) != null) { + Token tRename = tokener.required(T_ID, "identifier expected"); rename = tRename.getValue(); } - parser.required(T_SEMICOLON, "; expected"); + tokener.required(T_SEMICOLON, "; expected"); imports.add(new Import(start.getPosition(), importName, rename)); } - while (parser.hasNext()) { - Token next = parser.peek(); + while (tokener.hasNext()) { + Token next = tokener.peek(); if (next.getType() == T_FUNCTION) { - ParsedFunction function = ParsedFunction.parse(parser, environment); + ParsedFunction function = ParsedFunction.parse(tokener, environment); if (functions.containsKey(function.getName())) { environment.error(function.getPosition(), "function " + function.getName() + " already exists"); } functions.put(function.getName(), function); } else { - statements.add(Statement.read(parser, environment)); + statements.add(Statement.read(tokener, environment)); } } } + /** + * Gets the output classname for this file. + * + * @return output classname + */ public String getClassName() { return classname; } + /** + * Gets the input filename for this file. + * + * @return input filename + */ public String getFileName() { return filename; } + /** + * Gets the imports list. + * + * @return imports list + */ public List getImports() { return imports; } + /** + * Gets this file's script statements. + * + * @return script statement list + */ public List getStatements() { return statements; } + /** + * Gets the functions defined inside this file. + * + * @return script functions + */ public Map getFunctions() { return functions; } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/ZenRuntimeException.java b/ZenScript/src/main/java/stanhebben/zenscript/ZenRuntimeException.java index 2fdfa09..4703aeb 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/ZenRuntimeException.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/ZenRuntimeException.java @@ -1,14 +1,11 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript; /** - * - * @author Stanneke + * ZenRuntimeExceptions are thrown when an internal error occurs during + * execution of scripts. Since ZenScript is only partially typesafe, errors + * may occur at runtime due to impossible operations being executed. + * + * @author Stan Hebben */ public class ZenRuntimeException extends RuntimeException { public ZenRuntimeException(String message) { diff --git a/ZenScript/src/main/java/stanhebben/zenscript/ZenParser.java b/ZenScript/src/main/java/stanhebben/zenscript/ZenTokener.java similarity index 86% rename from ZenScript/src/main/java/stanhebben/zenscript/ZenParser.java rename to ZenScript/src/main/java/stanhebben/zenscript/ZenTokener.java index cfc4e28..0bff770 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/ZenParser.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/ZenTokener.java @@ -10,7 +10,13 @@ import stanhebben.zenscript.parser.Token; import stanhebben.zenscript.parser.TokenStream; import stanhebben.zenscript.symbols.IZenCompileEnvironment; -public class ZenParser extends TokenStream { +/** + * A tokener is capable of splitting a single file into tokens. It's intended + * for use by LL(*) parsers. + * + * @author Stan Hebben + */ +public class ZenTokener extends TokenStream { private static final HashMap KEYWORDS; public static final int T_ID = 1; @@ -222,22 +228,45 @@ public class ZenParser extends TokenStream { private final IZenCompileEnvironment environment; - public ZenParser(Reader contents, IZenCompileEnvironment environment) throws IOException { + /** + * Constructs a tokener from the given reader. + * + * @param contents file reader + * @param environment compile environment + * @throws IOException if the file could not be read properly + */ + public ZenTokener(Reader contents, IZenCompileEnvironment environment) throws IOException { super(contents, DFA); this.environment = environment; } - public ZenParser(String contents, IZenCompileEnvironment environment) throws IOException { + /** + * Constructs a tokener from the given string. + * + * @param contents content string + * @param environment compile environment + * @throws IOException shouldn't happen + */ + public ZenTokener(String contents, IZenCompileEnvironment environment) throws IOException { super(new StringReader(contents), DFA); this.environment = environment; } + /** + * Retrieves the compile environment of this tokener. + * + * @return compile environment + */ public IZenCompileEnvironment getEnvironment() { return environment; } + // ################################## + // ### TokenStream implementation ### + // ################################## + @Override public Token process(Token token) { if (token.getType() == T_ID) { diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/CompareType.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/CompareType.java index 525581e..df1a1f9 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/CompareType.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/CompareType.java @@ -1,17 +1,11 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; /** - * - * @author Stanneke + * Used to indicate comparison types. + * + * @author Stan Hebben */ public enum CompareType { - FULL, LT, GT, EQ, diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/IterableList.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/IterableList.java index 41a20bd..ceca76b 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/IterableList.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/IterableList.java @@ -1,9 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; import java.lang.annotation.ElementType; diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/IterableMap.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/IterableMap.java index 1a4c15a..732581a 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/IterableMap.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/IterableMap.java @@ -1,9 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; import java.lang.annotation.ElementType; diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/IterableSimple.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/IterableSimple.java index 3930590..b5530ad 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/IterableSimple.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/IterableSimple.java @@ -1,9 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; import java.lang.annotation.ElementType; @@ -12,9 +6,10 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Indicates a simple iterable. Should implement the iterable interface. + * Indicates a simple iterable. Annotated class must implement the iterable + * interface. * - * @author Stanneke + * @author Stan Hebben */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/NotNull.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/NotNull.java index d266814..6ce9999 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/NotNull.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/NotNull.java @@ -1,9 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; import java.lang.annotation.ElementType; @@ -12,8 +6,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * - * @author Stanneke + * Indicates that the given method parameter cannot be null. + * + * @author Stan Hebben */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/OperatorType.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/OperatorType.java index d8217fd..3171786 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/OperatorType.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/OperatorType.java @@ -1,14 +1,9 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; /** - * - * @author Stanneke + * Enum used to indicate operator type. + * + * @author Stan Hebben */ public enum OperatorType { ADD, diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/Optional.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/Optional.java index 3230126..1e02ad6 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/Optional.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/Optional.java @@ -1,9 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; import java.lang.annotation.ElementType; diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenCaster.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenCaster.java index ce88f47..6c77c5d 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenCaster.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenCaster.java @@ -1,9 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; import java.lang.annotation.ElementType; @@ -15,9 +9,13 @@ import java.lang.annotation.Target; * Denotes a caster. Casters are capable of converting one type into another. * They implement the 'as' operator. * + * For a native class, no arguments are provided. For an expansion method, the + * argument is the source value. + * * @author Stan Hebben */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ZenCaster { + } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenClass.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenClass.java index 1f14713..c9efe12 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenClass.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenClass.java @@ -1,9 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; import java.lang.annotation.ElementType; @@ -20,5 +14,11 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) public @interface ZenClass { + /** + * Contains the class' package and name. If omitted, the java package and + * name will be used. + * + * @return + */ String value() default ""; } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenExpansion.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenExpansion.java index bf7abf0..8fab394 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenExpansion.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenExpansion.java @@ -1,9 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; import java.lang.annotation.ElementType; @@ -12,11 +6,29 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * - * @author Stanneke + * Indicates that the given class contains an expansion for a certain type. + * The expansions themselves are given through annotated static methods. + * + * @author Stan Hebben */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) public @interface ZenExpansion { + /** + * Contains the type of the annotated class. May be any kind of ZenScript type. + * + * Examples: + *
    + *
  • int
  • + *
  • my.package.MyClass
  • + *
  • my.package.MyClass[]
  • + *
  • any
  • + *
  • any[]
  • + *
  • any[any]
  • + * + *
+ * + * @return expanded type + */ public String value(); } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenGetter.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenGetter.java index 31e6530..057193b 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenGetter.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenGetter.java @@ -1,9 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; import java.lang.annotation.ElementType; @@ -15,10 +9,18 @@ import java.lang.annotation.Target; * Indicates a getter. Will make the given method accessible as getter, that is, * it's called when value.name is being used. * + * For a native class, no arguments are provided. For an expansion, a single + * argument with the source value is provided. + * * @author Stan Hebben */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ZenGetter { + /** + * Getter name. If omitted, the method name will be used as value name. + * + * @return getter name + */ String value() default ""; } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMemberGetter.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMemberGetter.java index c548e9a..72f6073 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMemberGetter.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMemberGetter.java @@ -1,9 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; import java.lang.annotation.ElementType; @@ -12,8 +6,15 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * - * @author Stan + * Indicates a member getter. A member getter is a special kind of operator which + * is a fallback if a member could not be resolved. Can be used to make contents + * available as if they were members. + * + * If this method is a native class, it accepts a single string parameter with + * the member name. If this method is an expansion method, it accepts the source + * value and the member name. + * + * @author Stan Hebben */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMemberSetter.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMemberSetter.java index fe64cf9..ceb2f1b 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMemberSetter.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMemberSetter.java @@ -1,9 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; import java.lang.annotation.ElementType; @@ -12,8 +6,15 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * - * @author Stan + * Used to indicate a member setter. Companion to member getters, but allow + * setting contents of this object as if they were members. + * + * If this method is a native class, it accepts a string parameter with + * the member name and a second parameter with the value. If this method is an + * expansion method, it accepts the source value, the member name and the value + * to be assigned. + * + * @author Stan Hebben */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMethod.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMethod.java index d8732d1..1d1425f 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMethod.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMethod.java @@ -1,9 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; import java.lang.annotation.ElementType; @@ -12,11 +6,21 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * - * @author Stanneke + * Used to indicate an exposed method. + * + * If this method is part of a native class, it will simply accept the parameters + * as provided. If it is part of an expansion method, it will also accept the + * instance value as first parameter. + * + * @author Stan Hebben */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ZenMethod { + /** + * Method name. If omitted, the original method name will be used. + * + * @return method name + */ public String value() default ""; } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMethodStatic.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMethodStatic.java index 01c3ac4..7c1b0fa 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMethodStatic.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenMethodStatic.java @@ -12,11 +12,18 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * - * @author Stanneke + * Used to indicate static methods for expansions. For native classes, use ZenMethod + * instead on a static method. + * + * @author Stan Hebben */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ZenMethodStatic { + /** + * Method name. If omitted, the annotated method name will be used. + * + * @return method name + */ public String value() default ""; } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenOperator.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenOperator.java index 91b5b03..7ac7ada 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenOperator.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenOperator.java @@ -1,9 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; import java.lang.annotation.ElementType; @@ -12,11 +6,17 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * - * @author Stanneke + * Used to indicate an operator. The arguments depend on the kind of operator. + * + * @author Stan Hebben */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ZenOperator { + /** + * Operator type for this operator. + * + * @return operator type + */ OperatorType value(); } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenSetter.java b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenSetter.java index d8b37bc..875e2f4 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenSetter.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/annotations/ZenSetter.java @@ -1,9 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - package stanhebben.zenscript.annotations; import java.lang.annotation.ElementType; @@ -12,11 +6,21 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * - * @author Stanneke + * Used to annotate setters. Will make the given method accessible as setter, that is, + * it's called when value.name is being assinged a value. + * + * For a native class, a single argument with the assinged value is provided. + * For an expansion, the target object and assigned value are provided. + * + * @author Stan Hebben */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ZenSetter { + /** + * Setter name. If omitted, the method name is used as property name. + * + * @return setter name + */ String value() default ""; } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/compiler/IEnvironmentGlobal.java b/ZenScript/src/main/java/stanhebben/zenscript/compiler/IEnvironmentGlobal.java index e05f2e2..7a1aac8 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/compiler/IEnvironmentGlobal.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/compiler/IEnvironmentGlobal.java @@ -6,13 +6,11 @@ package stanhebben.zenscript.compiler; -import java.lang.reflect.Type; import stanhebben.zenscript.IZenErrorLogger; import stanhebben.zenscript.TypeExpansion; import stanhebben.zenscript.expression.partial.IPartialExpression; import stanhebben.zenscript.symbols.IZenCompileEnvironment; import stanhebben.zenscript.symbols.IZenSymbol; -import stanhebben.zenscript.type.ZenType; import stanhebben.zenscript.util.ZenPosition; /** diff --git a/ZenScript/src/main/java/stanhebben/zenscript/definitions/ParsedFunction.java b/ZenScript/src/main/java/stanhebben/zenscript/definitions/ParsedFunction.java index be03e12..3d0d1cc 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/definitions/ParsedFunction.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/definitions/ParsedFunction.java @@ -6,11 +6,11 @@ package stanhebben.zenscript.definitions; -import static stanhebben.zenscript.ZenParser.*; +import static stanhebben.zenscript.ZenTokener.*; import java.util.ArrayList; import java.util.List; -import stanhebben.zenscript.ZenParser; +import stanhebben.zenscript.ZenTokener; import stanhebben.zenscript.compiler.IEnvironmentGlobal; import stanhebben.zenscript.parser.Token; import stanhebben.zenscript.statements.Statement; @@ -23,9 +23,9 @@ import stanhebben.zenscript.util.ZenPosition; * @author Stanneke */ public class ParsedFunction { - public static ParsedFunction parse(ZenParser parser, IEnvironmentGlobal environment) { + public static ParsedFunction parse(ZenTokener parser, IEnvironmentGlobal environment) { parser.next(); - Token tName = parser.required(ZenParser.T_ID, "identifier expected"); + Token tName = parser.required(ZenTokener.T_ID, "identifier expected"); // function (argname [as type], argname [as type], ...) [as type] { ...contents... } parser.required(T_BROPEN, "( expected"); diff --git a/ZenScript/src/main/java/stanhebben/zenscript/docs/ZenScriptDoclet.java b/ZenScript/src/main/java/stanhebben/zenscript/docs/ZenScriptDoclet.java new file mode 100644 index 0000000..2b84391 --- /dev/null +++ b/ZenScript/src/main/java/stanhebben/zenscript/docs/ZenScriptDoclet.java @@ -0,0 +1,26 @@ +package stanhebben.zenscript.docs; + +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + + + +import com.sun.javadoc.ClassDoc; +import com.sun.javadoc.RootDoc; + +/** + * + * @author Stan + */ +public class ZenScriptDoclet { + public static boolean start(RootDoc root) { + ClassDoc[] classes = root.classes(); + for (int i = 0; i < classes.length; ++i) { + System.out.println(classes[i]); + } + return true; + } +} diff --git a/ZenScript/src/main/java/stanhebben/zenscript/expression/Expression.java b/ZenScript/src/main/java/stanhebben/zenscript/expression/Expression.java index e8400bd..6d70421 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/expression/Expression.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/expression/Expression.java @@ -1,7 +1,7 @@ package stanhebben.zenscript.expression; import org.objectweb.asm.Label; -import stanhebben.zenscript.ZenParser; +import stanhebben.zenscript.ZenTokener; import stanhebben.zenscript.compiler.IEnvironmentGlobal; import stanhebben.zenscript.compiler.IEnvironmentMethod; import stanhebben.zenscript.expression.partial.IPartialExpression; @@ -12,7 +12,7 @@ import stanhebben.zenscript.type.ZenTypeBool; import stanhebben.zenscript.util.ZenPosition; public abstract class Expression implements IPartialExpression { - public static final Expression parse(ZenParser parser, IEnvironmentMethod environment) { + public static final Expression parse(ZenTokener parser, IEnvironmentMethod environment) { return ParsedExpression.read(parser, environment) .compile(environment) .eval(environment); diff --git a/ZenScript/src/main/java/stanhebben/zenscript/package-info.java b/ZenScript/src/main/java/stanhebben/zenscript/package-info.java new file mode 100644 index 0000000..3536640 --- /dev/null +++ b/ZenScript/src/main/java/stanhebben/zenscript/package-info.java @@ -0,0 +1,40 @@ +/** + *

ZenScript library

+ * + * The goal of ZenScript was to provide a scripting system that fit several + * requirements: + *
    + *
  • Be usable by people without any prior programming knowledge, for simple tasks
  • + *
  • Be usable for advanced tasks by experienced programmers
  • + *
  • Integrate easily with Java classes
  • + *
  • Provide sufficient syntax and libraries to integrate with its environment
  • + *
  • Be clear and concise in its operation
  • + *
  • Be typesafe, such that both small and large applications can be made with it
  • + *
  • It should be efficient to run
  • + *
+ * + * ZenScript originated from MineTweaker where I needed a simple programming + * language that would allow users without programming knowledge to be able + * to execute simple commands by following the tutorials for it. + * + * Originally MineTweaker had a simple one-line-at-a-time parsed scripting system, + * but it quickly became clear that it wasn't flexible enough, so a simple parsed + * language was created. This parsed language worked quite well but was very + * inefficient as each value was wrapped into its own object. As I wanted to + * expand the capabilities, this language was not very efficient. + * + * Additionally, it wasn't type-safe. There were no type definitions. On one hand, + * this is handy, since I didn't want to bother people with types. Following the + * tutorial was easy and the code was short. However, this gives a problem for the + * more experienced user, wanting to go beyond the basic tutorials: what are these + * values I'm working with, which properties does it have and which methods are + * available no it? It's not clear. + * + * As a balance, ZenScript allows mixed typed and typeless behavior. You don't + * need to define types anywhere - the compile will infer them where possible + * and exhibit typeless behavior when the type is effectively unknown. In nearly + * all the cases, the type is perfectly known and execution runs at native java + * speed. Since there are types, they can be documented and enforced. + */ + +package stanhebben.zenscript; diff --git a/ZenScript/src/main/java/stanhebben/zenscript/parser/expression/ParsedExpression.java b/ZenScript/src/main/java/stanhebben/zenscript/parser/expression/ParsedExpression.java index 79696c3..e20fa83 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/parser/expression/ParsedExpression.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/parser/expression/ParsedExpression.java @@ -8,8 +8,8 @@ package stanhebben.zenscript.parser.expression; import java.util.ArrayList; import java.util.List; -import stanhebben.zenscript.ZenParser; -import static stanhebben.zenscript.ZenParser.*; +import stanhebben.zenscript.ZenTokener; +import static stanhebben.zenscript.ZenTokener.*; import stanhebben.zenscript.annotations.CompareType; import stanhebben.zenscript.annotations.OperatorType; import stanhebben.zenscript.compiler.IEnvironmentGlobal; @@ -36,11 +36,11 @@ import stanhebben.zenscript.util.ZenPosition; * @author Stanneke */ public abstract class ParsedExpression { - public static ParsedExpression read(ZenParser parser, IEnvironmentGlobal environment) { + public static ParsedExpression read(ZenTokener parser, IEnvironmentGlobal environment) { return readAssignExpression(parser, environment); } - private static ParsedExpression readAssignExpression(ZenParser parser, IEnvironmentGlobal environment) { + private static ParsedExpression readAssignExpression(ZenTokener parser, IEnvironmentGlobal environment) { ZenPosition position = parser.peek().getPosition(); ParsedExpression left = readConditionalExpression(position, parser, environment); @@ -80,7 +80,7 @@ public abstract class ParsedExpression { return left; } - private static ParsedExpression readConditionalExpression(ZenPosition position, ZenParser parser, IEnvironmentGlobal environment) { + private static ParsedExpression readConditionalExpression(ZenPosition position, ZenTokener parser, IEnvironmentGlobal environment) { ParsedExpression left = readOrOrExpression(position, parser, environment); if (parser.optional(T_QUEST) != null) { @@ -93,7 +93,7 @@ public abstract class ParsedExpression { return left; } - private static ParsedExpression readOrOrExpression(ZenPosition position, ZenParser parser, IEnvironmentGlobal environment) { + private static ParsedExpression readOrOrExpression(ZenPosition position, ZenTokener parser, IEnvironmentGlobal environment) { ParsedExpression left = readAndAndExpression(position, parser, environment); while (parser.optional(T_OR2) != null) { @@ -103,7 +103,7 @@ public abstract class ParsedExpression { return left; } - private static ParsedExpression readAndAndExpression(ZenPosition position, ZenParser parser, IEnvironmentGlobal environment) { + private static ParsedExpression readAndAndExpression(ZenPosition position, ZenTokener parser, IEnvironmentGlobal environment) { ParsedExpression left = readOrExpression(position, parser, environment); while (parser.optional(T_AND2) != null) { @@ -113,7 +113,7 @@ public abstract class ParsedExpression { return left; } - private static ParsedExpression readOrExpression(ZenPosition position, ZenParser parser, IEnvironmentGlobal environment) { + private static ParsedExpression readOrExpression(ZenPosition position, ZenTokener parser, IEnvironmentGlobal environment) { ParsedExpression left = readXorExpression(position, parser, environment); while (parser.optional(T_OR) != null) { @@ -123,7 +123,7 @@ public abstract class ParsedExpression { return left; } - private static ParsedExpression readXorExpression(ZenPosition position, ZenParser parser, IEnvironmentGlobal environment) { + private static ParsedExpression readXorExpression(ZenPosition position, ZenTokener parser, IEnvironmentGlobal environment) { ParsedExpression left = readAndExpression(position, parser, environment); while (parser.optional(T_XOR) != null) { @@ -133,7 +133,7 @@ public abstract class ParsedExpression { return left; } - private static ParsedExpression readAndExpression(ZenPosition position, ZenParser parser, IEnvironmentGlobal environment) { + private static ParsedExpression readAndExpression(ZenPosition position, ZenTokener parser, IEnvironmentGlobal environment) { ParsedExpression left = readCompareExpression(position, parser, environment); while (parser.optional(T_AND) != null) { @@ -143,7 +143,7 @@ public abstract class ParsedExpression { return left; } - private static ParsedExpression readCompareExpression(ZenPosition position, ZenParser parser, IEnvironmentGlobal environment) { + private static ParsedExpression readCompareExpression(ZenPosition position, ZenTokener parser, IEnvironmentGlobal environment) { ParsedExpression left = readAddExpression(position, parser, environment); switch (parser.peek() == null ? -1 : parser.peek().getType()) { @@ -187,7 +187,7 @@ public abstract class ParsedExpression { return left; } - private static ParsedExpression readAddExpression(ZenPosition position, ZenParser parser, IEnvironmentGlobal environment) { + private static ParsedExpression readAddExpression(ZenPosition position, ZenTokener parser, IEnvironmentGlobal environment) { ParsedExpression left = readMulExpression(position, parser, environment); while (true) { @@ -207,7 +207,7 @@ public abstract class ParsedExpression { return left; } - private static ParsedExpression readMulExpression(ZenPosition position, ZenParser parser, IEnvironmentGlobal environment) { + private static ParsedExpression readMulExpression(ZenPosition position, ZenTokener parser, IEnvironmentGlobal environment) { ParsedExpression left = readUnaryExpression(position, parser, environment); while (true) { @@ -228,7 +228,7 @@ public abstract class ParsedExpression { return left; } - private static ParsedExpression readUnaryExpression(ZenPosition position, ZenParser parser, IEnvironmentGlobal environment) { + private static ParsedExpression readUnaryExpression(ZenPosition position, ZenTokener parser, IEnvironmentGlobal environment) { switch (parser.peek().getType()) { case T_NOT: parser.next(); @@ -247,7 +247,7 @@ public abstract class ParsedExpression { } } - private static ParsedExpression readPostfixExpression(ZenPosition position, ZenParser parser, IEnvironmentGlobal environment) { + private static ParsedExpression readPostfixExpression(ZenPosition position, ZenTokener parser, IEnvironmentGlobal environment) { ParsedExpression base = readPrimaryExpression(position, parser, environment); while (true) { @@ -293,7 +293,7 @@ public abstract class ParsedExpression { return base; } - private static ParsedExpression readPrimaryExpression(ZenPosition position, ZenParser parser, IEnvironmentGlobal environment) { + private static ParsedExpression readPrimaryExpression(ZenPosition position, ZenTokener parser, IEnvironmentGlobal environment) { switch (parser.peek().getType()) { case T_INTVALUE: return new ParsedExpressionValue( @@ -361,7 +361,7 @@ public abstract class ParsedExpression { Token start = parser.next(); List tokens = new ArrayList(); Token next = parser.next(); - while (next.getType() != ZenParser.T_GT) { + while (next.getType() != ZenTokener.T_GT) { tokens.add(next); next = parser.next(); } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/statements/Statement.java b/ZenScript/src/main/java/stanhebben/zenscript/statements/Statement.java index d34f9c6..b77e9df 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/statements/Statement.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/statements/Statement.java @@ -3,8 +3,8 @@ package stanhebben.zenscript.statements; import java.util.ArrayList; import java.util.List; -import stanhebben.zenscript.ZenParser; -import static stanhebben.zenscript.ZenParser.*; +import stanhebben.zenscript.ZenTokener; +import static stanhebben.zenscript.ZenTokener.*; import stanhebben.zenscript.compiler.IEnvironmentGlobal; import stanhebben.zenscript.compiler.IEnvironmentMethod; import stanhebben.zenscript.parser.Token; @@ -13,7 +13,7 @@ import stanhebben.zenscript.type.ZenType; import stanhebben.zenscript.util.ZenPosition; public abstract class Statement { - public static Statement read(ZenParser parser, IEnvironmentGlobal environment) { + public static Statement read(ZenTokener parser, IEnvironmentGlobal environment) { Token next = parser.peek(); switch (next.getType()) { case T_AOPEN: { diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenType.java b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenType.java index 1546cb5..5bc8402 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenType.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenType.java @@ -3,7 +3,7 @@ package stanhebben.zenscript.type; import java.io.IOException; import org.objectweb.asm.Type; import stanhebben.zenscript.TypeExpansion; -import stanhebben.zenscript.ZenParser; +import stanhebben.zenscript.ZenTokener; import stanhebben.zenscript.annotations.CompareType; import stanhebben.zenscript.annotations.OperatorType; import stanhebben.zenscript.compiler.IEnvironmentGlobal; @@ -37,52 +37,52 @@ public abstract class ZenType { public static ZenType parse(String type, IEnvironmentGlobal environment) { try { - ZenParser parser = new ZenParser(type, environment.getEnvironment()); + ZenTokener parser = new ZenTokener(type, environment.getEnvironment()); return read(parser, environment); } catch (IOException ex) { return null; } } - public static ZenType read(ZenParser parser, IEnvironmentGlobal environment) { + public static ZenType read(ZenTokener parser, IEnvironmentGlobal environment) { ZenType base; Token next = parser.next(); switch (next.getType()) { - case ZenParser.T_ANY: + case ZenTokener.T_ANY: base = ANY; break; - case ZenParser.T_VOID: + case ZenTokener.T_VOID: base = VOID; break; - case ZenParser.T_BOOL: + case ZenTokener.T_BOOL: base = BOOL; break; - case ZenParser.T_BYTE: + case ZenTokener.T_BYTE: base = BYTE; break; - case ZenParser.T_SHORT: + case ZenTokener.T_SHORT: base = SHORT; break; - case ZenParser.T_INT: + case ZenTokener.T_INT: base = INT; break; - case ZenParser.T_LONG: + case ZenTokener.T_LONG: base = LONG; break; - case ZenParser.T_FLOAT: + case ZenTokener.T_FLOAT: base = FLOAT; break; - case ZenParser.T_DOUBLE: + case ZenTokener.T_DOUBLE: base = DOUBLE; break; - case ZenParser.T_STRING: + case ZenTokener.T_STRING: base = STRING; break; - case ZenParser.T_ID: + case ZenTokener.T_ID: IPartialExpression partial = environment.getValue(next.getValue(), next.getPosition()); - while (parser.optional(ZenParser.T_DOT) != null) { - Token member = parser.required(ZenParser.T_ID, "identifier expected"); + while (parser.optional(ZenTokener.T_DOT) != null) { + Token member = parser.required(ZenTokener.T_ID, "identifier expected"); partial = partial.getMember(member.getPosition(), environment, member.getValue()); } base = partial.toType(environment); @@ -91,10 +91,10 @@ public abstract class ZenType { throw new ParseException(next, "Unknown type: " + next.getValue()); } - while (parser.optional(ZenParser.T_SQBROPEN) != null) { - if (parser.optional(ZenParser.T_SQBRCLOSE) == null) { + while (parser.optional(ZenTokener.T_SQBROPEN) != null) { + if (parser.optional(ZenTokener.T_SQBRCLOSE) == null) { base = new ZenTypeAssociative(base, read(parser, environment)); - parser.required(ZenParser.T_SQBRCLOSE, "] expected"); + parser.required(ZenTokener.T_SQBRCLOSE, "] expected"); } else { base = new ZenTypeArrayBasic(base); } @@ -213,7 +213,7 @@ public abstract class ZenType { OperatorType operator) { TypeExpansion expansion = environment.getExpansion(getName()); if (expansion != null) { - return expansion.trinary(position, environment, first, second, third, operator); + return expansion.ternary(position, environment, first, second, third, operator); } return null; } @@ -221,7 +221,7 @@ public abstract class ZenType { protected IPartialExpression memberExpansion(ZenPosition position, IEnvironmentGlobal environment, Expression value, String member) { TypeExpansion expansion = environment.getExpansion(getName()); if (expansion != null) { - return expansion.member(position, environment, value, member); + return expansion.instanceMember(position, environment, value, member); } return null; }