diff --git a/api/pom.xml b/api/pom.xml index f6a16be3..c25e8e4d 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -5,12 +5,12 @@ 4.0.0 ultimate-spell-system-api - 2.6.1-SNAPSHOT + 3.0.0-SNAPSHOT fr.jamailun.paper ultimate-spell-system - 2.6.1-SNAPSHOT + 3.0.0-SNAPSHOT @@ -22,8 +22,8 @@ fr.jamailun.paper - 2.6.1-SNAPSHOT - ultimate-spell-system-dsl + 3.0.0-SNAPSHOT + ultimate-spell-system-dsl2 compile diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/bind/ItemBinder.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/bind/ItemBinder.java index 994d7caf..40f792b7 100644 --- a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/bind/ItemBinder.java +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/bind/ItemBinder.java @@ -1,7 +1,7 @@ package fr.jamailun.ultimatespellsystem.api.bind; import fr.jamailun.ultimatespellsystem.api.spells.Spell; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/bind/SpellBindData.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/bind/SpellBindData.java index 759c8d91..59855b05 100644 --- a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/bind/SpellBindData.java +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/bind/SpellBindData.java @@ -1,7 +1,7 @@ package fr.jamailun.ultimatespellsystem.api.bind; import fr.jamailun.ultimatespellsystem.api.spells.Spell; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/CallbackAction.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/CallbackAction.java index fa6dec38..db149fa7 100644 --- a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/CallbackAction.java +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/CallbackAction.java @@ -2,7 +2,7 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.objects.CallbackEvent; +import fr.jamailun.ultimatespellsystem.dsl2.callbacks.CallbackEvent; import lombok.Getter; import org.bukkit.event.Event; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/CustomEntity.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/CustomEntity.java index 741e9538..be7292df 100644 --- a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/CustomEntity.java +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/CustomEntity.java @@ -117,4 +117,15 @@ public void remove() { public @NotNull PersistentDataContainer getNBT() { return transientDataContainer; } + + @Override + public Optional getEntityAs(Class clazz) { + return getBukkitEntity().map(e -> { + try { + return clazz.cast(e); + } catch(Exception ex) { + return null; + } + }); + } } diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/SpellEntity.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/SpellEntity.java index 1932af97..708369f2 100644 --- a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/SpellEntity.java +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/SpellEntity.java @@ -22,6 +22,7 @@ public interface SpellEntity { * Get the UUID of the entity. * @return a non-null, unique UUID. */ + @Contract(pure = true) @NotNull UUID getUniqueId(); /** @@ -31,10 +32,21 @@ public interface SpellEntity { @Contract(pure = true) @NotNull Optional getBukkitEntity(); + /** + * Get the entity as a specific bukkit class. + * @param clazz the class to cast the bukkit entity to. + * @return an empty optional if the entity is not bukkit-based, or if the instance cannot be + * cast to the parameter. + * @param the output requested type. + */ + @Contract(pure = true) + Optional getEntityAs(Class clazz); + /** * Test if the current entity has a bukkit representation. * @return true if a call to {@link #getBukkitEntity()} returns something. */ + @Contract(pure = true) default boolean isBukkit() { return getBukkitEntity().isPresent(); } diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/SummonAttributes.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/SummonAttributes.java index 92f7e046..5541214e 100644 --- a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/SummonAttributes.java +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/entities/SummonAttributes.java @@ -2,7 +2,7 @@ import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import fr.jamailun.ultimatespellsystem.api.utils.AttributesHolder; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.bukkit.Location; import org.bukkit.event.Event; import org.bukkit.scheduler.BukkitRunnable; diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/providers/CallbackEventProvider.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/providers/CallbackEventProvider.java index 425d57d8..2025a4fa 100644 --- a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/providers/CallbackEventProvider.java +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/providers/CallbackEventProvider.java @@ -1,8 +1,8 @@ package fr.jamailun.ultimatespellsystem.api.providers; import fr.jamailun.ultimatespellsystem.api.entities.CallbackAction; -import fr.jamailun.ultimatespellsystem.dsl.objects.CallbackEvent; -import fr.jamailun.ultimatespellsystem.dsl.registries.CallbackEventRegistry; +import fr.jamailun.ultimatespellsystem.dsl2.callbacks.CallbackEvent; +import fr.jamailun.ultimatespellsystem.dsl2.registries.CallbackEventRegistry; import org.jetbrains.annotations.NotNull; import java.util.Optional; diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/providers/EntityTypeProvider.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/providers/EntityTypeProvider.java index 29b17afb..de7357d2 100644 --- a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/providers/EntityTypeProvider.java +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/providers/EntityTypeProvider.java @@ -1,7 +1,7 @@ package fr.jamailun.ultimatespellsystem.api.providers; import fr.jamailun.ultimatespellsystem.api.entities.UssEntityType; -import fr.jamailun.ultimatespellsystem.dsl.registries.EntityTypeRegistry; +import fr.jamailun.ultimatespellsystem.dsl2.registries.EntityTypeRegistry; import org.jetbrains.annotations.NotNull; /** diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/providers/JavaFunctionProvider.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/providers/JavaFunctionProvider.java index 9f039e93..2df10919 100644 --- a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/providers/JavaFunctionProvider.java +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/providers/JavaFunctionProvider.java @@ -1,7 +1,7 @@ package fr.jamailun.ultimatespellsystem.api.providers; import fr.jamailun.ultimatespellsystem.api.runner.functions.RunnableJavaFunction; -import fr.jamailun.ultimatespellsystem.dsl.registries.FunctionDefinitionsRegistry; +import fr.jamailun.ultimatespellsystem.dsl2.registries.FunctionDefinitionsRegistry; import org.jetbrains.annotations.NotNull; /** diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/FunctionsSet.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/FunctionsSet.java new file mode 100644 index 00000000..c6cb4bbb --- /dev/null +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/FunctionsSet.java @@ -0,0 +1,35 @@ +package fr.jamailun.ultimatespellsystem.api.runner; + +import fr.jamailun.ultimatespellsystem.api.runner.functions.GlobalFunction; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionSignature; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * A set of functions. + */ +public interface FunctionsSet { + + /** + * Get a function. + * @param signature the function signature key. + * @return the content of the variable, or {@code null} if not defined. + */ + @Nullable GlobalFunction get(@NotNull FunctionSignature signature); + + /** + * Create an inherited functions set. + * @return a new instance. Mutating existing vars of the instance will mutate {@code this} instance. + * But adding new functions will not. + */ + @Contract(" -> new") + @NotNull FunctionsSet inherit(); + + /** + * Register a new function. + * @param function the function to register. + */ + void register(@NotNull GlobalFunction function); + +} diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/SpellRuntime.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/SpellRuntime.java index ccd64235..1659fd99 100644 --- a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/SpellRuntime.java +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/SpellRuntime.java @@ -1,6 +1,7 @@ package fr.jamailun.ultimatespellsystem.api.runner; import fr.jamailun.ultimatespellsystem.api.entities.SpellEntity; +import fr.jamailun.ultimatespellsystem.api.runner.structs.Struct; import fr.jamailun.ultimatespellsystem.api.spells.Spell; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -32,16 +33,16 @@ public interface SpellRuntime { @NotNull VariablesSet variables(); /** - * Test if the runtime has been stopped. - * @return true if no more statements should be executed. + * A reference to the functions set. + * @return the final reference to the functions. */ - boolean isStopped(); + @NotNull FunctionsSet functions(); /** - * Stop the current execution. - * @param exitCode the exit code to use. + * Test if the runtime has been stopped. + * @return true if no more statements should be executed. */ - void stop(int exitCode); + boolean isStopped(); /** * Break the flow. @@ -58,6 +59,12 @@ public interface SpellRuntime { */ void acceptContinue(); + /** + * Handle a return statement. + * @param value output-ed value. + */ + void statementReturn(@Nullable Object value); + /** * Get the state of the control flow. * @return a state. @@ -69,7 +76,17 @@ public interface SpellRuntime { * @return a new instance of a runtime, with the same context. */ @Contract(" -> new") - @NotNull SpellRuntime makeChild(); + default @NotNull SpellRuntime makeChild() { + return makeChild(false); + } + + /** + * Create a child of this runtime. + * @param function if {@code true}, the child runtime will be a function. + * @return a new instance of a runtime, with the same context. + */ + @Contract("_ -> new") + @NotNull SpellRuntime makeChild(boolean function); /** * Create a child instance of this runtime, but with a different caster. @@ -80,11 +97,26 @@ public interface SpellRuntime { @NotNull SpellRuntime makeChildNewCaster(@NotNull SpellEntity newCaster); /** - * Get the final exit code. - * @return {@code zero} if it's a success (or not stopped). Any other value means an error occurred. + * Get the structure out of a value. + * @param structDefinitionName name of the structure of the type. + * @param value the value to wrap. + * @return {@code null} if cannot match. + */ + @Contract("_,null->null;_,!null->!null") + @Nullable Struct getStructOf(@NotNull String structDefinitionName, @Nullable Object value); + + /** + * Get the returned value. + * @return something. * @see #isStopped() */ - int getFinalExitCode(); + @Nullable Object getReturnedValue(); + + /** + * Test if the returned value is considered as a success. + * @return true if return value is {@code null}, or {@code 0}, or {@code true}. + */ + boolean isReturnValueSuccess(); /** * Evaluate a value. diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/functions/GlobalFunction.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/functions/GlobalFunction.java new file mode 100644 index 00000000..f66ca413 --- /dev/null +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/functions/GlobalFunction.java @@ -0,0 +1,32 @@ +package fr.jamailun.ultimatespellsystem.api.runner.functions; + +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; +import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionSignature; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * A global function. Either from the Java code, or from the USS script. + */ +public interface GlobalFunction { + + /** + * Get the signature of the function. + * @return the instance function signature. + */ + @NotNull FunctionSignature getSignature(); + + /** + * Call the function with parameters. + * @param pos token position. + * @param arguments params of the function. + * @param runtime spell runtime. + * @return the output value. + */ + @Nullable Object call(@NotNull TokenPosition pos, @NotNull List arguments, @NotNull SpellRuntime runtime); + +} diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/functions/RunnableJavaFunction.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/functions/RunnableJavaFunction.java index 38a2a9d7..ed3eaa3b 100644 --- a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/functions/RunnableJavaFunction.java +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/functions/RunnableJavaFunction.java @@ -2,12 +2,15 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionDefinition; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionSignature; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; import lombok.Getter; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -15,7 +18,7 @@ * A runnable code declaration */ @Getter -public abstract class RunnableJavaFunction { +public abstract class RunnableJavaFunction implements GlobalFunction { private final @NotNull String id; private final @NotNull Type type; @@ -34,6 +37,16 @@ public RunnableJavaFunction(@NotNull String id, @NotNull Type type, @NotNull Lis this.arguments = arguments; } + @Override + public @NotNull FunctionSignature getSignature() { + return FunctionSignature.of(id, arguments); + } + + @Override + public @Nullable Object call(@NotNull TokenPosition pos, @NotNull List arguments, @NotNull SpellRuntime runtime) { + return compute(arguments, runtime); + } + /** * Compute the value, using the arguments. * @param arguments the arguments values returned. Must be computed in the runtime. diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/structs/Struct.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/structs/Struct.java new file mode 100644 index 00000000..473db0b8 --- /dev/null +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/structs/Struct.java @@ -0,0 +1,39 @@ +package fr.jamailun.ultimatespellsystem.api.runner.structs; + +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * Instance of a structured object. + */ +public interface Struct { + + /** + * Get a field value. + * @param pos token position requesting the data. + * @param fieldName name of the field. + * @return the field value. + */ + @Nullable Object getField(@NotNull TokenPosition pos, @NotNull String fieldName); + + /** + * Set a field value. + * @param pos token position requesting the data. + * @param fieldName name of the field. + * @param value the field new value. + */ + void setField(@NotNull TokenPosition pos, @NotNull String fieldName, @Nullable Object value); + + /** + * Call a function of the object. + * @param pos token position requesting the data. + * @param functionName name fo the function. + * @param parameters parameters of the function. + * @return the function output. + */ + @Nullable Object callFunction(@NotNull TokenPosition pos, @NotNull String functionName, @NotNull List parameters); + +} diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/structs/StructDefinition.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/structs/StructDefinition.java new file mode 100644 index 00000000..90809ae8 --- /dev/null +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/runner/structs/StructDefinition.java @@ -0,0 +1,58 @@ +package fr.jamailun.ultimatespellsystem.api.runner.structs; + +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Function; + +/** + * A structure definition. + * @param the underlying type of the structure. + */ +public interface StructDefinition { + + /** + * Get the struct name. + * @return the non-null name. + */ + @NotNull String getName(); + + /** + * Get the DSL type matching the value. + * @return the type equivalence. + */ + default @NotNull Type asType() { + return Type.of(getName()); + } + + /** + * Instantiate the value. + * @param value value to wrap. + * @return a non-null instance. + */ + @NotNull Struct instantiate(S value); + + /** + * Register a new field on the struct. + * @param name the name of the field. If not unique, an exception will be thrown. + * @param type type of the field. + * @param getter the getter of the field. + * @param setter optional setter for the field. + * @param type of the field. + */ + void registerField(@NotNull String name, @NotNull Type type, @NotNull Function getter, @Nullable BiConsumer setter); + + /** + * Register a new function on the struct. + * @param functionDefinition the DSL function definition. + * @param function the function that handles the runtime. + * @param the output type of the function. + */ + void registerFunction(@NotNull FunctionDefinition functionDefinition, @NotNull BiFunction, T> function); + +} diff --git a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/spells/ExternalExecutor.java b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/spells/ExternalExecutor.java index 6f6d8496..286ef950 100644 --- a/api/src/main/java/fr/jamailun/ultimatespellsystem/api/spells/ExternalExecutor.java +++ b/api/src/main/java/fr/jamailun/ultimatespellsystem/api/spells/ExternalExecutor.java @@ -4,8 +4,8 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; import org.bukkit.entity.LivingEntity; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; diff --git a/dsl/README.md b/dsl/README.md deleted file mode 100644 index 1e1fc3ae..00000000 --- a/dsl/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# USS - DSL - - ![](https://img.shields.io/badge/Code%20overage-90%25-lime?style=for-the-badge&link=https://github.com/jamailun/UltimateSpellSystem/tree/master/dsl) - diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/UnknownFunctionException.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/UnknownFunctionException.java deleted file mode 100644 index f5a6cdcb..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/UnknownFunctionException.java +++ /dev/null @@ -1,19 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.errors; - -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import org.jetbrains.annotations.NotNull; - -/** - * An exception threw when a function has not been registered. - */ -public class UnknownFunctionException extends UssException { - - /** - * New exception. - * @param pos token position. - * @param functionId ID of the unknown function. - */ - public UnknownFunctionException(@NotNull TokenPosition pos, @NotNull String functionId) { - super(pos, "Unknown function ID: '"+functionId+"'."); - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/metadata/MetadataRule.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/metadata/MetadataRule.java deleted file mode 100644 index 93477a50..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/metadata/MetadataRule.java +++ /dev/null @@ -1,25 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.metadata; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.statements.MetadataStatement; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import org.jetbrains.annotations.NotNull; - -/** - * A metadata rule uses the metadata statements to change the behaviour of the spell compilation. - */ -public interface MetadataRule { - - /** - * Get the name this rule will apply to. - * @return a non-null string. - */ - @NotNull String getName(); - - /** - * Apply this rule to a context. - * @param context the context. - * @param metadata the statement to apply the rule to. - */ - void apply(@NotNull TypesContext context, @NotNull MetadataStatement metadata); - -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/metadata/MetadataRulesManager.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/metadata/MetadataRulesManager.java deleted file mode 100644 index d9602473..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/metadata/MetadataRulesManager.java +++ /dev/null @@ -1,42 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.metadata; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Unmodifiable; - -import java.util.*; - -/** - * Register and expose all {@link MetadataRule}. - */ -public final class MetadataRulesManager { - private MetadataRulesManager() {} - - private static final Map> RULES = new HashMap<>(); - - /** - * Register a new rule. - * @param rule the rule to register. - */ - public static void registerRule(@NotNull MetadataRule rule) { - RULES.putIfAbsent(rule.getName(), new ArrayList<>()); - RULES.get(rule.getName()).add(rule); - } - - /** - * Get all rules for a name. - * @param name a non-null name. - * @return an unmodifiable list of rules. If not rule exist, the list will be empty. - */ - public static @NotNull @Unmodifiable List getRulesForName(@NotNull String name) { - return Collections.unmodifiableList(RULES.getOrDefault(name, Collections.emptyList())); - } - - /** - * List existing rules. - * @return an unmodifiable collection of names. - */ - public static @NotNull @Unmodifiable Collection existingKeys() { - return Collections.unmodifiableSet( RULES.keySet() ); - } - -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/metadata/rules/DefaultMetadataRules.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/metadata/rules/DefaultMetadataRules.java deleted file mode 100644 index 2fed0429..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/metadata/rules/DefaultMetadataRules.java +++ /dev/null @@ -1,24 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.metadata.rules; - -import fr.jamailun.ultimatespellsystem.dsl.metadata.MetadataRulesManager; - -/** - * Load the default ruleset for metadata statements. - */ -public final class DefaultMetadataRules { - private DefaultMetadataRules() {} - - private static boolean initialized = false; - - /** - * Initialize the metadata rules system. - */ - public static void initialize() { - if(initialized) return; - initialized = true; - - // Register rules - MetadataRulesManager.registerRule(new ParamDefinitionMetadata()); - } - -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/metadata/rules/ParamDefinitionMetadata.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/metadata/rules/ParamDefinitionMetadata.java deleted file mode 100644 index 9e2a3448..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/metadata/rules/ParamDefinitionMetadata.java +++ /dev/null @@ -1,41 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.metadata.rules; - -import fr.jamailun.ultimatespellsystem.dsl.errors.MetadataRuleFailureException; -import fr.jamailun.ultimatespellsystem.dsl.metadata.MetadataRule; -import fr.jamailun.ultimatespellsystem.dsl.nodes.statements.MetadataStatement; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import org.jetbrains.annotations.NotNull; - -/** - * Apply for {@code @param(NAME, TYPE)} - */ -public class ParamDefinitionMetadata implements MetadataRule { - - @Override - public void apply(@NotNull TypesContext context, @NotNull MetadataStatement metadata) { - // Read objets - if(metadata.getParams().size() < 2) - throw new MetadataRuleFailureException(metadata.getPosition(), "Invalid number of parameters. Expected at least 2, got " + metadata.getParams().size() + "."); - if(!(metadata.getParams().getFirst() instanceof String name)) - throw new MetadataRuleFailureException(metadata.getPosition(), "For @param: invalid type for 'name'. Expected String, got " + metadata.getParams().getFirst()); - if(!(metadata.getParams().get(1) instanceof String type)) - throw new MetadataRuleFailureException(metadata.getPosition(), "For @param: invalid type for 'type'. Expected String, got " + metadata.getParams().get(1)); - boolean collection = false; - if(metadata.getParams().size() > 2) { - if(!(metadata.getParams().get(2) instanceof Boolean isColl)) - throw new MetadataRuleFailureException(metadata.getPosition(), "For @param: invalid type for 'type'. Expected String, got " + metadata.getParams().get(1)); - collection = isColl; - } - // Guarantee variable - TypePrimitive primitive = TypePrimitive.parsePrimitive(type); - if(primitive == null) - throw new MetadataRuleFailureException(metadata.getPosition(), "For @param, unknown primitive value '" + type + "'."); - context.promiseVariable(name, primitive.asType(collection)); - } - - @Override - public @NotNull String getName() { - return "param"; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/StatementNode.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/StatementNode.java deleted file mode 100644 index f05f8b67..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/StatementNode.java +++ /dev/null @@ -1,83 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.statements.blocks.*; -import fr.jamailun.ultimatespellsystem.dsl.errors.SyntaxException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.statements.*; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import org.jetbrains.annotations.NotNull; - -/** - * A statement is an instruction in the code. It can use other statements, or {@link ExpressionNode expressions}.
- * Can be visited by a {@link StatementVisitor}. - * This class can parse a statement with the {@link #parseNextStatement(TokenStream)} method. - */ -public abstract class StatementNode extends Node { - - /** - * Make this statement be visited. - * @param visitor the visitor to use. - */ - public abstract void visit(@NotNull StatementVisitor visitor); - - /** - * Read a new statement from the tokens stream. - * @param tokens the stream of tokens. - * @return a non-null statement. - * @throws fr.jamailun.ultimatespellsystem.dsl.errors.UssException if a problem occurs. - */ - public static @NotNull StatementNode parseNextStatement(@NotNull TokenStream tokens) { - Token token = tokens.next(); - return switch (token.getType()) { - // Empty statement - case SEMI_COLON -> parseNextStatement(tokens); - - // Metadata - case CHAR_AT -> MetadataStatement.parseMetadata(tokens); - - // Blocks - case BRACES_OPEN -> BlockStatement.parseNextBlock(tokens); - case RUN -> RunLaterStatement.parseRunLater(tokens); - case REPEAT -> RepeatStatement.parseRepeat(tokens); - case CALLBACK -> CallbackStatement.parseCallback(tokens); - - // Increment / decrement - case INCREMENT -> IncrementStatement.parseIncrementOrDecrement(tokens, true); - case DECREMENT -> IncrementStatement.parseIncrementOrDecrement(tokens, false); - - // Variable set - case DEFINE -> DefineStatement.parseNextDefine(tokens); - case VALUE_VARIABLE -> { - tokens.back(); - yield DefineStatement.parseNextDefine(tokens); - } - - // Statements - case SEND -> SendStatement.parseSendStatement(tokens); - case STOP -> StopStatement.parseStop(tokens); - case SUMMON -> SummonStatement.parseSummonStatement(tokens); - case TELEPORT -> TeleportStatement.parseTeleport(tokens); - case PLAY -> PlayStatement.parsePlay(tokens); - case GIVE -> GiveStatement.parseNextGiveStatement(tokens); - - // Control-Flow - case IF -> IfElseStatement.parseIfStatement(tokens); - case ELSE -> throw new SyntaxException(token, "An ELSE must follow an IF (or the IF's child statement)."); - case FOR -> ForLoopStatement.parseForLoop(tokens); - case FOREACH -> ForeachLoopStatement.parseForLoop(tokens); - case WHILE -> WhileLoopStatement.parseWhileLoop(tokens, true); - case DO -> WhileLoopStatement.parseWhileLoop(tokens, false); - case BREAK -> BreakContinueStatement.parseNextBreakContinue(tokens, false); - case CONTINUE -> BreakContinueStatement.parseNextBreakContinue(tokens, true); - - default -> { - tokens.back(); - ExpressionNode expressionNode = ExpressionNode.readNextExpression(tokens, true); - yield new SimpleExpressionStatement(expressionNode); - } - //throw new SyntaxException(token, "Unexpected token to begin a statement."); - }; - } - -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/ArrayExpression.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/ArrayExpression.java deleted file mode 100644 index 5886a1c0..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/ArrayExpression.java +++ /dev/null @@ -1,87 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions; - -import fr.jamailun.ultimatespellsystem.dsl.errors.TypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.*; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; - -/** - * Raw array value. - */ -public class ArrayExpression extends ExpressionNode { - - @Getter - private final List elements; - private TypePrimitive typePrimitive; - - protected ArrayExpression(TokenPosition position, List elements) { - super(position); - this.elements = elements; - } - - @Override - public @NotNull Type getExpressionType() { - if(typePrimitive == null) - throw new TypeException(firstTokenPosition(), "Type of primitive has not been set."); - return typePrimitive.asType(true); - } - - @Override - public void visit(@NotNull ExpressionVisitor visitor) { - visitor.handleArray(this); - } - - @Override - public void validateTypes(@NotNull TypesContext contextParent) { - // avoid non-intentional propagation - TypesContext context = contextParent.childContext(); - - // Check type for all expressions : they must share the same type. - for(ExpressionNode node : elements) { - node.validateTypes(context); - - if(typePrimitive == null) { - typePrimitive = node.getExpressionType().primitive(); - } else { - assertExpressionType(node, CollectionFilter.MONO_ELEMENT, typePrimitive); - } - } - if(typePrimitive == null) - typePrimitive = TypePrimitive.NULL; - } - - @PreviousIndicator(expected = TokenType.ARRAY_OPEN) - public static ArrayExpression parseNextArrayConcat(TokenStream tokens) { - TokenPosition pos = tokens.position(); - List nodes = new ArrayList<>(); - boolean first = true; - while(tokens.hasMore()) { - Token peek = tokens.peek(); - if(peek.getType() == TokenType.ARRAY_CLOSE) - break; - if( ! first) { - tokens.dropOrThrow(TokenType.COMMA); - } - first = false; - ExpressionNode node = ExpressionNode.readNextExpression(tokens); - nodes.add(node); - } - tokens.dropOrThrow(TokenType.ARRAY_CLOSE); - return new ArrayExpression(pos, nodes); - } - - @Override - public String toString() { - return "ARRAY("+(typePrimitive==null?"? type":typePrimitive.asType())+")[" + elements + "]"; - } - -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/compute/AllEntitiesAroundExpression.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/compute/AllEntitiesAroundExpression.java deleted file mode 100644 index 6d0923f1..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/compute/AllEntitiesAroundExpression.java +++ /dev/null @@ -1,88 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.compute; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; -import lombok.Getter; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; - -/** - * 'all entities' within, around expression. Returns a collection of entities. - */ -@Getter -public class AllEntitiesAroundExpression extends ExpressionNode { - - private final ExpressionNode entityType; - private final ExpressionNode source; - private final ExpressionNode distance; - private final boolean including; - - protected AllEntitiesAroundExpression(TokenPosition pos, ExpressionNode entityType, boolean including, ExpressionNode source, ExpressionNode distance) { - super(pos); - this.entityType = entityType; - this.including = including; - this.source = source; - this.distance = distance; - } - - @Override - public @NotNull Type getExpressionType() { - return new Type(TypePrimitive.ENTITY, true); - } - - @Override - public void visit(@NotNull ExpressionVisitor visitor) { - visitor.handleAllAround(this); - } - - @Override - public void validateTypes(@NotNull TypesContext context) { - // Distance must be a number - assertExpressionType(distance, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.NUMBER); - - // Scope can be entity-type OR custom - assertExpressionType(entityType, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.ENTITY_TYPE, TypePrimitive.CUSTOM, TypePrimitive.STRING); - - // Source can be entity OR location - assertExpressionType(source, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.ENTITY, TypePrimitive.LOCATION); - } - - @Override - public String toString() { - return "FETCH_ALL{" + entityType + " around " + source + (including ?"(STRICT)":"") + ", within "+ distance + "}"; - } - - /** - * Parse the next all-entities-around expression. - * @param tokens stream of tokens. - * @return a new instance. - */ - @PreviousIndicator(expected = {TokenType.ALL}) // all (SCOPE) within (DISTANCE) around (SOURCE) [[including]] - @Contract("_ -> new") - public static @NotNull AllEntitiesAroundExpression parseAllExpression(@NotNull TokenStream tokens) { - TokenPosition pos = tokens.position(); - - // Entity type - ExpressionNode scope = ExpressionNode.readNextExpression(tokens, true); - - // - tokens.dropOrThrow(TokenType.WITHIN); - ExpressionNode distance = ExpressionNode.readNextExpression(tokens); - - // DistanceSource - tokens.dropOrThrow(TokenType.AROUND); - ExpressionNode source = ExpressionNode.readNextExpression(tokens); - boolean including = tokens.dropOptional(TokenType.INCLUDING); - - return new AllEntitiesAroundExpression(pos, scope, including, source, distance); - } - -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/compute/PositionOfExpression.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/compute/PositionOfExpression.java deleted file mode 100644 index 069b126f..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/compute/PositionOfExpression.java +++ /dev/null @@ -1,59 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.compute; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; -import org.jetbrains.annotations.NotNull; - -/** - * Position of an entity. - */ -public class PositionOfExpression extends ExpressionNode { - - private final ExpressionNode entityNode; - private boolean isCollection = false; - - public PositionOfExpression(TokenPosition pos, ExpressionNode entityNode) { - super(pos); - this.entityNode = entityNode; - } - - public ExpressionNode getEntity() { - return entityNode; - } - - @Override - public @NotNull Type getExpressionType() { - return TypePrimitive.LOCATION.asType(isCollection); - } - - @Override - public void visit(@NotNull ExpressionVisitor visitor) { - visitor.handlePositionOf(this); - } - - @Override - public void validateTypes(@NotNull TypesContext context) { - assertExpressionType(entityNode, context, TypePrimitive.ENTITY); - isCollection = entityNode.getExpressionType().isCollection(); - } - - @PreviousIndicator(expected = TokenType.POSITION) - public static @NotNull PositionOfExpression parsePositionOf(@NotNull TokenStream tokens) { - TokenPosition pos = tokens.position(); - tokens.dropOrThrow(TokenType.OF); - ExpressionNode entityNode = ExpressionNode.readNextExpression(tokens); - return new PositionOfExpression(pos, entityNode); - } - - @Override - public String toString() { - return "position_of(" + entityNode + ")"; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/compute/SizeOfExpression.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/compute/SizeOfExpression.java deleted file mode 100644 index 4159c16b..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/compute/SizeOfExpression.java +++ /dev/null @@ -1,61 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.compute; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; - -/** - * Size of a collection. - */ -@Getter -public class SizeOfExpression extends ExpressionNode { - - private final ExpressionNode child; - - protected SizeOfExpression(TokenPosition position, ExpressionNode child) { - super(position); - this.child = child; - } - - @Override - public @NotNull Type getExpressionType() { - return TypePrimitive.NUMBER.asType(); - } - - @Override - public void visit(@NotNull ExpressionVisitor visitor) { - visitor.handleSizeOf(this); - } - - @Override - public void validateTypes(@NotNull TypesContext context) { - child.validateTypes(context); - // Should we only accept lists? - } - - @PreviousIndicator(expected = TokenType.SIZEOF) - public static @NotNull SizeOfExpression parseSizeOf(@NotNull TokenStream tokens) { - TokenPosition position = tokens.position(); - boolean parenthesis = tokens.dropOptional(TokenType.BRACKET_OPEN); - - ExpressionNode child = ExpressionNode.readNextExpression(tokens); - - if(parenthesis) - tokens.dropOrThrow(TokenType.BRACKET_CLOSE); - - return new SizeOfExpression(position, child); - } - - @Override - public String toString() { - return "size-of(" + child + ")"; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/functions/FunctionArgument.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/functions/FunctionArgument.java deleted file mode 100644 index 08711ddc..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/functions/FunctionArgument.java +++ /dev/null @@ -1,18 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions; - -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; - -/** - * A declaration of a function argument. - * @param type the type of the argument. - * @param debugName the name of the argument. - * @param optional if true, argument is not mandatory. - */ -public record FunctionArgument(@NotNull FunctionType type, @NotNull String debugName, boolean optional) { - @Contract(pure = true) - @Override - public @NotNull String toString() { - return type + " " + debugName + (optional?"*":""); - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/functions/FunctionCallExpression.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/functions/FunctionCallExpression.java deleted file mode 100644 index 7bdabff8..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/functions/FunctionCallExpression.java +++ /dev/null @@ -1,99 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions; - -import fr.jamailun.ultimatespellsystem.dsl.errors.SyntaxException; -import fr.jamailun.ultimatespellsystem.dsl.errors.TypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.*; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; - -/** - * A function call statement. - */ -@Getter -public final class FunctionCallExpression extends ExpressionNode { - - private final FunctionDefinition function; - private final List arguments; - - public FunctionCallExpression(@NotNull TokenPosition position, @NotNull FunctionDefinition function, @NotNull List arguments) { - super(position); - this.function = function; - this.arguments = arguments; - } - - @Override - public void validateTypes(@NotNull TypesContext contextRaw) { - TypesContext context = contextRaw.childContext(); - - // Check argument amount - List listArgs = function.arguments(); - - // Then validate arguments types - for(int i = 0; i < arguments.size(); i++) { - FunctionArgument expected = listArgs.get(i); - ExpressionNode obtained = arguments.get(i); - obtained.validateTypes(context); - - FunctionType.TestResult result = expected.type().accepts(obtained.getExpressionType()); - if(result.isError()) - throw new TypeException(obtained, "Argument '" + expected.debugName() + "': " + result.getError()); - } - } - - @Override - public void visit(@NotNull ExpressionVisitor visitor) { - visitor.handleFunction(this); - } - - @Override - public @NotNull Type getExpressionType() { - return function.returnedType(); - } - - /** - * Parse a new function call expression from the tokens stream. - * @param functionDefinition found definition. - * @param tokens tokens streams. - * @return a new instance. - */ - @PreviousIndicator(expected = TokenType.BRACKET_OPEN) - public static @NotNull FunctionCallExpression readNextFunctionCall(@NotNull FunctionDefinition functionDefinition, @NotNull TokenStream tokens) { - List arguments = new ArrayList<>(); - TokenPosition position = tokens.position(); - - boolean first = true; - while(tokens.hasMore()) { - Token peek = tokens.peek(); - if(peek.getType() == TokenType.BRACKET_CLOSE) - break; - if( ! first) { - tokens.dropOrThrow(TokenType.COMMA); - } first = false; - - ExpressionNode argument = ExpressionNode.readNextExpression(tokens); - arguments.add(argument); - } - tokens.dropOrThrow(TokenType.BRACKET_CLOSE); - - // Assert obtained arguments count is expected - if(arguments.size() < functionDefinition.mandatoryArgumentsCount()) - throw new SyntaxException(position, "Invalid arguments count. Expected " + functionDefinition.arguments().size() + " mandatory, got " + arguments.size()); - if(arguments.size() > functionDefinition.arguments().size()) - throw new SyntaxException(position, "Invalid arguments count. Expected " + functionDefinition.arguments().size() + ", got " + arguments.size()); - - // Create and return node - return new FunctionCallExpression(position, functionDefinition, arguments); - } - - @Override - public @NotNull String toString() { - return "F-call{"+function.id()+" (" + arguments + ")}"; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/functions/FunctionType.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/functions/FunctionType.java deleted file mode 100644 index 983e02e9..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/functions/FunctionType.java +++ /dev/null @@ -1,96 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions; - -import com.google.common.base.Preconditions; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -/** - * A lax-collection type for a function. - */ -@AllArgsConstructor(access = AccessLevel.PRIVATE) -public class FunctionType { - - private final List primitives; - private final CollectionFilter collectionFilter; - - /** - * Create a new function-type, that accepts a restricted amount of type primitives. - * @param types varargs of allowed types. - * @return a new instance. - */ - @Contract("_ -> new") - public static @NotNull FunctionType accept(@NotNull TypePrimitive @NotNull ... types) { - Preconditions.checkArgument(types.length > 0, "Cannot have zero primitive."); - return new FunctionType(List.of(types), CollectionFilter.ANY); - } - - /** - * Create a new function-type, that accepts a restricted amount of type primitives as non-collection. - * @param types varargs of allowed types. - * @return a new instance. - */ - @Contract("_ -> new") - public static @NotNull FunctionType acceptOnlyMono(@NotNull TypePrimitive @NotNull ... types) { - Preconditions.checkArgument(types.length > 0, "Cannot have zero primitive."); - return new FunctionType(List.of(types), CollectionFilter.MONO_ELEMENT); - } - - /** - * Create a new function-type, that accepts a restricted amount of type primitives as collection. - * @param types varargs of allowed types. - * @return a new instance. - */ - @Contract("_ -> new") - public static @NotNull FunctionType acceptOnlyCollection(@NotNull TypePrimitive @NotNull ... types) { - Preconditions.checkArgument(types.length > 0, "Cannot have zero primitive."); - return new FunctionType(List.of(types), CollectionFilter.LIST); - } - - /** - * Compute a strict {@link Type} correspondance. - * @return a non-null, new Type instance. - */ - public @NotNull Type asType() { - return primitives.getFirst().asType(collectionFilter == CollectionFilter.LIST); - } - - public @NotNull TestResult accepts(@NotNull Type type) { - if( ! primitives.contains(type.primitive())) { - return TestResult.error("expected one of " + primitives + ", got " + type.primitive() + "."); - } - - if( ! collectionFilter.isValid(type)) { - if(collectionFilter == CollectionFilter.LIST) - return TestResult.error("expected a LIST, got " + type + "."); - return TestResult.error("did not expect a LIST, got " + type + "."); - } - - return TestResult.success(); - } - - @Getter @AllArgsConstructor(access = AccessLevel.PRIVATE) - public static final class TestResult { - private final String error; - public static @NotNull TestResult success() { - return new TestResult(null); - } - public static @NotNull TestResult error(@NotNull String error) { - return new TestResult(error); - } - public boolean isError() { - return error != null; - } - public boolean isSuccess() { - return error == null; - } - } - -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/EntityTypeExpression.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/EntityTypeExpression.java deleted file mode 100644 index 067c27e1..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/EntityTypeExpression.java +++ /dev/null @@ -1,46 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; -import org.jetbrains.annotations.NotNull; - -/** - * A raw {@link org.bukkit.entity.EntityType} literal. - */ -public class EntityTypeExpression extends LiteralExpression { - - private final String type; - - /** - * New instance. - * @param position token position. - * @param type entity-type value. - */ - public EntityTypeExpression(@NotNull TokenPosition position, @NotNull String type) { - super(position); - this.type = type; - } - - @Override - public String getRaw() { - return type; - } - - @Override - public @NotNull Type getExpressionType() { - return TypePrimitive.ENTITY_TYPE.asType(); - } - - @Override - public String toString() { - return PREFIX + "EntityType." + type + SUFFIX; - } - - @Override - public void visit(@NotNull ExpressionVisitor visitor) { - visitor.handleEntityTypeLiteral(this); - } - -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/NullExpression.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/NullExpression.java deleted file mode 100644 index c4a69478..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/NullExpression.java +++ /dev/null @@ -1,39 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; -import org.jetbrains.annotations.NotNull; - -/** - * The {@code NULL} representation. - */ -public class NullExpression extends LiteralExpression { - - /** - * New instance. - * @param pos position of the keyword. - */ - public NullExpression(@NotNull TokenPosition pos) { - super(pos); - } - - @Override - public Void getRaw() {return null;} - - @Override - public @NotNull Type getExpressionType() { - return TypePrimitive.NULL.asType(); - } - - @Override - public String toString() { - return "NULL"; - } - - @Override - public void visit(@NotNull ExpressionVisitor visitor) { - visitor.handleNullLiteral(this); - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/RuntimeLiteral.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/RuntimeLiteral.java deleted file mode 100644 index fad6c634..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/RuntimeLiteral.java +++ /dev/null @@ -1,44 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; -import org.jetbrains.annotations.NotNull; - -/** - * A literal, can be anything. Not really used... - */ -public class RuntimeLiteral extends LiteralExpression { - - private final String value; - - /** - * New literal runtime. - * @param token token to use. - */ - public RuntimeLiteral(@NotNull Token token) { - super(token.pos()); - this.value = token.getContentString(); - } - - @Override - public String getRaw() { - return value; - } - - @Override - public @NotNull Type getExpressionType() { - return TypePrimitive.CUSTOM.asType(); - } - - @Override - public String toString() { - return PREFIX + "?'" + value + "'" + SUFFIX; - } - - @Override - public void visit(@NotNull ExpressionVisitor visitor) { - visitor.handleRuntimeLiteral(this); - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/MathFunctionOperator.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/MathFunctionOperator.java deleted file mode 100644 index 3525b0ee..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/MathFunctionOperator.java +++ /dev/null @@ -1,55 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators; - -import fr.jamailun.ultimatespellsystem.dsl.errors.TypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import org.jetbrains.annotations.NotNull; - -/** - * Math-function mono-operator. - */ -public class MathFunctionOperator extends MonoOperator { - - private final MonoOpeType type; - - /** - * New instance. - * @param pos position of the token. - * @param expression expression to use. - * @param type type of operator. - */ - public MathFunctionOperator(@NotNull TokenPosition pos, @NotNull ExpressionNode expression, @NotNull MonoOpeType type) { - super(pos, expression); - this.type = type; - } - - @Override - public @NotNull MonoOpeType getType() { - return type; - } - - @Override - public void validateTypes(@NotNull Type childType) { - // No collection - if(childType.isCollection()) { - throw new TypeException(this, "A MathOperation("+type+") cannot handle collections."); - } - - // Only numbers - if(! childType.is(TypePrimitive.NUMBER)) { - throw new TypeException(this, "A MathOperation("+type+") can only handle numbers."); - } - } - - @Override - public @NotNull Type getExpressionType() { - return TypePrimitive.NUMBER.asType(); - } - - @Override - public String toString() { - return type + "(" + child + ")"; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/MonoOperator.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/MonoOperator.java deleted file mode 100644 index b41790f9..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/MonoOperator.java +++ /dev/null @@ -1,71 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Arrays; -import java.util.function.Function; - -/** - * Mono-operator, on a single expression. - */ -@Getter -public abstract class MonoOperator extends ExpressionNode { - - protected final ExpressionNode child; - - protected MonoOperator(TokenPosition position, ExpressionNode child) { - super(position); - this.child = child; - } - - /** - * Get this instance type of operation. - * @return a non-null type of mono-operation. - */ - public abstract @NotNull MonoOpeType getType(); - - @Override - public void visit(@NotNull ExpressionVisitor visitor) { - visitor.handleMonoOperator(this); - } - - @Override - public final void validateTypes(@NotNull TypesContext context) { - child.validateTypes(context); - - validateTypes(child.getExpressionType()); - } - - /** - * Validate the static-type of the code usage. - * @param childType the type to test. - */ - public abstract void validateTypes(@NotNull Type childType); - - public enum MonoOpeType { - NOT(x -> x), - SIN(x -> Math.sin(x.doubleValue())), - COS(x -> Math.cos(x.doubleValue())), - TAN(x -> Math.tan(x.doubleValue())), - SQRT(x -> Math.sqrt(x.doubleValue())), - ABS(x -> x instanceof Integer || x instanceof Long || x instanceof Short || x instanceof Byte ? Math.abs(x.longValue()) : Math.abs(x.doubleValue())), - ; - public final Function function; - MonoOpeType(Function function) { - this.function = function; - } - public static @Nullable MonoOpeType find(@NotNull String value) { - return Arrays.stream(values()) - .filter(v -> v.name().equalsIgnoreCase(value)) - .findAny().orElse(null); - } - } - -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/DefineStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/DefineStatement.java deleted file mode 100644 index 4cb8a4c0..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/DefineStatement.java +++ /dev/null @@ -1,71 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; - -/** - * Define statement will set a variable to something. - */ -@Getter -@RequiredArgsConstructor -public class DefineStatement extends StatementNode { - - private final String varName; - private final ExpressionNode expression; - - @Override - public void validateTypes(@NotNull TypesContext context) { - expression.validateTypes(context); - // Register variable - context.registerVariable(varName, expression); - } - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handleDefine(this); - } - - @Override - public String toString() { - return "DEFINE{%" + varName + " <- " + expression + "}"; - } - - /** - * Parse a define statement. - * @param tokens streams of tokens. - * @return a new instance. - */ - @PreviousIndicator(expected = {TokenType.DEFINE}) - public static @NotNull StatementNode parseNextDefine(@NotNull TokenStream tokens) { - // %VAR_NAME - Token varToken = tokens.nextOrThrow(TokenType.VALUE_VARIABLE); - String varName = varToken.getContentString(); - - // = - if(tokens.dropOptional(TokenType.LIST_ADD, TokenType.LIST_REM, TokenType.LIST_REM_INDEX, TokenType.LIST_CONTAINS)) { - // Wait, this is not a define statement: it's a list-ope ! - tokens.back(); - tokens.back(); - StatementNode statement = new SimpleExpressionStatement( ExpressionNode.readNextExpression(tokens) ); - tokens.dropOptional(TokenType.SEMI_COLON); - return statement; - } - tokens.dropOrThrow(TokenType.EQUAL); - - ExpressionNode expression = ExpressionNode.readNextExpression(tokens); - - // optional ; - tokens.dropOptional(TokenType.SEMI_COLON); - - return new DefineStatement(varName, expression); - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/GiveStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/GiveStatement.java deleted file mode 100644 index c3204dd2..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/GiveStatement.java +++ /dev/null @@ -1,96 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral.NumberExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * A give-statement, to five an ItemStack to a Player. - */ -@Getter -@RequiredArgsConstructor -public class GiveStatement extends StatementNode { - - private final @NotNull ExpressionNode target; - private final @Nullable ExpressionNode optAmount; - private final @Nullable ExpressionNode optType; - private final @Nullable ExpressionNode optProperties; - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handleGive(this); - } - - @Override - public void validateTypes(@NotNull TypesContext context) { - assertExpressionType(target, context, TypePrimitive.ENTITY); - if(optAmount != null) - assertExpressionType(optAmount, context, TypePrimitive.NUMBER); - if(optType != null) - assertExpressionType(optType, context, TypePrimitive.STRING, TypePrimitive.CUSTOM); - if(optProperties != null) - assertExpressionType(optProperties, context, TypePrimitive.PROPERTIES_SET); - } - - @Override - public String toString() { - return "GIVE{" - + (getOptAmount()==null?"":getOptAmount()+" ") - + (getOptType()==null?"":getOptType()+" ") - + "TO " + getTarget() - + (getOptProperties()==null?"":" WITH: " + getOptProperties())+"}"; - } - - /** - * Parse a give statement. - * @param tokens streams of tokens. - * @return a new instance. - */ - @PreviousIndicator(expected = TokenType.GIVE) // GIVE [[] ] TO [WITH: ] - public static @NotNull GiveStatement parseNextGiveStatement(@NotNull TokenStream tokens) { - // Amount + type. both are optional, but 'amount' is even more optional. - ExpressionNode amount, type; - if(tokens.dropOptional(TokenType.TO)) { - // No amount + type - amount = null; - type = null; - } else { - ExpressionNode node = ExpressionNode.readNextExpression(tokens, true); - if(tokens.dropOptional(TokenType.TO)) { - type = node; - amount = new NumberExpression(tokens.position(), 1); - } else { - amount = node; - type = ExpressionNode.readNextExpression(tokens, true); - tokens.dropOrThrow(TokenType.TO); - } - } - - // Now, target - ExpressionNode target = ExpressionNode.readNextExpression(tokens); - - // With ? - ExpressionNode properties; - if(tokens.dropOptional(TokenType.WITH)) { - tokens.dropOrThrow(TokenType.COLON); - properties = ExpressionNode.readNextExpression(tokens); - } else { - properties = null; - } - - tokens.dropOptional(TokenType.SEMI_COLON); - - // create - return new GiveStatement(target, amount, type, properties); - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/IncrementStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/IncrementStatement.java deleted file mode 100644 index 0f4ff738..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/IncrementStatement.java +++ /dev/null @@ -1,58 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; - -import fr.jamailun.ultimatespellsystem.dsl.errors.SyntaxException; -import fr.jamailun.ultimatespellsystem.dsl.errors.TypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.VariableDefinition; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.*; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; - -/** - * Either {@code increment} or {@code decrement}. - */ -@Getter -@RequiredArgsConstructor -public class IncrementStatement extends StatementNode { - - private final TokenPosition tokenPosition; - private final String varName; - private final boolean positive; - - @Override - public void validateTypes(@NotNull TypesContext context) { - VariableDefinition variableDefinition = context.findVariable(varName); - if(variableDefinition == null) - throw new SyntaxException(tokenPosition, "Unknown variable to " + (positive?"increment":"decrement") + " : '" + varName + "'."); - Type type = variableDefinition.getType(context); - if(type.primitive() != TypePrimitive.NUMBER) - throw new TypeException(tokenPosition, "For " + (positive?"increment":"decrement") + " %"+varName+", expected NUMBER. Got type " + type + "."); - } - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handleIncrement(this); - } - - /** - * Parse a increment/decrement statement. - * @param tokens streams of tokens. - * @return a new instance. - */ - @PreviousIndicator(expected = {TokenType.INCREMENT, TokenType.DECREMENT}) - public static @NotNull IncrementStatement parseIncrementOrDecrement(@NotNull TokenStream tokens, boolean increment) { - Token var = tokens.nextOrThrow(TokenType.VALUE_VARIABLE); - tokens.dropOptional(TokenType.SEMI_COLON); - return new IncrementStatement(var.pos(), var.getContentString(), increment); - } - - @Override - public String toString() { - return (positive ?"++":"--") + "%" + varName; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/MetadataStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/MetadataStatement.java deleted file mode 100644 index 40e08b13..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/MetadataStatement.java +++ /dev/null @@ -1,89 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; - -import fr.jamailun.ultimatespellsystem.dsl.metadata.MetadataRulesManager; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.*; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.Unmodifiable; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.StringJoiner; - -/** - * A metadata statement of a spell. - * Should not be "executed" as such. - */ -@RequiredArgsConstructor -@Getter -public class MetadataStatement extends StatementNode { - - private final TokenPosition position; - private final @NotNull String name; - private final @NotNull @Unmodifiable List params; - - /** - * Parse a metadata statement. - * @param tokens streams of tokens. - * @return a new instance. - */ - @PreviousIndicator(expected = TokenType.CHAR_AT) - public static @NotNull MetadataStatement parseMetadata(@NotNull TokenStream tokens) { - TokenPosition position = tokens.position(); - List parameters = new ArrayList<>(); - - String name = tokens.nextOrThrow(TokenType.IDENTIFIER).getContentString(); - if(tokens.dropOptional(TokenType.BRACKET_OPEN)) { - Object raw; - while ((raw = readNextRaw(tokens)) != null) { - parameters.add(raw); - tokens.dropOptional(TokenType.COMMA); - } - tokens.dropOrThrow(TokenType.BRACKET_CLOSE); - } - - return new MetadataStatement(position, name, Collections.unmodifiableList(parameters)); - } - - private static @Nullable Object readNextRaw(@NotNull TokenStream tokens) { - Token token = tokens.peek(); - if(token.getType().isRawValue()) { - tokens.drop(); - return switch(token.getType()) { - case TRUE -> true; - case FALSE -> false; - case IDENTIFIER, VALUE_STRING -> token.getContentString(); - case VALUE_DURATION -> new Duration(token.getContentNumber(), token.getContentTimeUnit()); - case VALUE_NUMBER -> token.getContentNumber(); - default -> throw new RuntimeException("Not reachable (" + token + ")"); - }; - } - return null; - } - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handleMetadata(this); - } - - @Override - public void validateTypes(@NotNull TypesContext context) { - MetadataRulesManager.getRulesForName(getName()) - .forEach(rule -> rule.apply(context, this)); - } - - @Override - public String toString() { - String prefix = "@" + getName() + "("; - StringJoiner sj = new StringJoiner(", "); - params.forEach(p -> sj.add(p.toString())); - return prefix + sj + ")"; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/PlayStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/PlayStatement.java deleted file mode 100644 index a882115f..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/PlayStatement.java +++ /dev/null @@ -1,97 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; - -import fr.jamailun.ultimatespellsystem.dsl.errors.SyntaxException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; - -/** - * A play statement : with a specific {@link Type}. - */ -@Getter -@RequiredArgsConstructor -public class PlayStatement extends StatementNode { - - private final Type type; - private final ExpressionNode location, properties; - - @Override - public void validateTypes(@NotNull TypesContext context) { - assertExpressionType(location, context, TypePrimitive.LOCATION, TypePrimitive.ENTITY); - assertExpressionType(properties, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.PROPERTIES_SET); - } - - /** - * Parse a play statement. - * @param tokens streams of tokens. - * @return a new instance. - */ - @PreviousIndicator(expected = TokenType.PLAY) // PLAY AT WITH: ; - public static @NotNull PlayStatement parsePlay(@NotNull TokenStream tokens) { - Type type = readType(tokens); - tokens.dropOrThrow(TokenType.AT); - ExpressionNode location = ExpressionNode.readNextExpression(tokens); - tokens.dropOrThrow(TokenType.WITH); - tokens.dropOptional(TokenType.COLON); - ExpressionNode properties = ExpressionNode.readNextExpression(tokens); - tokens.dropOptional(TokenType.SEMI_COLON); - return new PlayStatement(type, location, properties); - } - - private static @NotNull Type readType(@NotNull TokenStream tokens) { - Token next = tokens.next(); - String nextValue = next.getContentString(); - return switch(nextValue.toLowerCase()) { - case "block", "b", "bloc" -> Type.BLOCK; - case "particle", "p", "part" -> Type.PARTICLE; - case "sound", "s" -> Type.SOUND; - case "animation", "a", "anim" -> Type.ANIMATION; - default -> throw new SyntaxException(next, "Expected either 'block', 'particle' or 'sound' after a 'PLAY' statement."); - }; - } - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handlePlay(this); - } - - /** - * A type of {@link PlayStatement}. - */ - public enum Type { - /** - * An in-world block, changed for the clients. - */ - BLOCK, - - /** - * A particle-play, sent to clients. - */ - PARTICLE, - - /** - * A sound, played to nearby players. - */ - SOUND, - - /** - * Complex animation. - */ - ANIMATION - } - - @Override - public String toString() { - return "Play_"+type+" :: " + properties; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SendAttributeStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SendAttributeStatement.java deleted file mode 100644 index 278a25f9..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SendAttributeStatement.java +++ /dev/null @@ -1,89 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Optional; - -/** - * Send a bukkit Attribute to a Bukkit Entity. - */ -@Getter -public class SendAttributeStatement extends SendStatement { - - private final ExpressionNode numericValue; - private final ExpressionNode attributeType; - private final @Nullable ExpressionNode attributeMode; - private final ExpressionNode duration; - - public SendAttributeStatement(ExpressionNode target, ExpressionNode numericValue, ExpressionNode attributeType, @Nullable ExpressionNode attributeMode, ExpressionNode duration) { - super(target); - this.numericValue = numericValue; - this.attributeType = attributeType; - this.attributeMode = attributeMode; - this.duration = duration; - } - - @Override - public void validateTypes(@NotNull TypesContext context) { - super.validateTypes(context); - - assertExpressionType(numericValue, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.NUMBER); - assertExpressionType(attributeType, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.CUSTOM, TypePrimitive.STRING); - assertExpressionType(duration, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.DURATION); - if(attributeMode != null) - assertExpressionType(attributeMode, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.CUSTOM, TypePrimitive.STRING); - } - - public Optional getAttributeMode() { - return Optional.ofNullable(attributeMode); - } - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handleSendAttribute(this); - } - - /** - * Parse a send-attribute statement. Called by {@link SendStatement#parseSendStatement(TokenStream)}. - * @param tokens streams of tokens. - * @return a new instance. - */ - @PreviousIndicator(expected = {TokenType.SEND/* + ATTRIBUTE */}) - public static @NotNull SendAttributeStatement parseAttributeEffect(@NotNull ExpressionNode target, @NotNull TokenStream tokens) { - // Value - ExpressionNode numericValue = ExpressionNode.readNextExpression(tokens); - - // Type - ExpressionNode attributeType = ExpressionNode.readNextExpression(tokens, true); - - // Syntax: "[mode] for " - ExpressionNode mode = null; - if( ! tokens.dropOptional(TokenType.FOR)) { - mode = ExpressionNode.readNextExpression(tokens, true); - tokens.dropOrThrow(TokenType.FOR); - } - - ExpressionNode duration = ExpressionNode.readNextExpression(tokens); - - // Optional EOL - tokens.dropOptional(TokenType.SEMI_COLON); - - // return - return new SendAttributeStatement(target, numericValue, attributeType, mode, duration); - } - - @Override - public String toString() { - return "SEND_ATTRIBUTE{to="+target+", attr=" + numericValue + " " + attributeType + (attributeMode==null?"":" ("+attributeMode + ")") + ", for=" + duration + "}"; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SendEffectStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SendEffectStatement.java deleted file mode 100644 index fdef6063..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SendEffectStatement.java +++ /dev/null @@ -1,82 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; - -import java.util.Optional; - -/** - * Send a potion effect to a Bukkit entity. - */ -public class SendEffectStatement extends SendStatement { - - @Getter private final ExpressionNode effectType; - @Getter private final ExpressionNode effectDuration; - private final ExpressionNode effectPower; // nullable ! - - public SendEffectStatement(ExpressionNode target, ExpressionNode effectType, ExpressionNode effectDuration, ExpressionNode effectPower) { - super(target); - this.effectType = effectType; - this.effectDuration = effectDuration; - this.effectPower = effectPower; - } - - @Override - public void validateTypes(@NotNull TypesContext context) { - super.validateTypes(context); - - assertExpressionType(effectType, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.STRING, TypePrimitive.CUSTOM); - assertExpressionType(effectDuration, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.DURATION); - if(effectPower != null) - assertExpressionType(effectPower, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.NUMBER); - } - - public Optional getEffectPower() { - return Optional.ofNullable(effectPower); - } - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handleSendEffect(this); - } - - /** - * Parse a send-effect statement. Called by {@link SendStatement#parseSendStatement(TokenStream)}. - * @param tokens streams of tokens. - * @return a new instance. - */ - @PreviousIndicator(expected = {TokenType.SEND/* + EFFECT */}) - public static @NotNull SendEffectStatement parseSendEffect(@NotNull ExpressionNode target, @NotNull TokenStream tokens) { - // Effect type - ExpressionNode effectType = ExpressionNode.readNextExpression(tokens, true); - - // If FOR just after : no power. - ExpressionNode effectPower; - if( ! tokens.dropOptional(TokenType.FOR)) { - effectPower = ExpressionNode.readNextExpression(tokens); - tokens.dropOrThrow(TokenType.FOR); - } else effectPower = null; - - // Duration - ExpressionNode effectDuration = ExpressionNode.readNextExpression(tokens); - - // Optional EOL - tokens.dropOptional(TokenType.SEMI_COLON); - - // return - return new SendEffectStatement(target, effectType, effectDuration, effectPower); - } - - @Override - public String toString() { - return "SEND_EFFECT{to="+target+", effect=" + effectType + (effectPower==null?"":", power="+effectPower) + ", for=" + effectDuration + "}"; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SendMessageStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SendMessageStatement.java deleted file mode 100644 index 50789411..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SendMessageStatement.java +++ /dev/null @@ -1,56 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; - -/** - * Send a message to a player. - */ -@Getter -public class SendMessageStatement extends SendStatement { - - private final ExpressionNode message; - - public SendMessageStatement(@NotNull ExpressionNode target, @NotNull ExpressionNode message) { - super(target); - this.message = message; - } - - @Override - public void validateTypes(@NotNull TypesContext context) { - super.validateTypes(context); - assertExpressionType(message, context, TypePrimitive.STRING); - } - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handleSendMessage(this); - } - - /** - * Parse a send-message statement. Called by {@link SendStatement#parseSendStatement(TokenStream)}. - * @param tokens streams of tokens. - * @return a new instance. - */ - @PreviousIndicator(expected = {TokenType.SEND/* + MESSAGE */}) - public static @NotNull SendMessageStatement parseSendMessage(@NotNull ExpressionNode target, @NotNull TokenStream tokens) { - ExpressionNode message = ExpressionNode.readNextExpression(tokens); - - // Optional EOL - tokens.dropOptional(TokenType.SEMI_COLON); - - return new SendMessageStatement(target, message); - } - - @Override - public String toString() { - return "SEND_MSG{to="+target+", " + message + "}"; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SendNbtStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SendNbtStatement.java deleted file mode 100644 index b15f4dc6..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SendNbtStatement.java +++ /dev/null @@ -1,68 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; - -/** - * Send a NBT k/v to a Bukkit entity. - */ -public class SendNbtStatement extends SendStatement { - - @Getter private final ExpressionNode nbtName; - @Getter private final ExpressionNode nbtValue; - @Getter private final ExpressionNode nbtDuration; - - public SendNbtStatement(ExpressionNode target, ExpressionNode nbtName, ExpressionNode nbtValue, ExpressionNode nbtDuration) { - super(target); - this.nbtName = nbtName; - this.nbtValue = nbtValue; - this.nbtDuration = nbtDuration; - } - - @Override - public void validateTypes(@NotNull TypesContext context) { - super.validateTypes(context); - - assertExpressionType(nbtName, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.STRING, TypePrimitive.CUSTOM); - assertExpressionType(nbtDuration, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.DURATION); - nbtValue.validateTypes(context.childContext()); - } - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handleSendNbt(this); - } - - /** - * Parse a send-nbt statement. Called by {@link SendStatement#parseSendStatement(TokenStream)}. - * @param tokens streams of tokens. - * @return a new instance. - */ - @PreviousIndicator(expected = {TokenType.SEND/* + NBT */}) // = for ; - public static @NotNull SendNbtStatement parseSendNbt(@NotNull ExpressionNode target, @NotNull TokenStream tokens) { - ExpressionNode nbtName = ExpressionNode.readNextExpression(tokens, true); - tokens.dropOrThrow(TokenType.EQUAL); - ExpressionNode nbtValue = ExpressionNode.readNextExpression(tokens, true); - tokens.dropOrThrow(TokenType.FOR); - ExpressionNode nbtDuration = ExpressionNode.readNextExpression(tokens); - - // Optional EOL - tokens.dropOptional(TokenType.SEMI_COLON); - - // return - return new SendNbtStatement(target, nbtName, nbtValue, nbtDuration); - } - - @Override - public String toString() { - return "SEND_NBT{to="+target+", name=" + nbtName + ", val=" + nbtValue + ", for=" + nbtDuration + "}"; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SendStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SendStatement.java deleted file mode 100644 index 65e46461..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SendStatement.java +++ /dev/null @@ -1,55 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; - -import fr.jamailun.ultimatespellsystem.dsl.errors.SyntaxException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; - -/** - * Abstract send statement. - */ -@Getter -@RequiredArgsConstructor -public abstract class SendStatement extends StatementNode { - - protected final ExpressionNode target; - - @Override - public void validateTypes(@NotNull TypesContext context) { - assertExpressionType(target, context, TypePrimitive.ENTITY); - } - - /** - * Parse a metadata statement. - * @param tokens streams of tokens. - * @return a new instance. - */ - @PreviousIndicator(expected = {TokenType.SEND}) // SEND (to) TARGET (...) - public static @NotNull StatementNode parseSendStatement(@NotNull TokenStream tokens) { - // Optional "to" - tokens.dropOptional(TokenType.TO); - - // Read target expression - ExpressionNode target = ExpressionNode.readNextExpression(tokens); - - // Type of send - Token token = tokens.next(); - String type = token.getContentString(); - return switch (type.toLowerCase()) { - case "message" -> SendMessageStatement.parseSendMessage(target, tokens); - case "effect" -> SendEffectStatement.parseSendEffect(target, tokens); - case "attribute", "attributes" -> SendAttributeStatement.parseAttributeEffect(target, tokens); - case "nbt" -> SendNbtStatement.parseSendNbt(target, tokens); - default -> throw new SyntaxException(token, "Expected SEND type to be one of (message, effect, attribute, nbt)."); - }; - } - -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/StopStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/StopStatement.java deleted file mode 100644 index f453d987..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/StopStatement.java +++ /dev/null @@ -1,57 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import lombok.AllArgsConstructor; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * A {@code stop} statement will stop the spell execution. - */ -@AllArgsConstructor -@Getter -public class StopStatement extends StatementNode { - - private final @Nullable ExpressionNode exitCodeNode; - - @Override - public void validateTypes(@NotNull TypesContext context) { - if(exitCodeNode != null) - assertExpressionType(exitCodeNode, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.NUMBER); - } - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handleStop(this); - } - - /** - * Parse a STOP statement. - * @param tokens streams of tokens. - * @return a new instance. - */ - @PreviousIndicator(expected = TokenType.STOP) - public static @NotNull StopStatement parseStop(@NotNull TokenStream tokens) { - if(tokens.dropOptional(TokenType.SEMI_COLON)) { - return new StopStatement(null); - } else { - ExpressionNode exitNode = ExpressionNode.readNextExpression(tokens); - tokens.dropOrThrow(TokenType.SEMI_COLON); - return new StopStatement(exitNode); - } - } - - @Override - public String toString() { - return "STOP" + (exitCodeNode==null?"":"(" + exitCodeNode + ")"); - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SummonStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SummonStatement.java deleted file mode 100644 index a921c1b1..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SummonStatement.java +++ /dev/null @@ -1,104 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.*; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Optional; - -/** - * Summon an entity (by the caster). - */ -@RequiredArgsConstructor -public class SummonStatement extends StatementNode { - - @Getter private final @NotNull ExpressionNode entityType; - private final @Nullable ExpressionNode optSource; // nullable - private final @Nullable Token optVarName; // nullable - @Getter private final @NotNull ExpressionNode duration; - private final @Nullable ExpressionNode optProperties; // nullable - - @Override - public void validateTypes(@NotNull TypesContext context) { - assertExpressionType(entityType, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.ENTITY_TYPE); - assertExpressionType(duration, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.DURATION); - if(optProperties != null) - assertExpressionType(optProperties, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.PROPERTIES_SET); - - // Register varName - if(optVarName != null) { - context.registerVariable(optVarName.getContentString(), optVarName.pos(), TypePrimitive.ENTITY.asType()); - } - } - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handleSummon(this); - } - - /** - * Parse a summon statement. - * @param tokens streams of tokens. - * @return a new instance. - */ - // SUMMON (ENTITY_TYPE) [AT (POSITION/ENTITY)] [[AS (VAR_NAME)]] FOR (DURATION) [WITH : (PROPS)] - @PreviousIndicator(expected = {TokenType.SUMMON}) - public static @NotNull SummonStatement parseSummonStatement(@NotNull TokenStream tokens) { - //IRON_GOLEM as %ig for 10 seconds with: - ExpressionNode entityType = ExpressionNode.readNextExpression(tokens); - - ExpressionNode source = null; - if(tokens.dropOptional(TokenType.AT)) { - source = ExpressionNode.readNextExpression(tokens); - } - - // AS (VARIABLE) - Token varName = null; - if(tokens.dropOptional(TokenType.AS)) { - varName = tokens.nextOrThrow(TokenType.VALUE_VARIABLE); - } - - tokens.dropOrThrow(TokenType.FOR); - ExpressionNode duration = ExpressionNode.readNextExpression(tokens); - - ExpressionNode optProperties = null; - if(tokens.dropOptional(TokenType.WITH)) { - tokens.dropOrThrow(TokenType.COLON); - optProperties = ExpressionNode.readNextExpression(tokens); - } - - tokens.dropOptional(TokenType.SEMI_COLON); - - return new SummonStatement(entityType, source, varName, duration, optProperties); - } - - @Override - public String toString() { - return "SUMMON{" + entityType - + (optSource != null ? " AT " + optSource : "") - + (optVarName != null ? " AS %" + optVarName.getContentString() : "") - + " FOR " + duration - + (optProperties !=null?" WITH " + optProperties : "") - + "}"; - } - - public Optional getVarName() { - return optVarName == null ? Optional.empty() : Optional.of(optVarName.getContentString()); - } - - public Optional getProperties() { - return Optional.ofNullable(optProperties); - } - - public Optional getSource() { - return Optional.ofNullable(optSource); - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/TeleportStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/TeleportStatement.java deleted file mode 100644 index 2b0ec572..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/TeleportStatement.java +++ /dev/null @@ -1,55 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; - -/** - * Teleport a bukkit entity to a location (or another entity). - */ -@Getter -@RequiredArgsConstructor -public class TeleportStatement extends StatementNode { - - private final ExpressionNode entity; - private final ExpressionNode target; - - @Override - public void validateTypes(@NotNull TypesContext context) { - assertExpressionType(entity, context, TypePrimitive.ENTITY); - assertExpressionType(target, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.ENTITY, TypePrimitive.LOCATION); - } - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handleTeleport(this); - } - - /** - * Parse a teleport statement. - * @param tokens streams of tokens. - * @return a new instance. - */ - @PreviousIndicator(expected = TokenType.TELEPORT) - public static @NotNull TeleportStatement parseTeleport(@NotNull TokenStream tokens) { - ExpressionNode entity = ExpressionNode.readNextExpression(tokens); - tokens.dropOrThrow(TokenType.TO); - ExpressionNode target = ExpressionNode.readNextExpression(tokens); - tokens.dropOptional(TokenType.SEMI_COLON); - return new TeleportStatement(entity, target); - } - - @Override - public String toString() { - return "TELEPORT " + entity + " TO " + target; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/CallbackStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/CallbackStatement.java deleted file mode 100644 index cff0ae94..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/CallbackStatement.java +++ /dev/null @@ -1,108 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements.blocks; - -import fr.jamailun.ultimatespellsystem.dsl.errors.SyntaxException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.VariableDefinition; -import fr.jamailun.ultimatespellsystem.dsl.objects.CallbackEvent; -import fr.jamailun.ultimatespellsystem.dsl.registries.CallbackEventRegistry; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.*; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Optional; - -/** - * A statement used to trigger an action happens. - */ -@Getter -public class CallbackStatement extends BlockHolder { - - private final TokenPosition firstPosition; - private final String listenVariableName; - private final CallbackEvent callbackType; - private final @Nullable String outputVariable; - - public CallbackStatement(TokenPosition firstPosition, String listenVariableName, CallbackEvent callbackType, @Nullable String outputVariable, StatementNode child) { - super(child); - this.firstPosition = firstPosition; - this.listenVariableName = listenVariableName; - this.callbackType = callbackType; - this.outputVariable = outputVariable; - } - - @Override - public void validateTypes(@NotNull TypesContext context) { - // variable must exist and be an entity. - VariableDefinition input = context.findVariable(listenVariableName); - if(input == null) - throw new SyntaxException(firstPosition, "Unknown variable name: '" + listenVariableName + "'."); - Type inputType = input.getType(context); - if(!inputType.is(TypePrimitive.ENTITY)) - throw new SyntaxException(firstPosition, "Variable "+listenVariableName+" for a callback must be an entity. Current type is: " + inputType + "'."); - if(inputType.isCollection()) - throw new SyntaxException(firstPosition, "Variable "+listenVariableName+" for a callback must be an entity, not an array."); - - TypesContext childContext = context.childContext(); - // declare variable (if set) - if(outputVariable != null) { - assert callbackType.argument() != null; // compiler helper - childContext.registerVariable(outputVariable, firstPosition, callbackType.argument().type().asType()); - } - - // Validate child - child.validateTypes(childContext); - } - - public Optional getOutputVariable() { - return Optional.ofNullable(outputVariable); - } - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handleCallback(this); - } - - /** - * Parse a callback statement. - * @param tokens streams of tokens. - * @return a new instance. - */ - @PreviousIndicator(expected = TokenType.CALLBACK) // CALLBACK % [ %]: {CHILD} - public static @NotNull CallbackStatement parseCallback(@NotNull TokenStream tokens) { - TokenPosition pos = tokens.position(); - String varName = tokens.nextOrThrow(TokenType.VALUE_VARIABLE).getContentString(); - - Token eventToken = tokens.next(); - if(eventToken.getType() != TokenType.VALUE_STRING && eventToken.getType() != TokenType.IDENTIFIER) { - throw new SyntaxException(eventToken, "Invalid token for callback type. Expected a string or an identifier. Got " + eventToken + "."); - } - String eventName = eventToken.getContentString(); - CallbackEvent eventType = CallbackEventRegistry.get(eventName); - if(eventType == null) { - throw new SyntaxException(eventToken, "Unregistered callback type: '" + eventName + "'."); - } - - String argVariable; - if(tokens.dropOptional(TokenType.COLON)) { - argVariable = null; - } else { - if(eventType.argument() == null) - throw new SyntaxException(tokens.position(), "Callback type " + eventType.name() + " does ot accept any argument. As such, a ':' was expected."); - if(eventType.argument().keyword() != tokens.peek().getType()) - throw new SyntaxException(tokens.position(), "Callback type " + eventType.name() + " only accept argument with keyword " + eventType.argument().keyword() + ". Got " + tokens.peek() + "."); - tokens.drop(); - argVariable = tokens.nextOrThrow(TokenType.VALUE_VARIABLE).getContentString(); - tokens.dropOrThrow(TokenType.COLON); - } - - StatementNode child = StatementNode.parseNextStatement(tokens); - tokens.dropOptional(TokenType.SEMI_COLON); - - return new CallbackStatement(pos, varName, eventType, argVariable, child); - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/ForeachLoopStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/ForeachLoopStatement.java deleted file mode 100644 index b44bb7a2..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/ForeachLoopStatement.java +++ /dev/null @@ -1,75 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements.blocks; - -import fr.jamailun.ultimatespellsystem.dsl.errors.TypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; - -/** - * Foreach iteration over a collection. - */ -@RequiredArgsConstructor -public class ForeachLoopStatement extends StatementNode { - - private final Token varName; - @Getter private final ExpressionNode source; - @Getter private final StatementNode child; - - public String getVariableName() { - return varName.getContentString(); - } - - @Override - public void validateTypes(@NotNull TypesContext context) { - TypesContext childContext = context.childContext(); - - // Source - source.validateTypes(context); - if(!source.getExpressionType().isCollection()) { - throw new TypeException(source, "A FOREACH statement must use a collection for the source."); - } - - // declare variable - childContext.registerVariable(varName.getContentString(), varName.pos(), source.getExpressionType().asMonoElement()); - - // Validate child - child.validateTypes(childContext); - } - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handleForeachLoop(this); - } - - /** - * Parse a foreach statement. - * @param tokens streams of tokens. - * @return a new instance. - */ - @PreviousIndicator(expected = TokenType.FOREACH) // FOREACH( : ) - public static @NotNull ForeachLoopStatement parseForLoop(@NotNull TokenStream tokens) { - tokens.dropOrThrow(TokenType.BRACKET_OPEN); - - Token varName = tokens.nextOrThrow(TokenType.VALUE_VARIABLE); - tokens.dropOrThrow(TokenType.COLON); - ExpressionNode source = ExpressionNode.readNextExpression(tokens); - - tokens.dropOrThrow(TokenType.BRACKET_CLOSE); - StatementNode child = StatementNode.parseNextStatement(tokens); - - return new ForeachLoopStatement(varName, source, child); - } - - @Override - public String toString() { - return "FOREACH( %" + varName + " IN " + source + "): " + child; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/RepeatStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/RepeatStatement.java deleted file mode 100644 index b30cecbf..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/RepeatStatement.java +++ /dev/null @@ -1,111 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements.blocks; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Optional; - -/** - * Statement of a {@code repeat times}. - */ -public class RepeatStatement extends BlockHolder { - - /** - * Name of the variable set by this statement. - */ - public static final String INDEX_VARIABLE = "_repeat_index"; - - private final @Nullable ExpressionNode delay; // optional - @Getter private @Nullable final ExpressionNode totalCount; // either 'count' or 'totalDuration' - @Getter private @NotNull final ExpressionNode period; - @Getter private @Nullable final ExpressionNode totalDuration; - - public RepeatStatement(@NotNull StatementNode child, @Nullable ExpressionNode delay, @Nullable ExpressionNode totalCount, @NotNull ExpressionNode period, @Nullable ExpressionNode totalDuration) { - super(child); - this.delay = delay; - this.totalCount = totalCount; - this.period = period; - this.totalDuration = totalDuration; - } - - @Override - public void validateTypes(@NotNull TypesContext context) { - TypesContext childContext = context.childContext(); - childContext.promiseVariable(INDEX_VARIABLE, TypePrimitive.NUMBER.asType()); - - if(delay != null) - assertExpressionType(delay, CollectionFilter.MONO_ELEMENT, childContext, TypePrimitive.DURATION); - if(totalCount != null) - assertExpressionType(totalCount, CollectionFilter.MONO_ELEMENT, childContext, TypePrimitive.NUMBER); - assertExpressionType(period, CollectionFilter.MONO_ELEMENT, childContext, TypePrimitive.DURATION); - if(totalDuration != null) - assertExpressionType(totalDuration, CollectionFilter.MONO_ELEMENT, childContext, TypePrimitive.DURATION); - - child.validateTypes(childContext.childContext()); - } - - public Optional getDelay() { - return Optional.ofNullable(delay); - } - - /** - * Parse a "repeat N times" statement. - * @param tokens streams of tokens. - * @return a new instance. - */ - // REPEAT [[AFTER (DURATION)]] (COUNT) TIMES EVERY (FREQ): {} - // REPEAT [[AFTER (DURATION)]] EVERY (FREQ) FOR (DURATION): {} - @PreviousIndicator(expected = {TokenType.REPEAT}) - public static RepeatStatement parseRepeat(TokenStream tokens) { - ExpressionNode delay = null; - if(tokens.dropOptional(TokenType.AFTER)) { - delay = ExpressionNode.readNextExpression(tokens); - } - - ExpressionNode freq; - ExpressionNode count; - ExpressionNode duration; - - // 2nd syntax : EVERY f FOR d - if(tokens.dropOptional(TokenType.EVERY)) { - freq = ExpressionNode.readNextExpression(tokens); - tokens.dropOrThrow(TokenType.FOR); - duration = ExpressionNode.readNextExpression(tokens); - count = null; - } - // 1st syntax : c TIMES EVERY f - else { - count = ExpressionNode.readNextExpression(tokens); - tokens.dropOrThrow(TokenType.TIMES); - tokens.dropOrThrow(TokenType.EVERY); - freq = ExpressionNode.readNextExpression(tokens); - duration = null; - } - - // Always present: child nodes. - tokens.dropOrThrow(TokenType.COLON); - StatementNode child = StatementNode.parseNextStatement(tokens); - tokens.dropOptional(TokenType.SEMI_COLON); - return new RepeatStatement(child, delay, count, freq, duration); - } - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handleRepeatRun(this); - } - - @Override - public String toString() { - return "RUN{"+(delay==null?"":" AFTER " + period)+" " + totalCount + " times every " + period + "}: " + child; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/RunLaterStatement.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/RunLaterStatement.java deleted file mode 100644 index daa14263..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/RunLaterStatement.java +++ /dev/null @@ -1,61 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements.blocks; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import org.jetbrains.annotations.NotNull; - -/** - * Run a block of code after a delay. - */ -public class RunLaterStatement extends BlockHolder { - - private final ExpressionNode duration; - - public RunLaterStatement(@NotNull StatementNode child, @NotNull ExpressionNode duration) { - super(child); - this.duration = duration; - } - - @Override - public void validateTypes(@NotNull TypesContext context) { - assertExpressionType(duration, CollectionFilter.MONO_ELEMENT, context, TypePrimitive.DURATION); - child.validateTypes(context.childContext()); - } - - public @NotNull ExpressionNode getDuration() { - return duration; - } - - /** - * Parse a "run later" statement. - * @param tokens streams of tokens. - * @return a new instance. - */ - // RUN AFTER (DURATION): {} - @PreviousIndicator(expected = {TokenType.RUN}) - public static RunLaterStatement parseRunLater(TokenStream tokens) { - tokens.dropOrThrow(TokenType.AFTER); - ExpressionNode duration = ExpressionNode.readNextExpression(tokens); - tokens.dropOrThrow(TokenType.COLON); - StatementNode child = StatementNode.parseNextStatement(tokens); - tokens.dropOptional(TokenType.SEMI_COLON); - return new RunLaterStatement(child, duration); - } - - @Override - public void visit(@NotNull StatementVisitor visitor) { - visitor.handleRunLater(this); - } - - @Override - public String toString() { - return "RUN{AFTER " + duration + "}: " + child; - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/Type.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/Type.java deleted file mode 100644 index 8f56fff3..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/Type.java +++ /dev/null @@ -1,45 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.type; - -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; - -/** - * Represents the type of an expression. - * @param primitive the kind of type. - * @param isCollection if true, this is a collection of primitives. - */ -public record Type(@NotNull TypePrimitive primitive, boolean isCollection) { - - /** - * Check if this type is of a primitive. - * @param primitive the primitive to compare this type with. - * @return true if the primitives are equals. - */ - public boolean is(TypePrimitive primitive) { - return this.primitive == primitive; - } - - @Contract(pure = true) - @Override - public @NotNull String toString() { - return primitive + (isCollection?"[]":""); - } - - /** - * Get this type as a non-list. - * @return a new instance of a type. - */ - @Contract(" -> new") - public @NotNull Type asMonoElement() { - return new Type(primitive, false); - } - - /** - * Get this type as a list. - * @return a new instance of a type. - */ - @Contract(" -> new") - public @NotNull Type asCollection() { - return new Type(primitive, true); - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/variables/TypesContext.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/variables/TypesContext.java deleted file mode 100644 index eb5a80b2..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/variables/TypesContext.java +++ /dev/null @@ -1,89 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables; - -import fr.jamailun.ultimatespellsystem.dsl.errors.SyntaxException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; -import java.util.Map; - -/** - * A context for type validation. - */ -public class TypesContext { - - private final Map vars = new HashMap<>(); - - /** - * Create a new context, and register the {@code %caster} variable. - */ - public TypesContext() { - promiseVariable("caster", TypePrimitive.ENTITY.asType()); - } - - /** - * Register a new variable. - * @param varName the name of the variable. - * @param variable the expression defining the variable. - */ - public void registerVariable(@NotNull String varName, @NotNull ExpressionNode variable) { - if("caster".equals(varName)) { - throw new SyntaxException(variable.firstTokenPosition(), "Cannot override variable '%" + varName + "'."); - } - - vars.putIfAbsent(varName, new VariableDefinition(varName)); - vars.get(varName).register(new VariableReference.Dynamic(variable)); - vars.get(varName).getType(this); - } - - /** - * Guarantee a variable will be set by a runtime implementation. - * @param name the name of the variable. - * @param type the type of the variable. - */ - public void promiseVariable(@NotNull String name, @NotNull Type type) { - vars.putIfAbsent(name, new VariableDefinition(name)); - vars.get(name).register(new VariableReference.Constant(type, TokenPosition.unknown())); - } - - /** - * Register a variable, with an already guaranteed type. - * @param varName the variable name. - * @param position the position of the declaration. - * @param type the type of variable. - */ - public void registerVariable(@NotNull String varName, @NotNull TokenPosition position, @NotNull Type type) { - if("caster".equals(varName)) { - throw new SyntaxException(position, "Cannot override variable '%" + varName + "'."); - } - - vars.putIfAbsent(varName, new VariableDefinition(varName)); - vars.get(varName).register(new VariableReference.Constant(type, position)); - } - - /** - * Lookup for a specific variable. - * @param varName the name of the variable to look for. - * @return {@code null} if nothing was found. - */ - public @Nullable VariableDefinition findVariable(@NotNull String varName) { - return vars.get(varName); - } - - /** - * Create a new context. This allows sub-scopes to be independents. - * @return a new instance of context, copying the current variables. - */ - @Contract(" -> new") - public @NotNull TypesContext childContext() { - TypesContext child = new TypesContext(); - child.vars.putAll(vars); - return child; - } - -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/validators/StructureValidationVisitor.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/validators/StructureValidationVisitor.java deleted file mode 100644 index f58da5f7..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/validators/StructureValidationVisitor.java +++ /dev/null @@ -1,114 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.validators; - -import fr.jamailun.ultimatespellsystem.dsl.errors.TreeValidationException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.statements.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.statements.blocks.*; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; -import org.jetbrains.annotations.NotNull; - -/** - * Structure validation. - */ -public class StructureValidationVisitor implements StatementVisitor { - private boolean stopMet = false; - private boolean breakMet = false; - private boolean metadataAllowed = true; - - private StructureValidationVisitor child() { - StructureValidationVisitor clone = new StructureValidationVisitor(); - clone.metadataAllowed = metadataAllowed; - clone.stopMet = stopMet; - clone.breakMet = breakMet; - return clone; - } - - @Override - public void handleMetadata(@NotNull MetadataStatement statement) { - if(!metadataAllowed) - throw new TreeValidationException(TokenPosition.unknown(), "Meta-data can only be the first statements."); - } - - @Override - public void handleStop(@NotNull StopStatement statement) { - handleMono(); - stopMet = true; - } - @Override - public void handleBreakContinue(@NotNull BreakContinueStatement statement) { - handleMono(); - breakMet = true; - } - - @Override - public void handleBlock(@NotNull BlockStatement statement) { - handleMono(); - StructureValidationVisitor child = child(); - statement.getChildren().forEach(n -> n.visit(child)); - } - - private void handleSub(@NotNull StatementNode child) { - child.visit(child()); - } - - private void handleMono() { - metadataAllowed = false; - if(stopMet) { - throw new TreeValidationException(TokenPosition.unknown(), "Cannot have a statement after a STOP."); - } - if(breakMet) { - throw new TreeValidationException(TokenPosition.unknown(), "Cannot have a statement in the block after a BREAK or a CONTINUE."); - } - } - - @Override - public void handleIf(@NotNull IfElseStatement statement) { - handleSub(statement.getChild()); - statement.getElse().ifPresent(this::handleSub); - } - @Override - public void handleForLoop(@NotNull ForLoopStatement statement) { - handleSub(statement.getChild()); - } - @Override - public void handleForeachLoop(@NotNull ForeachLoopStatement statement) { - handleSub(statement.getChild()); - } - @Override - public void handleWhileLoop(@NotNull WhileLoopStatement statement) { - handleSub(statement.getChild()); - } - @Override - public void handleRunLater(@NotNull RunLaterStatement statement) { - statement.getChild().visit(child()); - } - @Override - public void handleRepeatRun(@NotNull RepeatStatement statement) {statement.getChild().visit(child());} - @Override - public void handleCallback(@NotNull CallbackStatement statement) {statement.getChild().visit(child());} - - @Override - public void handleSendMessage(@NotNull SendMessageStatement statement) {handleMono();} - @Override - public void handleSendNbt(@NotNull SendNbtStatement statement) {handleMono();} - @Override - public void handleSendEffect(@NotNull SendEffectStatement statement) {handleMono();} - @Override - public void handleSendAttribute(@NotNull SendAttributeStatement statement) {handleMono();} - - @Override - public void handleDefine(@NotNull DefineStatement statement) {handleMono();} - @Override - public void handleSummon(@NotNull SummonStatement statement) {handleMono();} - @Override - public void handleIncrement(@NotNull IncrementStatement statement) {handleMono();} - @Override - public void handleTeleport(@NotNull TeleportStatement statement) {handleMono();} - @Override - public void handlePlay(@NotNull PlayStatement statement) {handleMono();} - @Override - public void handleGive(@NotNull GiveStatement statement) {handleMono();} - @Override - public void handleSimpleExpression(@NotNull SimpleExpressionStatement statement) {handleMono();} -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/visitor/ExpressionVisitor.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/visitor/ExpressionVisitor.java deleted file mode 100644 index 129b72c4..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/visitor/ExpressionVisitor.java +++ /dev/null @@ -1,45 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.visitor; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.compute.AllEntitiesAroundExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionCallExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.compute.PositionOfExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.compute.SizeOfExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators.BiOperator; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators.MonoOperator; -import org.jetbrains.annotations.NotNull; - -/** - * A visitor. Can interact with the node-tree. - */ -public interface ExpressionVisitor { - - // Literals - void handleNullLiteral(@NotNull NullExpression literal); - void handleBooleanLiteral(@NotNull BooleanExpression literal); - void handleNumberLiteral(@NotNull NumberExpression literal); - void handleStringLiteral(@NotNull StringExpression literal); - void handleEntityTypeLiteral(@NotNull EntityTypeExpression literal); - void handleRuntimeLiteral(@NotNull RuntimeLiteral literal); - void handleDurationLiteral(@NotNull DurationExpression literal); - void handleLocationLiteral(@NotNull LocationLiteral literal); - - // Operators-ish - void handleBiOperator(@NotNull BiOperator operator); - void handleMonoOperator(@NotNull MonoOperator operator); - void handleParenthesis(@NotNull ParenthesisExpression parenthesis); - void handleArrayGet(@NotNull ArrayGetterExpression arrayGetter); - - // Specifics - void handlePropertiesSet(@NotNull PropertiesExpression expression); - void handleArray(@NotNull ArrayExpression expression); - void handleVariable(@NotNull VariableExpression expression); - - // Functions - void handleAllAround(@NotNull AllEntitiesAroundExpression expression); - void handlePositionOf(@NotNull PositionOfExpression expression); - void handleSizeOf(@NotNull SizeOfExpression expression); - void handleFunction(@NotNull FunctionCallExpression expression); - -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/visitor/PrintingVisitor.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/visitor/PrintingVisitor.java deleted file mode 100644 index be7e80da..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/visitor/PrintingVisitor.java +++ /dev/null @@ -1,557 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.visitor; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionCallExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.compute.SizeOfExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.statements.blocks.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.compute.AllEntitiesAroundExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.compute.PositionOfExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators.BiOperator; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators.MonoOperator; -import fr.jamailun.ultimatespellsystem.dsl.nodes.statements.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; -import org.jetbrains.annotations.NotNull; - -import java.text.DecimalFormat; -import java.util.List; -import java.util.Map; - -/** - * Made to print content. - */ -public class PrintingVisitor implements StatementVisitor, ExpressionVisitor { - - private final static DecimalFormat formatNumber = new DecimalFormat("#.##"); - - private final int indentDelta; - private String indentBuffer; - private int currentIndent = 0; - private boolean dirty = true; - - private StringBuilder builder; - - private PrintingVisitor(int indent) { - this.indentDelta = indent; - } - - private @NotNull String visit(@NotNull List statements) { - builder = new StringBuilder(); - for(StatementNode statement : statements) { - statement.visit(this); - eol(); - } - return builder.toString(); - } - - /** - * Print multiple statements to sys-out, with an indentation of {@code 2}. - * @param statements the non-null statements to visit. - */ - public static void print(@NotNull List statements) { - print(statements, 2); - } - - /** - * Print multiple statements to sys-out. - * @param statements list of statements to print. - * @param indent specific indent to use. - */ - public static void print(@NotNull List statements, int indent) { - System.out.println(toString(statements, indent)); - } - - /** - * Print multiple statements to a String. - * @param statements list of statements to print. - * @return the print output. - */ - public static @NotNull String toString(@NotNull List statements) { - return toString(statements, 2); - } - - /** - * Print multiple statements to a String. - * @param statements list of statements to print. - * @param indent specific indent to use. - * @return the print output. - */ - public static @NotNull String toString(@NotNull List statements, int indent) { - return new PrintingVisitor(indent).visit(statements); - } - - private @NotNull String indent() { - if(dirty) { - indentBuffer = " ".repeat(currentIndent); - dirty = false; - } - return indentBuffer; - } - - private void right() { - currentIndent += indentDelta; - dirty = true; - } - - private void left() { - currentIndent -= indentDelta; - if(currentIndent < 0) { - currentIndent = 0; - } - dirty = true; - } - - private void eol() { - builder.append(";\n"); - } - - @Override - public void handleStop(@NotNull StopStatement statement) { - builder.append(indent()).append("stop"); - } - - @Override - public void handleSendMessage(@NotNull SendMessageStatement statement) { - builder.append(indent()).append("send to "); - statement.getTarget().visit(this); - builder.append(" message "); - statement.getMessage().visit(this); - } - - @Override - public void handleSendNbt(@NotNull SendNbtStatement statement) { - builder.append(indent()).append("send to "); - statement.getTarget().visit(this); - builder.append(" NBT "); - statement.getNbtName().visit(this); - builder.append(" = "); - statement.getNbtValue().visit(this); - builder.append(" for "); - statement.getNbtDuration().visit(this); - } - - @Override - public void handleSendEffect(@NotNull SendEffectStatement statement) { - builder.append(indent()).append("send to "); - statement.getTarget().visit(this); - builder.append(" effect "); - statement.getEffectType().visit(this); - statement.getEffectPower().ifPresent(e -> { - builder.append(" "); - e.visit(this); - }); - builder.append(" for "); - statement.getEffectDuration().visit(this); - } - - @Override - public void handleSendAttribute(@NotNull SendAttributeStatement statement) { - builder.append(indent()).append("send to "); - statement.getTarget().visit(this); - builder.append(" attribute "); - statement.getNumericValue().visit(this); - builder.append(" "); - statement.getAttributeType().visit(this); - statement.getAttributeMode().ifPresent(e -> { - builder.append(" ("); - e.visit(this); - builder.append(")"); - }); - builder.append(" for "); - statement.getDuration().visit(this); - } - - @Override - public void handleDefine(@NotNull DefineStatement statement) { - builder.append(indent()) - .append("define %") - .append(statement.getVarName()) - .append(" = "); - statement.getExpression().visit(this); - } - - @Override - public void handleRunLater(@NotNull RunLaterStatement statement) { - builder.append(indent()).append("run after "); - statement.getDuration().visit(this); - builder.append(" : "); - statement.getChild().visit(this); - } - - @Override - public void handleRepeatRun(@NotNull RepeatStatement statement) { - builder.append(indent()).append("run "); - statement.getDelay().ifPresent(e -> { - builder.append("after "); - e.visit(this); - builder.append(", "); - }); - if(statement.getTotalCount() != null) { - statement.getTotalCount().visit(this); - builder.append(" times every "); - statement.getPeriod().visit(this); - } else { - assert statement.getTotalDuration() != null; - builder.append("every "); - statement.getPeriod().visit(this); - builder.append(" for "); - statement.getTotalDuration().visit(this); - } - builder.append(" : "); - statement.getChild().visit(this); - } - - @Override - public void handleSummon(@NotNull SummonStatement statement) { - builder.append(indent()).append("summon "); - statement.getEntityType().visit(this); - statement.getSource().ifPresent(p -> { - builder.append(" at "); - p.visit(this); - }); - builder.append(" for "); - statement.getDuration().visit(this); - statement.getVarName().ifPresent(v -> builder.append(" as %").append(v)); - statement.getProperties().ifPresent(p -> { - builder.append(" with: "); - p.visit(this); - }); - } - - @Override - public void handleBlock(@NotNull BlockStatement statement) { - builder.append("{\n"); - right(); - for(StatementNode child : statement.getChildren()) { - child.visit(this); - eol(); - } - left(); - builder.append(indent()).append("}"); - } - - @Override - public void handleIncrement(@NotNull IncrementStatement statement) { - builder.append(statement.isPositive() ? "++" : "--") - .append("%").append(statement.getVarName()); - } - - @Override - public void handleTeleport(@NotNull TeleportStatement statement) { - builder.append("teleport "); - statement.getEntity().visit(this); - builder.append(" to "); - statement.getTarget().visit(this); - } - - @Override - public void handlePlay(@NotNull PlayStatement statement) { - builder.append("PLAY ") - .append(statement.getType()) - .append(" AT "); - statement.getLocation().visit(this); - builder.append(" WITH "); - statement.getProperties().visit(this); - } - - @Override - public void handleGive(@NotNull GiveStatement statement) { - builder.append("GIVE"); - if(statement.getOptAmount() != null) { - builder.append(" "); - statement.getOptAmount().visit(this); - } - if(statement.getOptType() != null) { - builder.append(" "); - statement.getOptType().visit(this); - } - builder.append(" TO "); - statement.getTarget().visit(this); - if(statement.getOptProperties() != null) { - builder.append(" WITH: "); - statement.getOptProperties().visit(this); - } - } - - @Override - public void handleCallback(@NotNull CallbackStatement statement) { - builder.append("CALLBACK %") - .append(statement.getListenVariableName()) - .append(" ON @") - .append(statement.getCallbackType().name()); - statement.getOutputVariable().ifPresent(output -> { - assert statement.getCallbackType().argument() != null; // compiler hint - builder.append(statement.getCallbackType().argument().keyword()) - .append(" %") - .append(output); - }); - builder.append(": "); - statement.getChild().visit(this); - } - - @Override - public void handleSimpleExpression(@NotNull SimpleExpressionStatement statement) { - builder.append("{"); - statement.getChild().visit(this); - builder.append("}"); - } - - @Override - public void handleMetadata(@NotNull MetadataStatement statement) { - builder.append(indent()).append("@").append(statement.getName()); - boolean big = statement.getParams().size() > 1; - if(big) builder.append("("); - boolean first = true; - for(Object node : statement.getParams()) { - if(first) first = false; else builder.append(", "); - builder.append(node); - } - if(big) builder.append(")"); - } - - @Override - public void handleIf(@NotNull IfElseStatement statement) { - builder.append(indent()).append("IF("); - statement.getCondition().visit(this); - builder.append("):"); - right(); - statement.getChild().visit(this); - left(); - builder.append("\n"); - - statement.getElse().ifPresent(e -> { - builder.append(indent()).append("ELSE : "); - right(); - e.visit(this); - left(); - builder.append("\n"); - }); - } - - @Override - public void handleForLoop(@NotNull ForLoopStatement statement) { - builder.append(indent()) - .append("FOR("); - if(statement.getInitialization() != null) statement.getInitialization().visit(this); - statement.getCondition().visit(this); - builder.append(";"); - if(statement.getIteration() != null) statement.getIteration().visit(this); - builder.append("):"); - statement.getChild().visit(this); - } - - @Override - public void handleForeachLoop(@NotNull ForeachLoopStatement statement) { - builder.append(indent()) - .append("FOREACH(%") - .append(statement.getVariableName()) - .append(" : "); - statement.getSource().visit(this); - builder.append("):"); - statement.getChild().visit(this); - } - - @Override - public void handleWhileLoop(@NotNull WhileLoopStatement statement) { - if(statement.isWhileFirst()) { - builder.append("WHILE("); - statement.getCondition().visit(this); - builder.append(") "); - } else { - builder.append("DO "); - } - statement.getChild().visit(this); - if(!statement.isWhileFirst()) { - builder.append(" WHILE("); - statement.getCondition().visit(this); - builder.append(") "); - } - } - - @Override - public void handleBreakContinue(@NotNull BreakContinueStatement statement) { - builder.append(statement.isContinue() ? "CONTINUE" : "BREAK"); - } - - @Override - public void handleNullLiteral(@NotNull NullExpression literal) { - builder.append("NULL"); - } - - @Override - public void handleBooleanLiteral(@NotNull BooleanExpression literal) { - builder.append(literal.getRaw()); - } - - @Override - public void handleNumberLiteral(@NotNull NumberExpression literal) { - double num = literal.getRaw(); - builder.append(formatNumber.format(num)); - } - - @Override - public void handleStringLiteral(@NotNull StringExpression literal) { - builder.append("\"").append(literal.getRaw()).append("\""); - } - - @Override - public void handleEntityTypeLiteral(@NotNull EntityTypeExpression literal) { - builder.append("EntityType.").append(literal.getRaw()); - } - - @Override - public void handleRuntimeLiteral(@NotNull RuntimeLiteral literal) { - builder.append("'").append(literal.getRaw()).append("'"); - } - - @Override - public void handleDurationLiteral(@NotNull DurationExpression literal) { - Duration duration = literal.getRaw(); - builder.append(formatNumber.format(duration.amount())) - .append(" ") - .append(duration.niceUnit()); - } - - @Override - public void handleLocationLiteral(@NotNull LocationLiteral literal) { - builder.append("Location("); - literal.getWorld().visit(this); builder.append(", "); - literal.getVectorX().visit(this); builder.append(", "); - literal.getVectorY().visit(this); builder.append(", "); - literal.getVectorZ().visit(this); - if(literal.asYawAndPitch()) { - builder.append(", "); - literal.getYaw().visit(this); - builder.append(", "); - literal.getPitch().visit(this); - } - builder.append(")"); - } - - @Override - public void handleBiOperator(@NotNull BiOperator operator) { - operator.getLeft().visit(this); - String ope = switch (operator.getType()) { - case ADD -> "+"; - case SUB -> "-"; - case MUL -> "*"; - case DIV -> "/"; - case EQUAL -> "=="; - case NOT_EQUAL -> "!="; - case GREATER_OR_EQ -> ">="; - case GREATER -> ">"; - case LESSER_OR_EQ -> "<="; - case LESSER -> "<"; - case AND -> "and"; - case OR -> "or"; - case LIST_ADD -> "append"; - case LIST_REM -> "remove"; - case LIST_CONTAINS -> "contains"; - case LIST_REM_INDEX -> "remove_idx"; - }; - builder.append(" ").append(ope).append(" "); - operator.getRight().visit(this); - } - - @Override - public void handleMonoOperator(@NotNull MonoOperator operator) { - String ope = operator.getType().name(); - builder.append(ope).append("("); - operator.getChild().visit(this); - builder.append(")"); - } - - @Override - public void handleParenthesis(@NotNull ParenthesisExpression parenthesis) { - builder.append("("); - parenthesis.getExpression().visit(this); - builder.append(")"); - } - - @Override - public void handleArrayGet(@NotNull ArrayGetterExpression arrayGetter) { - arrayGetter.getArray().visit(this); - builder.append("["); - arrayGetter.getIndex().visit(this); - builder.append("]"); - } - - @Override - public void handlePropertiesSet(@NotNull PropertiesExpression expression) { - builder.append("{{"); - if(expression.getExpressions().isEmpty()) { - builder.append("}}"); - return; - } - builder.append("\n"); - right(); - boolean first = true; - for(Map.Entry entry : expression.getExpressions().entrySet()) { - if(first) first = false; else builder.append(",\n"); - builder.append(indent()) - .append(entry.getKey()) - .append(" = "); - entry.getValue().visit(this); - } - builder.append("\n"); - left(); - builder.append(indent()).append("}}"); - } - - @Override - public void handleAllAround(@NotNull AllEntitiesAroundExpression expression) { - builder.append(""); - } - - @Override - public void handlePositionOf(@NotNull PositionOfExpression expression) { - builder.append("position of ("); - expression.getEntity().visit(this); - builder.append(")"); - } - - @Override - public void handleSizeOf(@NotNull SizeOfExpression expression) { - builder.append("sizeof("); - expression.getChild().visit(this); - builder.append(")"); - } - - @Override - public void handleFunction(@NotNull FunctionCallExpression expression) { - builder.append(":") - .append(expression.getFunction().id()) - .append("("); - boolean first = true; - for(ExpressionNode arg : expression.getArguments()) { - if(first) first = false; else builder.append(", "); - arg.visit(this); - } - builder.append(")"); - } - - @Override - public void handleArray(@NotNull ArrayExpression expression) { - builder.append("["); - boolean first = true; - for(ExpressionNode child : expression.getElements()) { - if(first) first = false; else builder.append(", "); - child.visit(this); - } - builder.append("]"); - } - - @Override - public void handleVariable(@NotNull VariableExpression expression) { - builder.append("%").append(expression.getVariableName()); - } -} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/visitor/StatementVisitor.java b/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/visitor/StatementVisitor.java deleted file mode 100644 index 97f1f470..00000000 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/visitor/StatementVisitor.java +++ /dev/null @@ -1,35 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl.visitor; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.statements.blocks.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.statements.*; -import org.jetbrains.annotations.NotNull; - -/** - * A visitor. Can interact with the node-tree. - */ -public interface StatementVisitor { - - void handleStop(@NotNull StopStatement statement); - void handleSendAttribute(@NotNull SendAttributeStatement statement); - void handleSendEffect(@NotNull SendEffectStatement statement); - void handleSendMessage(@NotNull SendMessageStatement statement); - void handleSendNbt(@NotNull SendNbtStatement statement); - void handleDefine(@NotNull DefineStatement statement); - void handleRunLater(@NotNull RunLaterStatement statement); - void handleRepeatRun(@NotNull RepeatStatement statement); - void handleSummon(@NotNull SummonStatement statement); - void handleBlock(@NotNull BlockStatement statement); - void handleIncrement(@NotNull IncrementStatement statement); - void handleTeleport(@NotNull TeleportStatement statement); - void handlePlay(@NotNull PlayStatement statement); - void handleGive(@NotNull GiveStatement statement); - void handleCallback(@NotNull CallbackStatement statement); - void handleSimpleExpression(@NotNull SimpleExpressionStatement statement); - void handleMetadata(@NotNull MetadataStatement statement); - - void handleIf(@NotNull IfElseStatement statement); - void handleForLoop(@NotNull ForLoopStatement statement); - void handleForeachLoop(@NotNull ForeachLoopStatement statement); - void handleWhileLoop(@NotNull WhileLoopStatement statement); - void handleBreakContinue(@NotNull BreakContinueStatement statement); -} diff --git a/dsl/src/test/java/fr/jamailun/ultimatespellsystem/dsl/CorrectParsingTests.java b/dsl/src/test/java/fr/jamailun/ultimatespellsystem/dsl/CorrectParsingTests.java deleted file mode 100644 index 524c05da..00000000 --- a/dsl/src/test/java/fr/jamailun/ultimatespellsystem/dsl/CorrectParsingTests.java +++ /dev/null @@ -1,79 +0,0 @@ -package fr.jamailun.ultimatespellsystem.dsl; - -import fr.jamailun.ultimatespellsystem.dsl.errors.UssException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionDefinition; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.objects.CallbackEvent; -import fr.jamailun.ultimatespellsystem.dsl.registries.CallbackEventRegistry; -import fr.jamailun.ultimatespellsystem.dsl.registries.FunctionDefinitionsRegistry; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import org.jetbrains.annotations.NotNull; -import org.junit.jupiter.api.Test; - -import java.io.File; -import java.util.List; - -/** - * Multiple tests for valid USS files. - */ -public class CorrectParsingTests extends ParsingTest { - - @Test - void correctStatements() { - testFolder("corrects/statements"); - } - @Test - void correctBlocks() { - testFolder("corrects/blocks"); - } - @Test - void correctOperators() { - testFolder("corrects/operators"); - } - @Test - void correctMix() { - testFolder("corrects/mix"); - } - @Test - void correctMetadata() { - testFolder("corrects/metadata"); - } - - @Test - void correctWithCustom() { - // Register "custom_add" - FunctionDefinition definition = new FunctionDefinition( - "custom_add", - TypePrimitive.NUMBER.asType(), - List.of( - new FunctionArgument(FunctionType.accept(TypePrimitive.NUMBER), "a", false), - new FunctionArgument(FunctionType.accept(TypePrimitive.NUMBER), "b", false) - ) - ); - FunctionDefinitionsRegistry.register(definition); - - // Callback - CallbackEventRegistry.register( - CallbackEvent.of("landed", TokenType.AT, TypePrimitive.LOCATION) - ); - - // Parse - testFolder("corrects_with_custom"); - } - - private void testFolder(@NotNull String folder) { - for(File file : listTests(folder)) { - try { - parseAndVerify(file); - addOk(); - } catch (UssException e) { - e.printStackTrace(); - addFails(file, toString(e)); - } - } - printResults(); - } - -} diff --git a/dsl/src/test/resources/parsing/bad_mix/invalid_param_meta.uss b/dsl/src/test/resources/parsing/bad_mix/invalid_param_meta.uss deleted file mode 100644 index db31ab9e..00000000 --- a/dsl/src/test/resources/parsing/bad_mix/invalid_param_meta.uss +++ /dev/null @@ -1,3 +0,0 @@ -@param(12, ""); - -define %a = 2; diff --git a/dsl/src/test/resources/parsing/bad_mix/unknown_function.uss b/dsl/src/test/resources/parsing/bad_mix/unknown_function.uss deleted file mode 100644 index 055a585e..00000000 --- a/dsl/src/test/resources/parsing/bad_mix/unknown_function.uss +++ /dev/null @@ -1 +0,0 @@ -define %a = i_dont_exist("toto"); \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/bad_parsing/bad_number.uss b/dsl/src/test/resources/parsing/bad_parsing/bad_number.uss deleted file mode 100644 index d1da7e46..00000000 --- a/dsl/src/test/resources/parsing/bad_parsing/bad_number.uss +++ /dev/null @@ -1 +0,0 @@ -define %a = 5..1; \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/bad_parsing/bad_string.uss b/dsl/src/test/resources/parsing/bad_parsing/bad_string.uss deleted file mode 100644 index b807acac..00000000 --- a/dsl/src/test/resources/parsing/bad_parsing/bad_string.uss +++ /dev/null @@ -1,2 +0,0 @@ -define %a = "a -b"; \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/bad_syntax/bad_else.uss b/dsl/src/test/resources/parsing/bad_syntax/bad_else.uss deleted file mode 100644 index 1efc7306..00000000 --- a/dsl/src/test/resources/parsing/bad_syntax/bad_else.uss +++ /dev/null @@ -1,3 +0,0 @@ -if(1 == 1) stop; -else stop; -else stop; diff --git a/dsl/src/test/resources/parsing/bad_syntax/bad_entity_type.uss b/dsl/src/test/resources/parsing/bad_syntax/bad_entity_type.uss deleted file mode 100644 index 6af8ceec..00000000 --- a/dsl/src/test/resources/parsing/bad_syntax/bad_entity_type.uss +++ /dev/null @@ -1,3 +0,0 @@ -# Unknown subtype of send'. - -summon I_DONT_EXIST for 4s; diff --git a/dsl/src/test/resources/parsing/bad_syntax/bad_send.uss b/dsl/src/test/resources/parsing/bad_syntax/bad_send.uss deleted file mode 100644 index e8e1f09f..00000000 --- a/dsl/src/test/resources/parsing/bad_syntax/bad_send.uss +++ /dev/null @@ -1,3 +0,0 @@ -# Unknown subtype of send'. - -send to %caster I_DONT_EXIST "I'm a failure"; diff --git a/dsl/src/test/resources/parsing/bad_syntax/bad_var.uss b/dsl/src/test/resources/parsing/bad_syntax/bad_var.uss deleted file mode 100644 index 7fa3c971..00000000 --- a/dsl/src/test/resources/parsing/bad_syntax/bad_var.uss +++ /dev/null @@ -1,2 +0,0 @@ -define %correct = 12; -%correct; \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/bad_syntax/redefine_caster.uss b/dsl/src/test/resources/parsing/bad_syntax/redefine_caster.uss deleted file mode 100644 index 4ccdb855..00000000 --- a/dsl/src/test/resources/parsing/bad_syntax/redefine_caster.uss +++ /dev/null @@ -1 +0,0 @@ -define %caster = 2; diff --git a/dsl/src/test/resources/parsing/bad_tree/after_break.uss b/dsl/src/test/resources/parsing/bad_tree/after_break.uss deleted file mode 100644 index 865eb84b..00000000 --- a/dsl/src/test/resources/parsing/bad_tree/after_break.uss +++ /dev/null @@ -1,6 +0,0 @@ -for(%i = 1; %i < 3; increment %i) { - if(%i == 2) { - break; - send to %caster message "oops"; - } -} \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/bad_tree/after_meta_1.uss b/dsl/src/test/resources/parsing/bad_tree/after_meta_1.uss deleted file mode 100644 index f4b62256..00000000 --- a/dsl/src/test/resources/parsing/bad_tree/after_meta_1.uss +++ /dev/null @@ -1,5 +0,0 @@ -@meta_flag -if(1==1){ - @meta_flag - send to %caster message "foo"; -} diff --git a/dsl/src/test/resources/parsing/bad_tree/after_meta_2.uss b/dsl/src/test/resources/parsing/bad_tree/after_meta_2.uss deleted file mode 100644 index b62c339f..00000000 --- a/dsl/src/test/resources/parsing/bad_tree/after_meta_2.uss +++ /dev/null @@ -1,5 +0,0 @@ -@meta_flag -{ - send to %caster message "foo"; -} -@meta_flag diff --git a/dsl/src/test/resources/parsing/bad_tree/after_stop_1.uss b/dsl/src/test/resources/parsing/bad_tree/after_stop_1.uss deleted file mode 100644 index 139cee45..00000000 --- a/dsl/src/test/resources/parsing/bad_tree/after_stop_1.uss +++ /dev/null @@ -1,2 +0,0 @@ -stop; -stop; \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/bad_tree/after_stop_2.uss b/dsl/src/test/resources/parsing/bad_tree/after_stop_2.uss deleted file mode 100644 index 0b7a38ba..00000000 --- a/dsl/src/test/resources/parsing/bad_tree/after_stop_2.uss +++ /dev/null @@ -1,3 +0,0 @@ -send to %caster message "a"; -stop; -send to %caster message "b"; \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/bad_tree/after_stop_3.uss b/dsl/src/test/resources/parsing/bad_tree/after_stop_3.uss deleted file mode 100644 index 9248fcef..00000000 --- a/dsl/src/test/resources/parsing/bad_tree/after_stop_3.uss +++ /dev/null @@ -1,5 +0,0 @@ -@meta_flag -stop; -{ - send to %caster message "foo"; -} \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/bad_type/bad_collection_teleport.uss b/dsl/src/test/resources/parsing/bad_type/bad_collection_teleport.uss deleted file mode 100644 index 1bcf6687..00000000 --- a/dsl/src/test/resources/parsing/bad_type/bad_collection_teleport.uss +++ /dev/null @@ -1,4 +0,0 @@ - -define %coll = all entities within 10 around %caster; - -teleport %caster to %coll; diff --git a/dsl/src/test/resources/parsing/bad_type/bad_list_append.uss b/dsl/src/test/resources/parsing/bad_type/bad_list_append.uss deleted file mode 100644 index 60f785a2..00000000 --- a/dsl/src/test/resources/parsing/bad_type/bad_list_append.uss +++ /dev/null @@ -1,3 +0,0 @@ -%l = [[]]; -%l :+ "a"; -%l :+ true; diff --git a/dsl/src/test/resources/parsing/bad_type/bad_ope.uss b/dsl/src/test/resources/parsing/bad_type/bad_ope.uss deleted file mode 100644 index b7e3807c..00000000 --- a/dsl/src/test/resources/parsing/bad_type/bad_ope.uss +++ /dev/null @@ -1,5 +0,0 @@ -# Valid -define %x = 1 * 2; - -# Not valid -define %z = [[1]] * 2; \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/bad_type/bad_ope_2.uss b/dsl/src/test/resources/parsing/bad_type/bad_ope_2.uss deleted file mode 100644 index 2f815f23..00000000 --- a/dsl/src/test/resources/parsing/bad_type/bad_ope_2.uss +++ /dev/null @@ -1,6 +0,0 @@ -# Valid -define %x = 1 + "1" -define %y = "1" + 1; - -# Not valid -define %z = 1 * "oops"; diff --git a/dsl/src/test/resources/parsing/bad_type/bad_ope_3.uss b/dsl/src/test/resources/parsing/bad_type/bad_ope_3.uss deleted file mode 100644 index d6d21b41..00000000 --- a/dsl/src/test/resources/parsing/bad_type/bad_ope_3.uss +++ /dev/null @@ -1,7 +0,0 @@ -# Valid -%a = true; -%b = !%a; - -# Invalid -%c = 14; -%d = !%c; diff --git a/dsl/src/test/resources/parsing/bad_type/increment_type.uss b/dsl/src/test/resources/parsing/bad_type/increment_type.uss deleted file mode 100644 index f2f8f169..00000000 --- a/dsl/src/test/resources/parsing/bad_type/increment_type.uss +++ /dev/null @@ -1,2 +0,0 @@ -define %i = "a"; -decrement %i; diff --git a/dsl/src/test/resources/parsing/bad_type/redefine_difftype.uss b/dsl/src/test/resources/parsing/bad_type/redefine_difftype.uss deleted file mode 100644 index d13c23cf..00000000 --- a/dsl/src/test/resources/parsing/bad_type/redefine_difftype.uss +++ /dev/null @@ -1,2 +0,0 @@ -define %a = 1; -define %a = "toto"; \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/bad_type/stop_type.uss b/dsl/src/test/resources/parsing/bad_type/stop_type.uss deleted file mode 100644 index f0623a9a..00000000 --- a/dsl/src/test/resources/parsing/bad_type/stop_type.uss +++ /dev/null @@ -1 +0,0 @@ -stop "non"; \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/corrects/blocks/for.uss b/dsl/src/test/resources/parsing/corrects/blocks/for.uss deleted file mode 100644 index abc070ed..00000000 --- a/dsl/src/test/resources/parsing/corrects/blocks/for.uss +++ /dev/null @@ -1,14 +0,0 @@ -for(define %i = 0; %i < 5; increment %i) { - send to %caster message "i=%i"; -} - -%x = 12; -for(; %x < 5; decrement %x) { - send to %caster message "x=%x"; -} - -%z = 8; -for(; %x > 5; ) { - decrement %z; - send to %caster message "z=%z"; -} \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/corrects/blocks/for_break.uss b/dsl/src/test/resources/parsing/corrects/blocks/for_break.uss deleted file mode 100644 index 0c24ebbd..00000000 --- a/dsl/src/test/resources/parsing/corrects/blocks/for_break.uss +++ /dev/null @@ -1,5 +0,0 @@ -for(define %i = 0; %i < 5; increment %i) { - send to %caster message "[%i]"; - if(%i > 3) - break; -} \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/corrects/blocks/foreach.uss b/dsl/src/test/resources/parsing/corrects/blocks/foreach.uss deleted file mode 100644 index d0356410..00000000 --- a/dsl/src/test/resources/parsing/corrects/blocks/foreach.uss +++ /dev/null @@ -1,6 +0,0 @@ -define %around = (all PLAYER within 50 around %caster); - -foreach(%p : %around) { - send to %caster message "Found " + %p; -} -send to %caster message "All = %around"; \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/corrects/blocks/ifelse_p1.uss b/dsl/src/test/resources/parsing/corrects/blocks/ifelse_p1.uss deleted file mode 100644 index f6e36220..00000000 --- a/dsl/src/test/resources/parsing/corrects/blocks/ifelse_p1.uss +++ /dev/null @@ -1,7 +0,0 @@ -define %a = null; -if(%caster == %caster) - define %a = "a"; -else - define %a = "b"; - -send to %caster message %a; \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/corrects/blocks/ifelse_p2.uss b/dsl/src/test/resources/parsing/corrects/blocks/ifelse_p2.uss deleted file mode 100644 index e2c674a3..00000000 --- a/dsl/src/test/resources/parsing/corrects/blocks/ifelse_p2.uss +++ /dev/null @@ -1,20 +0,0 @@ -define %a = 2; -define %even = null; - -if(%a == 0) { - define %even = true; -} else if(%a == 1) { - define %even = false; -} else if(%a == 2) { - define %even = true; -} else if(%a == 3) { - define %even = false; -} else if(%a == 4) { - define %even = true; -} else if(%a == 5) { - define %even = false; -} else { - send to %caster message "trop duuur !"; - stop; -} -send to %caster message "even ? %even"; diff --git a/dsl/src/test/resources/parsing/corrects/blocks/repeat.uss b/dsl/src/test/resources/parsing/corrects/blocks/repeat.uss deleted file mode 100644 index d69744ce..00000000 --- a/dsl/src/test/resources/parsing/corrects/blocks/repeat.uss +++ /dev/null @@ -1,13 +0,0 @@ -repeat after 1s 5 times every 2 seconds: { - send to %caster message "boum 1."; -} - -repeat 2 times every 5 seconds: { - send to %caster message "boum 2."; -} - -define %count = 1 + 1; -define %delay = 3sec; -repeat %count times every %delay: { - send to %caster message "boum 3."; -} diff --git a/dsl/src/test/resources/parsing/corrects/blocks/repeat_2.uss b/dsl/src/test/resources/parsing/corrects/blocks/repeat_2.uss deleted file mode 100644 index 39727800..00000000 --- a/dsl/src/test/resources/parsing/corrects/blocks/repeat_2.uss +++ /dev/null @@ -1,9 +0,0 @@ -repeat after 1s every 2 seconds for 2 m: { - send to %caster message "boum 1."; -} - -%dur = 1 minute; -%freq = 15s; -repeat every %freq for %dur: { - send %caster message "test"; -} diff --git a/dsl/src/test/resources/parsing/corrects/blocks/run_later.uss b/dsl/src/test/resources/parsing/corrects/blocks/run_later.uss deleted file mode 100644 index 37ec5afc..00000000 --- a/dsl/src/test/resources/parsing/corrects/blocks/run_later.uss +++ /dev/null @@ -1,9 +0,0 @@ -send to %caster message "Timer: &a1 minute."; -run after 1 minute: { - send to %caster message "Timer is over."; -} - -define %delay = 3sec; -run after %delay: { - send to %caster message "post 3 secs."; -} diff --git a/dsl/src/test/resources/parsing/corrects/blocks/while.uss b/dsl/src/test/resources/parsing/corrects/blocks/while.uss deleted file mode 100644 index 6bebbaee..00000000 --- a/dsl/src/test/resources/parsing/corrects/blocks/while.uss +++ /dev/null @@ -1,15 +0,0 @@ -define %i = 0; - -while(%i < 10) { - send to %caster message "&a+&f > i=%i"; - increment %i; - if(%i > 100) - continue; -} - -do { - send to %caster message "&c-&f > i=%i"; - decrement %i; -} while(%i > 0); - -send to %caster message "done"; diff --git a/dsl/src/test/resources/parsing/corrects/metadata/param_metadata.uss b/dsl/src/test/resources/parsing/corrects/metadata/param_metadata.uss deleted file mode 100644 index e637dc2b..00000000 --- a/dsl/src/test/resources/parsing/corrects/metadata/param_metadata.uss +++ /dev/null @@ -1,3 +0,0 @@ -@param(test, int) - -define %foo = 3 + %test; diff --git a/dsl/src/test/resources/parsing/corrects/mix/cercle.uss b/dsl/src/test/resources/parsing/corrects/mix/cercle.uss deleted file mode 100644 index dd98fbe4..00000000 --- a/dsl/src/test/resources/parsing/corrects/mix/cercle.uss +++ /dev/null @@ -1,12 +0,0 @@ -define %pos = position of %caster; - -define %pos = %pos + [[0,-1,0]]; -for(define %x = -5; %x <= 5; increment %x) { - for(define %z = -5; %z <= 5; increment %z) { - define %temp = %pos + [[%x, 0, %z]]; - play block at %pos with: {{ - type: MAGMA_BLOCK, - duration: 3 secs - }} - } -} \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/corrects/mix/collections.uss b/dsl/src/test/resources/parsing/corrects/mix/collections.uss deleted file mode 100644 index e1e4bb58..00000000 --- a/dsl/src/test/resources/parsing/corrects/mix/collections.uss +++ /dev/null @@ -1,8 +0,0 @@ -define %msgs = [["a", "b", "c"]]; -send to %caster message %msgs; - -send to %caster message "1st is '" + %msgs[0] + "'"; - -for(define %i = 0; %i < sizeof(%msgs); increment %i) { - send to %caster message "&e MSG[%i] = '%a" + %msgs[%i] + "&e'"; -} diff --git a/dsl/src/test/resources/parsing/corrects/mix/empty.uss b/dsl/src/test/resources/parsing/corrects/mix/empty.uss deleted file mode 100644 index e69de29b..00000000 diff --git a/dsl/src/test/resources/parsing/corrects/mix/implicit_define.uss b/dsl/src/test/resources/parsing/corrects/mix/implicit_define.uss deleted file mode 100644 index 965dd96e..00000000 --- a/dsl/src/test/resources/parsing/corrects/mix/implicit_define.uss +++ /dev/null @@ -1,2 +0,0 @@ -define %a = 1; -%a = 2; \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/corrects/mix/metadata.uss b/dsl/src/test/resources/parsing/corrects/mix/metadata.uss deleted file mode 100644 index 20c60e4d..00000000 --- a/dsl/src/test/resources/parsing/corrects/mix/metadata.uss +++ /dev/null @@ -1,5 +0,0 @@ -@name("a nice spell") -@color("&b") -@param("a", int) - -send to %caster message ""; diff --git a/dsl/src/test/resources/parsing/corrects/mix/null_recovery.uss b/dsl/src/test/resources/parsing/corrects/mix/null_recovery.uss deleted file mode 100644 index 7c825e60..00000000 --- a/dsl/src/test/resources/parsing/corrects/mix/null_recovery.uss +++ /dev/null @@ -1,6 +0,0 @@ -%a = 1; -%a = null; -%a = 1 - -send to %caster message "a = " + %a; - diff --git a/dsl/src/test/resources/parsing/corrects/mix/null_set.uss b/dsl/src/test/resources/parsing/corrects/mix/null_set.uss deleted file mode 100644 index f6e78789..00000000 --- a/dsl/src/test/resources/parsing/corrects/mix/null_set.uss +++ /dev/null @@ -1,7 +0,0 @@ -define %a = 1; -define %b = null; - -if(%b == null) - define %b = 2; - -define %c = %a + %b; diff --git a/dsl/src/test/resources/parsing/corrects/mix/particle_shape.uss b/dsl/src/test/resources/parsing/corrects/mix/particle_shape.uss deleted file mode 100644 index e27159a3..00000000 --- a/dsl/src/test/resources/parsing/corrects/mix/particle_shape.uss +++ /dev/null @@ -1,8 +0,0 @@ -define %pos = position of %caster; -play particle at %pos with: {{ - type: FIRE, - shape: {{ - type: "circle", - radius: 6.5 - }} -}} \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/corrects/mix/test_allof.uss b/dsl/src/test/resources/parsing/corrects/mix/test_allof.uss deleted file mode 100644 index cc68297c..00000000 --- a/dsl/src/test/resources/parsing/corrects/mix/test_allof.uss +++ /dev/null @@ -1,6 +0,0 @@ -define %coll = all entities within 10 around %caster; - -send to %coll message "paf"; - -teleport %coll to %caster; - diff --git a/dsl/src/test/resources/parsing/corrects/mix/test_basic.uss b/dsl/src/test/resources/parsing/corrects/mix/test_basic.uss deleted file mode 100644 index 3aacf6fa..00000000 --- a/dsl/src/test/resources/parsing/corrects/mix/test_basic.uss +++ /dev/null @@ -1,4 +0,0 @@ -send to %caster message "&eT'es trop fort."; -send to %caster effect SPEED 2 for 4s; # valid - -define %truc = -12; diff --git a/dsl/src/test/resources/parsing/corrects/mix/test_complex_tp.uss b/dsl/src/test/resources/parsing/corrects/mix/test_complex_tp.uss deleted file mode 100644 index 33add40c..00000000 --- a/dsl/src/test/resources/parsing/corrects/mix/test_complex_tp.uss +++ /dev/null @@ -1,27 +0,0 @@ -# -- config test # -- config -define %delay = 2 seconds; -define %output = @("world", -50, 100, 50); - -# If monsters around, cancel -if(sizeof(all monsters within 5 around %caster) != 0) { - send to %caster message "&cDes monstres sont trop proches de toi."; - stop; -} - -# Intro -send to %caster message "&bTéléportation vers le &2Stronghold&b..."; -play sound at %caster with: {{ - type: BLOCK_BEACON_ACTIVATE, - pitch: 0.8 -}}; -send to %caster effect slowness 10 for %delay; -send to %caster effect resistance 10 for %delay; - -# Teleport after 5 seconds (sound effect + resistance for falling-damage) -run after %delay: { - teleport %caster to %output; - send to %caster effect resistance 5 for 2s; - play sound at %caster with: {{ - type: ITEM_CHORUS_FRUIT_TELEPORT - }}; -} \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/corrects/mix/test_location_literal.uss b/dsl/src/test/resources/parsing/corrects/mix/test_location_literal.uss deleted file mode 100644 index 5275ac29..00000000 --- a/dsl/src/test/resources/parsing/corrects/mix/test_location_literal.uss +++ /dev/null @@ -1,2 +0,0 @@ -define %a = @("world", 1, 2, 3); -define %b = @("world", 1, -2, 3.5, 5, 5); diff --git a/dsl/src/test/resources/parsing/corrects/mix/test_null.uss b/dsl/src/test/resources/parsing/corrects/mix/test_null.uss deleted file mode 100644 index 7a7a8b28..00000000 --- a/dsl/src/test/resources/parsing/corrects/mix/test_null.uss +++ /dev/null @@ -1,5 +0,0 @@ -define %i = null; - -if(%i == null) { - send to %caster message "a"; -} \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/corrects/mix/test_teleport.uss b/dsl/src/test/resources/parsing/corrects/mix/test_teleport.uss deleted file mode 100644 index 6f912ddd..00000000 --- a/dsl/src/test/resources/parsing/corrects/mix/test_teleport.uss +++ /dev/null @@ -1,6 +0,0 @@ -summon EntityType.PIG as %pig for 4s; - -run after 3900ms: { - send to %caster message "&e&owhoooooooosh"; - teleport %caster to %pig; -} \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/corrects/operators/bool_operators.uss b/dsl/src/test/resources/parsing/corrects/operators/bool_operators.uss deleted file mode 100644 index 74f8342f..00000000 --- a/dsl/src/test/resources/parsing/corrects/operators/bool_operators.uss +++ /dev/null @@ -1,2 +0,0 @@ -%a = 7; -%b = (false || 1 == 1 && (4 >= 2) && !(%a > 10)); \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/corrects/operators/conditions.uss b/dsl/src/test/resources/parsing/corrects/operators/conditions.uss deleted file mode 100644 index 3735c21a..00000000 --- a/dsl/src/test/resources/parsing/corrects/operators/conditions.uss +++ /dev/null @@ -1,13 +0,0 @@ -define %a = 55; -define %b = 56; - -# Nice separation with parenthesis -if((%a == 1) || (%a == 2)) - send to %caster message "A"; - -# No separation -if(%a == 3 || %b == 4) - send to %caster message "A"; - -#if(%a == 33 || true) -# send to %caster message "B"; diff --git a/dsl/src/test/resources/parsing/corrects/operators/list_append.uss b/dsl/src/test/resources/parsing/corrects/operators/list_append.uss deleted file mode 100644 index f47893a1..00000000 --- a/dsl/src/test/resources/parsing/corrects/operators/list_append.uss +++ /dev/null @@ -1,16 +0,0 @@ -# Type not set (i.e. NULL) -%l = [[]]; - -# Append a value to the list. -%l :+ 1; -%l :+ 2; - -# because its an expression... -(%l :+ 12) :+ 27; - -# ":?" == contains -%bool = %l :? 1; # true -%num = sizeof(%l); # 4 - -# ":-" == remove (value) -%l :- 1; diff --git a/dsl/src/test/resources/parsing/corrects/operators/math.uss b/dsl/src/test/resources/parsing/corrects/operators/math.uss deleted file mode 100644 index de5882e8..00000000 --- a/dsl/src/test/resources/parsing/corrects/operators/math.uss +++ /dev/null @@ -1,3 +0,0 @@ -define %c = cos(3.14); -define %s = cos(3.14); -define %t = tan(3.14); diff --git a/dsl/src/test/resources/parsing/corrects/operators/operator_priority.uss b/dsl/src/test/resources/parsing/corrects/operators/operator_priority.uss deleted file mode 100644 index ec147fc4..00000000 --- a/dsl/src/test/resources/parsing/corrects/operators/operator_priority.uss +++ /dev/null @@ -1,11 +0,0 @@ -define %a = 2; -define %b = 3; -define %c = 5; - -define %zz1 = %a + %b + %c; # (a+(b+c)) - -define %zz2 = %a + %b * %c; # (a+(b*c)) - -define %zz3 = %a / %b - %c; # ((a/b)-c) - -define %zz4 = %a / %b - %c; # ((a/b)-c) diff --git a/dsl/src/test/resources/parsing/corrects/operators/parenthesis.uss b/dsl/src/test/resources/parsing/corrects/operators/parenthesis.uss deleted file mode 100644 index 926375be..00000000 --- a/dsl/src/test/resources/parsing/corrects/operators/parenthesis.uss +++ /dev/null @@ -1,6 +0,0 @@ -define %a = 1; -define %b = 2; -define %c = 3; -define %d = 5; - -define %pp1 = %a - (%b + %c) * %d; # (a+(b+c)) diff --git a/dsl/src/test/resources/parsing/corrects/operators/type_operators.uss b/dsl/src/test/resources/parsing/corrects/operators/type_operators.uss deleted file mode 100644 index 52e7645f..00000000 --- a/dsl/src/test/resources/parsing/corrects/operators/type_operators.uss +++ /dev/null @@ -1,5 +0,0 @@ -%a = "1" + 1; -%a = 1 + "1"; - -%dur = 2 minutes * 2; -%n = 2 minutes / 2 minutes; diff --git a/dsl/src/test/resources/parsing/corrects/statements/define.uss b/dsl/src/test/resources/parsing/corrects/statements/define.uss deleted file mode 100644 index 177aef2e..00000000 --- a/dsl/src/test/resources/parsing/corrects/statements/define.uss +++ /dev/null @@ -1,12 +0,0 @@ -# Some declarations -define %as_str = "a"; -define %b = 1; -define %a = 1 + 21 / 3; -define %cc = %a - (%a + %b); - -# Broken-lines : code still valid -define - %z - = 6 - / 2 - ; diff --git a/dsl/src/test/resources/parsing/corrects/statements/give.uss b/dsl/src/test/resources/parsing/corrects/statements/give.uss deleted file mode 100644 index add81e9a..00000000 --- a/dsl/src/test/resources/parsing/corrects/statements/give.uss +++ /dev/null @@ -1,10 +0,0 @@ -give EMERALD to %caster; -give 2 EMERALD to %caster; - -give 3 STONE_AXE to %caster with: {{ - name: "nice &6axe", - lore: [[ - "line 1", - "line 2 !" - ]] -}}; diff --git a/dsl/src/test/resources/parsing/corrects/statements/increment.uss b/dsl/src/test/resources/parsing/corrects/statements/increment.uss deleted file mode 100644 index 56090ecd..00000000 --- a/dsl/src/test/resources/parsing/corrects/statements/increment.uss +++ /dev/null @@ -1,3 +0,0 @@ -define %i = 0; -increment %i; -decrement %i; diff --git a/dsl/src/test/resources/parsing/corrects/statements/play.uss b/dsl/src/test/resources/parsing/corrects/statements/play.uss deleted file mode 100644 index 63ffedb3..00000000 --- a/dsl/src/test/resources/parsing/corrects/statements/play.uss +++ /dev/null @@ -1,17 +0,0 @@ -# Play at '%caster' location - -play PARTICLE at %caster with: {{ - type: lava, - count: 12 -}}; - -play "sound" at %caster with: {{ - type: ENTITY_POLAR_BEAR_WARNING, - volume: 1.1, - pitch: 0.8 -}}; - -play BLOCK at %caster with: {{ - type: MAGMA_BLOCK, - duration: 2 seconds -}}; diff --git a/dsl/src/test/resources/parsing/corrects/statements/send.uss b/dsl/src/test/resources/parsing/corrects/statements/send.uss deleted file mode 100644 index 5a10c889..00000000 --- a/dsl/src/test/resources/parsing/corrects/statements/send.uss +++ /dev/null @@ -1,22 +0,0 @@ -# --- Message - -send to %caster message "Simple message"; - -define %msg = "&cRed message !"; -send to %caster message %msg; - -send to %caster message [["message 1", "message 2", "message 3"]]; - -# --- Effect - -send to %caster effect LEVITATION 2 for 3 seconds; -send to %caster effect POISON for 4 seconds; - -define %dur = 1 minute; -define %pow = 2 + 2; -send to %caster effect "strength" %pow for %dur; - -# --- Attributes - -send to %caster attribute 2 ARMOR for 5 s; -send to %caster attribute %pow "MAX_HEALTH" ADD_NUMBER for %dur; diff --git a/dsl/src/test/resources/parsing/corrects/statements/send_nbt.uss b/dsl/src/test/resources/parsing/corrects/statements/send_nbt.uss deleted file mode 100644 index 2eed25bc..00000000 --- a/dsl/src/test/resources/parsing/corrects/statements/send_nbt.uss +++ /dev/null @@ -1 +0,0 @@ -send %caster nbt "test" = 12 for 12s; \ No newline at end of file diff --git a/dsl/src/test/resources/parsing/corrects/statements/stop_1.uss b/dsl/src/test/resources/parsing/corrects/statements/stop_1.uss deleted file mode 100644 index 28faeb67..00000000 --- a/dsl/src/test/resources/parsing/corrects/statements/stop_1.uss +++ /dev/null @@ -1,2 +0,0 @@ -# Exit with code -stop 3.14; diff --git a/dsl/src/test/resources/parsing/corrects/statements/stop_2.uss b/dsl/src/test/resources/parsing/corrects/statements/stop_2.uss deleted file mode 100644 index 32eff907..00000000 --- a/dsl/src/test/resources/parsing/corrects/statements/stop_2.uss +++ /dev/null @@ -1,2 +0,0 @@ -# Exit normally -stop; diff --git a/dsl/src/test/resources/parsing/corrects/statements/stop_3.uss b/dsl/src/test/resources/parsing/corrects/statements/stop_3.uss deleted file mode 100644 index 99d552aa..00000000 --- a/dsl/src/test/resources/parsing/corrects/statements/stop_3.uss +++ /dev/null @@ -1,3 +0,0 @@ -# Exit with code -define %code = 90/8; -stop %code; diff --git a/dsl/src/test/resources/parsing/corrects/statements/summon.uss b/dsl/src/test/resources/parsing/corrects/statements/summon.uss deleted file mode 100644 index b8a219d2..00000000 --- a/dsl/src/test/resources/parsing/corrects/statements/summon.uss +++ /dev/null @@ -1,9 +0,0 @@ -summon IRON_GOLEM at %caster as %ent for 5 minutes with: {{ - name: "Michel" -}}; - -summon DOLPHIN at %caster for 3 seconds with: {{}}; - -define %type = ZOMBIE; -define %dur = 3 days; -summon %type at %caster for %dur; diff --git a/dsl/src/test/resources/parsing/corrects/statements/teleport.uss b/dsl/src/test/resources/parsing/corrects/statements/teleport.uss deleted file mode 100644 index bac5a143..00000000 --- a/dsl/src/test/resources/parsing/corrects/statements/teleport.uss +++ /dev/null @@ -1,4 +0,0 @@ -teleport %caster to %caster; - -teleport all monsters within 50 around %caster to %caster + [[0,10,0]]; -# same as teleport (all monsters within 50) around %caster to (%caster + [[0,10,0]]); diff --git a/dsl/src/test/resources/parsing/corrects_with_custom/callback.uss b/dsl/src/test/resources/parsing/corrects_with_custom/callback.uss deleted file mode 100644 index 65c9f487..00000000 --- a/dsl/src/test/resources/parsing/corrects_with_custom/callback.uss +++ /dev/null @@ -1,6 +0,0 @@ -summon arrow at %caster as %ar for 5s; - -callback %ar LANDED at %pos: { - send %caster message "landed at %pos."; - teleport %caster to %pos; -} diff --git a/dsl/src/test/resources/parsing/corrects_with_custom/custom.uss b/dsl/src/test/resources/parsing/corrects_with_custom/custom.uss deleted file mode 100644 index 603239cf..00000000 --- a/dsl/src/test/resources/parsing/corrects_with_custom/custom.uss +++ /dev/null @@ -1,4 +0,0 @@ -define %a = 1; -define %b = 2; - -define %res = custom_add(%a, %b); diff --git a/dsl2/README.md b/dsl2/README.md new file mode 100644 index 00000000..dc661274 --- /dev/null +++ b/dsl2/README.md @@ -0,0 +1,97 @@ +# USS - DSL 2 + +### Objectif + +```javascript + +let position = position_of(caster); +position += [0, 2, 0]; + +for(let entity in query_entities(position, 20, "players")) { + entity.send_message("Hello World!"); + entity.send_effect("resistance", D`20s`, 1); +} + + +``` + +```cpp +void main() { + vector position = position_of(caster); + position += (vector){0, 2, 0}; + + entity_query_result result = query_entities(position, 20, "players"); + for(int i = 0; i < result.size; i++) { + entity entity = result.entities[i]; + entity_send_message(entity, "Hello World!"); + entity_send_effect(entity, "resistance", duration_from_seconds(20), 1); + } +} +``` + + +## syntax + +``` +IDENTIFIER ::= [a-zA-Z_][a-zA-Z0-9_]* +STRING ::= '"' .* '"' +NUMBER ::= [0-9]*(.[0-9]+)? +BOOLEAN ::= "true" | "false" + +LITERAL ::= + STRING + | NUMBER + | BOOLEAN + | "null" + | LIST + | MAP + +LIST ::= [ (EXPRESSION (EXPRESSION )*)? ] + +MAP ::= { (IDENTIFIER: EXPRESSION,)* } + +a.b[c].d(x).e = z + +EXPRESSION ::= + LITERAL + | IDENTIFIER + | IDENTIFIER(PARAMETERS) + | EXPRESSION OPERATOR EXPRESSION + | (EXPRESSION) + | -EXPRESSION + | !EXPRESSION + | EXPRESSION[EXPRESSION] + | EXPRESSION.EXPRESSION + +ANNOTATION ::= "@" IDENTIFIER ( "(" EXPRESSIONS (, EXPRESSION)* ")" )? + +PARAMETERS ::= TYPE IDENTIFIER (, TYPE IDENTIFIER)* | ε + +TYPE ::= IDENTIFIER | "void" + +OPERATOR ::= "+" | "-" | "*" | "/" | "%" | "==" | "!=" | "<" | ">" | "<=" | ">=" | "&&" | "||" + +STATEMENT ::= + TYPE IDENTIFIER (= EXPRESSION)?; + | EXPRESSION = EXPRESSION; + | for(STATEMENT; STATEMENT; STATEMENT) BLOCK_STATEMENTS + | foreach(TYPE IDENTIFIER in EXPRESSION) BLOCK_STATEMENTS + | while(EXPRESSION) BLOCK_STATEMENTS + | do BLOCK_STATEMENTS while(EXPRESSION); + | if(EXPRESSION) BLOCK_STATEMENTS (else BLOCK_STATEMENTS)? + | "break"; | "continue"; | "return" (EXPRESSION)?; + | EXPRESSION(PARAMETERS); + +BLOCK_STATEMENTS ::= + { + STATEMENT (, STATEMENT)* + } + +FUNCTION ::= + TYPE IDENTIFIER(PARAMETERS) { + STATEMENT (, STATEMENT)* + } + + +``` + diff --git a/dsl/pom.xml b/dsl2/pom.xml similarity index 93% rename from dsl/pom.xml rename to dsl2/pom.xml index 83cca853..a7378b38 100644 --- a/dsl/pom.xml +++ b/dsl2/pom.xml @@ -4,13 +4,13 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - ultimate-spell-system-dsl - 2.6.1-SNAPSHOT + ultimate-spell-system-dsl2 + 3.0.0-SNAPSHOT fr.jamailun.paper ultimate-spell-system - 2.6.1-SNAPSHOT + 3.0.0-SNAPSHOT diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/UltimateSpellSystemDSL.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/UltimateSpellSystemDSL2.java similarity index 68% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/UltimateSpellSystemDSL.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/UltimateSpellSystemDSL2.java index b95d7a02..7110a5c3 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/UltimateSpellSystemDSL.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/UltimateSpellSystemDSL2.java @@ -1,9 +1,14 @@ -package fr.jamailun.ultimatespellsystem.dsl; +package fr.jamailun.ultimatespellsystem.dsl2; -import fr.jamailun.ultimatespellsystem.dsl.metadata.rules.DefaultMetadataRules; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.*; +import fr.jamailun.ultimatespellsystem.dsl2.library.structs.ConsoleStruct; +import fr.jamailun.ultimatespellsystem.dsl2.library.structs.EntityStruct; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.registries.ObjectsDefinitionRegistry; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.CharStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenType; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Tokenizer; import org.jetbrains.annotations.NotNull; import java.io.File; @@ -13,12 +18,13 @@ /** * Central access to the DSL. */ -public final class UltimateSpellSystemDSL { - private UltimateSpellSystemDSL() {} +public final class UltimateSpellSystemDSL2 { + private UltimateSpellSystemDSL2() {} // Load the default metadata rules on class load. static { - DefaultMetadataRules.initialize(); + ObjectsDefinitionRegistry.registerDefaultStruct(new EntityStruct()); + ObjectsDefinitionRegistry.registerDefaultStruct(new ConsoleStruct()); } /** diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/objects/CallbackEvent.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/callbacks/CallbackEvent.java similarity index 81% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/objects/CallbackEvent.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/callbacks/CallbackEvent.java index c8e976da..b62053bf 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/objects/CallbackEvent.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/callbacks/CallbackEvent.java @@ -1,7 +1,7 @@ -package fr.jamailun.ultimatespellsystem.dsl.objects; +package fr.jamailun.ultimatespellsystem.dsl2.callbacks; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenType; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -15,7 +15,7 @@ public record CallbackEvent(@NotNull String name, @Nullable CallbackArgument arg public CallbackEvent { if(name.indexOf(' ') > -1) { - throw new RuntimeException("Invalid callback name. Cannot contain spaces."); + throw new IllegalArgumentException("Invalid callback name. Cannot contain spaces."); } } @@ -50,8 +50,6 @@ public record CallbackArgument(@NotNull TokenType keyword, @NotNull TypePrimitiv public CallbackArgument { if(!keyword.letters) throw new RuntimeException("Invalid keyword type. Should be a 'letters' keyword."); - if(type == TypePrimitive.NULL) - throw new RuntimeException("Invalid callback argument type. Cannot be null."); } } diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/MetadataRuleFailureException.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/MetadataRuleFailureException.java similarity index 76% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/MetadataRuleFailureException.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/MetadataRuleFailureException.java index be6c33f4..9ffa32a9 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/MetadataRuleFailureException.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/MetadataRuleFailureException.java @@ -1,6 +1,6 @@ -package fr.jamailun.ultimatespellsystem.dsl.errors; +package fr.jamailun.ultimatespellsystem.dsl2.errors; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; import org.jetbrains.annotations.NotNull; /** diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/ParsingException.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/ParsingException.java similarity index 85% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/ParsingException.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/ParsingException.java index 07cdccd7..9ea5752b 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/ParsingException.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/ParsingException.java @@ -1,8 +1,9 @@ -package fr.jamailun.ultimatespellsystem.dsl.errors; +package fr.jamailun.ultimatespellsystem.dsl2.errors; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; import org.jetbrains.annotations.NotNull; + /** * Exception throw in the parsing phase. */ diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/SyntaxException.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/SyntaxException.java similarity index 81% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/SyntaxException.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/SyntaxException.java index ee60e982..cf81d603 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/SyntaxException.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/SyntaxException.java @@ -1,8 +1,8 @@ -package fr.jamailun.ultimatespellsystem.dsl.errors; +package fr.jamailun.ultimatespellsystem.dsl2.errors; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenType; import java.util.List; diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/TreeValidationException.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/TreeValidationException.java similarity index 73% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/TreeValidationException.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/TreeValidationException.java index 9e0c09b6..699daf52 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/TreeValidationException.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/TreeValidationException.java @@ -1,6 +1,6 @@ -package fr.jamailun.ultimatespellsystem.dsl.errors; +package fr.jamailun.ultimatespellsystem.dsl2.errors; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; /** * Tree validation : relation between statements. diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/TypeException.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/TypeException.java similarity index 67% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/TypeException.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/TypeException.java index c3b87d5e..94cb8334 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/TypeException.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/TypeException.java @@ -1,8 +1,9 @@ -package fr.jamailun.ultimatespellsystem.dsl.errors; +package fr.jamailun.ultimatespellsystem.dsl2.errors; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; /** * Bad type in a spell. @@ -18,6 +19,9 @@ public TypeException(ExpressionNode expression, TypePrimitive expected) { super(expression.firstTokenPosition(), "Expression " + expression + " has type " + expression.getExpressionType() + ", expected " + expected); } + public TypeException(ExpressionNode expression, Type expected) { + super(expression.firstTokenPosition(), "Expression " + expression + " has type " + expression.getExpressionType() + ", expected " + expected); + } /** * Unexpected expression type. * @param expression expression source of tbe exception. Must have a type set. diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/UnknownFieldException.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/UnknownFieldException.java new file mode 100644 index 00000000..5f8509ce --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/UnknownFieldException.java @@ -0,0 +1,20 @@ +package fr.jamailun.ultimatespellsystem.dsl2.errors; + +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; + +/** + * Exception thrown when a requested field does not exist. + */ +public class UnknownFieldException extends UssException { + + /** + * New instance. + * @param pos position of the token. + * @param type type of the struct. + * @param fieldName requested field name. + */ + public UnknownFieldException(TokenPosition pos, String type, String fieldName) { + super(pos, "The type " + type + " has not field '" + fieldName + "'."); + } + +} diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/UnknownFunctionException.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/UnknownFunctionException.java new file mode 100644 index 00000000..61a6846a --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/UnknownFunctionException.java @@ -0,0 +1,29 @@ +package fr.jamailun.ultimatespellsystem.dsl2.errors; + +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import org.jetbrains.annotations.NotNull; + +/** + * An exception threw when a function has not been registered. + */ +public class UnknownFunctionException extends UssException { + + /** + * New exception. + * @param pos token position. + * @param functionId ID of the unknown function. + */ + public UnknownFunctionException(@NotNull TokenPosition pos, @NotNull String functionId) { + super(pos, "Unknown function ID: '"+functionId+"'."); + } + + /** + * New exception for a struct. + * @param pos token position. + * @param structName name of the structure. + * @param functionId ID of the unknown function. + */ + public UnknownFunctionException(@NotNull TokenPosition pos, @NotNull String structName, @NotNull String functionId) { + super(pos, "Unknown function ID: '"+functionId+"' in struct " + structName + "."); + } +} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/UssException.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/UssException.java similarity index 80% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/UssException.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/UssException.java index c38802b6..2dfcdb6f 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/errors/UssException.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/errors/UssException.java @@ -1,7 +1,7 @@ -package fr.jamailun.ultimatespellsystem.dsl.errors; +package fr.jamailun.ultimatespellsystem.dsl2.errors; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; import org.jetbrains.annotations.NotNull; /** diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/library/ObjectsLibrary.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/library/ObjectsLibrary.java new file mode 100644 index 00000000..b97d2037 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/library/ObjectsLibrary.java @@ -0,0 +1,61 @@ +package fr.jamailun.ultimatespellsystem.dsl2.library; + +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.FunctionDeclarationStatement; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.registries.ObjectsDefinitionRegistry; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; +import java.util.SequencedCollection; + +public class ObjectsLibrary { + + private final Map functions = new HashMap<>(); + private final Map structs = new HashMap<>(); + private final Map types = new HashMap<>(); + + public ObjectsLibrary() { + this(true); + } + + public ObjectsLibrary(boolean registerDefaults) { + types.putAll(TypePrimitive.getTypesMap()); + if(registerDefaults) { + ObjectsDefinitionRegistry.getDefaultStructs().forEach(this::registerStruct); + } + } + + public void registerStruct(@NotNull StructDefinition struct) { + structs.put(struct.getName(), struct); + types.put(struct.getName(), struct.asType()); + } + + public void registerStatements(@NotNull SequencedCollection statements) { + for(StatementNode statement : statements) { + if(statement instanceof FunctionDeclarationStatement fda) { + registerFunction(fda); + } + } + } + + public void registerFunction(@NotNull FunctionDeclarationStatement declaration) { + functions.put(declaration.getFunctionName(), declaration); + } + + public @Nullable FunctionDeclarationStatement getFunction(String name) { + return functions.get(name); + } + + public @Nullable StructDefinition getStruct(String name) { + return structs.get(name); + } + + public @Nullable Type getType(String name) { + return types.get(name); + } + +} diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/library/StructDefinition.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/library/StructDefinition.java new file mode 100644 index 00000000..28e4ccfc --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/library/StructDefinition.java @@ -0,0 +1,49 @@ +package fr.jamailun.ultimatespellsystem.dsl2.library; + +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +@RequiredArgsConstructor +public class StructDefinition { + + @Getter private final String name; + private final Map fields = new HashMap<>(); + private final Map functions = new HashMap<>(); + + public void registerField(@NotNull String fieldName, @NotNull Type type) { + fields.put(fieldName, type); + } + + public void registerField(@NotNull String fieldName, @NotNull TypePrimitive primitive) { + fields.put(fieldName, new Type(primitive, 0)); + } + + protected void registerField(@NotNull String fieldName, @NotNull String lazyType) { + fields.put(fieldName, new Type(lazyType, 0)); + } + + public void registerFunction(@NotNull FunctionDefinition function) { + functions.put(function.id(), function); + } + + public @Nullable Type getFieldType(@NotNull String fieldName) { + return fields.get(fieldName); + } + + public @Nullable FunctionDefinition getFunction(@NotNull String functionName) { + return functions.get(functionName); + } + + public @NotNull Type asType() { + return new Type(name, 0); + } + +} diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/library/structs/ConsoleStruct.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/library/structs/ConsoleStruct.java new file mode 100644 index 00000000..28101b6c --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/library/structs/ConsoleStruct.java @@ -0,0 +1,46 @@ +package fr.jamailun.ultimatespellsystem.dsl2.library.structs; + +import fr.jamailun.ultimatespellsystem.dsl2.library.StructDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; + +public class ConsoleStruct extends StructDefinition { + + public static final String NAME = "console"; + + public ConsoleStruct() { + super(NAME); + initFunctions(); + } + + private void initFunctions() { + registerFunction(FunctionDefinition.of( + "send", + Type.NULL, + FunctionArgument.of(TypePrimitive.STRING) + )); + registerFunction(FunctionDefinition.of( + "info", + Type.NULL, + FunctionArgument.of(TypePrimitive.STRING) + )); + registerFunction(FunctionDefinition.of( + "debug", + Type.NULL, + FunctionArgument.of(TypePrimitive.STRING) + )); + registerFunction(FunctionDefinition.of( + "warning", + Type.NULL, + FunctionArgument.of(TypePrimitive.STRING) + )); + registerFunction(FunctionDefinition.of( + "error", + Type.NULL, + FunctionArgument.of(TypePrimitive.STRING) + )); + } + +} diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/library/structs/EntityStruct.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/library/structs/EntityStruct.java new file mode 100644 index 00000000..98fd6745 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/library/structs/EntityStruct.java @@ -0,0 +1,57 @@ +package fr.jamailun.ultimatespellsystem.dsl2.library.structs; + +import fr.jamailun.ultimatespellsystem.dsl2.library.StructDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; + +public class EntityStruct extends StructDefinition { + + public static final String NAME = TypePrimitive.ENTITY.name().toLowerCase(); + + public EntityStruct() { + super(NAME); + initFields(); + initFunctions(); + } + + private void initFields() { + registerField("name", TypePrimitive.STRING); + + registerField("location", TypePrimitive.LOCATION); + registerField("eye_location", TypePrimitive.LOCATION); + + // Location + registerField("x", TypePrimitive.NUMBER); + registerField("y", TypePrimitive.NUMBER); + registerField("z", TypePrimitive.NUMBER); + registerField("yaw", TypePrimitive.NUMBER); + registerField("pitch", TypePrimitive.NUMBER); + + // Attributes + registerField("health", TypePrimitive.NUMBER); + registerField("max_health", TypePrimitive.NUMBER); + } + + private void initFunctions() { + registerFunction(FunctionDefinition.of( + "teleport", + Type.NULL, + FunctionArgument.of(TypePrimitive.LOCATION) + )); + + registerFunction(FunctionDefinition.of( + "heal", + Type.NULL, + FunctionArgument.of(TypePrimitive.NUMBER) + )); + + registerFunction(FunctionDefinition.of( + "send_message", + Type.NULL, + FunctionArgument.of(TypePrimitive.STRING) + )); + } + +} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/ExpressionNode.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/ExpressionNode.java similarity index 51% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/ExpressionNode.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/ExpressionNode.java index 6b76bb6d..14496ec1 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/ExpressionNode.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/ExpressionNode.java @@ -1,25 +1,17 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes; - -import fr.jamailun.ultimatespellsystem.dsl.errors.SyntaxException; -import fr.jamailun.ultimatespellsystem.dsl.errors.UnknownFunctionException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.compute.AllEntitiesAroundExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.compute.PositionOfExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.compute.SizeOfExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.registries.EntityTypeRegistry; -import fr.jamailun.ultimatespellsystem.dsl.registries.FunctionDefinitionsRegistry; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; +package fr.jamailun.ultimatespellsystem.dsl2.nodes; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.SyntaxException; +import fr.jamailun.ultimatespellsystem.dsl2.errors.UssException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.*; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.litteral.*; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators.*; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.*; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; import org.jetbrains.annotations.NotNull; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Deque; import java.util.List; @@ -64,29 +56,18 @@ protected ExpressionNode(@NotNull TokenPosition position) { * Extract the next Expression-Node from a tokens-stream. * @param tokens the tokens-stream to create the next expression with. * @return a non-null expression. - * @throws fr.jamailun.ultimatespellsystem.dsl.errors.UssException if a problems occurs. + * @throws UssException if a problems occurs. */ public static @NotNull ExpressionNode readNextExpression(@NotNull TokenStream tokens) { - return readNextExpression(tokens, false); - } - - /** - * Extract the next Expression-Node from a tokens-stream. - * @param tokens the tokens-stream to create the next expression with. - * @param allowCustom if true, an unknown Identifier will be returned as a specific literal. - * @return a non-null expression. - * @throws fr.jamailun.ultimatespellsystem.dsl.errors.UssException if a problems occurs. - */ - public static @NotNull ExpressionNode readNextExpression(@NotNull TokenStream tokens, boolean allowCustom) { - return readNextExpression(tokens, allowCustom, new MathParsingQueue(false), true); + return readNextExpression(tokens, new MathParsingQueue(false), true); } - private static ExpressionNode readNextExpression(TokenStream tokens, boolean allowCustom, MathParsingQueue mathStack, boolean logicFirst) { - ExpressionNode raw = readNextExpressionBuffer(tokens, allowCustom); + private static @NotNull ExpressionNode readNextExpression(TokenStream tokens, MathParsingQueue mathStack, boolean logicFirst) { + ExpressionNode raw = readNextExpressionBuffer(tokens); // Check if the element is accessed ! if(tokens.dropOptional(TokenType.SQUARE_BRACKET_OPEN)) { ExpressionNode index = readNextExpression(tokens); - tokens.dropOrThrow(TokenType.SQUARE_BRACKET_CLOSE); + tokens.dropOrThrow(TokenType.SQUARE_BRACKET_CLOSE, "A ')' is required after an expression that started with a '('."); raw = new ArrayGetterExpression(raw, index); } @@ -94,7 +75,7 @@ private static ExpressionNode readNextExpression(TokenStream tokens, boolean all return tryConvertLogicalExpression(withMath, tokens, logicFirst); } - private static @NotNull ExpressionNode readNextExpressionBuffer(@NotNull TokenStream tokens, boolean allowCustom) { + private static @NotNull ExpressionNode readNextExpressionBuffer(@NotNull TokenStream tokens) { Token token = tokens.next(); return switch (token.getType()) { // Mono-operators @@ -105,74 +86,111 @@ private static ExpressionNode readNextExpression(TokenStream tokens, boolean all case OPE_SUB -> { TokenPosition position = tokens.position(); ExpressionNode nextExpression = readNextExpression(tokens); - yield new SubOperator(position, new NumberExpression(position, 0), nextExpression); + yield new SubOperator(position, new NumberLiteral(position, 0), nextExpression); } + // Literals - case VALUE_NUMBER -> new NumberExpression(token); - case TRUE, FALSE -> new BooleanExpression(token); - case VALUE_STRING -> new StringExpression(token); - case VALUE_DURATION -> new DurationExpression(token); - case NULL -> new NullExpression(token.pos()); - case IDENTIFIER -> { - String value = token.getContentString(); - - // EntityType ? - if(EntityTypeRegistry.isAllowed(value)) { - yield new EntityTypeExpression(token.pos(), value); - } else if("EntityType".equals(value)) { - tokens.dropOrThrow(TokenType.DOT); - Token real = tokens.nextOrThrow(TokenType.IDENTIFIER); - String v = real.getContentString(); - if(EntityTypeRegistry.isAllowed(v)) { - yield new EntityTypeExpression(token.pos(), v); - } else { - throw new SyntaxException(token, "Unknown (or disallowed) EntityType '" + v + "'."); - } - } - - // Parenthesis ? maybe a function. - if(tokens.dropOptional(TokenType.BRACKET_OPEN)) { - MonoOperator.MonoOpeType monoOpeType = MonoOperator.MonoOpeType.find(value.toUpperCase()); - if(monoOpeType != null) { - ExpressionNode child = ExpressionNode.readNextExpression(tokens, true); - tokens.dropOrThrow(TokenType.BRACKET_CLOSE); - yield new MathFunctionOperator(token.pos(), child, monoOpeType); - } - - FunctionDefinition functionDefinition = FunctionDefinitionsRegistry.find(value); - if(functionDefinition != null) { - FunctionCallExpression exp = FunctionCallExpression.readNextFunctionCall(functionDefinition, tokens); - tokens.dropOptional(TokenType.SEMI_COLON); - yield exp; - } - throw new UnknownFunctionException(token.pos(), value); - } - - // Custom value : checked at runtime ! - if(allowCustom) { - yield new RuntimeLiteral(token); - } - - throw new SyntaxException(token, "Expected an expression."); - } + case VALUE_NUMBER -> new NumberLiteral(token); + case VALUE_BOOLEAN -> new BooleanLiteral(token); + case VALUE_STRING -> new StringLiteral(token); + case VALUE_DURATION -> new DurationLiteral(token); + case NULL -> new NullLiteral(token.pos()); case CHAR_AT -> LocationLiteral.readNextLocation(tokens); - // Var - case VALUE_VARIABLE -> new VariableExpression(token); - // Openers: '{{', '[[', '(' - case PROPERTY_OPEN -> PropertiesExpression.parseProperties(tokens); - case ARRAY_OPEN -> ArrayExpression.parseNextArrayConcat(tokens); + + // Increment / decrement / sizeof + case INCREMENT -> IncrementExpression.parseIncrementOrDecrement(tokens, true); + case DECREMENT -> IncrementExpression.parseIncrementOrDecrement(tokens, false); + case SIZE_OF -> SizeOfOperator.parseSizeOf(tokens); + + // Toutes les compositions de + // "A.B", "A.B(...)", "A[B]" et "A". + case IDENTIFIER -> parseIdentifierExpression(token, tokens); + + + // Openers: '{', '[', '(' + case BRACES_OPEN -> MapLiteral.parseMap(tokens); + case SQUARE_BRACKET_OPEN -> ArrayLiteral.readNextArrayLiteral(tokens); case BRACKET_OPEN -> ParenthesisExpression.parseParenthesis(tokens); - // 'function'-expressions - case ALL -> AllEntitiesAroundExpression.parseAllExpression(tokens); - case POSITION -> PositionOfExpression.parsePositionOf(tokens); - case SIZEOF -> SizeOfExpression.parseSizeOf(tokens); // Other default -> throw new SyntaxException(token, "Unexpected expression-start."); }; } + @PreviousIndicator(expected = TokenType.IDENTIFIER) + public static @NotNull ExpressionNode parseIdentifierExpression(@NotNull Token first, @NotNull TokenStream tokens) { + if(tokens.dropOptional(TokenType.INCREMENT)) { + return new IncrementExpression(first, true, true); + } else if(tokens.dropOptional(TokenType.DECREMENT)) { + return new IncrementExpression(first, false, true); + } + + // IDENTIFIER( ? + if(tokens.dropOptional(TokenType.BRACKET_OPEN)) { + List arguments = parseArgumentsParameter(tokens); + ExpressionNode expression = new FunctionCallExpression(null, first, arguments); + return parseIdentifierExpression(expression, tokens); + } + + + ExpressionNode left = new ReferenceExpression(first); + return parseIdentifierExpression(left, tokens); + } + + // a.b.c + // first = 'a' + private static @NotNull ExpressionNode parseIdentifierExpression(@NotNull ExpressionNode left, @NotNull TokenStream tokens) { + // IDENTIFIER. ? + if(tokens.dropOptional(TokenType.DOT)) { + // Il faut une expression ! + // i.e. "a.IDENTIFIER" ! + Token identifier = tokens.nextOrThrow(TokenType.IDENTIFIER, "After 'IDENTIFIER.' can only accept a 'IDENTIFIER'."); + + // Parenthèse ? + // a.IDENTIFIER(...) + if(tokens.dropOptional(TokenType.BRACKET_OPEN)) { + List arguments = parseArgumentsParameter(tokens); + ExpressionNode fctCall = new FunctionCallExpression(left, identifier, arguments); + + // Après "a.b(...)" on peut avoir une suite. Donc, on refait une boucle. + return parseIdentifierExpression(fctCall, tokens); + } + + // Pas de parenthèse, on a bien un simple "a.b" + // On package le tout en une expression + ExpressionNode fieldGet = new FieldGetExpression(left, identifier.getContentString()); + + // (a.b).c + return parseIdentifierExpression(fieldGet, tokens); + } + + // IDENTIFIER[ ? + if(tokens.dropOptional(TokenType.SQUARE_BRACKET_OPEN)) { + ExpressionNode index = ExpressionNode.readNextExpression(tokens); + tokens.dropOrThrow(TokenType.SQUARE_BRACKET_CLOSE, "Expected an array-get close ']' after it was opened."); + ArrayGetterExpression arrayGet = new ArrayGetterExpression(left, index); + + // On peut avoir "a[b].c", donc on refait un tour + return parseIdentifierExpression(arrayGet, tokens); + } + + // à priori, cas par défaut : on renvoie tout simplement l'expression qu'on a reçu. + // Dans le cas VRAIMENT par défaut, c'est donc une référence de variable. + return left; + } + + public static @NotNull List parseArgumentsParameter(@NotNull TokenStream tokens) { + List list = new ArrayList<>(); + boolean first = true; + while(!tokens.dropOptional(TokenType.BRACKET_CLOSE)) { + if(first) first = false; else tokens.dropOrThrow(TokenType.COMMA, "A COMMA is required between parameters."); + ExpressionNode expression = ExpressionNode.readNextExpression(tokens); + list.add(expression); + } + return list; + } + private final static List LOW_PRIORITY_OPERATORS = List.of(TokenType.OPE_ADD, TokenType.OPE_SUB); private final static List HIGH_PRIORITY_OPERATORS = List.of(TokenType.OPE_MUL, TokenType.OPE_DIV); @@ -186,14 +204,14 @@ private static ExpressionNode tryConvertMathOperations(ExpressionNode expr, @Not stack.expressionStack.push(expr); stack.operandsStack.push(token); // fetch next one - return readNextExpression(tokens, true, stack, true); + return readNextExpression(tokens, stack, true); } // High-priority operators if(HIGH_PRIORITY_OPERATORS.contains(token.getType())) { tokens.drop(); // don't push to stack. Get the next one and convert directly - ExpressionNode nextOne = readNextExpression(tokens, true, new MathParsingQueue(true), true); + ExpressionNode nextOne = readNextExpression(tokens, new MathParsingQueue(true), true); BiOperator current = BiOperator.parseBiOperator(expr, token, nextOne); // And redo (try to have more operators) return tryConvertMathOperations(current, tokens, stack); @@ -206,16 +224,16 @@ private static ExpressionNode tryConvertMathOperations(ExpressionNode expr, @Not private static @NotNull ExpressionNode tryConvertLogicalExpression(ExpressionNode expr, @NotNull TokenStream tokens, boolean firstLevel) { Token token = tokens.peek(); return switch(token.getType()) { - case OPE_OR, OPE_AND, LIST_ADD, LIST_REM, LIST_REM_INDEX -> { + case OPE_OR, OPE_AND, LIST_ADD, LIST_REM, LIST_REM_INDEX -> { if(!firstLevel) yield expr; tokens.drop(); - ExpressionNode right = readNextExpression(tokens, false, new MathParsingQueue(false), true); + ExpressionNode right = readNextExpression(tokens, new MathParsingQueue(false), true); yield BiOperator.parseBiOperator(expr, token, right); } - case COMP_NE, COMP_EQ, COMP_GT, COMP_LT, COMP_LE, COMP_GE, LIST_CONTAINS -> { + case COMP_NE, COMP_EQ, COMP_GT, COMP_LT, COMP_LE, COMP_GE -> { tokens.drop(); - ExpressionNode right = readNextExpression(tokens, false, new MathParsingQueue(false), false); + ExpressionNode right = readNextExpression(tokens, new MathParsingQueue(false), false); BiOperator newFormed = BiOperator.parseBiOperator(expr, token, right); yield tryConvertLogicalExpression(newFormed, tokens, true); } diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/Node.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/Node.java similarity index 73% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/Node.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/Node.java index ac3b0218..4701a794 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/Node.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/Node.java @@ -1,9 +1,10 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes; +package fr.jamailun.ultimatespellsystem.dsl2.nodes; -import fr.jamailun.ultimatespellsystem.dsl.errors.TypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.CollectionFilter; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -29,13 +30,13 @@ public abstract class Node { * @param otherTypes a variadic for other allowed types. */ protected void assertExpressionType(@NotNull ExpressionNode expression, @NotNull CollectionFilter filter, @NotNull TypePrimitive type, TypePrimitive... otherTypes) { - if(expression.getExpressionType().primitive() == TypePrimitive.NULL) + if(expression.getExpressionType().is(Type.NULL)) return; // Ignore NULL type : it is accepted by everything. List allowed = new ArrayList<>(List.of(otherTypes)); allowed.add(type); - if(!allowed.contains(expression.getExpressionType().primitive())) + if(! expression.getExpressionType().isOneOf(allowed.toArray(new TypePrimitive[0]))) throw new TypeException(expression, type); if(!filter.isValid(expression.getExpressionType())) { @@ -43,6 +44,14 @@ protected void assertExpressionType(@NotNull ExpressionNode expression, @NotNull } } + protected void assertExpressionType(@NotNull ExpressionNode expression, @NotNull Type type) { + if(type.isNull()) + return; // On ignore tlr type null + + if(!expression.getExpressionType().equals(type)) + throw new TypeException(expression, "Type is correct, but expected a "+type+"."); + } + /** * Validate the type of expression, and then it to be of a specific type. * @param expression the expression to check. diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/StatementNode.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/StatementNode.java new file mode 100644 index 00000000..9563d6c6 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/StatementNode.java @@ -0,0 +1,129 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.ParsingException; +import fr.jamailun.ultimatespellsystem.dsl2.errors.SyntaxException; +import fr.jamailun.ultimatespellsystem.dsl2.errors.UssException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.*; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks.ForLoopStatement; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks.IfElseStatement; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks.WhileLoopStatement; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.PreviousIndicator; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenType; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.StatementVisitor; +import org.jetbrains.annotations.NotNull; + +/** + * A statement is an instruction in the code. It can use other statements, or {@link ExpressionNode expressions}.
+ * Can be visited by a {@link StatementVisitor}. + * This class can parse a statement with the {@link #parseNextStatement(TokenStream)} method. + */ +public abstract class StatementNode extends Node { + + /** + * Make this statement be visited. + * @param visitor the visitor to use. + */ + public abstract void visit(@NotNull StatementVisitor visitor); + + @PreviousIndicator(expected = TokenType.IDENTIFIER) + private static @NotNull StatementNode parseFromIdentifier(@NotNull Token first, @NotNull TokenStream tokens) { + if(!tokens.hasMore()) + throw new ParsingException(tokens.position(), "Unexpected end of tokens after identifier."); + + // Si c'est encore un IDENTIFIER : c'est soit une déclaration de variable ou de fonction. + if(tokens.peekIs(TokenType.IDENTIFIER)) { + Token second = tokens.next(); // identifier + + // "A B =" : variable declaration + if(tokens.dropOptional(TokenType.EQUAL)) { + ExpressionNode definition = ExpressionNode.readNextExpression(tokens); + StatementNode output = new DeclareNewVariableStatement(first, second, definition); + tokens.dropOptional(TokenType.SEMI_COLON); + return output; + } + + // "A B(..." : function declaration + if(tokens.dropOptional(TokenType.BRACKET_OPEN)) { + return FunctionDeclarationStatement.parseNextFunction(first, second, tokens); + } + + if (tokens.dropOptional(TokenType.SEMI_COLON)) { + return new DeclareNewVariableStatement(first, second, null); + // le semi-colon a déjà été retiré :) + } + + // Illegal ? + throw new SyntaxException(tokens.position(), "Unexpected token after 'IDENTIFIER IDENTIFIER' : " + tokens.peek()); + } + + // On essaye de wrapper le token en expression ("a" ou "a.b().c") pour voir si on a un EQUAL ensuite. + ExpressionNode wrapped = ExpressionNode.parseIdentifierExpression(first, tokens); + + // Point virgule ? On wrap juste tout ça. + if(tokens.dropOptional(TokenType.SEMI_COLON)) { + //TODO interdire les "faux-statements" qui n'ont aucun effet ? Ou faire ça dans AST complet. + return new SimpleExpressionStatement(wrapped); + } + + // EQUAL ? On désigne le tout comme une affectation + if(tokens.dropOptional(TokenType.EQUAL)) { + return AffectationStatement.parseNextDefine(wrapped, tokens); + } + + // Other ? + return new SimpleExpressionStatement(wrapped); + } + + /** + * Read a new statement from the tokens stream. + * @param tokens the stream of tokens. + * @return a non-null statement. + * @throws UssException if a problem occurs. + */ + public static @NotNull StatementNode parseNextStatement(@NotNull TokenStream tokens) { + Token token = tokens.next(); + return switch (token.getType()) { + // Empty statement + case SEMI_COLON -> parseNextStatement(tokens); + + case VAR -> { + Token varName = tokens.nextOrThrow(TokenType.IDENTIFIER, "Expect an IDENTIFIER after a VAR."); + ExpressionNode expression = null; + if(tokens.dropOptional(TokenType.EQUAL)) { + expression = ExpressionNode.readNextExpression(tokens); + } + StatementNode output = new DeclareNewVariableStatement(null, varName, expression); + tokens.dropOrThrow(TokenType.SEMI_COLON, "Expected a semi-colon, after a variable declaration."); + yield output; + } + case IDENTIFIER -> parseFromIdentifier(token, tokens); + + // Metadata + //TODO case CHAR_AT -> MetadataStatement.parseMetadata(tokens); + + // Blocks + case BRACES_OPEN -> BlockStatement.parseNextBlock(tokens); + + // Control-Flow + case IF -> IfElseStatement.parseIfStatement(tokens); + case ELSE -> throw new SyntaxException(token, "An ELSE must follow an IF (or the IF's child statement)."); + case FOR -> ForLoopStatement.parseForLoop(tokens); + //TODO case FOREACH -> ForeachLoopStatement.parseForLoop(tokens); + case WHILE -> WhileLoopStatement.parseWhileLoop(tokens, true); + case DO -> WhileLoopStatement.parseWhileLoop(tokens, false); + case BREAK -> BreakContinueStatement.parseNextBreakContinue(tokens, false); + case CONTINUE -> BreakContinueStatement.parseNextBreakContinue(tokens, true); + case RETURN -> ReturnStatement.parseReturn(tokens); + + default -> { + tokens.back(); + ExpressionNode expressionNode = ExpressionNode.readNextExpression(tokens); + yield new SimpleExpressionStatement(expressionNode); + } + //throw new SyntaxException(token, "Unexpected token to begin a statement."); + }; + } + +} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/ArrayGetterExpression.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/ArrayGetterExpression.java similarity index 58% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/ArrayGetterExpression.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/ArrayGetterExpression.java index 2e73009d..43a82e9b 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/ArrayGetterExpression.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/ArrayGetterExpression.java @@ -1,12 +1,12 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions; - -import fr.jamailun.ultimatespellsystem.dsl.errors.TypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.CollectionFilter; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; import lombok.Getter; import org.jetbrains.annotations.NotNull; @@ -19,7 +19,7 @@ public class ArrayGetterExpression extends ExpressionNode { private final ExpressionNode array; private final ExpressionNode index; - public ArrayGetterExpression(ExpressionNode array, ExpressionNode index) { + public ArrayGetterExpression(@NotNull ExpressionNode array, @NotNull ExpressionNode index) { super(array.firstTokenPosition()); this.array = array; this.index = index; @@ -27,7 +27,7 @@ public ArrayGetterExpression(ExpressionNode array, ExpressionNode index) { @Override public @NotNull Type getExpressionType() { - return array.getExpressionType().asMonoElement(); + return array.getExpressionType().popArray(); } @Override @@ -38,7 +38,7 @@ public void validateTypes(@NotNull TypesContext context) { // Array must be a collection array.validateTypes(context); Type typeArray = array.getExpressionType(); - if( ! typeArray.is(TypePrimitive.NULL) && ! typeArray.isCollection()) { + if( ! typeArray.isNull() && ! typeArray.isCollection()) { throw new TypeException(this, "Cannot get the value of a non-array."); } } diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/FieldGetExpression.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/FieldGetExpression.java new file mode 100644 index 00000000..63c410fe --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/FieldGetExpression.java @@ -0,0 +1,56 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.library.StructDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; + +/** + * Get array value at index. + */ +@Getter +public class FieldGetExpression extends ExpressionNode { + + private final ExpressionNode leftExpression; + private final String fieldName; + + private StructDefinition leftStruct; + + public FieldGetExpression(@NotNull ExpressionNode leftExpression, @NotNull String fieldName) { + super(leftExpression.firstTokenPosition()); + this.leftExpression = leftExpression; + this.fieldName = fieldName; + } + + @Override + public @NotNull Type getExpressionType() { + return leftStruct.asType(); + } + + @Override + public void validateTypes(@NotNull TypesContext context) { + // 1. Valider le holder, récupérer son type. + leftExpression.validateTypes(context); + Type type = leftExpression.getExpressionType(); + + // 2. Trouver la structure qui correspond au type + StructDefinition leftStruct = context.findStruct(type); + if(leftStruct == null) { + throw new TypeException(leftExpression.firstTokenPosition(), "Type value " + leftExpression + " of type " + type + " as not structure referenced. As such, cannot get field '" + fieldName + "' on it."); + } + } + + @Override + public void visit(@NotNull ExpressionVisitor visitor) { + visitor.handleFieldGet(this); + } + + @Override + public String toString() { + return firstTokenPosition() + "." + fieldName; + } +} diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/FunctionCallExpression.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/FunctionCallExpression.java new file mode 100644 index 00000000..fe401ac6 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/FunctionCallExpression.java @@ -0,0 +1,110 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.SyntaxException; +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.library.StructDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionSignature; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.FunctionDeclarationStatement; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +@Getter +public class FunctionCallExpression extends ExpressionNode { + + private Type runtimeType = null; + + private final TokenPosition position; + private final @Nullable ExpressionNode caller; + private final String functionName; + private final List arguments; + + // post build + private @Nullable StructDefinition callerStruct; + private @Nullable FunctionSignature signature; + + public FunctionCallExpression(@Nullable ExpressionNode caller, @NotNull Token functionName, @NotNull List arguments) { + super(functionName.pos()); + this.caller = caller; + this.position = functionName.pos(); + this.functionName = functionName.getContentString(); + this.arguments = arguments; + } + + @Override + public @NotNull Type getExpressionType() { + assert runtimeType != null; + return runtimeType; + } + + @Override + public void validateTypes(@NotNull TypesContext context) { + // 1. Propagate to arguments + List paramTypes = new ArrayList<>(); + for(ExpressionNode argument : arguments) { + argument.validateTypes(context.childContext()); + paramTypes.add(argument.getExpressionType()); + } + signature = new FunctionSignature(functionName, paramTypes); + + // 2. If we have a caller : we check the function from the type definition. + FunctionDefinition function; + if(caller != null) { + caller.validateTypes(context); + Type callerType = caller.getExpressionType(); + callerStruct = context.findStruct(callerType); + if(callerStruct == null) { + throw new TypeException(position, "Unknown struct for type " + callerType); + } + function = callerStruct.getFunction(functionName); + if(function == null) { + throw new TypeException(position, "Cannot call function '" + functionName + "' on type " + callerType + "."); + } + } + // Pas de caller : function globale + else { + FunctionDefinition definition = context.findFunction(functionName); + if(definition == null) { + throw new SyntaxException(position, "Global function '" + functionName + "' not found"); + } + function = definition; + } + + // 3. Set our type + this.runtimeType = function.returnedType(); + + // 4. Check arguments list match requested types + if(arguments.size() != function.arguments().size()) { + throw new SyntaxException(position, "Function argument count mismatch. Expected " + function.arguments().size() + " but got " + arguments.size() + "."); + } + for(int i = 0; i < arguments.size(); i++) { + ExpressionNode arg = arguments.get(i); + FunctionArgument def = function.arguments().get(i); + if(!Objects.equals(arg.getExpressionType(), def.type())) { + throw new TypeException(arg.firstTokenPosition(), "Bad argument type. Function " + functionName + " expected " + def.type() + " on argument n°" + (i+1) + ", but got " + arg.getExpressionType() + "."); + } + } + } + + @Override + public void visit(@NotNull ExpressionVisitor visitor) { + visitor.handleFunctionCall(this); + } + + @Override + public String toString() { + return (caller == null ? "" : caller + ".") + functionName + "(" + arguments + ")"; + } +} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/ParenthesisExpression.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/ParenthesisExpression.java similarity index 56% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/ParenthesisExpression.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/ParenthesisExpression.java index 766c96fe..fa593f43 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/ParenthesisExpression.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/ParenthesisExpression.java @@ -1,13 +1,13 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions; + +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.PreviousIndicator; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenType; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; import lombok.Getter; import org.jetbrains.annotations.NotNull; @@ -19,7 +19,7 @@ public class ParenthesisExpression extends ExpressionNode { private final ExpressionNode expression; - protected ParenthesisExpression(TokenPosition position, ExpressionNode expression) { + protected ParenthesisExpression(@NotNull TokenPosition position, @NotNull ExpressionNode expression) { super(position); this.expression = expression; } @@ -48,8 +48,8 @@ public String toString() { @PreviousIndicator(expected = {TokenType.BRACKET_OPEN}) public static ParenthesisExpression parseParenthesis(TokenStream tokens) { TokenPosition pos = tokens.position(); - ExpressionNode expression = ExpressionNode.readNextExpression(tokens, true); - tokens.dropOrThrow(TokenType.BRACKET_CLOSE); + ExpressionNode expression = ExpressionNode.readNextExpression(tokens); + tokens.dropOrThrow(TokenType.BRACKET_CLOSE, "Missing matching closing bracket."); return new ParenthesisExpression(pos, expression); } } diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/VariableExpression.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/ReferenceExpression.java similarity index 59% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/VariableExpression.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/ReferenceExpression.java index 8c723720..0aecb32c 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/VariableExpression.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/ReferenceExpression.java @@ -1,18 +1,18 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions; - -import fr.jamailun.ultimatespellsystem.dsl.errors.SyntaxException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.VariableDefinition; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.SyntaxException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.VariableDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; import org.jetbrains.annotations.NotNull; /** - * Variable reference expression. + * A raw reference expression */ -public class VariableExpression extends ExpressionNode { +public class ReferenceExpression extends ExpressionNode { private final String varName; private Type runtimeType; @@ -22,11 +22,16 @@ public class VariableExpression extends ExpressionNode { * The reference will be obtained during type validation. * @param token the token of the variable itself. */ - public VariableExpression(@NotNull Token token) { + public ReferenceExpression(@NotNull Token token) { super(token.pos()); this.varName = token.getContentString(); } + public void signalType(@NotNull Type type) { + //TODO trucs + runtimeType = type; + } + /** * Get the name of the variable. * @return a non-null string. diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/functions/FunctionArgument.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/functions/FunctionArgument.java new file mode 100644 index 00000000..6b8c64e3 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/functions/FunctionArgument.java @@ -0,0 +1,35 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions; + +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +/** + * A declaration of a function argument. + * @param type the type of the argument. + * @param name the name of the argument. + * @param optional if true, argument is not mandatory. + */ +public record FunctionArgument(@NotNull Type type, @NotNull String name, boolean optional) { + @Contract(pure = true) + @Override + public @NotNull String toString() { + return type + " " + name + (optional?"*":""); + } + + @Contract("_ -> new") + public static @NotNull FunctionArgument of(@NotNull String type) { + return of(Type.of(type)); + } + + @Contract("_ -> new") + public static @NotNull FunctionArgument of(@NotNull TypePrimitive type) { + return of(Type.of(type)); + } + + @Contract("_ -> new") + public static @NotNull FunctionArgument of(@NotNull Type type) { + return new FunctionArgument(type, type.getName(), false); + } +} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/functions/FunctionDefinition.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/functions/FunctionDefinition.java similarity index 66% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/functions/FunctionDefinition.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/functions/FunctionDefinition.java index df570903..62aafe1c 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/functions/FunctionDefinition.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/functions/FunctionDefinition.java @@ -1,6 +1,6 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -21,7 +21,14 @@ public int mandatoryArgumentsCount() { return (int) arguments.stream() .filter(a -> ! a.optional()) .count(); + } + public static FunctionDefinition of( + @NotNull String id, + @NotNull Type type, + @NotNull FunctionArgument... arguments + ) { + return new FunctionDefinition(id, type, List.of(arguments)); } } diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/functions/FunctionSignature.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/functions/FunctionSignature.java new file mode 100644 index 00000000..77a45dd2 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/functions/FunctionSignature.java @@ -0,0 +1,20 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions; + +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * Defines the unicity of a function. + * @param name name of the function. + * @param paramsTypes arguments types. + */ +public record FunctionSignature( + @NotNull String name, + @NotNull List paramsTypes +) { + public static @NotNull FunctionSignature of(@NotNull String id, @NotNull List args) { + return new FunctionSignature(id, args.stream().map(FunctionArgument::type).toList()); + } +} diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/ArrayLiteral.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/ArrayLiteral.java new file mode 100644 index 00000000..a5d69fce --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/ArrayLiteral.java @@ -0,0 +1,90 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.litteral; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.*; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * Raw array value. + */ +public class ArrayLiteral extends ExpressionNode { + + @Getter + private final List elements; + + private Type selfType; + private Type elementsType; + + protected ArrayLiteral(TokenPosition position, List elements) { + super(position); + this.elements = elements; + } + + @Override + public @NotNull Type getExpressionType() { + if(selfType == null) + throw new TypeException(firstTokenPosition(), "Type of primitive has not been set."); + return selfType; + } + + @Override + public void visit(@NotNull ExpressionVisitor visitor) { + visitor.handleArray(this); + } + + @Override + public void validateTypes(@NotNull TypesContext contextParent) { + // avoid non-intentional propagation + TypesContext context = contextParent.childContext(); + + // Check type for all expressions : they must share the same type. + for(ExpressionNode node : elements) { + node.validateTypes(context); + + if(elementsType == null) { + elementsType = node.getExpressionType(); + } else { + assertExpressionType(node, elementsType); + } + } + + // Array is empty : type is null as array ? + if(elementsType == null) { + elementsType = Type.NULL; + } + + // Set self type at the end + selfType = elementsType.pushArray(); + } + + @PreviousIndicator(expected = TokenType.SQUARE_BRACKET_OPEN) + public static ArrayLiteral readNextArrayLiteral(@NotNull TokenStream tokens) { + TokenPosition pos = tokens.position(); + List nodes = new ArrayList<>(); + boolean first = true; + while(!tokens.dropOptional(TokenType.SQUARE_BRACKET_CLOSE)) { + if( ! first) { + tokens.dropOrThrow(TokenType.COMMA, "Elements in array must be separated by a comma."); + } + first = false; + ExpressionNode node = ExpressionNode.readNextExpression(tokens); + nodes.add(node); + } + return new ArrayLiteral(pos, nodes); + } + + @Override + public String toString() { + return "ARRAY("+(selfType==null?"? type":selfType)+")[" + elements + "]"; + } + +} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/BooleanExpression.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/BooleanLiteral.java similarity index 61% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/BooleanExpression.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/BooleanLiteral.java index bc8673d3..46e70525 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/BooleanExpression.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/BooleanLiteral.java @@ -1,15 +1,15 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.litteral; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; import org.jetbrains.annotations.NotNull; /** * A raw boolean literal. */ -public class BooleanExpression extends LiteralExpression { +public class BooleanLiteral extends LiteralExpression { private final boolean rawValue; @@ -17,7 +17,7 @@ public class BooleanExpression extends LiteralExpression { * New instance, from a token. * @param token non-null token to use. */ - public BooleanExpression(@NotNull Token token) { + public BooleanLiteral(@NotNull Token token) { super(token.pos()); this.rawValue = token.getContentBoolean(); } diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/DurationExpression.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/DurationLiteral.java similarity index 60% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/DurationExpression.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/DurationLiteral.java index 09ac7de9..fcb207e3 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/DurationExpression.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/DurationLiteral.java @@ -1,16 +1,16 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.litteral; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; import org.jetbrains.annotations.NotNull; /** * A raw {@link Duration} literal. */ -public class DurationExpression extends LiteralExpression { +public class DurationLiteral extends LiteralExpression { private final Duration duration; @@ -18,7 +18,7 @@ public class DurationExpression extends LiteralExpression { * New instance, from a token. * @param token token to use. */ - public DurationExpression(@NotNull Token token) { + public DurationLiteral(@NotNull Token token) { super(token.pos()); this.duration = new Duration(token.getContentNumber(), token.getContentTimeUnit()); } diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/LiteralExpression.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/LiteralExpression.java similarity index 74% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/LiteralExpression.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/LiteralExpression.java index 0492727a..23cd5a58 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/LiteralExpression.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/LiteralExpression.java @@ -1,8 +1,8 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.litteral; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; import org.jetbrains.annotations.NotNull; /** diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/LocationLiteral.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/LocationLiteral.java similarity index 63% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/LocationLiteral.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/LocationLiteral.java index b1529915..cb11290b 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/LocationLiteral.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/LocationLiteral.java @@ -1,14 +1,14 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.litteral; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.PreviousIndicator; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenType; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; import lombok.Getter; import org.jetbrains.annotations.NotNull; @@ -35,13 +35,13 @@ protected LocationLiteral(TokenPosition position, ExpressionNode world, Expressi this.pitch = pitch; } - public boolean asYawAndPitch() { + public boolean hasYawAndPitch() { return yaw != null && pitch != null; } @Override public @NotNull Type getExpressionType() { - return TypePrimitive.LOCATION.asType(); + return Type.of(TypePrimitive.LOCATION); } @Override @@ -56,7 +56,7 @@ public void validateTypes(@NotNull TypesContext context) { assertExpressionType(vectorY, context, TypePrimitive.NUMBER); assertExpressionType(vectorZ, context, TypePrimitive.NUMBER); - if(asYawAndPitch()) { + if(hasYawAndPitch()) { assertExpressionType(yaw, context, TypePrimitive.NUMBER); assertExpressionType(pitch, context, TypePrimitive.NUMBER); } @@ -71,15 +71,15 @@ public void validateTypes(@NotNull TypesContext context) { public static @NotNull LocationLiteral readNextLocation(@NotNull TokenStream tokens) { TokenPosition position = tokens.position(); // Open - tokens.dropOrThrow(TokenType.BRACKET_OPEN); + tokens.dropOrThrow(TokenType.BRACKET_OPEN, "A '(' is required after a '@' to create a location."); // World + vector ExpressionNode world = ExpressionNode.readNextExpression(tokens); - tokens.dropOrThrow(TokenType.COMMA); + tokens.dropOrThrow(TokenType.COMMA, "A location literal needs a X coordinate after the world."); ExpressionNode x = ExpressionNode.readNextExpression(tokens); - tokens.dropOrThrow(TokenType.COMMA); + tokens.dropOrThrow(TokenType.COMMA, "A location literal needs a Y coordinate after the world and X."); ExpressionNode y = ExpressionNode.readNextExpression(tokens); - tokens.dropOrThrow(TokenType.COMMA); + tokens.dropOrThrow(TokenType.COMMA, "A location literal needs a Z coordinate avec world and X + Y coordinates."); ExpressionNode z = ExpressionNode.readNextExpression(tokens); // Optional yaw + pitch @@ -87,19 +87,18 @@ public void validateTypes(@NotNull TypesContext context) { ExpressionNode pitch = null; if(tokens.dropOptional(TokenType.COMMA)) { yaw = ExpressionNode.readNextExpression(tokens); - } - if(tokens.dropOptional(TokenType.COMMA)) { + tokens.dropOrThrow(TokenType.COMMA, "In a location literal, after the yaw, a pitch value is required."); pitch = ExpressionNode.readNextExpression(tokens); } // Close - tokens.dropOrThrow(TokenType.BRACKET_CLOSE); + tokens.dropOrThrow(TokenType.BRACKET_CLOSE, "A location literal needs a ')' at the end."); return new LocationLiteral(position, world, x, y, z, yaw, pitch); } @Override public String toString() { - return "Loc{"+world+", ("+vectorX+","+vectorY+","+vectorZ+")}"; + return "LOC<"+world+", ("+vectorX+","+vectorY+","+vectorZ+")>"; } } diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/PropertiesExpression.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/MapLiteral.java similarity index 59% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/PropertiesExpression.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/MapLiteral.java index 0bf4ec26..0c290d6f 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/PropertiesExpression.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/MapLiteral.java @@ -1,12 +1,12 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.litteral; -import fr.jamailun.ultimatespellsystem.dsl.errors.SyntaxException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.*; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; +import fr.jamailun.ultimatespellsystem.dsl2.errors.SyntaxException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.*; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; import lombok.Getter; import org.jetbrains.annotations.NotNull; @@ -17,28 +17,28 @@ * Raw properties set. */ @Getter -public class PropertiesExpression extends ExpressionNode { +public class MapLiteral extends LiteralExpression> { private final Map expressions; - public PropertiesExpression(TokenPosition pos, Map expressions) { + public MapLiteral(TokenPosition pos, Map expressions) { super(pos); this.expressions = expressions; } @Override public @NotNull Type getExpressionType() { - return TypePrimitive.PROPERTIES_SET.asType(); + return TypePrimitive.MAP.asType(); } @Override public void visit(@NotNull ExpressionVisitor visitor) { - visitor.handlePropertiesSet(this); + visitor.handleMapLiteral(this); } @Override public String toString() { - return "{" + expressions + "}"; + return "MAP" + PREFIX + expressions + SUFFIX; } @Override @@ -48,12 +48,17 @@ public void validateTypes(@NotNull TypesContext contextParent) { expression.validateTypes(context); } - @PreviousIndicator(expected = {TokenType.PROPERTY_OPEN}) - public static PropertiesExpression parseProperties(TokenStream tokens) { + @Override + public Map getRaw() { + return expressions; + } + + @PreviousIndicator(expected = {TokenType.BRACKET_OPEN}) + public static MapLiteral parseMap(TokenStream tokens) { TokenPosition pos = tokens.position(); Map expressions = new HashMap<>(); while(tokens.hasMore()) { - if(tokens.peek().getType() == TokenType.PROPERTY_CLOSE) { + if(tokens.dropOptional(TokenType.BRACES_CLOSE)) { // EOP break; } @@ -73,11 +78,10 @@ public static PropertiesExpression parseProperties(TokenStream tokens) { // : tokens.dropOrThrow(TokenType.COLON); // VALUE - ExpressionNode value = ExpressionNode.readNextExpression(tokens, true); + ExpressionNode value = ExpressionNode.readNextExpression(tokens); // build expressions.put(propKey, value); } - tokens.dropOrThrow(TokenType.PROPERTY_CLOSE); - return new PropertiesExpression(pos, expressions); + return new MapLiteral(pos, expressions); } } diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/NullLiteral.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/NullLiteral.java new file mode 100644 index 00000000..374e4ff5 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/NullLiteral.java @@ -0,0 +1,39 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.litteral; + +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; +import org.jetbrains.annotations.NotNull; + +/** + * The {@code NULL} representation. + */ +public class NullLiteral extends LiteralExpression { + + /** + * New instance. + * @param pos position of the keyword. + */ + public NullLiteral(@NotNull TokenPosition pos) { + super(pos); + } + + @Override + public Void getRaw() {return null;} + + @Override + public @NotNull Type getExpressionType() { + return Type.NULL; + } + + @Override + public String toString() { + return PREFIX + "NULL" + SUFFIX; + } + + @Override + public void visit(@NotNull ExpressionVisitor visitor) { + visitor.handleNullLiteral(this); + } +} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/NumberExpression.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/NumberLiteral.java similarity index 54% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/NumberExpression.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/NumberLiteral.java index 3c314ed0..eb86a3ae 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/NumberExpression.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/NumberLiteral.java @@ -1,24 +1,24 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.litteral; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; import org.jetbrains.annotations.NotNull; /** * A raw number literal. */ -public class NumberExpression extends LiteralExpression { +public class NumberLiteral extends LiteralExpression { - private final Double rawValue; + private final double rawValue; /** * New literal, using a token. * @param token token to use. */ - public NumberExpression(@NotNull Token token) { + public NumberLiteral(@NotNull Token token) { super(token.pos()); this.rawValue = token.getContentNumber(); } @@ -28,13 +28,13 @@ public NumberExpression(@NotNull Token token) { * @param position position of the token. * @param number value. */ - public NumberExpression(@NotNull TokenPosition position, double number) { + public NumberLiteral(@NotNull TokenPosition position, double number) { super(position); this.rawValue = number; } @Override - public Double getRaw() { + public @NotNull Double getRaw() { return rawValue; } diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/StringExpression.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/StringLiteral.java similarity index 60% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/StringExpression.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/StringLiteral.java index 64f4867a..f87af22e 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/litteral/StringExpression.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/litteral/StringLiteral.java @@ -1,15 +1,15 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.litteral; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; import org.jetbrains.annotations.NotNull; /** * A raw string literal. */ -public class StringExpression extends LiteralExpression { +public class StringLiteral extends LiteralExpression { private final String rawValue; @@ -17,7 +17,7 @@ public class StringExpression extends LiteralExpression { * New raw string. * @param token token to use. */ - public StringExpression(@NotNull Token token) { + public StringLiteral(@NotNull Token token) { super(token.pos()); this.rawValue = token.getContentString(); } diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/AddOperator.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/AddOperator.java similarity index 64% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/AddOperator.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/AddOperator.java index a03dc628..3286ac2e 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/AddOperator.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/AddOperator.java @@ -1,11 +1,11 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators; - -import fr.jamailun.ultimatespellsystem.dsl.errors.TypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; import org.jetbrains.annotations.NotNull; /** @@ -30,16 +30,14 @@ public AddOperator(TokenPosition pos, ExpressionNode left, ExpressionNode right) @Override public void validateTypes(@NotNull Type leftType, @NotNull Type rightType, @NotNull TypesContext context) { + //FIXME il faut changer tout ça. + // Les types seront indiqués comme supportant telle ou telle opération. + // 1) One of them is a String : always compatible if(leftType.is(TypePrimitive.STRING) || rightType.is(TypePrimitive.STRING)) { producedType = TypePrimitive.STRING.asType(); return; } - // 1.b) Special case : Loc+number[] - if(leftType.is(TypePrimitive.LOCATION) || rightType.primitive() == TypePrimitive.NUMBER && rightType.isCollection()) { - producedType = TypePrimitive.LOCATION.asType(); - return; - } // 2) Some types cannot be added at all. assertNotMathIncompatible(leftType); diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/BiOperator.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/BiOperator.java similarity index 78% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/BiOperator.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/BiOperator.java index 1f27fa1a..8b76a66d 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/BiOperator.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/BiOperator.java @@ -1,13 +1,12 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators; - -import fr.jamailun.ultimatespellsystem.dsl.errors.SyntaxException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.SyntaxException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; import org.jetbrains.annotations.NotNull; /** @@ -15,7 +14,7 @@ */ public abstract class BiOperator extends Operator { - protected Type producedType = TypePrimitive.NULL.asType(); + protected Type producedType = Type.NULL; protected final ExpressionNode left; protected final ExpressionNode right; @@ -79,14 +78,12 @@ public void visit(@NotNull ExpressionVisitor visitor) { public enum BiOpeType { // Math - ADD, SUB, MUL, DIV, // Logical - EQUAL, NOT_EQUAL, GREATER_OR_EQ, @@ -98,11 +95,11 @@ public enum BiOpeType { OR, // List - LIST_ADD, LIST_REM, LIST_REM_INDEX, LIST_CONTAINS + } } diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/IncrementExpression.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/IncrementExpression.java new file mode 100644 index 00000000..97a00762 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/IncrementExpression.java @@ -0,0 +1,70 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.SyntaxException; +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.VariableDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.*; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; + +/** + * Either {@code increment} or {@code decrement}. + */ +@Getter +public class IncrementExpression extends ExpressionNode { + + private final String varName; + private final boolean positive; + private final boolean afterVar; + + public IncrementExpression(@NotNull Token identifierToken, boolean positive, boolean afterVar) { + super(identifierToken.pos()); + this.varName = identifierToken.getContentString(); + this.positive = positive; + this.afterVar = afterVar; + } + + @Override + public void validateTypes(@NotNull TypesContext context) { + VariableDefinition variableDefinition = context.findVariable(varName); + if(variableDefinition == null) + throw new SyntaxException(firstTokenPosition(), "Unknown variable to " + (positive?"increment":"decrement") + " : '" + varName + "'."); + + Type type = variableDefinition.getType(context); + if(!type.is(TypePrimitive.NUMBER)) + throw new TypeException(firstTokenPosition(), "For " + (positive?"increment":"decrement") + " %"+varName+", expected NUMBER. Got type " + type + "."); + } + + @Override + public void visit(@NotNull ExpressionVisitor visitor) { + visitor.handleIncrementDecrement(this); + } + + /** + * Parse a increment/decrement statement. + * @param tokens streams of tokens. + * @return a new instance. + */ + @PreviousIndicator(expected = {TokenType.INCREMENT, TokenType.DECREMENT}) + public static @NotNull IncrementExpression parseIncrementOrDecrement(@NotNull TokenStream tokens, boolean increment) { + Token var = tokens.nextOrThrow(TokenType.IDENTIFIER, "After an " + (increment?"INCREMENT":"DECREMENT")+ " a variable name is required."); + tokens.dropOptional(TokenType.SEMI_COLON); + return new IncrementExpression(var, increment, false); + } + + @Override + public String toString() { + String symbol = positive ?"++":"--"; + return afterVar ? varName + symbol : symbol + varName; + } + + @Override + public @NotNull Type getExpressionType() { + return Type.of(TypePrimitive.NUMBER); + } +} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/ListOperator.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/ListOperator.java similarity index 72% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/ListOperator.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/ListOperator.java index 4a682153..f0199b7e 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/ListOperator.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/ListOperator.java @@ -1,14 +1,14 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators; -import fr.jamailun.ultimatespellsystem.dsl.errors.TypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.VariableExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.VariableDefinition; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.VariableReference; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.ReferenceExpression; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.VariableDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.VariableReference; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; import org.jetbrains.annotations.NotNull; /** @@ -37,16 +37,16 @@ public ListOperator(@NotNull Token operand, @NotNull ExpressionNode left, @NotNu @Override protected void validateTypes(@NotNull Type leftType, @NotNull Type rightType, @NotNull TypesContext context) { // Left must be a list, right cannot be null. - if(rightType.is(TypePrimitive.NULL)) + if(rightType.isNull()) throw new TypeException(firstTokenPosition(), "Cannot apply an operator with a NULL-typed right operand (" + right + ")"); if(! leftType.isCollection()) throw new TypeException(firstTokenPosition(), "A list operator (" + opeType + ") can ONLY be applied on a LIST for the left operand. Left is " + leftType); // We can, eventually, help to figure-out what variable if(opeType != BiOpeType.LIST_REM_INDEX) { - if(left.getExpressionType().is(TypePrimitive.NULL)) { + if(left.getExpressionType().isNull()) { helpCompleteVariable(rightType, context); - } else if(leftType.primitive() != rightType.primitive()) { + } else if( ! leftType.isLike(rightType)) { throw new TypeException(firstTokenPosition(), "Cannot have heterogeneous lists. List is " + leftType + ", right operand is " + rightType); } } @@ -64,10 +64,10 @@ protected void validateTypes(@NotNull Type leftType, @NotNull Type rightType, @N } private void helpCompleteVariable(Type rightType, TypesContext context) { - if(left instanceof VariableExpression varExpr) { + if(left instanceof ReferenceExpression varExpr) { VariableDefinition var = context.findVariable(varExpr.getVariableName()); if(var != null) { - var.register(new VariableReference.Constant(rightType.asCollection(), firstTokenPosition())); + var.register(new VariableReference.Constant(rightType.pushArray(), firstTokenPosition())); } } } diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/LogicalOperator.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/LogicalOperator.java similarity index 75% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/LogicalOperator.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/LogicalOperator.java index b0575072..09e2f49c 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/LogicalOperator.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/LogicalOperator.java @@ -1,11 +1,11 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators; -import fr.jamailun.ultimatespellsystem.dsl.errors.TypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; import org.jetbrains.annotations.NotNull; /** @@ -44,15 +44,15 @@ public void validateTypes(@NotNull Type leftType, @NotNull Type rightType, @NotN } // Only allow same type (but still allow NULL :) ) - if(!(leftType.is(TypePrimitive.NULL) || rightType.is(TypePrimitive.NULL))) { - if (leftType.primitive() != rightType.primitive()) { + if(!(leftType.isNull() || rightType.isNull())) { + if (!(leftType.equals(rightType))) { throw new TypeException(firstTokenPosition(), "Logical operator " + this + " has unequal types : " + leftType + " and " + rightType + "."); } } // If inequality, must be numeric if(type == BiOpeType.GREATER || type == BiOpeType.GREATER_OR_EQ || type == BiOpeType.LESSER || type == BiOpeType.LESSER_OR_EQ) { - if(leftType.primitive() != TypePrimitive.NUMBER && leftType.primitive() != TypePrimitive.DURATION) { + if( ! leftType.isOneOf(TypePrimitive.NUMBER, TypePrimitive.DURATION)) { throw new TypeException(this, "A comparison can only compare numeric values !"); } } diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/MonoOperator.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/MonoOperator.java new file mode 100644 index 00000000..21e87e0b --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/MonoOperator.java @@ -0,0 +1,57 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators; + +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.function.Function; + +/** + * Mono-operator, on a single expression. + */ +@Getter +public abstract class MonoOperator extends Operator { + + protected final ExpressionNode child; + + protected MonoOperator(TokenPosition position, ExpressionNode child) { + super(position); + this.child = child; + } + + /** + * Get this instance type of operation. + * @return a non-null type of mono-operation. + */ + public abstract @NotNull MonoOpeType getType(); + + @Override + public void visit(@NotNull ExpressionVisitor visitor) { + visitor.handleMonoOperator(this); + } + + @Override + public final void validateTypes(@NotNull TypesContext context) { + child.validateTypes(context); + + validateTypes(child.getExpressionType()); + } + + /** + * Validate the static-type of the code usage. + * @param childType the type to test. + */ + public abstract void validateTypes(@NotNull Type childType); + + public enum MonoOpeType { + NOT, + SIZE_OF + } + +} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/MulDivOperator.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/MulDivOperator.java similarity index 79% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/MulDivOperator.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/MulDivOperator.java index 8d982d50..623ca981 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/MulDivOperator.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/MulDivOperator.java @@ -1,11 +1,11 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators; -import fr.jamailun.ultimatespellsystem.dsl.errors.TypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; import org.jetbrains.annotations.NotNull; /** @@ -54,7 +54,7 @@ public void validateTypes(@NotNull Type leftType, @NotNull Type rightType, @NotN } // 3) Allow : (DURATION/LOCATION/NUMBER) with (NUMBER) - if(leftType.is(TypePrimitive.DURATION) || leftType.is(TypePrimitive.LOCATION) || leftType.is(TypePrimitive.NUMBER)) { + if(leftType.is(TypePrimitive.DURATION) || leftType.is(TypePrimitive.NUMBER)) { producedType = leftType; return; } diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/NotOperator.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/NotOperator.java similarity index 73% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/NotOperator.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/NotOperator.java index dcfb4b78..327bbba1 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/NotOperator.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/NotOperator.java @@ -1,10 +1,10 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators; -import fr.jamailun.ultimatespellsystem.dsl.errors.TypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; import org.jetbrains.annotations.NotNull; /** diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/Operator.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/Operator.java similarity index 52% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/Operator.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/Operator.java index 8d3f931f..af8ccb17 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/Operator.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/Operator.java @@ -1,9 +1,10 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators; -import fr.jamailun.ultimatespellsystem.dsl.errors.TypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.errors.SyntaxException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; import org.jetbrains.annotations.NotNull; /** @@ -29,10 +30,10 @@ protected Operator(@NotNull TokenPosition position) { * @param a type to use. */ protected void assertNotMathIncompatible(@NotNull Type a) { - switch (a.primitive()) { - case NULL, BOOLEAN, ENTITY_TYPE, ENTITY, STRING - -> throw new TypeException(this, "has type " + getExpressionType() + ". Type incompatible with a math operator."); - default -> {/* Nothing*/} + //TODO FIXME !! + boolean canBeAdded = a.is(TypePrimitive.DURATION) || a.is(TypePrimitive.NUMBER); + if(!canBeAdded) { + throw new SyntaxException(firstTokenPosition(), "The type " + a + " cannot be added."); } } diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/SizeOfOperator.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/SizeOfOperator.java new file mode 100644 index 00000000..740d9286 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/SizeOfOperator.java @@ -0,0 +1,60 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators; + + +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.PreviousIndicator; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenType; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; + +/** + * Size of a collection. + */ +@Getter +public class SizeOfOperator extends MonoOperator { + + protected SizeOfOperator(TokenPosition position, ExpressionNode child) { + super(position, child); + } + + @Override + public void validateTypes(@NotNull Type childType) { + // Just needs to be a collection ! + if( ! childType.isCollection()) { + throw new TypeException(this, "A SIZE_OF can only handle collections."); + } + } + + @Override + public @NotNull MonoOpeType getType() { + return MonoOpeType.SIZE_OF; + } + + @Override + public @NotNull Type getExpressionType() { + return TypePrimitive.NUMBER.asType(); + } + + @PreviousIndicator(expected = TokenType.SIZE_OF) + public static @NotNull SizeOfOperator parseSizeOf(@NotNull TokenStream tokens) { + TokenPosition position = tokens.position(); + boolean parenthesis = tokens.dropOptional(TokenType.BRACKET_OPEN); + + ExpressionNode child = ExpressionNode.readNextExpression(tokens); + + if(parenthesis) + tokens.dropOrThrow(TokenType.BRACKET_CLOSE, "Need a parenthesis to close the size-of operator."); + + return new SizeOfOperator(position, child); + } + + @Override + public String toString() { + return "size_of(" + child + ")"; + } +} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/SubOperator.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/SubOperator.java similarity index 63% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/SubOperator.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/SubOperator.java index 0152131d..7fa39e60 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/expressions/operators/SubOperator.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/expressions/operators/SubOperator.java @@ -1,11 +1,11 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators; - -import fr.jamailun.ultimatespellsystem.dsl.errors.TypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -29,7 +29,11 @@ public SubOperator(TokenPosition pos, ExpressionNode left, ExpressionNode right) return BiOpeType.SUB; } - private final static List ALLOWED = List.of(TypePrimitive.NUMBER, TypePrimitive.DURATION, TypePrimitive.LOCATION); + private final static List ALLOWED = List.of( + Type.of(TypePrimitive.NUMBER), + Type.of(TypePrimitive.DURATION), + Type.of(TypePrimitive.LOCATION) + ); @Override public void validateTypes(@NotNull Type leftType, @NotNull Type rightType, @NotNull TypesContext context) { @@ -38,13 +42,13 @@ public void validateTypes(@NotNull Type leftType, @NotNull Type rightType, @NotN throw new TypeException(this, "A NEGATION cannot handle collections."); } - if(!ALLOWED.contains(leftType.primitive())) + if(!leftType.isOneOf(ALLOWED)) throw new TypeException(this, "SUB cannot handle L=" + leftType); - if(!ALLOWED.contains(rightType.primitive())) + if(!rightType.isOneOf(ALLOWED)) throw new TypeException(this, "SUB cannot handle R=" + rightType); // Otherwise same type : always compatible - if(leftType.primitive() == rightType.primitive()) { + if(leftType.equals(rightType)) { producedType = leftType; return; } diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/AffectationStatement.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/AffectationStatement.java new file mode 100644 index 00000000..75ee0e84 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/AffectationStatement.java @@ -0,0 +1,76 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes.statements; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.ReferenceExpression; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenType; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.StatementVisitor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +/** + * Set a variable value. + */ +@Getter +@RequiredArgsConstructor +public class AffectationStatement extends StatementNode { + + private final ExpressionNode valueHolder; + private final ExpressionNode expression; + + @Override + public void validateTypes(@NotNull TypesContext context) { + // Validate right expression + expression.validateTypes(context); + Type typeRight = expression.getExpressionType(); + + // Validate left (propagate if needed) + valueHolder.validateTypes(context); + Type leftType = valueHolder.getExpressionType(); + + // If left is NULL : only happens with a VAR declaration + if(leftType.isNull()) { + // is it an assignment + if(valueHolder instanceof ReferenceExpression ref) { + ref.signalType(leftType); + } + return; + } + + // Left is not NULL (it's as such explicit) + if(!Objects.equals(leftType, typeRight)) { + throw new TypeException(expression, "Assignment for " + valueHolder + " expected " + leftType + ". Expression is of type " + typeRight); + } + } + + @Override + public void visit(@NotNull StatementVisitor visitor) { + visitor.handleAffectVariable(this); + } + + @Override + public @NotNull String toString() { + return valueHolder + " = " + expression; + } + + /** + * Parse a define statement. + * @param tokens streams of tokens. + * @return a new instance. + */ + public static @NotNull StatementNode parseNextDefine(@NotNull ExpressionNode affected, @NotNull TokenStream tokens) { + ExpressionNode expression = ExpressionNode.readNextExpression(tokens); + + // optional ; + tokens.dropOptional(TokenType.SEMI_COLON); + + return new AffectationStatement(affected, expression); + } +} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/BlockStatement.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/BlockStatement.java similarity index 76% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/BlockStatement.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/BlockStatement.java index 9ce0ac4a..bed2e1a8 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/BlockStatement.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/BlockStatement.java @@ -1,11 +1,11 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.statements; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.PreviousIndicator; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenType; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.StatementVisitor; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/BreakContinueStatement.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/BreakContinueStatement.java similarity index 68% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/BreakContinueStatement.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/BreakContinueStatement.java index 33e2f6bf..981666e1 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/BreakContinueStatement.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/BreakContinueStatement.java @@ -1,11 +1,11 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.statements; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.PreviousIndicator; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenType; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.StatementVisitor; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/DeclareNewVariableStatement.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/DeclareNewVariableStatement.java new file mode 100644 index 00000000..396eceb0 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/DeclareNewVariableStatement.java @@ -0,0 +1,79 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes.statements; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.SyntaxException; +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.StatementVisitor; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +/** + * Define statement will set a variable to something. + */ +@Getter +public class DeclareNewVariableStatement extends StatementNode { + + private final @NotNull TokenPosition position; + private final @Nullable String varType; + private final @NotNull String varName; + private final @Nullable ExpressionNode expression; + + private Type compiledType; + + public DeclareNewVariableStatement(@Nullable Token varType, @NotNull Token varName, @Nullable ExpressionNode expression) { + this.position = varName.pos(); + this.varType = varType == null ? null : varType.getContentString(); + this.varName = varName.getContentString(); + this.expression = expression; + } + + @Override + public void validateTypes(@NotNull TypesContext context) { + // 1. Check the variable does not already exist ? + var existingVariable = context.findVariable(varName); + if(existingVariable != null) { + throw new SyntaxException(position, "Variable '" + varName + "' is already set."); + } + + // 2. At least the type or the expression must be defined + if(varType == null && expression == null) { + throw new SyntaxException(position, "Variable '" + varName + "' cannot use the 'var' keyword without direct assignation."); + } + + // 3. Validate expression if possible. + if(expression != null) { + expression.validateTypes(context); + compiledType = expression.getExpressionType(); + } else { + compiledType = Type.ofAny(varType); + } + + // 4. If the type is explicit, check it matches + if(varType != null) { + if(!Objects.equals(Type.ofAny(varType), compiledType)) { + throw new TypeException(position, "Assignment for " + varName + " expected " + varType + ". Expression is of type " + compiledType); + } + } + + // 5. Register the variable + context.registerVariable(position, varName, compiledType); + } + + @Override + public void visit(@NotNull StatementVisitor visitor) { + visitor.handleDeclareVariable(this); + } + + @Override + public String toString() { + return Objects.requireNonNullElse(varType, "VAR") + " " + varName + (expression == null ? "" : " = " + expression); + } +} diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/FunctionDeclarationStatement.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/FunctionDeclarationStatement.java new file mode 100644 index 00000000..7899487e --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/FunctionDeclarationStatement.java @@ -0,0 +1,115 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes.statements; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.SyntaxException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Token; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenType; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.StatementVisitor; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +@Getter +@AllArgsConstructor +public class FunctionDeclarationStatement extends StatementNode { + + private final @NotNull TokenPosition position; + private final String functionReturnType; + private final String functionName; + private final List parameters; + private final List statements; + + public @NotNull FunctionDefinition asDefinition() { + return new FunctionDefinition( + functionName, + Type.ofAny(functionReturnType), + parameters.stream().map(FunctionParameter::asArgument).toList() + ); + } + + @Override + public void visit(@NotNull StatementVisitor visitor) { + visitor.handleFunctionDeclaration(this); + } + + public @NotNull Type getOutputType() { + return Type.ofAny(functionReturnType); + } + + @Override + public void validateTypes(@NotNull TypesContext context) { + // 1. Check function does not already exist + FunctionDefinition existingFunction = context.findFunction(functionName); + if (existingFunction != null) { + throw new SyntaxException(position, "The function '" + functionName + "' has already been defined. Signature is " + existingFunction); + } + + // 2. Register function and variables ! + context.registerFunction(this); + for(FunctionParameter parameter : parameters) { + context.registerVariable(position, parameter.name, parameter.getType()); + } + + // 3. Propagate to children + TypesContext child = context.childContext(); + for(StatementNode statement : statements) { + statement.validateTypes(child); + } + } + + public static @NotNull FunctionDeclarationStatement parseNextFunction(@NotNull Token typeIdentifier, @NotNull Token nameIdentifier, @NotNull TokenStream tokens) { + String functionReturnType = typeIdentifier.getContentString(); + String functionName = nameIdentifier.getContentString(); + + // on a déjà retiré le '('. + + List parameters = new ArrayList<>(); + boolean first = true; + while(! tokens.dropOptional(TokenType.BRACKET_CLOSE)) { + if(first) first = false; else tokens.dropOrThrow(TokenType.COMMA, "Arguments need to be separated by a comma."); + // Each parameter + Token identifierType = tokens.nextOrThrow(TokenType.IDENTIFIER, "Missing parameter type in function '" + functionName + "'."); + Token identifierName = tokens.nextOrThrow(TokenType.IDENTIFIER, "Missing parameter name in function '" + functionName + "'."); + parameters.add(new FunctionParameter(identifierType.getContentString(), identifierName.getContentString())); + } + + // On ne veut pas un 'block-statement' mais nécessairement des statements + tokens.dropOrThrow(TokenType.BRACES_OPEN, "A function need to have statements !"); + List statements = new ArrayList<>(); + while(! tokens.dropOptional(TokenType.BRACES_CLOSE)) { + statements.add(StatementNode.parseNextStatement(tokens)); + tokens.dropOptional(TokenType.SEMI_COLON); + } + + return new FunctionDeclarationStatement(typeIdentifier.pos(), functionReturnType, functionName, parameters, statements); + } + + public record FunctionParameter(@NotNull String type, @NotNull String name) { + public @NotNull Type getType() { + return Type.ofAny(type); + } + @Contract(" -> new") + public @NotNull FunctionArgument asArgument() { + return new FunctionArgument(Type.ofAny(type), name, false); + } + } + + @Override + public String toString() { + return "FUNCTION " + functionReturnType + " " + functionName + "(" + + parameters.toString() + + ") {" + + statements.toString() + + "}"; + } +} diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/ReturnStatement.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/ReturnStatement.java new file mode 100644 index 00000000..004f081f --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/ReturnStatement.java @@ -0,0 +1,65 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes.statements; + +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.PreviousIndicator; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenType; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.StatementVisitor; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * A {@code stop} statement will stop the spell execution. + */ +@AllArgsConstructor +@Getter +public class ReturnStatement extends StatementNode { + + private final TokenPosition pos; + private final @Nullable ExpressionNode exitCodeNode; + + @Override + public void validateTypes(@NotNull TypesContext context) { + if(exitCodeNode != null) + exitCodeNode.validateTypes(context); + } + + public @Nullable Type getReturnType() { + if(exitCodeNode != null) + return exitCodeNode.getExpressionType(); + return Type.NULL; + } + + @Override + public void visit(@NotNull StatementVisitor visitor) { + visitor.handleReturn(this); + } + + /** + * Parse a STOP statement. + * @param tokens streams of tokens. + * @return a new instance. + */ + @PreviousIndicator(expected = TokenType.RETURN) + public static @NotNull ReturnStatement parseReturn(@NotNull TokenStream tokens) { + TokenPosition pos = tokens.previousPos(); + if(tokens.dropOptional(TokenType.SEMI_COLON)) { + return new ReturnStatement(pos, null); + } else { + ExpressionNode exitNode = ExpressionNode.readNextExpression(tokens); + tokens.dropOrThrow(TokenType.SEMI_COLON, "Expected a semi-colon after a RETURN statement value."); + return new ReturnStatement(pos, exitNode); + } + } + + @Override + public String toString() { + return "RETURN" + (exitCodeNode==null?"":"(" + exitCodeNode + ")"); + } +} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SimpleExpressionStatement.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/SimpleExpressionStatement.java similarity index 70% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SimpleExpressionStatement.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/SimpleExpressionStatement.java index 92bd77ff..feac0bdb 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/SimpleExpressionStatement.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/SimpleExpressionStatement.java @@ -1,9 +1,9 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.statements; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.StatementVisitor; import lombok.Getter; import org.jetbrains.annotations.NotNull; diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/BlockHolder.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/blocks/BlockHolder.java similarity index 77% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/BlockHolder.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/blocks/BlockHolder.java index 299c25ec..26b5c81a 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/BlockHolder.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/blocks/BlockHolder.java @@ -1,7 +1,7 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements.blocks; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.statements.BlockStatement; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.BlockStatement; import org.jetbrains.annotations.NotNull; import java.util.List; diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/ForLoopStatement.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/blocks/ForLoopStatement.java similarity index 67% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/ForLoopStatement.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/blocks/ForLoopStatement.java index 8b236bce..16ff4219 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/ForLoopStatement.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/blocks/ForLoopStatement.java @@ -1,14 +1,14 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements.blocks; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.CollectionFilter; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.PreviousIndicator; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenType; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.StatementVisitor; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; @@ -47,7 +47,7 @@ public void visit(@NotNull StatementVisitor visitor) { */ @PreviousIndicator(expected = TokenType.FOR) public static @NotNull ForLoopStatement parseForLoop(@NotNull TokenStream tokens) { - tokens.dropOrThrow(TokenType.BRACKET_OPEN); + tokens.dropOrThrow(TokenType.BRACKET_OPEN, "This is not Python. A '(' is required after a FOR keyword."); // Optional init StatementNode init; @@ -60,7 +60,7 @@ public void visit(@NotNull StatementVisitor visitor) { // Required condition ExpressionNode condition = ExpressionNode.readNextExpression(tokens); - tokens.dropOrThrow(TokenType.SEMI_COLON); + tokens.dropOrThrow(TokenType.SEMI_COLON, "A semi-colo (';') is required between FOR definition statements."); // Optional iteration StatementNode iterator; @@ -68,7 +68,7 @@ public void visit(@NotNull StatementVisitor visitor) { iterator = null; } else { iterator = StatementNode.parseNextStatement(tokens); - tokens.dropOrThrow(TokenType.BRACKET_CLOSE); + tokens.dropOrThrow(TokenType.BRACKET_CLOSE, "Expected a ')' after the last FOR definition statements."); } StatementNode child = StatementNode.parseNextStatement(tokens); diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/IfElseStatement.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/blocks/IfElseStatement.java similarity index 68% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/IfElseStatement.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/blocks/IfElseStatement.java index d0b30ad2..d753cf56 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/IfElseStatement.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/blocks/IfElseStatement.java @@ -1,14 +1,14 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements.blocks; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.CollectionFilter; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.PreviousIndicator; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenType; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.StatementVisitor; import lombok.Getter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -54,9 +54,9 @@ public void visit(@NotNull StatementVisitor visitor) { @PreviousIndicator(expected = TokenType.IF) public static @NotNull IfElseStatement parseIfStatement(@NotNull TokenStream tokens) { // Condition - tokens.dropOrThrow(TokenType.BRACKET_OPEN); + tokens.dropOrThrow(TokenType.BRACKET_OPEN, "This is not Python, a '(' is required after the IF keyword."); ExpressionNode condition = ExpressionNode.readNextExpression(tokens); - tokens.dropOrThrow(TokenType.BRACKET_CLOSE); + tokens.dropOrThrow(TokenType.BRACKET_CLOSE, "A ')' is expected after the IF condition."); // Content StatementNode child = StatementNode.parseNextStatement(tokens); diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/WhileLoopStatement.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/blocks/WhileLoopStatement.java similarity index 61% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/WhileLoopStatement.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/blocks/WhileLoopStatement.java index fc9a4b56..5669b20d 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/statements/blocks/WhileLoopStatement.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/statements/blocks/WhileLoopStatement.java @@ -1,14 +1,14 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.statements.blocks; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.CollectionFilter; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.PreviousIndicator; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.CollectionFilter; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.PreviousIndicator; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenType; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.StatementVisitor; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; @@ -48,18 +48,18 @@ public static WhileLoopStatement parseWhileLoop(TokenStream tokens, boolean wasW ExpressionNode condition = null; if(wasWhile) { - tokens.dropOrThrow(TokenType.BRACKET_OPEN); + tokens.dropOrThrow(TokenType.BRACKET_OPEN, "A '(' is required after a WHILE keyword."); condition = ExpressionNode.readNextExpression(tokens); - tokens.dropOrThrow(TokenType.BRACKET_CLOSE); + tokens.dropOrThrow(TokenType.BRACKET_CLOSE, "A ')' is required after a WHILE condition."); } StatementNode child = StatementNode.parseNextStatement(tokens); if( ! wasWhile) { - tokens.dropOrThrow(TokenType.WHILE); - tokens.dropOrThrow(TokenType.BRACKET_OPEN); + tokens.dropOrThrow(TokenType.WHILE, "A WHILE keyword is expected after a DO statement."); + tokens.dropOrThrow(TokenType.BRACKET_OPEN, "A '(' is required after a DO keyword."); condition = ExpressionNode.readNextExpression(tokens); - tokens.dropOrThrow(TokenType.BRACKET_CLOSE); + tokens.dropOrThrow(TokenType.BRACKET_CLOSE, "A ')' is required after a DO condition."); tokens.dropOptional(TokenType.SEMI_COLON); } diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/CollectionFilter.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/CollectionFilter.java similarity index 92% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/CollectionFilter.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/CollectionFilter.java index 3653cb36..f7b51a8b 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/CollectionFilter.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/CollectionFilter.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.type; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.type; import org.jetbrains.annotations.NotNull; diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/Duration.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/Duration.java similarity index 98% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/Duration.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/Duration.java index 5e99023d..d36c9225 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/Duration.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/Duration.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.type; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.type; import com.google.common.base.Preconditions; import org.jetbrains.annotations.Contract; diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/SpellEntity.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/SpellEntity.java similarity index 96% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/SpellEntity.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/SpellEntity.java index 9dbb552d..35a7e874 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/SpellEntity.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/SpellEntity.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.type; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.type; import net.kyori.adventure.text.Component; import org.bukkit.Location; diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/Type.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/Type.java new file mode 100644 index 00000000..80d4aa2a --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/Type.java @@ -0,0 +1,144 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes.type; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Objects; +import java.util.Set; + +/** + * Represents the type of expression. + */ +public class Type { + + private final @Nullable TypePrimitive primitive; + private final @Nullable String objectClass; + private final boolean isNull; + private final int arrayLevel; + + /** + * The null value. + */ + public static final Type NULL = new Type(null, null, 0); + + public Type(@NotNull TypePrimitive primitive, int arrayLevel) { + this.primitive = primitive; + this.objectClass = null; + this.arrayLevel = arrayLevel; + this.isNull = false; + } + + public Type(@NotNull String objectClass, int arrayLevel) { + this.primitive = null; + this.objectClass = objectClass; + this.arrayLevel = arrayLevel; + this.isNull = false; + } + + private Type(@Nullable TypePrimitive primitive, @Nullable String objectClass, int arrayLevel) { + this.primitive = primitive; + this.objectClass = objectClass; + this.arrayLevel = arrayLevel; + this.isNull = (primitive == null && objectClass == null); + } + + /** + * Check if this type is of a primitive. + * @param primitive the primitive to compare this type with. + * @return true if the primitives are equals. + */ + public boolean is(@NotNull TypePrimitive primitive) { + return this.primitive != null && this.primitive == primitive; + } + + public boolean isOneOf(@NotNull TypePrimitive... primitives) { + if(this.primitive == null) return false; + return Set.of(primitives).contains(primitive); + } + + public boolean isOneOf(@NotNull Collection types) { + return types.stream().anyMatch(this::equals); + } + + public boolean is(@NotNull String objectClass) { + return this.objectClass != null && this.objectClass.equals(objectClass); + } + + public boolean is(@NotNull Type type) { + return this.equals(type); + } + + public boolean isCollection() { + return arrayLevel > 0; + } + + public boolean isNull() { + return isNull; + } + + public boolean isPrimitive() { + return primitive != null; + } + + @Contract(pure = true) + public @NotNull Type popArray() { + return new Type(primitive, objectClass, Math.max(0, arrayLevel - 1)); + } + + @Contract(pure = true) + public @NotNull Type pushArray() { + return new Type(primitive, objectClass, arrayLevel + 1); + } + + public @NotNull String getName() { + return primitive == null ? Objects.requireNonNull(objectClass) : primitive.name().toLowerCase(); + } + + @Contract(pure = true) + @Override + public @NotNull String toString() { + String arraySuffix = "[]".repeat(arrayLevel); + return (primitive==null?objectClass: primitive.name()) + arraySuffix; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + Type type = (Type) o; + return arrayLevel == type.arrayLevel && primitive == type.primitive && Objects.equals(objectClass, type.objectClass); + } + + @Override + public int hashCode() { + return Objects.hash(primitive, objectClass, arrayLevel); + } + + public static @NotNull Type of(@NotNull String name) { + return new Type(name, 0); + } + public static @NotNull Type of(@NotNull TypePrimitive name) { + return new Type(name, 0); + } + + /** + * Get the {@link Type} of an identifier. + * @param name the identifier to use. + * @return a non-null Type, either with a primitive or not. + */ + public static @NotNull Type ofAny(@NotNull String name) { + if("null".equals(name) || "void".equals(name)) return NULL; + TypePrimitive primitive = TypePrimitive.parsePrimitive(name); + return primitive == null ? Type.of(name) : Type.of(primitive); + } + + /** + * Test if a type is like this one, ignoring array level. + * @param other other object. + * @return true if types are similar. + */ + public boolean isLike(@NotNull Type other) { + return Objects.equals(other.objectClass, objectClass) || Objects.equals(other.primitive, primitive); + } +} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/TypePrimitive.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/TypePrimitive.java similarity index 61% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/TypePrimitive.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/TypePrimitive.java index 45cf2437..859e3395 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/TypePrimitive.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/TypePrimitive.java @@ -1,10 +1,14 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.type; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.type; import org.bukkit.Location; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; + /** * Enumeration of a possible types. */ @@ -13,28 +17,24 @@ public enum TypePrimitive { // Real Primitives /** A String primitive. */ STRING(String.class), + /** A number primitive. */ NUMBER(Number.class), + /** A boolean primitive. */ BOOLEAN(Boolean.class), - // In-game /** A temporal duration. */ DURATION(Duration.class), - /** An in-game entity. */ - ENTITY(SpellEntity.class), - /** A Bukkit entity-type. */ - ENTITY_TYPE(String.class), - /** A Bukkit location. */ + + ENTITY, + LOCATION(Location.class), - // Specials - /** A map of properties. */ - PROPERTIES_SET, - /** A string for custom values. */ - CUSTOM(String.class), - /** A {@code null} value. */ - NULL; + VECTOR(Vector.class), + + MAP(Map.class) + ; public final Class clazz; @@ -50,7 +50,7 @@ public enum TypePrimitive { * @return a new, non-null Type instance. */ public @NotNull Type asType() { - return new Type(this, false); + return new Type(this, 0); } /** @@ -60,7 +60,7 @@ public enum TypePrimitive { */ @Contract("_ -> new") public @NotNull Type asType(boolean collection) { - return new Type(this, collection); + return new Type(this, collection ? 1 : 0); } /** @@ -74,14 +74,31 @@ public enum TypePrimitive { case "number", "double", "float", "integer", "int", "short", "byte" -> NUMBER; case "boolean", "bool" -> BOOLEAN; case "duration", "time", "chrono" -> DURATION; - case "entity", "living_entity", "living-entity", "living" -> ENTITY; - case "entity_type" -> ENTITY_TYPE; - case "null" -> NULL; - case "loc", "location", "position", "pos" -> LOCATION; - case "map", "data", "properties", "properties-set", "properties_set" -> PROPERTIES_SET; - case "custom", "?", "any" -> CUSTOM; + case "map", "data", "properties", "properties-set", "properties_set" -> MAP; default -> null; }; } + public static @NotNull Map getTypesMap() { + Map map = new HashMap<>(); + for (TypePrimitive primitive : TypePrimitive.values()) { + if(primitive.clazz != null) + map.put(primitive.name().toLowerCase(), primitive.asType()); + } + return map; + } + + public boolean canImplicitCastTo(@NotNull TypePrimitive other) { + if(this == other || this == STRING) return true; + + return switch (other) { + case STRING -> true; + // location required ? we can always get it from the entity. + case LOCATION -> this == ENTITY; + // Vector needed ? We can still get it from the location / entity + case VECTOR -> this == LOCATION || this == ENTITY; + default -> false; + }; + } + } diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/variables/TypesContext.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/variables/TypesContext.java new file mode 100644 index 00000000..29530511 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/variables/TypesContext.java @@ -0,0 +1,138 @@ +package fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.SyntaxException; +import fr.jamailun.ultimatespellsystem.dsl2.library.ObjectsLibrary; +import fr.jamailun.ultimatespellsystem.dsl2.library.StructDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.library.structs.ConsoleStruct; +import fr.jamailun.ultimatespellsystem.dsl2.library.structs.EntityStruct; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.FunctionDeclarationStatement; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.registries.FunctionDefinitionsRegistry; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +/** + * A context for type validation. + */ +public class TypesContext { + + private final Map vars = new HashMap<>(); + private final ObjectsLibrary objectsLibrary; + + /** + * Create a new context.
+ * The variable {@code caster} will be registered. + */ + public TypesContext() { + this.objectsLibrary = new ObjectsLibrary(true); + promiseVariable("caster", Type.of(EntityStruct.NAME)); + promiseVariable("console", Type.of(ConsoleStruct.NAME)); + } + + /** + * Create a new context. + * @param objectsLibrary reference library to use. + */ + private TypesContext(@NotNull ObjectsLibrary objectsLibrary) { + this.objectsLibrary = objectsLibrary; + } + + /** + * Register a new variable. + * @param varName the name of the variable. + * @param variable the expression defining the variable. + */ + public void registerVariable(@NotNull String varName, @NotNull ExpressionNode variable) { + if("caster".equals(varName)) { + throw new SyntaxException(variable.firstTokenPosition(), "Cannot override variable '%" + varName + "'."); + } + + vars.putIfAbsent(varName, new VariableDefinition(varName)); + vars.get(varName).register(new VariableReference.Dynamic(variable)); + vars.get(varName).getType(this); + } + + /** + * Guarantee a variable will be set by a runtime implementation. + * @param name the name of the variable. + * @param type the type of the variable. + */ + public void promiseVariable(@NotNull String name, @NotNull Type type) { + vars.putIfAbsent(name, new VariableDefinition(name)); + vars.get(name).register(new VariableReference.Constant(type, TokenPosition.unknown())); + } + + /** + * Register a variable, with an already guaranteed type. + * @param varName the variable name. + * @param position the position of the declaration. + * @param type the type of variable. + */ + public void registerVariable(@NotNull TokenPosition position, @NotNull String varName, @NotNull Type type) { + if("caster".equals(varName)) { + throw new SyntaxException(position, "Cannot override variable '" + varName + "'."); + } + + vars.putIfAbsent(varName, new VariableDefinition(varName)); + vars.get(varName).register(new VariableReference.Constant(type, position)); + } + + /** + * Lookup for a specific variable. + * @param varName the name of the variable to look for. + * @return {@code null} if nothing was found. + */ + public @Nullable VariableDefinition findVariable(@NotNull String varName) { + return vars.get(varName); + } + + public @Nullable Type findType(@NotNull String name) { + return objectsLibrary.getType(name); + } + + public @Nullable FunctionDefinition findFunction(@NotNull String name) { + FunctionDeclarationStatement local = objectsLibrary.getFunction(name); + if(local == null) + return FunctionDefinitionsRegistry.find(name); + return local.asDefinition(); + } + + public @Nullable StructDefinition findStruct(@NotNull String name) { + return objectsLibrary.getStruct(name); + } + + public @Nullable StructDefinition findStruct(@NotNull Type type) { + if(type.isPrimitive()) { + //TODO specialized structs ? + return null; + } + return objectsLibrary.getStruct(type.getName()); + } + + /** + * Register a new function to the context + * @param declaration the declaration to use. + */ + public void registerFunction(@NotNull FunctionDeclarationStatement declaration) { + objectsLibrary.registerFunction(declaration); + } + + /** + * Create a new context. This allows sub-scopes to be independents. + * @return a new instance of context, copying the current variables. + */ + @Contract(" -> new") + public @NotNull TypesContext childContext() { + TypesContext child = new TypesContext(objectsLibrary); + child.vars.putAll(vars); + return child; + } + +} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/variables/VariableDefinition.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/variables/VariableDefinition.java similarity index 71% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/variables/VariableDefinition.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/variables/VariableDefinition.java index 3412f072..a0f36e5c 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/variables/VariableDefinition.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/variables/VariableDefinition.java @@ -1,7 +1,6 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; @@ -32,7 +31,7 @@ public void register(@NotNull VariableReference reference) { /** * Get the representation type of this variable. * @param context current context. - * @return a {@link TypePrimitive#NULL} type if unset. + * @return a {@link Type#NULL} type if unset. */ public @NotNull Type getType(@NotNull TypesContext context) { if(computedType != null) return computedType; @@ -40,20 +39,20 @@ public void register(@NotNull VariableReference reference) { // We need ot compute the type for(VariableReference reference : references) { Type type = reference.getType(context); - if(type.is(TypePrimitive.NULL) && !type.isCollection()) { + if(type.isNull() && !type.isCollection()) { // Nothing here continue; } - if(computedType == null || computedType.is(TypePrimitive.NULL)) { + if(computedType == null || computedType.isNull()) { computedType = type; // We CAN overload a variable that as NULL. - } else if(!computedType.is(TypePrimitive.NULL) && ! computedType.equals(type)) { + } else if(!computedType.isNull() && ! computedType.equals(type)) { throw reference.exception("Cannot change type of an already defined variable (%"+name+"). Previous type: " + computedType + ", new type: " + type + "."); } } // If type not set, then it's a NULL. - return Objects.requireNonNullElseGet(computedType, TypePrimitive.NULL::asType); + return Objects.requireNonNullElse(computedType, Type.NULL); } } diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/variables/VariableReference.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/variables/VariableReference.java similarity index 86% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/variables/VariableReference.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/variables/VariableReference.java index fa417be1..39627438 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/variables/VariableReference.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/variables/VariableReference.java @@ -1,9 +1,9 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables; -import fr.jamailun.ultimatespellsystem.dsl.errors.TypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/registries/CallbackEventRegistry.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/registries/CallbackEventRegistry.java similarity index 92% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/registries/CallbackEventRegistry.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/registries/CallbackEventRegistry.java index 874ce84d..0c0703ca 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/registries/CallbackEventRegistry.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/registries/CallbackEventRegistry.java @@ -1,6 +1,6 @@ -package fr.jamailun.ultimatespellsystem.dsl.registries; +package fr.jamailun.ultimatespellsystem.dsl2.registries; -import fr.jamailun.ultimatespellsystem.dsl.objects.CallbackEvent; +import fr.jamailun.ultimatespellsystem.dsl2.callbacks.CallbackEvent; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/registries/EntityTypeRegistry.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/registries/EntityTypeRegistry.java similarity index 97% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/registries/EntityTypeRegistry.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/registries/EntityTypeRegistry.java index 262e89b5..6f1680a4 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/registries/EntityTypeRegistry.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/registries/EntityTypeRegistry.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.dsl.registries; +package fr.jamailun.ultimatespellsystem.dsl2.registries; import org.bukkit.entity.EntityType; import org.jetbrains.annotations.NotNull; diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/registries/FunctionDefinitionsRegistry.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/registries/FunctionDefinitionsRegistry.java similarity index 91% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/registries/FunctionDefinitionsRegistry.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/registries/FunctionDefinitionsRegistry.java index 0b969e0d..1f9738fc 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/registries/FunctionDefinitionsRegistry.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/registries/FunctionDefinitionsRegistry.java @@ -1,6 +1,6 @@ -package fr.jamailun.ultimatespellsystem.dsl.registries; +package fr.jamailun.ultimatespellsystem.dsl2.registries; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionDefinition; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/registries/ObjectsDefinitionRegistry.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/registries/ObjectsDefinitionRegistry.java new file mode 100644 index 00000000..a5648af6 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/registries/ObjectsDefinitionRegistry.java @@ -0,0 +1,54 @@ +package fr.jamailun.ultimatespellsystem.dsl2.registries; + +import fr.jamailun.ultimatespellsystem.dsl2.library.StructDefinition; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Register for all default {@link StructDefinition}. + */ +public final class ObjectsDefinitionRegistry { + private ObjectsDefinitionRegistry() {/* private */} + + private static final Map DEFAULT_STRUCTS = new HashMap<>(); + + /** + * Register a new struct. + * @param definition non-null definition to use. + */ + public static void registerDefaultStruct(@NotNull StructDefinition definition) { + DEFAULT_STRUCTS.put(definition.getName(), definition); + } + + /** + * Get the registered names. + * @return a non-null view on the IDs. + */ + public static @NotNull @UnmodifiableView Collection getDefaultStructsNames() { + return Collections.unmodifiableCollection(DEFAULT_STRUCTS.keySet()); + } + + /** + * Get the registered structs. + * @return a non-null view on the values. + */ + public static @NotNull @UnmodifiableView Collection getDefaultStructs() { + return Collections.unmodifiableCollection(DEFAULT_STRUCTS.values()); + } + + /** + * Get a default struct. + * @param name the name of the struct. + * @return null if ot found. + */ + public static @Nullable StructDefinition getDefaultStruct(@NotNull String name) { + return DEFAULT_STRUCTS.get(name); + } + +} diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/registries/RegistryException.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/registries/RegistryException.java similarity index 72% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/registries/RegistryException.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/registries/RegistryException.java index 03dd44e0..4c4b44b7 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/registries/RegistryException.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/registries/RegistryException.java @@ -1,7 +1,7 @@ -package fr.jamailun.ultimatespellsystem.dsl.registries; +package fr.jamailun.ultimatespellsystem.dsl2.registries; -import fr.jamailun.ultimatespellsystem.dsl.errors.UssException; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.errors.UssException; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; import org.jetbrains.annotations.NotNull; /** diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/CharStream.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/CharStream.java similarity index 97% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/CharStream.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/CharStream.java index 5259d0c4..44522347 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/CharStream.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/CharStream.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.dsl.tokenization; +package fr.jamailun.ultimatespellsystem.dsl2.tokenization; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/PreviousIndicator.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/PreviousIndicator.java similarity index 89% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/PreviousIndicator.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/PreviousIndicator.java index cd12d26a..2fbd3ad1 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/PreviousIndicator.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/PreviousIndicator.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.dsl.tokenization; +package fr.jamailun.ultimatespellsystem.dsl2.tokenization; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/Token.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/Token.java similarity index 67% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/Token.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/Token.java index 1291dc9c..d09743e6 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/Token.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/Token.java @@ -1,9 +1,10 @@ -package fr.jamailun.ultimatespellsystem.dsl.tokenization; +package fr.jamailun.ultimatespellsystem.dsl2.tokenization; import com.google.common.base.Preconditions; import lombok.Getter; import org.jetbrains.annotations.NotNull; +import java.util.Objects; import java.util.concurrent.TimeUnit; /** @@ -17,6 +18,7 @@ public class Token { private Double contentNumber; private String contentString; private TimeUnit contentTimeUnit; + private Boolean contentBoolean; /** * New token. @@ -41,26 +43,26 @@ public Token(@NotNull TokenType type, @NotNull TokenPosition position) { } /** - * New token from a variable value. + * New token from a raw identifier. * @param string textual content. * @param position token position. * @return a new instance. */ - public static @NotNull Token fromVariable(@NotNull String string, @NotNull TokenPosition position) { - Token token = new Token(TokenType.VALUE_VARIABLE, position); + public static @NotNull Token fromIdentifier(@NotNull String string, @NotNull TokenPosition position) { + Token token = new Token(TokenType.IDENTIFIER, position); token.contentString = string; return token; } /** - * New token from a raw identifier. - * @param string textual content. + * New token from a raw boolean. + * @param value boolean content. * @param position token position. * @return a new instance. */ - public static @NotNull Token fromWord(@NotNull String string, @NotNull TokenPosition position) { - Token token = new Token(TokenType.IDENTIFIER, position); - token.contentString = string; + public static @NotNull Token fromBoolean(boolean value, @NotNull TokenPosition position) { + Token token = new Token(TokenType.VALUE_BOOLEAN, position); + token.contentBoolean = value; return token; } @@ -90,18 +92,6 @@ public Token(@NotNull TokenType type, @NotNull TokenPosition position) { return token; } - /** - * Get the boolean content, if it exists. - * @return a boolean value. - */ - public boolean getContentBoolean() { - return switch (type) { - case TRUE -> true; - case FALSE -> false; - default -> throw new RuntimeException("Cannot get the BOOL content of type " + type); - }; - } - /** * Get the numerical content, if it exists. * @return a numerical value. @@ -125,10 +115,19 @@ public boolean getContentBoolean() { * @return a textual value. */ public @NotNull String getContentString() { - Preconditions.checkState(type == TokenType.VALUE_STRING || type == TokenType.VALUE_VARIABLE || type == TokenType.IDENTIFIER, "Cannot get the STRING content of type " + type); + Preconditions.checkState(type == TokenType.VALUE_STRING || type == TokenType.IDENTIFIER, "Cannot get the STRING content of type " + type); return contentString; } + /** + * Get the boolean content, if it exists. + * @return a boolean value. + */ + public boolean getContentBoolean() { + Preconditions.checkState(type == TokenType.VALUE_BOOLEAN, "Cannot get the BOOLEAN content of type " + type); + return contentBoolean; + } + /** * Get the token position. * @return a non-null position instance. @@ -139,18 +138,29 @@ public boolean getContentBoolean() { @Override public String toString() { - if(type == TokenType.IDENTIFIER) { - return "[" + contentString + "]"; - } - if(type == TokenType.VALUE_DURATION) { - return type + "(" + contentNumber + " " + contentTimeUnit + ")"; - } - if(type == TokenType.VALUE_VARIABLE || type == TokenType.VALUE_STRING) { - return type + "(\"" + contentString + "\")"; - } - if(type == TokenType.VALUE_NUMBER) { - return type + "(" + contentNumber + ")"; - } - return type.name(); + return switch (type) { + case IDENTIFIER -> "[" + contentString + "]"; + case VALUE_STRING -> type + "(\"" + contentString + "\")"; + case VALUE_NUMBER -> type + "(" + contentNumber + ")"; + case VALUE_DURATION -> type + "(" + contentNumber + " " + contentTimeUnit + ")"; + case VALUE_BOOLEAN -> type + "(" + contentBoolean + ")"; + default -> type.name(); + }; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + Token token = (Token) o; + return type == token.type + && Objects.equals(contentNumber, token.contentNumber) + && Objects.equals(contentString, token.contentString) + && contentTimeUnit == token.contentTimeUnit + && Objects.equals(contentBoolean, token.contentBoolean); + } + + @Override + public int hashCode() { + return Objects.hash(type, contentNumber, contentString, contentTimeUnit, contentBoolean); } } diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/TokenPosition.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/TokenPosition.java similarity index 91% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/TokenPosition.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/TokenPosition.java index ad5b2615..49848bf1 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/TokenPosition.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/TokenPosition.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.dsl.tokenization; +package fr.jamailun.ultimatespellsystem.dsl2.tokenization; import org.jetbrains.annotations.NotNull; diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/TokenStream.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/TokenStream.java similarity index 74% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/TokenStream.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/TokenStream.java index beb1e28d..101758b9 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/TokenStream.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/TokenStream.java @@ -1,10 +1,11 @@ -package fr.jamailun.ultimatespellsystem.dsl.tokenization; +package fr.jamailun.ultimatespellsystem.dsl2.tokenization; import com.google.common.base.Preconditions; -import fr.jamailun.ultimatespellsystem.dsl.errors.SyntaxException; +import fr.jamailun.ultimatespellsystem.dsl2.errors.SyntaxException; import org.jetbrains.annotations.NotNull; import java.util.List; +import java.util.Set; import java.util.StringJoiner; /** @@ -33,6 +34,18 @@ public TokenStream(@NotNull List tokens) { return tokens.get(index); } + /** + * Test if the next token matches a type. + * @param allowedTypes allowed types. + * @return true if the next token has a specific type. + */ + public boolean peekIs(@NotNull TokenType @NotNull ... allowedTypes) { + Preconditions.checkState(hasMore(), "No more data."); + Preconditions.checkArgument(allowedTypes.length > 0, "Must have at least 1 value."); + TokenType peeked = peek().getType(); + return Set.of(allowedTypes).contains(peeked); + } + /** * Read the next character, then move cursor to the next token. * @return a non-null token. @@ -57,6 +70,13 @@ public TokenStream(@NotNull List tokens) { return next; } + public @NotNull Token nextOrThrow(@NotNull TokenType type, @NotNull String error) { + Token next = next(); + if(next.getType() != type) + throw new SyntaxException(next, error); + return next; + } + /** * Drop the current token, move the cursor. * @throws IllegalStateException if no more data exist. @@ -77,6 +97,13 @@ public void dropOrThrow(@NotNull TokenType expectedType) { if(next.getType() != expectedType) throw new SyntaxException(next, expectedType); } + + public void dropOrThrow(@NotNull TokenType expectedType, @NotNull String error) { + Token next = next(); + if(next.getType() != expectedType) + throw new SyntaxException(next, error); + } + /** * Assert the current token is of a specific type, then drop it if it matches * @param types expected types for the current token. @@ -115,6 +142,11 @@ public boolean hasMore() { return "TokenStream{index="+index+", TOKENS = [" + sj + "] }"; } + public @NotNull TokenPosition previousPos() { + Preconditions.checkState(index > 0, "Cannot fetch previous position on start."); + return tokens.get(index - 1).pos(); + } + /** * Get the current token position. * @return the current position. diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/TokenType.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/TokenType.java similarity index 57% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/TokenType.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/TokenType.java index a55f7d1c..85940207 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/TokenType.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/TokenType.java @@ -1,4 +1,6 @@ -package fr.jamailun.ultimatespellsystem.dsl.tokenization; +package fr.jamailun.ultimatespellsystem.dsl2.tokenization; + +import org.jetbrains.annotations.NotNull; /** * Type of token. @@ -12,12 +14,15 @@ public enum TokenType { OPE_SUB, // - OPE_MUL, // * OPE_DIV, // / + OPE_MOD, // % // MonoOperators OPE_NOT, // ! + INCREMENT, // ++ + DECREMENT, // -- + SIZE_OF(true), // sizeof() // Others - ANTISLASH, // \ COLON, // : SEMI_COLON, // ; COMMA, // , @@ -31,11 +36,6 @@ public enum TokenType { BRACES_CLOSE, // } COMP_LT, // < COMP_GT, // > - PROPERTY_OPEN, // {{ - PROPERTY_CLOSE, // }} - ARRAY_OPEN, // [[ - ARRAY_CLOSE, // ]] - CHAR_AT, // @ // == BI-CHAR OPERATORS @@ -52,8 +52,8 @@ public enum TokenType { LIST_CONTAINS, // :? // == KEYWORDS + CHAR_AT, // @ - STOP(true), IF(true), ELSE(true), FOR(true), @@ -61,48 +61,19 @@ public enum TokenType { DO(true), BREAK(true), CONTINUE(true), - - DEFINE(true), - SEND(true), - TO(true), - ALL(true), - INCLUDING(true), - AROUND(true), - WITHIN(true), - RUN(true), - AFTER(true), - TIMES(true), - REPEAT(true), - EVERY(true), - SUMMON(true), - AT(true), - BY(true), - AS(true), - WITH(true), - POSITION(true), - OF(true), - TELEPORT(true), - FOREACH(true), - PLAY(true), - SIZEOF(true), - GIVE(true), - CALLBACK(true), - - INCREMENT(true), - DECREMENT(true), + RETURN(true), + VAR(true), // == RAW VALUES - TRUE(true), - FALSE(true), NULL(true), // == N-CHARS OPERATORS IDENTIFIER, // any combination of character that is NOT a string - VALUE_VARIABLE, // a WORD starting with a '%' VALUE_STRING, // combination of characters between quotes VALUE_NUMBER, VALUE_DURATION, // number+ [s/ms/m/h/seconds] + VALUE_BOOLEAN, // true/false // == END OF FILE EOF; @@ -116,17 +87,8 @@ public enum TokenType { this.letters = letters; } - public Token toToken(TokenPosition position) { + public @NotNull Token toToken(@NotNull TokenPosition position) { return new Token(this, position); } - public boolean isRawValue() { - return this == IDENTIFIER || - this == VALUE_STRING || - this == VALUE_NUMBER || - this == VALUE_DURATION || - this == TRUE || - this == FALSE; - } - } diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/Tokenizer.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/Tokenizer.java similarity index 89% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/Tokenizer.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/Tokenizer.java index f17b9383..fa6dbe54 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/tokenization/Tokenizer.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/Tokenizer.java @@ -1,6 +1,6 @@ -package fr.jamailun.ultimatespellsystem.dsl.tokenization; +package fr.jamailun.ultimatespellsystem.dsl2.tokenization; -import fr.jamailun.ultimatespellsystem.dsl.errors.ParsingException; +import fr.jamailun.ultimatespellsystem.dsl2.errors.ParsingException; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -11,15 +11,15 @@ /** * Internal tokenizer. Transforms a string into a list of {@link Token tokens}. */ -public class Tokenizer { +public final class Tokenizer { + private final static Set OPERATOR_BI_START = Set.of('<', '>', '=', '!', '&', '|', '+', '-'); private final static Map OPERATORS_MONO = new HashMap<>(); private final static Map OPERATORS_BI = new HashMap<>(); private final static Map KEYWORDS = new HashMap<>(); private final static Map TIME_UNITS = new HashMap<>(); static { OPERATORS_MONO.put('/', TokenType.OPE_DIV); - OPERATORS_MONO.put('\\', TokenType.ANTISLASH); OPERATORS_MONO.put('+', TokenType.OPE_ADD); OPERATORS_MONO.put('-', TokenType.OPE_SUB); OPERATORS_MONO.put('*', TokenType.OPE_MUL); @@ -43,17 +43,15 @@ public class Tokenizer { OPERATORS_BI.put(">=", TokenType.COMP_GE); OPERATORS_BI.put("==", TokenType.COMP_EQ); OPERATORS_BI.put("!=", TokenType.COMP_NE); - OPERATORS_BI.put("{{", TokenType.PROPERTY_OPEN); - OPERATORS_BI.put("}}", TokenType.PROPERTY_CLOSE); OPERATORS_BI.put("&&", TokenType.OPE_AND); OPERATORS_BI.put("||", TokenType.OPE_OR); - OPERATORS_BI.put("[[", TokenType.ARRAY_OPEN); - OPERATORS_BI.put("]]", TokenType.ARRAY_CLOSE); + OPERATORS_BI.put("++", TokenType.INCREMENT); + OPERATORS_BI.put("--", TokenType.DECREMENT); OPERATORS_BI.put(":+", TokenType.LIST_ADD); - OPERATORS_BI.put(":?", TokenType.LIST_CONTAINS); OPERATORS_BI.put(":-", TokenType.LIST_REM); OPERATORS_BI.put(":/", TokenType.LIST_REM_INDEX); + OPERATORS_BI.put(":?", TokenType.LIST_CONTAINS); // words Arrays.stream(TokenType.values()) @@ -97,7 +95,7 @@ private TokenStream tokenize() { char current = chars.next(); // Whitespace-trash - if(current == '\s' || current == '\t' || current == '\r' || current == '\n') + if(current == ' ' || current == '\t' || current == '\r' || current == '\n') continue; // Comment @@ -109,7 +107,7 @@ private TokenStream tokenize() { // Basic symbols. // All bi-operators start with one of the mono... let's use this fact. // EDIT: just added AND and OR keywords start. - if(OPERATORS_MONO.containsKey(current) || current == '&' || current == '|') { + if(OPERATORS_MONO.containsKey(current) || OPERATOR_BI_START.contains(current)) { if(chars.hasMore()) { char next = chars.peek(); @@ -137,18 +135,15 @@ private TokenStream tokenize() { continue; } - if(current == '%') { - if( ! chars.hasMore()) { - throw new ParsingException(chars.pos(), current, "Cannot end file with a '%' : expected a variable name."); - } - tokens.add(Token.fromVariable(getWord(null), chars.pos())); - continue; - } - if(ALLOWED_WORD_START.test(String.valueOf(current))) { TokenPosition position = chars.pos(); String word = getWord(current); + if("true".equals(word) || "false".equals(word)) { + tokens.add(Token.fromBoolean(Boolean.parseBoolean(word), position)); + continue; + } + if(KEYWORDS.containsKey(word)) { tokens.add(new Token(KEYWORDS.get(word), position)); continue; @@ -156,7 +151,8 @@ private TokenStream tokenize() { if(TIME_UNITS.containsKey(word)) { if(tokens.isEmpty() || last().getType() != TokenType.VALUE_NUMBER ) { - throw new ParsingException(chars.pos(), "Unexpected time unit '"+word+"'."); + tokens.add(Token.fromIdentifier(word, position)); + continue; } // Replace number by duration double number = last().getContentNumber(); @@ -166,7 +162,7 @@ private TokenStream tokenize() { continue; } - tokens.add(Token.fromWord(word, position)); + tokens.add(Token.fromIdentifier(word, position)); continue; } diff --git a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/validators/DslValidator.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/validators/DslValidator.java similarity index 83% rename from dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/validators/DslValidator.java rename to dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/validators/DslValidator.java index 8060cbb6..0c289c59 100644 --- a/dsl/src/main/java/fr/jamailun/ultimatespellsystem/dsl/validators/DslValidator.java +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/validators/DslValidator.java @@ -1,7 +1,7 @@ -package fr.jamailun.ultimatespellsystem.dsl.validators; +package fr.jamailun.ultimatespellsystem.dsl2.validators; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; import org.jetbrains.annotations.NotNull; import java.util.List; diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/validators/StructureValidationVisitor.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/validators/StructureValidationVisitor.java new file mode 100644 index 00000000..4b0cb997 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/validators/StructureValidationVisitor.java @@ -0,0 +1,122 @@ +package fr.jamailun.ultimatespellsystem.dsl2.validators; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.TreeValidationException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.*; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks.ForLoopStatement; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks.IfElseStatement; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks.WhileLoopStatement; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.StatementVisitor; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +/** + * Structure validation. + */ +public class StructureValidationVisitor implements StatementVisitor { + + private TypeRef returnType = new TypeRef(); // reference + private boolean returnMet = false; + private boolean breakMet = false; + private boolean metadataAllowed = true; + + private @NotNull StructureValidationVisitor child() { + StructureValidationVisitor clone = new StructureValidationVisitor(); + clone.metadataAllowed = metadataAllowed; + clone.returnMet = returnMet; + clone.breakMet = breakMet; + clone.returnType = returnType; // copy ref + return clone; + } + + @Override + public void handleReturn(@NotNull ReturnStatement statement) { + handleMono(); + returnMet = true; + if(returnType.type != null && !Objects.equals(returnType.type, statement.getReturnType())) { + throw new TreeValidationException(statement.getPos(), "Cannot use a return of type " + statement.getReturnType() + " : another return in the same scoped returned a " + returnType.type); + } + returnType.type = statement.getReturnType(); + } + @Override + public void handleBreakContinue(@NotNull BreakContinueStatement statement) { + handleMono(); + breakMet = true; + } + + @Override + public void handleBlock(@NotNull BlockStatement statement) { + handleMono(); + StructureValidationVisitor child = child(); + statement.getChildren().forEach(n -> n.visit(child)); + } + + @Override + public void handleFunctionDeclaration(@NotNull FunctionDeclarationStatement function) { + // Prepare child context + StructureValidationVisitor child = child(); + child.returnType = new TypeRef(); + + // Apply to statements + function.getStatements().forEach(n -> n.visit(child)); + + // Check returns + if(!function.getOutputType().isNull()) { + // No return + if (!child.returnMet) + throw new TreeValidationException(function.getPosition(), "Function " + function.getFunctionName() + " should return " + function.getFunctionReturnType() + ", but not all branches return a value."); + // Different return type. + if (function.getOutputType().isNull()) { + if(!child.returnType.type.isNull()) + throw new TreeValidationException(function.getPosition(), "Function " + function.getFunctionName() + " should not return anything, but returned " + child.returnType.type + " instead."); + } else if (!Objects.equals(function.getOutputType(), child.returnType.type)) { + throw new TreeValidationException(function.getPosition(), "Function " + function.getFunctionName() + " should return " + function.getFunctionReturnType() + ", but returned " + child.returnType.type + " instead."); + } + } + } + + private void handleSub(@NotNull StatementNode child) { + child.visit(child()); + } + + private void handleMono() { + metadataAllowed = false; + if(returnMet) { + throw new TreeValidationException(TokenPosition.unknown(), "Cannot have a statement after a STOP."); + } + if(breakMet) { + throw new TreeValidationException(TokenPosition.unknown(), "Cannot have a statement in the block after a BREAK or a CONTINUE."); + } + } + + @Override + public void handleIf(@NotNull IfElseStatement statement) { + handleSub(statement.getChild()); + statement.getElse().ifPresent(this::handleSub); + } + @Override + public void handleForLoop(@NotNull ForLoopStatement statement) { + handleSub(statement.getChild()); + } + @Override + public void handleWhileLoop(@NotNull WhileLoopStatement statement) { + handleSub(statement.getChild()); + } + @Override + public void handleDeclareVariable(@NotNull DeclareNewVariableStatement statement) {handleMono();} + + @Override + public void handleAffectVariable(@NotNull AffectationStatement statement) { + handleMono(); + } + + @Override + public void handleSimpleExpression(@NotNull SimpleExpressionStatement statement) {handleMono();} + + private static class TypeRef { + Type type; + } +} diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/visitor/ExpressionVisitor.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/visitor/ExpressionVisitor.java new file mode 100644 index 00000000..a643e6dd --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/visitor/ExpressionVisitor.java @@ -0,0 +1,35 @@ +package fr.jamailun.ultimatespellsystem.dsl2.visitor; + +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.*; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.litteral.*; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators.*; +import org.jetbrains.annotations.NotNull; + +/** + * A visitor. Can interact with the node-tree. + */ +public interface ExpressionVisitor { + + // Literals + void handleNullLiteral(@NotNull NullLiteral literal); + void handleBooleanLiteral(@NotNull BooleanLiteral literal); + void handleNumberLiteral(@NotNull NumberLiteral literal); + void handleStringLiteral(@NotNull StringLiteral literal); + void handleMapLiteral(@NotNull MapLiteral literal); + void handleDurationLiteral(@NotNull DurationLiteral literal); + void handleLocationLiteral(@NotNull LocationLiteral literal); + + // Operators-ish + void handleBiOperator(@NotNull BiOperator operator); + void handleMonoOperator(@NotNull MonoOperator operator); + void handleParenthesis(@NotNull ParenthesisExpression parenthesis); + void handleArrayGet(@NotNull ArrayGetterExpression arrayGetter); + void handleFieldGet(@NotNull FieldGetExpression fieldGetter); + void handleFunctionCall(@NotNull FunctionCallExpression functionCall); + void handleIncrementDecrement(@NotNull IncrementExpression expression); + + // Specifics + void handleArray(@NotNull ArrayLiteral expression); + void handleVariable(@NotNull ReferenceExpression expression); + +} diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/visitor/PrintingVisitor.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/visitor/PrintingVisitor.java new file mode 100644 index 00000000..db003ac7 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/visitor/PrintingVisitor.java @@ -0,0 +1,393 @@ +package fr.jamailun.ultimatespellsystem.dsl2.visitor; + +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.*; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.litteral.*; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators.BiOperator; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators.IncrementExpression; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators.MonoOperator; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators.SizeOfOperator; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.*; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks.ForLoopStatement; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks.IfElseStatement; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks.WhileLoopStatement; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; +import org.jetbrains.annotations.NotNull; + +import java.text.DecimalFormat; +import java.util.List; + +/** + * Made to print content. + */ +public class PrintingVisitor implements StatementVisitor, ExpressionVisitor { + + private final static DecimalFormat formatNumber = new DecimalFormat("#.##"); + + private final int indentDelta; + private String indentBuffer; + private int currentIndent = 0; + private boolean dirty = true; + + private StringBuilder builder; + + private PrintingVisitor(int indent) { + this.indentDelta = indent; + } + + private @NotNull String visit(@NotNull List statements) { + builder = new StringBuilder(); + for(StatementNode statement : statements) { + statement.visit(this); + eol(); + } + return builder.toString(); + } + + /** + * Print multiple statements to sys-out, with an indentation of {@code 2}. + * @param statements the non-null statements to visit. + */ + public static void print(@NotNull List statements) { + print(statements, 2); + } + + /** + * Print multiple statements to sys-out. + * @param statements list of statements to print. + * @param indent specific indent to use. + */ + public static void print(@NotNull List statements, int indent) { + System.out.println(toString(statements, indent)); + } + + /** + * Print multiple statements to a String. + * @param statements list of statements to print. + * @return the print output. + */ + public static @NotNull String toString(@NotNull List statements) { + return toString(statements, 2); + } + + /** + * Print multiple statements to a String. + * @param statements list of statements to print. + * @param indent specific indent to use. + * @return the print output. + */ + public static @NotNull String toString(@NotNull List statements, int indent) { + return new PrintingVisitor(indent).visit(statements); + } + + private @NotNull String indent() { + if(dirty) { + indentBuffer = " ".repeat(currentIndent); + dirty = false; + } + return indentBuffer; + } + + private void right() { + currentIndent += indentDelta; + dirty = true; + } + + private void left() { + currentIndent -= indentDelta; + if(currentIndent < 0) { + currentIndent = 0; + } + dirty = true; + } + + private void eol() { + builder.append(";\n"); + } + + @Override + public void handleReturn(@NotNull ReturnStatement statement) { + builder.append(indent()).append("return"); + if(statement.getExitCodeNode() != null) { + builder.append(" "); + statement.getExitCodeNode().visit(this); + } + } + + @Override + public void handleDeclareVariable(@NotNull DeclareNewVariableStatement statement) { + builder.append(indent()) + .append(statement.getVarType() == null ? "VAR" : statement.getVarType()) + .append(" ") + .append(statement.getVarName()); + + if(statement.getExpression() != null) { + builder.append(" = "); + statement.getExpression().visit(this); + } + } + + @Override + public void handleAffectVariable(@NotNull AffectationStatement statement) { + statement.getValueHolder().visit(this); + builder.append(" := "); + statement.getExpression().visit(this); + } + + @Override + public void handleFunctionDeclaration(@NotNull FunctionDeclarationStatement statement) { + builder.append("FUNCTION ") + .append(statement.getFunctionReturnType()) + .append(" ") + .append(statement.getFunctionName()) + .append("("); + boolean first = true; + for(var arg : statement.getParameters()) { + if(first) first = false; else builder.append(", "); + builder.append(arg); + } + builder.append(") {\n"); + right(); + for(var st : statement.getStatements()) { + st.visit(this); + eol(); + } + left(); + builder.append("}"); + } + + + @Override + public void handleBlock(@NotNull BlockStatement statement) { + builder.append("{\n"); + right(); + for(StatementNode child : statement.getChildren()) { + child.visit(this); + eol(); + } + left(); + builder.append(indent()).append("}"); + } + + @Override + public void handleIncrementDecrement(@NotNull IncrementExpression expression) { + String symbol = expression.isPositive() ? "++" : "--"; + if(expression.isAfterVar()) { + builder.append(expression.getVarName()).append(symbol); + } else { + builder.append(symbol).append(expression.getVarName()); + } + } + + @Override + public void handleSimpleExpression(@NotNull SimpleExpressionStatement statement) { + builder.append("{"); + statement.getChild().visit(this); + builder.append("}"); + } + + @Override + public void handleIf(@NotNull IfElseStatement statement) { + builder.append(indent()).append("IF("); + statement.getCondition().visit(this); + builder.append("):"); + right(); + statement.getChild().visit(this); + left(); + builder.append("\n"); + + statement.getElse().ifPresent(e -> { + builder.append(indent()).append("ELSE : "); + right(); + e.visit(this); + left(); + builder.append("\n"); + }); + } + + @Override + public void handleForLoop(@NotNull ForLoopStatement statement) { + builder.append(indent()) + .append("FOR("); + if(statement.getInitialization() != null) statement.getInitialization().visit(this); + statement.getCondition().visit(this); + builder.append(";"); + if(statement.getIteration() != null) statement.getIteration().visit(this); + builder.append("):"); + statement.getChild().visit(this); + } + + + @Override + public void handleWhileLoop(@NotNull WhileLoopStatement statement) { + if(statement.isWhileFirst()) { + builder.append("WHILE("); + statement.getCondition().visit(this); + builder.append(") "); + } else { + builder.append("DO "); + } + statement.getChild().visit(this); + if(!statement.isWhileFirst()) { + builder.append(" WHILE("); + statement.getCondition().visit(this); + builder.append(") "); + } + } + + @Override + public void handleBreakContinue(@NotNull BreakContinueStatement statement) { + builder.append(statement.isContinue() ? "CONTINUE" : "BREAK"); + } + + @Override + public void handleNullLiteral(@NotNull NullLiteral literal) { + builder.append("NULL"); + } + + @Override + public void handleBooleanLiteral(@NotNull BooleanLiteral literal) { + builder.append(literal.getRaw()); + } + + @Override + public void handleNumberLiteral(@NotNull NumberLiteral literal) { + double num = literal.getRaw(); + builder.append(formatNumber.format(num)); + } + + @Override + public void handleStringLiteral(@NotNull StringLiteral literal) { + builder.append("\"").append(literal.getRaw()).append("\""); + } + + @Override + public void handleMapLiteral(@NotNull MapLiteral literal) { + builder.append("{"); + right(); + boolean first = true; + for(var entry : literal.getExpressions().entrySet()) { + if(first) first = false; else builder.append(","); + builder.append("\n").append(indent()).append(entry.getKey()).append(" : "); + entry.getValue().visit(this); + } + left(); + if(!literal.getExpressions().isEmpty()) + builder.append("\n").append(indent()); + builder.append("}"); + } + + @Override + public void handleDurationLiteral(@NotNull DurationLiteral literal) { + Duration duration = literal.getRaw(); + builder.append(formatNumber.format(duration.amount())) + .append(" ") + .append(duration.niceUnit()); + } + + @Override + public void handleLocationLiteral(@NotNull LocationLiteral literal) { + builder.append("Location("); + literal.getWorld().visit(this); builder.append(", "); + literal.getVectorX().visit(this); builder.append(", "); + literal.getVectorY().visit(this); builder.append(", "); + literal.getVectorZ().visit(this); + if(literal.hasYawAndPitch()) { + builder.append(", "); + literal.getYaw().visit(this); + builder.append(", "); + literal.getPitch().visit(this); + } + builder.append(")"); + } + + @Override + public void handleBiOperator(@NotNull BiOperator operator) { + operator.getLeft().visit(this); + String ope = switch (operator.getType()) { + case ADD -> "+"; + case SUB -> "-"; + case MUL -> "*"; + case DIV -> "/"; + case EQUAL -> "=="; + case NOT_EQUAL -> "!="; + case GREATER_OR_EQ -> ">="; + case GREATER -> ">"; + case LESSER_OR_EQ -> "<="; + case LESSER -> "<"; + case AND -> "and"; + case OR -> "or"; + case LIST_ADD -> ":+"; + case LIST_REM -> ":-"; + case LIST_REM_INDEX -> ":/"; + case LIST_CONTAINS -> ":?"; + }; + builder.append(" ").append(ope).append(" "); + operator.getRight().visit(this); + } + + @Override + public void handleMonoOperator(@NotNull MonoOperator operator) { + String ope = operator.getType().name(); + builder.append(ope).append("("); + operator.getChild().visit(this); + builder.append(")"); + } + + @Override + public void handleParenthesis(@NotNull ParenthesisExpression parenthesis) { + builder.append("("); + parenthesis.getExpression().visit(this); + builder.append(")"); + } + + @Override + public void handleArrayGet(@NotNull ArrayGetterExpression arrayGetter) { + arrayGetter.getArray().visit(this); + builder.append("["); + arrayGetter.getIndex().visit(this); + builder.append("]"); + } + + @Override + public void handleFieldGet(@NotNull FieldGetExpression fieldGetter) { + fieldGetter.getLeftExpression().visit(this); + builder.append(".") + .append(fieldGetter.getFieldName()); + } + + @Override + public void handleFunctionCall(@NotNull FunctionCallExpression functionCall) { + if(functionCall.getCaller() != null) { + functionCall.getCaller().visit(this); + builder.append("."); + } + builder.append(functionCall.getFunctionName()).append("("); + boolean first = true; + for(ExpressionNode arg : functionCall.getArguments()) { + if(first) first = false; else builder.append(", "); + arg.visit(this); + } + builder.append(")"); + } + + @Override + public void handleArray(@NotNull ArrayLiteral expression) { + builder.append("["); + boolean first = true; + for(ExpressionNode child : expression.getElements()) { + if(first) first = false; else builder.append(", "); + child.visit(this); + } + builder.append("]"); + } + + @Override + public void handleVariable(@NotNull ReferenceExpression expression) { + builder.append("VAR<") + .append(expression.getVariableName()) + .append(">"); + } + +} diff --git a/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/visitor/StatementVisitor.java b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/visitor/StatementVisitor.java new file mode 100644 index 00000000..4c127ce0 --- /dev/null +++ b/dsl2/src/main/java/fr/jamailun/ultimatespellsystem/dsl2/visitor/StatementVisitor.java @@ -0,0 +1,27 @@ +package fr.jamailun.ultimatespellsystem.dsl2.visitor; + +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.*; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks.ForLoopStatement; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks.IfElseStatement; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks.WhileLoopStatement; +import org.jetbrains.annotations.NotNull; + +/** + * A visitor. Can interact with the node-tree. + */ +public interface StatementVisitor { + + void handleDeclareVariable(@NotNull DeclareNewVariableStatement statement); + void handleAffectVariable(@NotNull AffectationStatement statement); + void handleFunctionDeclaration(@NotNull FunctionDeclarationStatement statement); + + void handleReturn(@NotNull ReturnStatement statement); + void handleBlock(@NotNull BlockStatement statement); + void handleSimpleExpression(@NotNull SimpleExpressionStatement statement); + + void handleIf(@NotNull IfElseStatement statement); + void handleForLoop(@NotNull ForLoopStatement statement); + //void handleForeachLoop(@NotNull ForeachLoopStatement statement); + void handleWhileLoop(@NotNull WhileLoopStatement statement); + void handleBreakContinue(@NotNull BreakContinueStatement statement); +} diff --git a/dsl2/src/test/java/fr/jamailun/ultimatespellsystem/dsl2/CorrectParsingTests.java b/dsl2/src/test/java/fr/jamailun/ultimatespellsystem/dsl2/CorrectParsingTests.java new file mode 100644 index 00000000..e0005e47 --- /dev/null +++ b/dsl2/src/test/java/fr/jamailun/ultimatespellsystem/dsl2/CorrectParsingTests.java @@ -0,0 +1,64 @@ +package fr.jamailun.ultimatespellsystem.dsl2; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.UssException; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.Test; + +import java.io.File; + +/** + * Multiple tests for valid USS files. + */ +public class CorrectParsingTests extends ParsingTest { + + @Test + void correctParsing() { + testFolder("corrects/parsing"); + } + + @Test + void correctBasics() { + testFolder("corrects/basics"); + } + + @Test + void correctLoops() { + testFolder("corrects/loops"); + } + + @Test + void correctLiterals() { + testFolder("corrects/literals"); + } + + @Test + void correctFunctions() { + testFolder("corrects/functions"); + } + + @Test + void correctArrays() { + testFolder("corrects/arrays"); + } + + @Test + void correctTypes() { + testFolder("corrects/types"); + } + + // -- + + private void testFolder(@NotNull String folder) { + for(File file : listTests(folder)) { + try { + parseAndVerify(file); + addOk(); + } catch (UssException e) { + e.printStackTrace(); + addFails(file, toString(e)); + } + } + printResults(); + } + +} diff --git a/dsl/src/test/java/fr/jamailun/ultimatespellsystem/dsl/FailuresParsingTests.java b/dsl2/src/test/java/fr/jamailun/ultimatespellsystem/dsl2/FailuresParsingTests.java similarity index 72% rename from dsl/src/test/java/fr/jamailun/ultimatespellsystem/dsl/FailuresParsingTests.java rename to dsl2/src/test/java/fr/jamailun/ultimatespellsystem/dsl2/FailuresParsingTests.java index f185963c..c4c507ca 100644 --- a/dsl/src/test/java/fr/jamailun/ultimatespellsystem/dsl/FailuresParsingTests.java +++ b/dsl2/src/test/java/fr/jamailun/ultimatespellsystem/dsl2/FailuresParsingTests.java @@ -1,6 +1,6 @@ -package fr.jamailun.ultimatespellsystem.dsl; +package fr.jamailun.ultimatespellsystem.dsl2; -import fr.jamailun.ultimatespellsystem.dsl.errors.*; +import fr.jamailun.ultimatespellsystem.dsl2.errors.*; import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Test; @@ -12,28 +12,23 @@ public class FailuresParsingTests extends ParsingTest { @Test - void badParsing() { - badParsing("bad_parsing", ParsingException.class); + void badType() { + badParsing("invalid/bad_type", TypeException.class); } @Test void badSyntax() { - badParsing("bad_syntax", SyntaxException.class); + badParsing("invalid/bad_syntax", SyntaxException.class); } @Test - void badType() { - badParsing("bad_type", TypeException.class); - } - - @Test - void badTreeValidation() { - badParsing("bad_tree", TreeValidationException.class); + void badParsing() { + badParsing("invalid/bad_parsing", ParsingException.class); } @Test - void badMix() { - badParsing("bad_mix", UssException.class); + void badTree() { + badParsing("invalid/bad_tree", TreeValidationException.class); } private void badParsing(@NotNull String folder, @NotNull Class clazz) { diff --git a/dsl/src/test/java/fr/jamailun/ultimatespellsystem/dsl/ParsingTest.java b/dsl2/src/test/java/fr/jamailun/ultimatespellsystem/dsl2/ParsingTest.java similarity index 80% rename from dsl/src/test/java/fr/jamailun/ultimatespellsystem/dsl/ParsingTest.java rename to dsl2/src/test/java/fr/jamailun/ultimatespellsystem/dsl2/ParsingTest.java index fde1d233..9507d2df 100644 --- a/dsl/src/test/java/fr/jamailun/ultimatespellsystem/dsl/ParsingTest.java +++ b/dsl2/src/test/java/fr/jamailun/ultimatespellsystem/dsl2/ParsingTest.java @@ -1,13 +1,13 @@ -package fr.jamailun.ultimatespellsystem.dsl; - -import fr.jamailun.ultimatespellsystem.dsl.errors.UssException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.CharStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Tokenizer; -import fr.jamailun.ultimatespellsystem.dsl.validators.DslValidator; -import fr.jamailun.ultimatespellsystem.dsl.visitor.PrintingVisitor; +package fr.jamailun.ultimatespellsystem.dsl2; + +import fr.jamailun.ultimatespellsystem.dsl2.errors.UssException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.CharStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Tokenizer; +import fr.jamailun.ultimatespellsystem.dsl2.validators.DslValidator; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.PrintingVisitor; import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Assertions; @@ -57,7 +57,7 @@ protected void parseAndVerify(@NotNull File file) throws UssException { System.out.println(tokens + "\n"); // Parse - List nodes = UltimateSpellSystemDSL.parse(tokens); + List nodes = UltimateSpellSystemDSL2.parse(tokens); System.out.println(" ----------------------- "); @@ -90,8 +90,7 @@ protected void printResults() { } System.out.println("\n" + WHITE_BOLD + "=====================================================" + RESET + "\n"); - if(!failures.isEmpty()) - System.exit(42); + Assertions.assertTrue(failures.isEmpty(), "Some tests failed."); } } diff --git a/dsl/src/test/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/DurationTests.java b/dsl2/src/test/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/DurationTests.java similarity index 66% rename from dsl/src/test/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/DurationTests.java rename to dsl2/src/test/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/DurationTests.java index 9eb526c8..aa591724 100644 --- a/dsl/src/test/java/fr/jamailun/ultimatespellsystem/dsl/nodes/type/DurationTests.java +++ b/dsl2/src/test/java/fr/jamailun/ultimatespellsystem/dsl2/nodes/type/DurationTests.java @@ -1,8 +1,9 @@ -package fr.jamailun.ultimatespellsystem.dsl.nodes.type; +package fr.jamailun.ultimatespellsystem.dsl2.nodes.type; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.time.temporal.TemporalUnit; import java.util.concurrent.TimeUnit; /** @@ -19,6 +20,7 @@ void testDurOpeDur() { Duration c = new Duration(1, TimeUnit.HOURS); Duration d = new Duration(1, TimeUnit.SECONDS); Assertions.assertEquals(new Duration(3601, TimeUnit.SECONDS), c.add(d)); + Assertions.assertEquals(new Duration(3599, TimeUnit.SECONDS), c.sub(d)); Assertions.assertEquals(new Duration(2, TimeUnit.HOURS), c.add(c)); } @@ -35,4 +37,12 @@ void testDurMul() { Assertions.assertEquals(new Duration(1, TimeUnit.HOURS), a.mul(5)); } + @Test + void conversionsTest() { + Duration oneSecond = new Duration(1, TimeUnit.SECONDS); + Assertions.assertEquals(1000L, oneSecond.toMs()); + Assertions.assertEquals(20L, oneSecond.toTicks()); + Assertions.assertEquals(java.time.Duration.ofSeconds(1), oneSecond.asJavaDuration()); + } + } diff --git a/dsl2/src/test/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/TokenizerTest.java b/dsl2/src/test/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/TokenizerTest.java new file mode 100644 index 00000000..f479a08e --- /dev/null +++ b/dsl2/src/test/java/fr/jamailun/ultimatespellsystem/dsl2/tokenization/TokenizerTest.java @@ -0,0 +1,139 @@ +package fr.jamailun.ultimatespellsystem.dsl2.tokenization; + +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +class TokenizerTest { + + @Test + void basic() { + String input = "var toto = 123"; + assertTokenize( + input, + List.of( + symbol(TokenType.VAR), + identifier("toto"), + symbol(TokenType.EQUAL), + number(123) + ) + ); + } + + @Test + void comparison() { + String input = """ + if(test() == true || false) { + dur = 3s * dt; + e = "\\\\"; + } + """; + assertTokenize( + input, + List.of( + symbol(TokenType.IF), + symbol(TokenType.BRACKET_OPEN), + identifier("test"), + symbol(TokenType.BRACKET_OPEN), + symbol(TokenType.BRACKET_CLOSE), + symbol(TokenType.COMP_EQ), + bool(true), + symbol(TokenType.OPE_OR), + bool(false), + symbol(TokenType.BRACKET_CLOSE), + symbol(TokenType.BRACES_OPEN), + identifier("dur"), + symbol(TokenType.EQUAL), + duration(new Duration(3, TimeUnit.SECONDS)), + symbol(TokenType.OPE_MUL), + identifier("dt"), + symbol(TokenType.SEMI_COLON), + identifier("e"), + symbol(TokenType.EQUAL), + string("\\"), + symbol(TokenType.SEMI_COLON), + symbol(TokenType.BRACES_CLOSE) + ) + ); + } + + @Test + void basicOperator() { + String input = "z = (-1 + 3) * x"; + assertTokenize( + input, + List.of( + identifier("z"), + symbol(TokenType.EQUAL), + symbol(TokenType.BRACKET_OPEN), + symbol(TokenType.OPE_SUB), + number(1), + symbol(TokenType.OPE_ADD), + number(3), + symbol(TokenType.BRACKET_CLOSE), + symbol(TokenType.OPE_MUL), + identifier("x") + ) + ); + } + + @Test + void basicString() { + String input = "str = \"val\\\"ue\";"; + assertTokenize( + input, + List.of( + identifier("str"), + symbol(TokenType.EQUAL), + string("val\"ue"), + symbol(TokenType.SEMI_COLON) + ) + ); + } + + // ---------------------------------- + + private static @NotNull List tokenize(@NotNull String input) { + var output = Tokenizer.tokenize(CharStream.from(input)); + List tokens = new ArrayList<>(); + while(output.hasMore()) { + tokens.add(output.next()); + } + return tokens; + } + + private static void assertTokenize(String input, @NotNull List tokens) { + List outputTokens = tokenize(input); + List expectedTokens = new ArrayList<>(tokens); + expectedTokens.add(symbol(TokenType.EOF)); + Assertions.assertEquals(expectedTokens.size(), outputTokens.size(), "Tokens are not the same length. E=" +expectedTokens+", O="+outputTokens); + for(int i = 0; i < expectedTokens.size(); i++) { + Assertions.assertEquals(expectedTokens.get(i), outputTokens.get(i), "Token of index " + i + " was NOT equal."); + } + } + + private static Token bool(boolean v) { + return Token.fromBoolean(v, TokenPosition.unknown()); + } + private static Token string(String v) { + return Token.fromString(v, TokenPosition.unknown()); + } + private static Token number(double v) { + return Token.fromNumber(v, TokenPosition.unknown()); + } + private static Token duration(Duration v) { + return Token.fromDuration(v.amount(), v.timeUnit(), TokenPosition.unknown()); + } + private static Token identifier(String v) { + return Token.fromIdentifier(v, TokenPosition.unknown()); + } + private static Token symbol(TokenType v) { + return new Token(v, TokenPosition.unknown()); + } + +} diff --git a/dsl2/src/test/resources/parsing/corrects/arrays/basic_get.uss b/dsl2/src/test/resources/parsing/corrects/arrays/basic_get.uss new file mode 100644 index 00000000..5df3f66f --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/arrays/basic_get.uss @@ -0,0 +1,2 @@ +var arr = [1, 2, 3]; +int a = arr[1]; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/arrays/multi_get.uss b/dsl2/src/test/resources/parsing/corrects/arrays/multi_get.uss new file mode 100644 index 00000000..a86ecd04 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/arrays/multi_get.uss @@ -0,0 +1,4 @@ +var arr = [[1, 2, 3], [4, 5, 6]]; +var l1 = arr[1]; +int v1 = l1[0]; +int v2 = arr[0][0]; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/arrays/sizeof.uss b/dsl2/src/test/resources/parsing/corrects/arrays/sizeof.uss new file mode 100644 index 00000000..2657ac40 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/arrays/sizeof.uss @@ -0,0 +1,2 @@ +var truc = ["a", "b"]; +int size = size_of(truc); diff --git a/dsl2/src/test/resources/parsing/corrects/basics/affect_reaffect.uss b/dsl2/src/test/resources/parsing/corrects/basics/affect_reaffect.uss new file mode 100644 index 00000000..bc7a208a --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/basics/affect_reaffect.uss @@ -0,0 +1,2 @@ +int foo = 3; +foo = 4; diff --git a/dsl2/src/test/resources/parsing/corrects/basics/basic_affectation.uss b/dsl2/src/test/resources/parsing/corrects/basics/basic_affectation.uss new file mode 100644 index 00000000..a81404c5 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/basics/basic_affectation.uss @@ -0,0 +1,4 @@ +int foo = 3; + +var bar = "oui"; + diff --git a/dsl2/src/test/resources/parsing/corrects/basics/basic_function_int.uss b/dsl2/src/test/resources/parsing/corrects/basics/basic_function_int.uss new file mode 100644 index 00000000..b0e2df09 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/basics/basic_function_int.uss @@ -0,0 +1,3 @@ +int foo() { + return 1; +} \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/basics/basic_function_void.uss b/dsl2/src/test/resources/parsing/corrects/basics/basic_function_void.uss new file mode 100644 index 00000000..8375d758 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/basics/basic_function_void.uss @@ -0,0 +1,3 @@ +void foo() { + return; +} \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/basics/block.uss b/dsl2/src/test/resources/parsing/corrects/basics/block.uss new file mode 100644 index 00000000..5e394d31 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/basics/block.uss @@ -0,0 +1,6 @@ +{ + int j = 3; + { + int i = 0; + } +} \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/basics/block_if.uss b/dsl2/src/test/resources/parsing/corrects/basics/block_if.uss new file mode 100644 index 00000000..708866a3 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/basics/block_if.uss @@ -0,0 +1,4 @@ +bool a = false; +if(a == true || false) { + console.info("ok"); +} \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/basics/block_if_else.uss b/dsl2/src/test/resources/parsing/corrects/basics/block_if_else.uss new file mode 100644 index 00000000..108d21d8 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/basics/block_if_else.uss @@ -0,0 +1,6 @@ +bool a = false; +if(a == true || false) { + console.info("ok"); +} else { + console.info("non"); +} \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/basics/block_if_elseif.uss b/dsl2/src/test/resources/parsing/corrects/basics/block_if_elseif.uss new file mode 100644 index 00000000..ae9c3e9b --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/basics/block_if_elseif.uss @@ -0,0 +1,8 @@ +bool a = false; +if(a) { + console.info("ok"); +} else if(!a) { + console.info("non"); +} else { + console.info("??"); +} \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/basics/declarations.uss b/dsl2/src/test/resources/parsing/corrects/basics/declarations.uss new file mode 100644 index 00000000..ac9b4dd8 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/basics/declarations.uss @@ -0,0 +1,4 @@ +int some_method() { + int some_var; + return some_var; +} \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/basics/field_access.uss b/dsl2/src/test/resources/parsing/corrects/basics/field_access.uss new file mode 100644 index 00000000..d4b90e43 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/basics/field_access.uss @@ -0,0 +1 @@ +console.info("test"); diff --git a/dsl2/src/test/resources/parsing/corrects/basics/increment_add.uss b/dsl2/src/test/resources/parsing/corrects/basics/increment_add.uss new file mode 100644 index 00000000..38f0537e --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/basics/increment_add.uss @@ -0,0 +1,3 @@ +int a = 0; +int b = a++ + 1; +int c = ++a + 1; diff --git a/dsl2/src/test/resources/parsing/corrects/basics/increment_decrement.uss b/dsl2/src/test/resources/parsing/corrects/basics/increment_decrement.uss new file mode 100644 index 00000000..c31d77d1 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/basics/increment_decrement.uss @@ -0,0 +1,5 @@ +int a = 0; +a++; +++a; +#a--; +#--a; diff --git a/dsl2/src/test/resources/parsing/corrects/functions/basic_function_void.uss b/dsl2/src/test/resources/parsing/corrects/functions/basic_function_void.uss new file mode 100644 index 00000000..8375d758 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/functions/basic_function_void.uss @@ -0,0 +1,3 @@ +void foo() { + return; +} \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/functions/fuction_call.uss b/dsl2/src/test/resources/parsing/corrects/functions/fuction_call.uss new file mode 100644 index 00000000..012da562 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/functions/fuction_call.uss @@ -0,0 +1,5 @@ +void foo() { + int a = 2; +} + +foo(); diff --git a/dsl2/src/test/resources/parsing/corrects/functions/function_call_args.uss b/dsl2/src/test/resources/parsing/corrects/functions/function_call_args.uss new file mode 100644 index 00000000..5902c36c --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/functions/function_call_args.uss @@ -0,0 +1,5 @@ +void foo(int a, string b) { + console.info("a = " + a + ", b = " + b); +} + +foo(12, "oui"); diff --git a/dsl2/src/test/resources/parsing/corrects/functions/function_call_expr.uss b/dsl2/src/test/resources/parsing/corrects/functions/function_call_expr.uss new file mode 100644 index 00000000..5dbf2a72 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/functions/function_call_expr.uss @@ -0,0 +1,6 @@ +int plus_one(int a) { + return a + 1; +} + +int three = plus_one(plus_one(1)); +int five = plus_one(three) + 1; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/literals/array_empty.uss b/dsl2/src/test/resources/parsing/corrects/literals/array_empty.uss new file mode 100644 index 00000000..a3227adb --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/literals/array_empty.uss @@ -0,0 +1 @@ +var arr = []; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/literals/array_small.uss b/dsl2/src/test/resources/parsing/corrects/literals/array_small.uss new file mode 100644 index 00000000..ef076cc6 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/literals/array_small.uss @@ -0,0 +1,3 @@ +var arr = [ + "a", "b", "c" +]; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/literals/array_xl.uss b/dsl2/src/test/resources/parsing/corrects/literals/array_xl.uss new file mode 100644 index 00000000..7305088c --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/literals/array_xl.uss @@ -0,0 +1,5 @@ +var arr = [ + ["a", "b", "c"], + ["d", "e", "f"], + ["g", "h", "i"] +]; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/literals/map_empty.uss b/dsl2/src/test/resources/parsing/corrects/literals/map_empty.uss new file mode 100644 index 00000000..8ee707c5 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/literals/map_empty.uss @@ -0,0 +1 @@ +var map = { }; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/literals/map_small.uss b/dsl2/src/test/resources/parsing/corrects/literals/map_small.uss new file mode 100644 index 00000000..52e2c88b --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/literals/map_small.uss @@ -0,0 +1,4 @@ +var map = { + foo: "foo", + bar: "bar" +}; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/literals/map_xl.uss b/dsl2/src/test/resources/parsing/corrects/literals/map_xl.uss new file mode 100644 index 00000000..ace172bb --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/literals/map_xl.uss @@ -0,0 +1,7 @@ +var map = { + foo: "foo", + bar: "bar", + intra: { + val: 23 + } +}; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/loops/do_while_.uss b/dsl2/src/test/resources/parsing/corrects/loops/do_while_.uss new file mode 100644 index 00000000..c4340313 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/loops/do_while_.uss @@ -0,0 +1,4 @@ +int i = 5; +do { + i = i - 1; +} while(i > 0); \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/loops/for_break.uss b/dsl2/src/test/resources/parsing/corrects/loops/for_break.uss new file mode 100644 index 00000000..d56ce86f --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/loops/for_break.uss @@ -0,0 +1,4 @@ +for(int i = 0; i < 5; ++i) { + caster.send_message("i = " + i); + break; +} diff --git a/dsl2/src/test/resources/parsing/corrects/loops/for_break_ctn.uss b/dsl2/src/test/resources/parsing/corrects/loops/for_break_ctn.uss new file mode 100644 index 00000000..2f4462f8 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/loops/for_break_ctn.uss @@ -0,0 +1,5 @@ +for(int i = 0; i < 5; ++i) { + caster.send_message("i = " + i); + if(i >= 3) continue; + break; +} diff --git a/dsl2/src/test/resources/parsing/corrects/loops/for_postfix.uss b/dsl2/src/test/resources/parsing/corrects/loops/for_postfix.uss new file mode 100644 index 00000000..a8b4c7a4 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/loops/for_postfix.uss @@ -0,0 +1,3 @@ +for(int i = 0; i < 5; i++) { + console.info("i = " + i); +} diff --git a/dsl2/src/test/resources/parsing/corrects/loops/for_prefix.uss b/dsl2/src/test/resources/parsing/corrects/loops/for_prefix.uss new file mode 100644 index 00000000..d0fed29c --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/loops/for_prefix.uss @@ -0,0 +1,3 @@ +for(int i = 0; i < 5; ++i) { + console.info("i = " + i); +} diff --git a/dsl2/src/test/resources/parsing/corrects/loops/while.uss b/dsl2/src/test/resources/parsing/corrects/loops/while.uss new file mode 100644 index 00000000..4c8021e9 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/loops/while.uss @@ -0,0 +1,4 @@ +int i = 5; +while(i > 0) { + i = i - 1; +} \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/parsing/numbers.uss b/dsl2/src/test/resources/parsing/corrects/parsing/numbers.uss new file mode 100644 index 00000000..c782a4fe --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/parsing/numbers.uss @@ -0,0 +1,3 @@ +int a = 1; +int b = 1.2; +int c = .3; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/parsing/string_escape.uss b/dsl2/src/test/resources/parsing/corrects/parsing/string_escape.uss new file mode 100644 index 00000000..10dcd06f --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/parsing/string_escape.uss @@ -0,0 +1 @@ +var a = "a\"b"; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/types/durations.uss b/dsl2/src/test/resources/parsing/corrects/types/durations.uss new file mode 100644 index 00000000..1ea49d35 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/types/durations.uss @@ -0,0 +1,8 @@ +var a = 3 seconds; +a = 3s; +var b = 5minutes; +b = 5m; +var c = 8 milliseconds; +c = 8 ms; +var d = 7 hours; +d = 7h; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/corrects/types/locations.uss b/dsl2/src/test/resources/parsing/corrects/types/locations.uss new file mode 100644 index 00000000..1eb7a5b4 --- /dev/null +++ b/dsl2/src/test/resources/parsing/corrects/types/locations.uss @@ -0,0 +1,3 @@ +var l = @("world", 0, 100, 0); + +l = @("world_the_end", 0, 100, 0, 0, 90); diff --git a/dsl2/src/test/resources/parsing/invalid/bad_parsing/string_invalid.uss b/dsl2/src/test/resources/parsing/invalid/bad_parsing/string_invalid.uss new file mode 100644 index 00000000..95ec3462 --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_parsing/string_invalid.uss @@ -0,0 +1,3 @@ +string val = "a +a +a"; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/invalid/bad_parsing/string_not_ending.uss b/dsl2/src/test/resources/parsing/invalid/bad_parsing/string_not_ending.uss new file mode 100644 index 00000000..621fa54c --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_parsing/string_not_ending.uss @@ -0,0 +1 @@ +string val = " \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/invalid/bad_syntax/bad_increment.uss b/dsl2/src/test/resources/parsing/invalid/bad_syntax/bad_increment.uss new file mode 100644 index 00000000..2506c9d9 --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_syntax/bad_increment.uss @@ -0,0 +1 @@ +++12; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/invalid/bad_syntax/caster_assign.uss b/dsl2/src/test/resources/parsing/invalid/bad_syntax/caster_assign.uss new file mode 100644 index 00000000..17f62803 --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_syntax/caster_assign.uss @@ -0,0 +1 @@ +int caster = 1; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/invalid/bad_syntax/empty_var.uss b/dsl2/src/test/resources/parsing/invalid/bad_syntax/empty_var.uss new file mode 100644 index 00000000..e39dc0ea --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_syntax/empty_var.uss @@ -0,0 +1 @@ +var foo; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/invalid/bad_syntax/function_call_void_expression.uss b/dsl2/src/test/resources/parsing/invalid/bad_syntax/function_call_void_expression.uss new file mode 100644 index 00000000..240f40be --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_syntax/function_call_void_expression.uss @@ -0,0 +1,5 @@ +void foo(int a) { + int b = a + 1; +} + +int three = 1 + foo(1); \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/invalid/bad_syntax/repeated_declaration.uss b/dsl2/src/test/resources/parsing/invalid/bad_syntax/repeated_declaration.uss new file mode 100644 index 00000000..d33bc8f7 --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_syntax/repeated_declaration.uss @@ -0,0 +1,2 @@ +int foo = 1; +int foo = 2; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/invalid/bad_syntax/repeated_function.uss b/dsl2/src/test/resources/parsing/invalid/bad_syntax/repeated_function.uss new file mode 100644 index 00000000..ba41b4d8 --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_syntax/repeated_function.uss @@ -0,0 +1,2 @@ +void a() {} +void a() {} diff --git a/dsl2/src/test/resources/parsing/invalid/bad_syntax/unknown_function.uss b/dsl2/src/test/resources/parsing/invalid/bad_syntax/unknown_function.uss new file mode 100644 index 00000000..4ff30255 --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_syntax/unknown_function.uss @@ -0,0 +1 @@ +some_function(); \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/invalid/bad_syntax/unknown_variable.uss b/dsl2/src/test/resources/parsing/invalid/bad_syntax/unknown_variable.uss new file mode 100644 index 00000000..a7b41895 --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_syntax/unknown_variable.uss @@ -0,0 +1 @@ +int a = i_do_not_exist + 1; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/invalid/bad_tree/func_bad_return.uss b/dsl2/src/test/resources/parsing/invalid/bad_tree/func_bad_return.uss new file mode 100644 index 00000000..bbf0fa6d --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_tree/func_bad_return.uss @@ -0,0 +1,3 @@ +int foo() { + return "non"; +} diff --git a/dsl2/src/test/resources/parsing/invalid/bad_tree/func_bad_return_2.uss b/dsl2/src/test/resources/parsing/invalid/bad_tree/func_bad_return_2.uss new file mode 100644 index 00000000..f5fd5ab4 --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_tree/func_bad_return_2.uss @@ -0,0 +1,5 @@ +int foo() { + if(1 == 1) + return "non"; + return 12; +} diff --git a/dsl2/src/test/resources/parsing/invalid/bad_tree/func_no_return.uss b/dsl2/src/test/resources/parsing/invalid/bad_tree/func_no_return.uss new file mode 100644 index 00000000..be22943d --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_tree/func_no_return.uss @@ -0,0 +1,3 @@ +int foo() { + console.info("non"); +} diff --git a/dsl2/src/test/resources/parsing/invalid/bad_tree/global_bad_return.uss b/dsl2/src/test/resources/parsing/invalid/bad_tree/global_bad_return.uss new file mode 100644 index 00000000..23bac20e --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_tree/global_bad_return.uss @@ -0,0 +1,3 @@ +if(1 == 1) + return 1; +return "autre"; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/invalid/bad_type/bad_array_get.uss b/dsl2/src/test/resources/parsing/invalid/bad_type/bad_array_get.uss new file mode 100644 index 00000000..1cf29111 --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_type/bad_array_get.uss @@ -0,0 +1,2 @@ +var a = [1, 2, 3]; +string v = a[0]; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/invalid/bad_type/bad_assignment.uss b/dsl2/src/test/resources/parsing/invalid/bad_type/bad_assignment.uss new file mode 100644 index 00000000..ca8cdd2d --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_type/bad_assignment.uss @@ -0,0 +1 @@ +int a = "string"; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/invalid/bad_type/bad_reassignment.uss b/dsl2/src/test/resources/parsing/invalid/bad_type/bad_reassignment.uss new file mode 100644 index 00000000..8b066b2a --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_type/bad_reassignment.uss @@ -0,0 +1,2 @@ +string a = "string"; +a = 2; \ No newline at end of file diff --git a/dsl2/src/test/resources/parsing/invalid/bad_type/function_call_bad_args.uss b/dsl2/src/test/resources/parsing/invalid/bad_type/function_call_bad_args.uss new file mode 100644 index 00000000..f2065b50 --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_type/function_call_bad_args.uss @@ -0,0 +1,5 @@ +void foo(int a, string b) { + console.info("a = " + a + ", b = " + b); +} + +foo(12, 4567); diff --git a/dsl2/src/test/resources/parsing/invalid/bad_type/increment_type.uss b/dsl2/src/test/resources/parsing/invalid/bad_type/increment_type.uss new file mode 100644 index 00000000..ba3a34f3 --- /dev/null +++ b/dsl2/src/test/resources/parsing/invalid/bad_type/increment_type.uss @@ -0,0 +1,2 @@ +string a = "a"; +a++; \ No newline at end of file diff --git a/plugin/pom.xml b/plugin/pom.xml index 367b8a74..084e6895 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -5,12 +5,12 @@ 4.0.0 ultimate-spell-system-plugin - 2.6.1-SNAPSHOT + 3.0.0-SNAPSHOT fr.jamailun.paper ultimate-spell-system - 2.6.1-SNAPSHOT + 3.0.0-SNAPSHOT @@ -25,8 +25,8 @@ fr.jamailun.paper - 2.6.1-SNAPSHOT - ultimate-spell-system-dsl + 3.0.0-SNAPSHOT + ultimate-spell-system-dsl2 compile diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/UssMain.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/UssMain.java index 987178bc..8d17b923 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/UssMain.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/UssMain.java @@ -17,7 +17,7 @@ import fr.jamailun.ultimatespellsystem.plugin.entities.BukkitSpellEntity; import fr.jamailun.ultimatespellsystem.plugin.entities.SummonsManagerImpl; import fr.jamailun.ultimatespellsystem.plugin.listeners.*; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.SendAttributeNode; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old.SendAttributeNode; import fr.jamailun.ultimatespellsystem.plugin.spells.SpellsManagerImpl; import fr.jamailun.ultimatespellsystem.plugin.spells.external.ExternalExecutorImpl; import fr.jamailun.ultimatespellsystem.plugin.updater.UpdateCheck; @@ -30,7 +30,6 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/ExtensionLoader.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/ExtensionLoader.java index 9bcd1fa0..f0190770 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/ExtensionLoader.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/ExtensionLoader.java @@ -52,17 +52,12 @@ public static synchronized void loadStatic() { JavaFunctionProvider.instance().registerFunction(new KnockbackFunction(), "set_velocity"); JavaFunctionProvider.instance().registerFunction(new DirectionOfFunction(), "dir_of"); JavaFunctionProvider.instance().registerFunction(new NormalizeFunction(), "norm"); - JavaFunctionProvider.instance().registerFunction(new GetHealthFunction()); - JavaFunctionProvider.instance().registerFunction(new GetMaxHealthFunction()); - JavaFunctionProvider.instance().registerFunction(new HealEntityFunction(), "heal_entity"); - JavaFunctionProvider.instance().registerFunction(new LocationToListFunction()); JavaFunctionProvider.instance().registerFunction(new AreAlliesFunction()); JavaFunctionProvider.instance().registerFunction(new EntityHasEffectFunction(), "entity_has_potion_effect", "has_potion_effect", "has_effect"); JavaFunctionProvider.instance().registerFunction(new SetAggroFunction()); JavaFunctionProvider.instance().registerFunction(new GetFoodLevelFunction()); JavaFunctionProvider.instance().registerFunction(new SetFoodLevelFunction()); JavaFunctionProvider.instance().registerFunction(new SolidBlockBellowFunction()); - LogFunctions.register(); // Others EntityAttributes.register(); diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationBlockCircle.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationBlockCircle.java index d0627777..45cbdf94 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationBlockCircle.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationBlockCircle.java @@ -2,7 +2,7 @@ import fr.jamailun.ultimatespellsystem.UssLogger; import fr.jamailun.ultimatespellsystem.api.providers.AnimationsProvider; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.bukkit.Location; import org.bukkit.Material; import org.jetbrains.annotations.NotNull; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationBlockShape.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationBlockShape.java index 24afae4d..380a416d 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationBlockShape.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationBlockShape.java @@ -1,7 +1,7 @@ package fr.jamailun.ultimatespellsystem.extension.animations; import fr.jamailun.ultimatespellsystem.api.animations.Animation; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import fr.jamailun.ultimatespellsystem.plugin.utils.Pair; import fr.jamailun.ultimatespellsystem.plugin.utils.holders.BlockHolder; import org.bukkit.Location; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationBlockSquare.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationBlockSquare.java index 6b647121..f269a5c1 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationBlockSquare.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationBlockSquare.java @@ -2,7 +2,7 @@ import fr.jamailun.ultimatespellsystem.UssLogger; import fr.jamailun.ultimatespellsystem.api.providers.AnimationsProvider; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.bukkit.Location; import org.bukkit.Material; import org.jetbrains.annotations.NotNull; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationItemsExplode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationItemsExplode.java index 8b37afbc..5b81bce6 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationItemsExplode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationItemsExplode.java @@ -4,7 +4,7 @@ import fr.jamailun.ultimatespellsystem.api.UltimateSpellSystem; import fr.jamailun.ultimatespellsystem.api.animations.Animation; import fr.jamailun.ultimatespellsystem.api.providers.AnimationsProvider; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import lombok.Getter; import org.bukkit.Location; import org.bukkit.Material; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationParticleCircle.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationParticleCircle.java index a70e762e..80296edc 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationParticleCircle.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationParticleCircle.java @@ -3,7 +3,7 @@ import fr.jamailun.ultimatespellsystem.UssLogger; import fr.jamailun.ultimatespellsystem.api.animations.AnimationParticle; import fr.jamailun.ultimatespellsystem.api.providers.AnimationsProvider; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import lombok.Getter; import org.bukkit.Location; import org.bukkit.Particle; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationParticleSpiraling.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationParticleSpiraling.java index 983bc4a6..6e5f3ac1 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationParticleSpiraling.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/animations/AnimationParticleSpiraling.java @@ -3,7 +3,7 @@ import fr.jamailun.ultimatespellsystem.UssLogger; import fr.jamailun.ultimatespellsystem.api.animations.AnimationParticle; import fr.jamailun.ultimatespellsystem.api.providers.AnimationsProvider; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import lombok.Getter; import lombok.Setter; import org.bukkit.Location; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/callbacks/EntityDeathCallbacks.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/callbacks/EntityDeathCallbacks.java index 8e1fbcf0..1eaa6fcd 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/callbacks/EntityDeathCallbacks.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/callbacks/EntityDeathCallbacks.java @@ -3,7 +3,7 @@ import fr.jamailun.ultimatespellsystem.api.UltimateSpellSystem; import fr.jamailun.ultimatespellsystem.api.entities.CallbackAction; import fr.jamailun.ultimatespellsystem.api.entities.SummonAttributes; -import fr.jamailun.ultimatespellsystem.dsl.objects.CallbackEvent; +import fr.jamailun.ultimatespellsystem.dsl2.callbacks.CallbackEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.entity.EntityDeathEvent; import org.jetbrains.annotations.NotNull; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/callbacks/ProjectileLandCallbacks.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/callbacks/ProjectileLandCallbacks.java index 43eb474d..fb11f70d 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/callbacks/ProjectileLandCallbacks.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/callbacks/ProjectileLandCallbacks.java @@ -3,10 +3,6 @@ import fr.jamailun.ultimatespellsystem.api.UltimateSpellSystem; import fr.jamailun.ultimatespellsystem.api.entities.CallbackAction; import fr.jamailun.ultimatespellsystem.api.entities.SummonAttributes; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.dsl.objects.CallbackEvent; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenType; -import fr.jamailun.ultimatespellsystem.plugin.entities.BukkitSpellEntity; import org.bukkit.event.EventHandler; import org.bukkit.event.entity.ProjectileHitEvent; import org.jetbrains.annotations.NotNull; @@ -28,8 +24,9 @@ void onEvent(@NotNull ProjectileHitEvent event) { @Override public @NotNull Collection> getCallbacks() { + //FIXME repair the callbacks system return List.of( - new CallbackAction<>( + /*new CallbackAction<>( CallbackEvent.of("landed", TokenType.AT, TypePrimitive.LOCATION), ProjectileHitEvent.class, e -> e.getEntity().getLocation() @@ -38,7 +35,7 @@ void onEvent(@NotNull ProjectileHitEvent event) { CallbackEvent.of("hit", TokenType.TO, TypePrimitive.ENTITY), ProjectileHitEvent.class, e -> new BukkitSpellEntity(e.getHitEntity()) - ) + )*/ ); } diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/callbacks/SummonExpiresCallbacks.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/callbacks/SummonExpiresCallbacks.java index 91f8bb22..9d1dfa0a 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/callbacks/SummonExpiresCallbacks.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/callbacks/SummonExpiresCallbacks.java @@ -2,7 +2,7 @@ import fr.jamailun.ultimatespellsystem.api.entities.CallbackAction; import fr.jamailun.ultimatespellsystem.api.events.SummonedEntityExpiredEvent; -import fr.jamailun.ultimatespellsystem.dsl.objects.CallbackEvent; +import fr.jamailun.ultimatespellsystem.dsl2.callbacks.CallbackEvent; import org.bukkit.event.EventHandler; import org.jetbrains.annotations.NotNull; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/citizens/CasterTrait.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/citizens/CasterTrait.java index c96d7204..9e2b46fc 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/citizens/CasterTrait.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/citizens/CasterTrait.java @@ -112,6 +112,17 @@ public void save(@NotNull DataKey key) { return Optional.empty(); } + @Override + public Optional getEntityAs(Class clazz) { + return getBukkitEntity().map(e -> { + try { + return clazz.cast(e); + } catch(Exception ex) { + return null; + } + }); + } + @Override public @NotNull Location getLocation() { return getBukkitEntity().map(Entity::getLocation).orElse(getNPC().getStoredLocation()); diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/citizens/SpellCastRule.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/citizens/SpellCastRule.java index b517d52d..0c1c55b4 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/citizens/SpellCastRule.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/citizens/SpellCastRule.java @@ -4,9 +4,9 @@ import fr.jamailun.ultimatespellsystem.api.entities.SpellEntity; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.UltimateSpellSystemDSL; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.UltimateSpellSystemDSL2; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import fr.jamailun.ultimatespellsystem.plugin.utils.DurationHelper; import lombok.Getter; import net.citizensnpcs.api.util.DataKey; @@ -41,7 +41,7 @@ private void load() { if(rawCondition.isEmpty()) { condition = null; } else { - ExpressionNode expression = UltimateSpellSystemDSL.parseExpression(rawCondition); + ExpressionNode expression = UltimateSpellSystemDSL2.parseExpression(rawCondition); condition = UltimateSpellSystem.getExternalExecutor().handleImplementation(expression); } } diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/citizens/SpellCasterCommand.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/citizens/SpellCasterCommand.java index 6055185c..912c3ece 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/citizens/SpellCasterCommand.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/citizens/SpellCasterCommand.java @@ -2,7 +2,7 @@ import fr.jamailun.ultimatespellsystem.api.UltimateSpellSystem; import fr.jamailun.ultimatespellsystem.api.spells.Spell; -import fr.jamailun.ultimatespellsystem.dsl.UltimateSpellSystemDSL; +import fr.jamailun.ultimatespellsystem.dsl2.UltimateSpellSystemDSL2; import fr.jamailun.ultimatespellsystem.plugin.utils.DurationHelper; import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.npc.NPC; @@ -137,7 +137,7 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command else condition = concat; // parse try { - UltimateSpellSystemDSL.parseExpression(condition); + UltimateSpellSystemDSL2.parseExpression(condition); } catch (Exception e) { sender.sendMessage("§cInvalid USS syntax: " + e.getMessage()); return true; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/AbstractFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/AbstractFunction.java index 124e3646..6512bd96 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/AbstractFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/AbstractFunction.java @@ -5,8 +5,9 @@ import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import fr.jamailun.ultimatespellsystem.api.runner.errors.InvalidTypeException; import fr.jamailun.ultimatespellsystem.api.runner.functions.RunnableJavaFunction; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; import fr.jamailun.ultimatespellsystem.plugin.entities.BukkitSpellEntity; import org.bukkit.Location; import org.bukkit.entity.Entity; @@ -76,4 +77,11 @@ protected double toDouble(@NotNull String context, @NotNull RuntimeExpression ex return n.doubleValue(); } + protected @NotNull Duration toDuration(@NotNull String context, @NotNull RuntimeExpression expression, @NotNull SpellRuntime runtime) { + Object raw = expression.evaluate(runtime); + if(raw instanceof Duration dur) + return dur; + throw new InvalidTypeException(context, "Duration", raw); + } + } diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/AreAlliesFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/AreAlliesFunction.java index d26fe46d..57e88173 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/AreAlliesFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/AreAlliesFunction.java @@ -4,9 +4,9 @@ import fr.jamailun.ultimatespellsystem.api.providers.AlliesProvider; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -26,11 +26,11 @@ public AreAlliesFunction() { // - b : entity 2 List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), + Type.of(TypePrimitive.ENTITY), "first-entity", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), + Type.of(TypePrimitive.ENTITY), "second-entity", false ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/CastSpellFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/CastSpellFunction.java index ad9e54e5..00966df5 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/CastSpellFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/CastSpellFunction.java @@ -6,9 +6,9 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import fr.jamailun.ultimatespellsystem.api.runner.errors.UnknownFunctionException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -28,11 +28,11 @@ public CastSpellFunction() { // - spell : the spell ID List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), + Type.of(TypePrimitive.ENTITY), "caster", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.STRING), + Type.of(TypePrimitive.STRING), "spell", false ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/DamageFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/DamageFunction.java index 4356016c..60cdc628 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/DamageFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/DamageFunction.java @@ -3,9 +3,9 @@ import fr.jamailun.ultimatespellsystem.api.events.EntityDamagedBySpellEvent; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import org.bukkit.Bukkit; import org.bukkit.entity.LivingEntity; import org.jetbrains.annotations.NotNull; @@ -26,15 +26,15 @@ public DamageFunction() { // Args : the location to strike List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), + Type.of(TypePrimitive.ENTITY), "target", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.NUMBER), + Type.of(TypePrimitive.NUMBER), "amount", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), + Type.of(TypePrimitive.ENTITY), "author", true ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/DirectionOfFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/DirectionOfFunction.java index 6487638e..5d91c96d 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/DirectionOfFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/DirectionOfFunction.java @@ -2,9 +2,8 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import org.bukkit.Location; import org.bukkit.entity.LivingEntity; import org.jetbrains.annotations.NotNull; @@ -20,11 +19,11 @@ public DirectionOfFunction() { super( "direction_of", // Returns "vector" - TypePrimitive.LOCATION.asType(), + TypePrimitive.VECTOR.asType(), // Args : the entity to read direction of List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), + TypePrimitive.ENTITY.asType(), "entity", false ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/DistanceFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/DistanceFunction.java index 4f489e39..d50a0d06 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/DistanceFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/DistanceFunction.java @@ -2,9 +2,8 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import org.bukkit.Location; import org.jetbrains.annotations.NotNull; @@ -25,11 +24,11 @@ public DistanceFunction() { // - b : location B List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.LOCATION, TypePrimitive.ENTITY), + TypePrimitive.LOCATION.asType(), "a", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.LOCATION, TypePrimitive.ENTITY), + TypePrimitive.LOCATION.asType(), "b", false ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/EntityHasEffectFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/EntityHasEffectFunction.java index 1942391a..5d35a121 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/EntityHasEffectFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/EntityHasEffectFunction.java @@ -3,10 +3,9 @@ import fr.jamailun.ultimatespellsystem.UssLogger; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.SendEffectNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old.SendEffectNode; import org.bukkit.entity.LivingEntity; import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; @@ -27,15 +26,15 @@ public EntityHasEffectFunction() { // Args : entity, effect, [min level] List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), + TypePrimitive.ENTITY.asType(), "entity", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.STRING, TypePrimitive.CUSTOM), + TypePrimitive.STRING.asType(), "effect", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.NUMBER), + TypePrimitive.NUMBER.asType(), "level", true ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/GetFoodLevelFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/GetFoodLevelFunction.java index aa30203f..2357388d 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/GetFoodLevelFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/GetFoodLevelFunction.java @@ -2,9 +2,9 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.LivingEntity; import org.jetbrains.annotations.NotNull; @@ -24,7 +24,7 @@ public GetFoodLevelFunction() { // Args : the entity to get health from List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), + Type.of(TypePrimitive.ENTITY), "entity", false ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/GetHealthFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/GetHealthFunction.java deleted file mode 100644 index f534a333..00000000 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/GetHealthFunction.java +++ /dev/null @@ -1,40 +0,0 @@ -package fr.jamailun.ultimatespellsystem.extension.functions; - -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; -import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import org.bukkit.entity.LivingEntity; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -/** - * get the health of an entity - */ -public class GetHealthFunction extends AbstractFunction { - - public GetHealthFunction() { - super( - "get_health", - // Returns the health value - TypePrimitive.NUMBER.asType(), - // Args : the entity to get health from - List.of( - new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), - "entity", false - ) - ) - ); - } - - @Override - public Double compute(@NotNull List arguments, @NotNull SpellRuntime runtime) { - LivingEntity target = toLivingEntity("get_health:entity", arguments.getFirst(), runtime); - if(target == null) - return 0d; - return target.getHealth(); - } -} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/GetMaxHealthFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/GetMaxHealthFunction.java deleted file mode 100644 index 7a5a2e1e..00000000 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/GetMaxHealthFunction.java +++ /dev/null @@ -1,45 +0,0 @@ -package fr.jamailun.ultimatespellsystem.extension.functions; - -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; -import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import org.bukkit.attribute.Attribute; -import org.bukkit.attribute.AttributeInstance; -import org.bukkit.entity.LivingEntity; -import org.jetbrains.annotations.NotNull; - -import java.util.List; -import java.util.Optional; - -/** - * Get the maximum health of a bukkit entity. - */ -public class GetMaxHealthFunction extends AbstractFunction { - - public GetMaxHealthFunction() { - super( - "get_max_health", - // Returns the health value - TypePrimitive.NUMBER.asType(), - // Args : the entity to get health from - List.of( - new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), - "entity", false - ) - ) - ); - } - - @Override - public Double compute(@NotNull List arguments, @NotNull SpellRuntime runtime) { - LivingEntity target = toLivingEntity("get_max_health:entity", arguments.getFirst(), runtime); - if(target == null) - return 0d; - return Optional.ofNullable(target.getAttribute(Attribute.GENERIC_MAX_HEALTH)) - .map(AttributeInstance::getValue) - .orElse(0d); - } -} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/HealEntityFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/HealEntityFunction.java deleted file mode 100644 index 8ae1c2c3..00000000 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/HealEntityFunction.java +++ /dev/null @@ -1,55 +0,0 @@ -package fr.jamailun.ultimatespellsystem.extension.functions; - -import fr.jamailun.ultimatespellsystem.api.events.EntityHealedBySpellEvent; -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; -import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import org.bukkit.Bukkit; -import org.bukkit.entity.LivingEntity; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -/** - * Heal an entity. - */ -public class HealEntityFunction extends AbstractFunction { - - public HealEntityFunction() { - super( - "heal", - // Returns new health - TypePrimitive.NUMBER.asType(), - // Args : the entity to heal, and the amount - List.of( - new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), - "entity", false - ), - new FunctionArgument( - FunctionType.accept(TypePrimitive.NUMBER), - "amount", false - ) - ) - ); - } - - @Override - public Double compute(@NotNull List arguments, @NotNull SpellRuntime runtime) { - LivingEntity target = toLivingEntity("heal:entity", arguments.get(0), runtime); - double amount = toDouble("heal:amount", arguments.get(1), runtime); - if(target == null) - return 0d; - - // Heal with an event - var event = new EntityHealedBySpellEvent(target, runtime.getCaster(), runtime.getSpell(), amount); - Bukkit.getPluginManager().callEvent(event); - if(!event.isCancelled()) { - target.heal(amount); - } - - return target.getHealth(); - } -} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/IsValidFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/IsValidFunction.java index 6be33280..5032e130 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/IsValidFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/IsValidFunction.java @@ -4,9 +4,8 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import fr.jamailun.ultimatespellsystem.api.runner.errors.InvalidTypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import org.bukkit.entity.Entity; import org.jetbrains.annotations.NotNull; @@ -25,7 +24,7 @@ public IsValidFunction() { // Args : the entity tio check. List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), + TypePrimitive.ENTITY.asType(), "entity", false ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/KnockbackFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/KnockbackFunction.java index a748de59..96f1438c 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/KnockbackFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/KnockbackFunction.java @@ -4,9 +4,9 @@ import fr.jamailun.ultimatespellsystem.api.entities.SpellEntity; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import fr.jamailun.ultimatespellsystem.plugin.utils.TypeInterpretation; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; @@ -22,22 +22,22 @@ public KnockbackFunction() { super( "knockback", // Returns nothing - TypePrimitive.NULL.asType(), + Type.NULL, // Args : // - entity : entity to knockback // - vector : velocity to apply. // - optional LENGTH List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), + Type.of(TypePrimitive.ENTITY), "entity", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.LOCATION, TypePrimitive.NUMBER), + Type.of(TypePrimitive.VECTOR), "velocity", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.NUMBER), + Type.of(TypePrimitive.NUMBER), "length", true ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/LocationToListFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/LocationToListFunction.java deleted file mode 100644 index 49c0d53b..00000000 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/LocationToListFunction.java +++ /dev/null @@ -1,58 +0,0 @@ -package fr.jamailun.ultimatespellsystem.extension.functions; - -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; -import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.api.runner.errors.InvalidTypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import org.bukkit.Location; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; - -/** - * Transform a location to a vector. - */ -public class LocationToListFunction extends AbstractFunction { - - public LocationToListFunction() { - super( - "loc_to_list", - // Returns true if success - TypePrimitive.NUMBER.asType(true), - // Args : the location to strike - List.of( - new FunctionArgument( - FunctionType.accept(TypePrimitive.LOCATION, TypePrimitive.NUMBER), - "location", false - ) - ) - ); - } - - @Override - public Object compute(@NotNull List arguments, @NotNull SpellRuntime runtime) { - Object arg = arguments.getFirst().evaluate(runtime); - if(arg instanceof Location loc) { - return List.of(loc.getX(), loc.getY(), loc.getZ()); - } else if(arg instanceof List list) { - List output = new ArrayList<>(); - for(Object obj : list) { - if(!(obj instanceof Double d)) - throw new InvalidTypeException("loc_to_list:loc", "got a list with a non-number: " + obj); - // Add the double. - output.add(d); - if(output.size() == 3) - break; - } - // Fill with 0 if needed - for(int i = output.size(); i < 3; i++) output.add(0d); - return output; - } else if(arg instanceof Double) { - throw new InvalidTypeException("loc_to_list:loc", "the argument must be a LIST of numbers, not just a single number."); - } - throw new InvalidTypeException("loc_to_list:loc", "location/number[]", arg); - } -} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/LogFunctions.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/LogFunctions.java deleted file mode 100644 index 20bac6dd..00000000 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/LogFunctions.java +++ /dev/null @@ -1,57 +0,0 @@ -package fr.jamailun.ultimatespellsystem.extension.functions; - -import fr.jamailun.ultimatespellsystem.UssLogger; -import fr.jamailun.ultimatespellsystem.api.providers.JavaFunctionProvider; -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; -import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import org.jetbrains.annotations.NotNull; - -import java.util.List; -import java.util.Objects; -import java.util.function.Consumer; - -public abstract class LogFunctions extends AbstractFunction { - - private final Consumer function; - protected LogFunctions(String id, Consumer function) { - super(id, TypePrimitive.NULL.asType(), List.of(new FunctionArgument(FunctionType.accept(TypePrimitive.STRING), "str", false))); - this.function = function; - } - @Override - public final Void compute(@NotNull List arguments, @NotNull SpellRuntime runtime) { - function.accept(Objects.toString(arguments.getFirst().evaluate(runtime))); - return null; - } - - public static void register() { - JavaFunctionProvider.instance().registerFunction(new LogInfoFunction()); - JavaFunctionProvider.instance().registerFunction(new LogWarnFunction()); - JavaFunctionProvider.instance().registerFunction(new LogDebugFunction()); - JavaFunctionProvider.instance().registerFunction(new LogErrorFunction()); - } - - public static class LogInfoFunction extends LogFunctions { - public LogInfoFunction() { - super("INFO", UssLogger::logInfo); - } - } - public static class LogWarnFunction extends LogFunctions { - public LogWarnFunction() { - super("WARN", UssLogger::logWarning); - } - } - public static class LogDebugFunction extends LogFunctions { - public LogDebugFunction() { - super("DEBUG", UssLogger::logDebug); - } - } - public static class LogErrorFunction extends LogFunctions { - public LogErrorFunction() { - super("ERROR", UssLogger::logError); - } - } - -} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/NormalizeFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/NormalizeFunction.java index 09067db5..0e2b54a0 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/NormalizeFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/NormalizeFunction.java @@ -2,9 +2,9 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import fr.jamailun.ultimatespellsystem.plugin.utils.TypeInterpretation; import org.jetbrains.annotations.NotNull; @@ -19,12 +19,12 @@ public NormalizeFunction() { super( "normalize", // Returns nothing - TypePrimitive.LOCATION.asType(), + TypePrimitive.VECTOR.asType(), // Args : // location-vector to normalize List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.LOCATION), + Type.of(TypePrimitive.VECTOR), "vector", false ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/RandFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/RandFunction.java index 4772d569..c01f2e66 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/RandFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/RandFunction.java @@ -2,9 +2,8 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -27,11 +26,11 @@ public RandFunction() { // - upper bound List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.NUMBER), + TypePrimitive.NUMBER.asType(), "lower_bound", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.NUMBER), + TypePrimitive.NUMBER.asType(), "upper_bound", false ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/RandIntFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/RandIntFunction.java index 575e478a..63f54a65 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/RandIntFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/RandIntFunction.java @@ -2,9 +2,9 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -27,11 +27,11 @@ public RandIntFunction() { // - upper bound List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.NUMBER), + Type.of(TypePrimitive.NUMBER), "lower_bound", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.NUMBER), + Type.of(TypePrimitive.NUMBER), "upper_bound", false ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/RayCastFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/RayCastFunction.java index 1de48390..82056924 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/RayCastFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/RayCastFunction.java @@ -4,9 +4,9 @@ import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import fr.jamailun.ultimatespellsystem.api.runner.errors.InvalidTypeException; import fr.jamailun.ultimatespellsystem.api.entities.SpellEntity; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import org.bukkit.FluidCollisionMode; import org.bukkit.Location; import org.bukkit.util.RayTraceResult; @@ -31,15 +31,15 @@ public RayCastFunction() { // - max : max travel distance List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.LOCATION, TypePrimitive.ENTITY), + Type.of(TypePrimitive.LOCATION), "source", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.NUMBER, TypePrimitive.NULL, TypePrimitive.LOCATION, TypePrimitive.ENTITY), + Type.of(TypePrimitive.VECTOR), "direction", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.NUMBER), + Type.of(TypePrimitive.NUMBER), "max", false ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SetAggroFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SetAggroFunction.java index 96721bb7..54dc241a 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SetAggroFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SetAggroFunction.java @@ -2,9 +2,9 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Mob; import org.jetbrains.annotations.NotNull; @@ -19,14 +19,14 @@ public class SetAggroFunction extends AbstractFunction { public SetAggroFunction() { super( "set_aggro", - TypePrimitive.NULL.asType(), + Type.NULL, List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), + Type.of("entity"), "entity", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), + Type.of("entity"), "target", false ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SetFireFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SetFireFunction.java index 0b30383d..2d37e651 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SetFireFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SetFireFunction.java @@ -2,9 +2,10 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; import org.bukkit.entity.LivingEntity; import org.jetbrains.annotations.NotNull; @@ -23,11 +24,11 @@ public SetFireFunction() { // Args : the entity to set on fire List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), + Type.of(TypePrimitive.ENTITY), "entity", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.NUMBER), + Type.of(TypePrimitive.DURATION), "ticks", false ) ) @@ -39,8 +40,8 @@ public Object compute(@NotNull List arguments, @NotNull Spell LivingEntity entity = toLivingEntity("set_fire:entity", arguments.getFirst(), runtime); if(entity == null) return false; - int ticks = toInteger("set_fire:ticks", arguments.get(1), runtime); - entity.setFireTicks(ticks); + Duration duration = toDuration("set_fire:ticks", arguments.get(1), runtime); + entity.setFireTicks((int) duration.toTicks()); return true; } diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SetFoodLevelFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SetFoodLevelFunction.java index 26f71dc2..248d0af0 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SetFoodLevelFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SetFoodLevelFunction.java @@ -2,9 +2,9 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.LivingEntity; import org.jetbrains.annotations.NotNull; @@ -24,11 +24,11 @@ public SetFoodLevelFunction() { // Args : the entity to set on fire List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), + Type.of(TypePrimitive.ENTITY), "entity", false ), new FunctionArgument( - FunctionType.accept(TypePrimitive.NUMBER), + Type.of(TypePrimitive.NUMBER), "amount", false ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SetNameFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SetNameFunction.java deleted file mode 100644 index 96dd52c2..00000000 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SetNameFunction.java +++ /dev/null @@ -1,42 +0,0 @@ -package fr.jamailun.ultimatespellsystem.extension.functions; - -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; -import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import org.bukkit.entity.LivingEntity; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -/** - * Set the custom name of an entity. - */ -public class SetNameFunction extends AbstractFunction { - - public SetNameFunction() { - super( - "set_name", - TypePrimitive.NULL.asType(), - List.of( - new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), - "entity", false - ), - new FunctionArgument( - FunctionType.accept(TypePrimitive.STRING), - "name", false - ) - ) - ); - } - - @Override - public Void compute(@NotNull List arguments, @NotNull SpellRuntime runtime) { - LivingEntity entity = toLivingEntity("v:entity", arguments.get(0), runtime); - String value = runtime.safeEvaluate(arguments.get(1), String.class); - entity.setCustomName(value); - return null; - } -} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SolidBlockBellowFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SolidBlockBellowFunction.java index 052c8b62..8975b2e8 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SolidBlockBellowFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/SolidBlockBellowFunction.java @@ -2,12 +2,11 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import org.bukkit.Location; import org.bukkit.block.Block; -import org.bukkit.entity.LivingEntity; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -20,8 +19,8 @@ public SolidBlockBellowFunction() { TypePrimitive.LOCATION.asType(), List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY), - "entity", false + Type.of(TypePrimitive.LOCATION), + "location", false ) ) ); @@ -29,14 +28,14 @@ public SolidBlockBellowFunction() { @Override public Location compute(@NotNull List arguments, @NotNull SpellRuntime runtime) { - LivingEntity entity = toLivingEntity("block_below:entity", arguments.getFirst(), runtime); - if(entity == null) return null; - int worldMinY = entity.getWorld().getMinHeight(); - int x = entity.getLocation().getBlockX(); - int z = entity.getLocation().getBlockZ(); + Location location = toLocation("block_below:entity", arguments.getFirst(), runtime); - for(int y = entity.getLocation().getBlockY(); y >= worldMinY; y--) { - Block block = entity.getWorld().getBlockAt(x, y, z); + int worldMinY = location.getWorld().getMinHeight(); + int x = location.getBlockX(); + int z = location.getBlockZ(); + + for(int y = location.getBlockY(); y >= worldMinY; y--) { + Block block = location.getWorld().getBlockAt(x, y, z); if( !block.isEmpty() && !block.isPassable()) { return block.getLocation(); } diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/StrikeFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/StrikeFunction.java index 74531191..c7cb0025 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/StrikeFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/functions/StrikeFunction.java @@ -2,9 +2,9 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import org.bukkit.Location; import org.jetbrains.annotations.NotNull; @@ -23,7 +23,7 @@ public StrikeFunction() { // Args : the location to strike List.of( new FunctionArgument( - FunctionType.accept(TypePrimitive.ENTITY, TypePrimitive.LOCATION), + Type.of(TypePrimitive.LOCATION), "target", false ) ) diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/providers/EntityTypes.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/providers/EntityTypes.java index 2f8b8348..653a259b 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/providers/EntityTypes.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/extension/providers/EntityTypes.java @@ -2,7 +2,7 @@ import fr.jamailun.ultimatespellsystem.api.entities.UssEntityType; import fr.jamailun.ultimatespellsystem.api.providers.EntityTypeProvider; -import fr.jamailun.ultimatespellsystem.dsl.registries.EntityTypeRegistry; +import fr.jamailun.ultimatespellsystem.dsl2.registries.EntityTypeRegistry; import fr.jamailun.ultimatespellsystem.plugin.entities.implem.Orb; import org.bukkit.entity.EntityType; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/ItemBinderImpl.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/ItemBinderImpl.java index 7516baed..257dea77 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/ItemBinderImpl.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/ItemBinderImpl.java @@ -6,7 +6,7 @@ import fr.jamailun.ultimatespellsystem.api.events.ItemBoundEvent; import fr.jamailun.ultimatespellsystem.api.events.ItemUnBoundEvent; import fr.jamailun.ultimatespellsystem.UssKeys; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.bukkit.Bukkit; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/LegacySpellBindData.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/LegacySpellBindData.java index 0fd7b2dc..7c26d7a9 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/LegacySpellBindData.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/LegacySpellBindData.java @@ -7,7 +7,7 @@ import fr.jamailun.ultimatespellsystem.api.bind.SpellCost; import fr.jamailun.ultimatespellsystem.api.bind.SpellTrigger; import fr.jamailun.ultimatespellsystem.api.spells.Spell; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import fr.jamailun.ultimatespellsystem.plugin.bind.costs.ItemAmountSpellCost; import fr.jamailun.ultimatespellsystem.plugin.bind.costs.NoneSpellCost; import fr.jamailun.ultimatespellsystem.plugin.spells.NotFoundSpell; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/SpellBindDataImpl.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/SpellBindDataImpl.java index 96649157..1d043f32 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/SpellBindDataImpl.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/SpellBindDataImpl.java @@ -3,7 +3,7 @@ import fr.jamailun.ultimatespellsystem.api.bind.SpellBindData; import fr.jamailun.ultimatespellsystem.api.bind.SpellTrigger; import fr.jamailun.ultimatespellsystem.api.spells.Spell; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/SpellBindDataSerializer.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/SpellBindDataSerializer.java index ae32123d..45267251 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/SpellBindDataSerializer.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/bind/SpellBindDataSerializer.java @@ -4,7 +4,7 @@ import fr.jamailun.ultimatespellsystem.api.bind.ItemBindTrigger; import fr.jamailun.ultimatespellsystem.api.bind.SpellBindData; import fr.jamailun.ultimatespellsystem.api.spells.Spell; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import fr.jamailun.ultimatespellsystem.plugin.bind.costs.SpellCostFactory; import fr.jamailun.ultimatespellsystem.plugin.spells.NotFoundSpell; import org.jetbrains.annotations.NotNull; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/commands/UssCommand.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/commands/UssCommand.java index 5f7d9ccc..da30e2ac 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/commands/UssCommand.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/commands/UssCommand.java @@ -9,12 +9,12 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.spells.Spell; import fr.jamailun.ultimatespellsystem.api.utils.MultivaluedMap; -import fr.jamailun.ultimatespellsystem.dsl.UltimateSpellSystemDSL; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.UltimateSpellSystemDSL2; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import fr.jamailun.ultimatespellsystem.plugin.bind.SpellBindDataImpl; import fr.jamailun.ultimatespellsystem.plugin.bind.SpellTriggerImpl; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.SendAttributeNode; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old.SendAttributeNode; import fr.jamailun.ultimatespellsystem.plugin.configuration.UssConfig; import fr.jamailun.ultimatespellsystem.plugin.utils.DurationHelper; import fr.jamailun.ultimatespellsystem.plugin.utils.Pair; @@ -95,7 +95,7 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command // Parse try { - ExpressionNode raw = UltimateSpellSystemDSL.parseExpression(code); + ExpressionNode raw = UltimateSpellSystemDSL2.parseExpression(code); RuntimeExpression expression = UltimateSpellSystem.getExternalExecutor().handleImplementation(raw); Object out = expression.evaluate(UltimateSpellSystem.getExternalExecutor().generateRuntime(player)); diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/configuration/MainConfiguration.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/configuration/MainConfiguration.java index 2e9e7c6f..9d52ae93 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/configuration/MainConfiguration.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/configuration/MainConfiguration.java @@ -2,7 +2,7 @@ import fr.jamailun.ultimatespellsystem.api.bind.ItemBindTrigger; import fr.jamailun.ultimatespellsystem.api.bind.SpellCost; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnmodifiableView; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/configuration/MainConfigurationVersion1.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/configuration/MainConfigurationVersion1.java index 3b420000..2c3969f9 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/configuration/MainConfigurationVersion1.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/configuration/MainConfigurationVersion1.java @@ -7,7 +7,7 @@ import fr.jamailun.ultimatespellsystem.api.bind.ItemBindTrigger; import fr.jamailun.ultimatespellsystem.api.bind.SpellCost; import fr.jamailun.ultimatespellsystem.api.bind.SpellCostEntry; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import fr.jamailun.ultimatespellsystem.plugin.bind.costs.NoneSpellCost; import fr.jamailun.ultimatespellsystem.plugin.utils.DurationHelper; import lombok.Getter; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/configuration/UssConfig.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/configuration/UssConfig.java index a8068cb3..f212e3bc 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/configuration/UssConfig.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/configuration/UssConfig.java @@ -5,7 +5,7 @@ import fr.jamailun.ultimatespellsystem.UssLogger; import fr.jamailun.ultimatespellsystem.api.bind.ItemBindTrigger; import fr.jamailun.ultimatespellsystem.api.bind.SpellCost; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import fr.jamailun.ultimatespellsystem.plugin.utils.observable.AbstractObservable; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.plugin.Plugin; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/entities/BukkitSpellEntity.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/entities/BukkitSpellEntity.java index d0c04eda..4cf1249c 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/entities/BukkitSpellEntity.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/entities/BukkitSpellEntity.java @@ -74,6 +74,17 @@ public void setVelocity(@NotNull Vector vector) { getBukkitEntity().ifPresent(entity -> entity.setVelocity(vector)); } + @Override + public Optional getEntityAs(Class clazz) { + return getBukkitEntity().map(e -> { + try { + return clazz.cast(e); + } catch(Exception ex) { + return null; + } + }); + } + @Override public boolean equals(Object other) { if(other == null) return false; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/entities/SummonAttributesImpl.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/entities/SummonAttributesImpl.java index 9ea02a00..73f16803 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/entities/SummonAttributesImpl.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/entities/SummonAttributesImpl.java @@ -8,7 +8,7 @@ import fr.jamailun.ultimatespellsystem.api.events.SummonedEntityExpiredEvent; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import fr.jamailun.ultimatespellsystem.api.providers.SummonPropertiesProvider; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.*; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/listeners/BoundSpellCastListener.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/listeners/BoundSpellCastListener.java index 9ea9b8dd..35411e5e 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/listeners/BoundSpellCastListener.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/listeners/BoundSpellCastListener.java @@ -2,7 +2,7 @@ import fr.jamailun.ultimatespellsystem.api.events.BoundSpellCastEvent; import fr.jamailun.ultimatespellsystem.api.utils.StringTransformation; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import fr.jamailun.ultimatespellsystem.plugin.configuration.UssConfig; import fr.jamailun.ultimatespellsystem.plugin.spells.SpellsCooldowns; import org.bukkit.GameMode; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/listeners/PlayerLeaveListener.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/listeners/PlayerLeaveListener.java index 70fc1fc7..ea6f5f5a 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/listeners/PlayerLeaveListener.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/listeners/PlayerLeaveListener.java @@ -1,7 +1,7 @@ package fr.jamailun.ultimatespellsystem.plugin.listeners; import fr.jamailun.ultimatespellsystem.api.UltimateSpellSystem; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.SendAttributeNode; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old.SendAttributeNode; import fr.jamailun.ultimatespellsystem.plugin.spells.SpellsCooldowns; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/AbstractSpellRuntime.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/AbstractSpellRuntime.java index 501f01a1..dd42c148 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/AbstractSpellRuntime.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/AbstractSpellRuntime.java @@ -1,11 +1,13 @@ package fr.jamailun.ultimatespellsystem.plugin.runner; -import fr.jamailun.ultimatespellsystem.api.runner.FlowState; -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; -import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.api.runner.VariablesSet; +import fr.jamailun.ultimatespellsystem.api.runner.*; +import fr.jamailun.ultimatespellsystem.api.runner.structs.Struct; import fr.jamailun.ultimatespellsystem.api.spells.Spell; +import fr.jamailun.ultimatespellsystem.plugin.runner.structs.ConsoleDefinition; +import fr.jamailun.ultimatespellsystem.plugin.runner.structs.EntityDefinition; +import fr.jamailun.ultimatespellsystem.plugin.runner.structs.StructsLibrary; import lombok.Getter; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -17,25 +19,40 @@ */ public abstract class AbstractSpellRuntime implements SpellRuntime { + protected final Map cachedStructures = new HashMap<>(); + protected final StructsLibrary structsLibrary; protected final VariablesSet variables; + protected final FunctionsSet functions; protected final ExitCode exitCode; @Getter protected final Spell spell; protected boolean flagBreak = false; protected boolean flagContinue = false; + protected final boolean inFunction; - AbstractSpellRuntime(@NotNull AbstractSpellRuntime parent) { + AbstractSpellRuntime(@NotNull AbstractSpellRuntime parent, boolean inFunction) { exitCode = parent.exitCode; variables = parent.variables.inherit(); + functions = parent.functions.inherit(); flagContinue = parent.flagContinue; flagBreak = parent.flagBreak; spell = parent.spell; + cachedStructures.putAll(parent.cachedStructures); + this.inFunction = inFunction; + structsLibrary = parent.structsLibrary; } AbstractSpellRuntime(@NotNull ExitCode exitCode, @Nullable Spell spell) { this.exitCode = exitCode; variables = new VariablesSetImpl(); + functions = new FunctionsSetImpl(); this.spell = spell; + structsLibrary = new StructsLibrary(); + inFunction = false; + + // Register base structs + structsLibrary.register(new EntityDefinition()); + structsLibrary.register(new ConsoleDefinition()); } @Override @@ -48,6 +65,11 @@ public boolean isStopped() { return variables; } + @Override + public @NotNull FunctionsSet functions() { + return functions; + } + @Override public @Nullable T safeEvaluate(RuntimeExpression expression, Class clazz) { if(expression == null) @@ -83,25 +105,23 @@ public boolean isStopped() { } @Override - public void stop(int exitCode) { - this.exitCode.set(exitCode); + public @Nullable Object getReturnedValue() { + return exitCode.getValue(); } @Override - public int getFinalExitCode() { - return exitCode.getCode(); + public boolean isReturnValueSuccess() { + return switch (getReturnedValue()) { + case null -> true; + case Number num -> num.intValue() == 0; + case Boolean b -> b; + default -> false; + }; } - @Getter - public static class ExitCode { - private int code = 0; - private boolean set = false; - public void set(int value) { - if(!set) { - set = true; - code = value; - } - } + @Override + public void statementReturn(@Nullable Object value) { + exitCode.set(value); } @Override @@ -131,4 +151,37 @@ public void acceptContinue() { return FlowState.RUNNING; } + @Override + public @Nullable Struct getStructOf(@NotNull String structName, @Nullable Object value) { + if(value == null) return null; + + StructPtr ptr = StructPtr.of(structName, value); + return cachedStructures.computeIfAbsent(ptr, x -> + structsLibrary.instantiate(structName, value) + ); + } + + // ---- utils + + @Getter + public static class ExitCode { + private Object value; + private boolean set = false; + public void set(Object value) { + if(!set) { + set = true; + this.value = value; + } + } + } + + protected record StructPtr( + String structName, + int objHash + ) { + @Contract("_, _ -> new") + static @NotNull StructPtr of(String structName, Object object) { + return new StructPtr(structName, Objects.hashCode(object)); + } + } } diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/FunctionsSetImpl.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/FunctionsSetImpl.java new file mode 100644 index 00000000..ea45e7cb --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/FunctionsSetImpl.java @@ -0,0 +1,35 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner; + +import fr.jamailun.ultimatespellsystem.api.runner.FunctionsSet; +import fr.jamailun.ultimatespellsystem.api.runner.functions.GlobalFunction; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionSignature; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +/** + * A set of keyed variables. + */ +public final class FunctionsSetImpl implements FunctionsSet { + + private final Map functions = new HashMap<>(); + + @Override + public @Nullable GlobalFunction get(@NotNull FunctionSignature signature) { + return functions.get(signature); + } + + @Override + public @NotNull FunctionsSetImpl inherit() { + FunctionsSetImpl output = new FunctionsSetImpl(); + output.functions.putAll(functions); + return output; + } + + @Override + public void register(@NotNull GlobalFunction function) { + functions.put(function.getSignature(), function); + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/SpellRuntimeImpl.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/SpellRuntimeImpl.java index 5f3e1b58..fb0ce595 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/SpellRuntimeImpl.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/SpellRuntimeImpl.java @@ -1,6 +1,7 @@ package fr.jamailun.ultimatespellsystem.plugin.runner; import fr.jamailun.ultimatespellsystem.api.entities.SpellEntity; +import fr.jamailun.ultimatespellsystem.api.runner.FunctionsSet; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import fr.jamailun.ultimatespellsystem.api.spells.Spell; import fr.jamailun.ultimatespellsystem.plugin.entities.BukkitSpellEntity; @@ -17,6 +18,11 @@ public final class SpellRuntimeImpl extends AbstractSpellRuntime { private final SpellEntity caster; + /** + * Create a new context. + * @param caster bukkit-implementation of the caster. + * @param spell spell to use. + */ public SpellRuntimeImpl(@NotNull LivingEntity caster, @Nullable Spell spell) { this(new BukkitSpellEntity(caster), spell); } @@ -24,26 +30,28 @@ public SpellRuntimeImpl(@NotNull LivingEntity caster, @Nullable Spell spell) { /** * Create a new context. * @param caster the caster to declare. + * @param spell spell to use. */ public SpellRuntimeImpl(@NotNull SpellEntity caster, @Nullable Spell spell) { super(new ExitCode(), spell); this.caster = caster; variables.set("caster", caster); + variables.set("console", new Object()); } - private SpellRuntimeImpl(@NotNull SpellRuntimeImpl parent) { - super(parent); - this.caster = parent.caster; + private SpellRuntimeImpl(@NotNull SpellRuntimeImpl parent, @NotNull SpellEntity caster, boolean inFunction) { + super(parent, inFunction); + this.caster = caster; } @Override - public @NotNull SpellRuntime makeChild() { - return makeChildNewCaster(caster); + public @NotNull SpellRuntime makeChild(boolean inFunction) { + return new SpellRuntimeImpl(this, caster, inFunction); } @Override public @NotNull SpellRuntime makeChildNewCaster(@NotNull SpellEntity newCaster) { - return new SpellRuntimeImpl(this); + return new SpellRuntimeImpl(this, newCaster, false); } @Override diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/builder/ExpressionQueue.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/builder/ExpressionQueue.java index 915babba..9c7153fe 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/builder/ExpressionQueue.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/builder/ExpressionQueue.java @@ -1,26 +1,31 @@ package fr.jamailun.ultimatespellsystem.plugin.runner.builder; import fr.jamailun.ultimatespellsystem.api.providers.JavaFunctionProvider; -import fr.jamailun.ultimatespellsystem.api.runner.errors.UnknownFunctionException; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; -import fr.jamailun.ultimatespellsystem.plugin.runner.functions.JavaFunctionCallNode; import fr.jamailun.ultimatespellsystem.api.runner.functions.RunnableJavaFunction; +import fr.jamailun.ultimatespellsystem.dsl2.library.StructDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.FunctionCallExpression; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.litteral.NullLiteral; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators.IncrementExpression; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.plugin.runner.functions.JavaFunctionCallNode; import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.compute.AllEntitiesAroundExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionCallExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.compute.PositionOfExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.compute.SizeOfExpression; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators.BiOperator; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators.MonoOperator; -import fr.jamailun.ultimatespellsystem.dsl.visitor.ExpressionVisitor; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.*; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.litteral.*; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators.BiOperator; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.operators.MonoOperator; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.ExpressionVisitor; import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.expressions.*; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list.ArrayGetNode; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list.ListAddRemOpe; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list.ListContainsOpe; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list.ListRemIndexOpe; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list.RunListAddOpe; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list.RunListContainsOpe; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list.RunListRemIndexOpe; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list.RunListRemOpe; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.objects.ArrayGetNode; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.objects.GlobalFunctionCallNode; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.objects.StructFieldGetNode; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.objects.StructFunctionCallNode; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -39,52 +44,42 @@ RuntimeExpression fetch() { } @Override - public void handlePropertiesSet(@NotNull PropertiesExpression expression) { - Map map = new HashMap<>(); - for(Map.Entry dslEntry : expression.getExpressions().entrySet()) { - RuntimeExpression node = evaluate(dslEntry.getValue()); - map.put(dslEntry.getKey(), node); - } - add(new PropertiesLiteral(map)); + public void handleNullLiteral(@NotNull NullLiteral literal) { + add(new fr.jamailun.ultimatespellsystem.plugin.runner.nodes.expressions.NullLiteral()); } @Override - public void handleAllAround(@NotNull AllEntitiesAroundExpression expression) { - RuntimeExpression distance = evaluate(expression.getDistance()); - RuntimeExpression scope = evaluate(expression.getEntityType()); - RuntimeExpression source = evaluate(expression.getSource()); - boolean including = expression.isIncluding(); - add(new AllAroundNode(distance, scope, source, including)); + public void handleBooleanLiteral(@NotNull BooleanLiteral literal) { + add(new RawLiteral<>(literal.getRaw())); } @Override - public void handlePositionOf(@NotNull PositionOfExpression expression) { - RuntimeExpression entity = evaluate(expression.getEntity()); - add(new PositionOfNode(entity, expression.getExpressionType().isCollection())); + public void handleNumberLiteral(@NotNull NumberLiteral literal) { + add(new RawLiteral<>(literal.getRaw())); } @Override - public void handleSizeOf(@NotNull SizeOfExpression expression) { - RuntimeExpression child = evaluate(expression.getChild()); - add(new SizeOfNode(child)); + public void handleStringLiteral(@NotNull StringLiteral literal) { + add(new RawLiteral<>(literal.getRaw())); } @Override - public void handleFunction(@NotNull FunctionCallExpression expression) { - // 1. Find the EXECUTION of the function definition - RunnableJavaFunction function = JavaFunctionProvider.instance().find(expression.getFunction().id()); - if(function == null) - throw new UnknownFunctionException(expression.getFunction().id()); - // 2. Map arguments - List arguments = expression.getArguments().stream() - .map(this::evaluate) - .toList(); - // 3. Create node - add(new JavaFunctionCallNode(function, arguments)); + public void handleDurationLiteral(@NotNull DurationLiteral literal) { + add(new RawLiteral<>(literal.getRaw())); } @Override - public void handleArray(@NotNull ArrayExpression expression) { + public void handleMapLiteral(@NotNull MapLiteral literal) { + Map map = new HashMap<>(); + for(Map.Entry dslEntry : literal.getExpressions().entrySet()) { + RuntimeExpression node = evaluate(dslEntry.getValue()); + map.put(dslEntry.getKey(), node); + } + add(new PropertiesLiteral(map)); + } + + @Override + public void handleArray(@NotNull ArrayLiteral expression) { List elements = expression.getElements() .stream() .map(this::evaluate) @@ -93,45 +88,10 @@ public void handleArray(@NotNull ArrayExpression expression) { } @Override - public void handleVariable(@NotNull VariableExpression expression) { + public void handleVariable(@NotNull ReferenceExpression expression) { add(new VariableNode(expression.getVariableName())); } - @Override - public void handleNullLiteral(@NotNull NullExpression literal) { - add(new NullLiteral()); - } - - @Override - public void handleBooleanLiteral(@NotNull BooleanExpression literal) { - add(new RawLiteral<>(literal)); - } - - @Override - public void handleNumberLiteral(@NotNull NumberExpression literal) { - add(new RawLiteral<>(literal)); - } - - @Override - public void handleStringLiteral(@NotNull StringExpression literal) { - add(new RawLiteral<>(literal)); - } - - @Override - public void handleEntityTypeLiteral(@NotNull EntityTypeExpression literal) { - add(new EntityTypeLiteral(literal)); - } - - @Override - public void handleRuntimeLiteral(@NotNull RuntimeLiteral literal) { - add(new RawLiteral<>(literal)); - } - - @Override - public void handleDurationLiteral(@NotNull DurationExpression literal) { - add(new RawLiteral<>(literal)); - } - @Override public void handleLocationLiteral(@NotNull LocationLiteral literal) { RuntimeExpression world = evaluate(literal.getWorld()); @@ -139,7 +99,7 @@ public void handleLocationLiteral(@NotNull LocationLiteral literal) { RuntimeExpression y = evaluate(literal.getVectorY()); RuntimeExpression z = evaluate(literal.getVectorZ()); RuntimeExpression yaw = null, pitch = null; - if(literal.asYawAndPitch()) { + if(literal.hasYawAndPitch()) { yaw = evaluate(literal.getYaw()); pitch = evaluate(literal.getPitch()); } @@ -163,21 +123,21 @@ public void handleBiOperator(@NotNull BiOperator operator) { case LESSER -> new RunCompOpe(left, right, false, false); case AND -> new RunAndOrOpe(left, right, true); case OR -> new RunAndOrOpe(left, right, false); - case LIST_ADD -> new ListAddRemOpe(left, right, true); - case LIST_REM -> new ListAddRemOpe(left, right, false); - case LIST_CONTAINS -> new ListContainsOpe(left, right); - case LIST_REM_INDEX -> new ListRemIndexOpe(left, right); + case LIST_ADD -> new RunListAddOpe(left, right); + case LIST_REM -> new RunListRemOpe(left, right); + case LIST_REM_INDEX -> new RunListRemIndexOpe(left, right); + case LIST_CONTAINS -> new RunListContainsOpe(left, right); }); } @Override public void handleMonoOperator(@NotNull MonoOperator operator) { RuntimeExpression child = evaluate(operator.getChild()); - if(operator.getType() == MonoOperator.MonoOpeType.NOT) { - add(new RunNotOpe(child)); - } else { - add(new RunMathOpe(child, operator.getType())); - } + RuntimeMonoOperator expr = switch (operator.getType()) { + case NOT -> new RunNotOpe(child); + case SIZE_OF -> new RunSizeofOpe(child); + }; + add(expr); } @Override @@ -192,11 +152,60 @@ public void handleArrayGet(@NotNull ArrayGetterExpression arrayGetter) { add(new ArrayGetNode(array, index)); } + @Override + public void handleFieldGet(@NotNull FieldGetExpression fieldGetter) { + RuntimeExpression pointer = evaluate(fieldGetter.getLeftExpression()); + StructDefinition pointerStruct = fieldGetter.getLeftStruct(); + String fieldName = fieldGetter.getFieldName(); + add(new StructFieldGetNode(fieldGetter.firstTokenPosition(), pointer, pointerStruct, fieldName)); + } + + @Override + public void handleFunctionCall(@NotNull FunctionCallExpression functionCall) { + RuntimeExpression caller = evaluate(functionCall.getCaller()); + String functionName = functionCall.getFunctionName(); + TokenPosition pos = functionCall.getPosition(); + + // Map parameters + List parameters = new ArrayList<>(); + for(ExpressionNode param : functionCall.getArguments()) { + parameters.add(evaluate(param)); + } + + // No caller : "global" function + if(caller == null) { + // Is it a java function ? + RunnableJavaFunction function = JavaFunctionProvider.instance().find(functionName); + if(function != null) { + add(new JavaFunctionCallNode(pos, function, parameters)); + } + // User-defined function instead + else { + add(new GlobalFunctionCallNode(pos, functionCall.getSignature(), parameters)); + } + return; + } + + // A caller : struct-function call. + StructDefinition callerStruct = functionCall.getCallerStruct(); + add(new StructFunctionCallNode(pos, caller, callerStruct, functionName, parameters)); + } + + @Override + public void handleIncrementDecrement(@NotNull IncrementExpression expression) { + String varName = expression.getVarName(); + boolean increment = expression.isPositive(); + boolean postFix = expression.isAfterVar(); + add(new IncrementNode(varName, increment, postFix)); + } + private void add(RuntimeExpression expression) { currentExpressions.add(expression); } + @Contract("null -> null; !null -> new") private RuntimeExpression evaluate(ExpressionNode dsl) { + if(dsl == null) return null; currentExpressions = new ArrayDeque<>(); dsl.visit(this); RuntimeExpression node = currentExpressions.pop(); diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/builder/SpellBuilderVisitor.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/builder/SpellBuilderVisitor.java index 91982fbb..f6a13ca3 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/builder/SpellBuilderVisitor.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/builder/SpellBuilderVisitor.java @@ -1,28 +1,26 @@ package fr.jamailun.ultimatespellsystem.plugin.runner.builder; -import fr.jamailun.ultimatespellsystem.dsl.objects.CallbackEvent; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.MetadataNode; +import fr.jamailun.ultimatespellsystem.api.runner.functions.GlobalFunction; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.blocks.*; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.expressions.ExpressionWrapperNode; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.play.*; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.IncrementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.statements.*; -import fr.jamailun.ultimatespellsystem.dsl.nodes.statements.blocks.*; -import fr.jamailun.ultimatespellsystem.dsl.visitor.StatementVisitor; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.statements.ExpressionWrapperNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.*; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.blocks.*; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.StatementVisitor; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.*; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.RuntimeFunctionDeclaration; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.statements.AffectVarNode; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.statements.ReturnNode; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.statements.DeclareVarNode; import lombok.Getter; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Deque; -import java.util.List; +import java.util.*; /** * A visitor used to build a runtime-node tree from the DSL. @@ -35,91 +33,60 @@ public class SpellBuilderVisitor implements StatementVisitor { private final List statementsAccumulator = new ArrayList<>(); private final Deque> accumulatorsStack = new ArrayDeque<>(); + @Getter private final Map functions = new HashMap<>(); + public SpellBuilderVisitor() { currentQueue = statementsAccumulator; } - public static @NotNull List build(@NotNull List dsl) { + public static @NotNull SpellStructure build(@NotNull List dsl) { SpellBuilderVisitor visitor = new SpellBuilderVisitor(); for(StatementNode statement : dsl) { statement.visit(visitor); } - return visitor.statementsAccumulator; - } - - @Override - public void handleStop(@NotNull StopStatement statement) { - RuntimeExpression exitCode = convert(statement.getExitCodeNode()); - add(new StopNode(exitCode)); - } - - @Override - public void handleSendAttribute(@NotNull SendAttributeStatement statement) { - RuntimeExpression target = convert(statement.getTarget()); - RuntimeExpression value = convert(statement.getNumericValue()); - RuntimeExpression type = convert(statement.getAttributeType()); - RuntimeExpression mode = convert(statement.getAttributeMode().orElse(null)); - RuntimeExpression duration = convert(statement.getDuration()); - add(new SendAttributeNode(target, value, type, mode, duration)); - } - - @Override - public void handleSendEffect(@NotNull SendEffectStatement statement) { - RuntimeExpression target = convert(statement.getTarget()); - RuntimeExpression effect = convert(statement.getEffectType()); - RuntimeExpression power = convert(statement.getEffectPower().orElse(null)); - RuntimeExpression duration = convert(statement.getEffectDuration()); - add(new SendEffectNode(target, effect, duration, power)); - } - - @Override - public void handleSendMessage(@NotNull SendMessageStatement statement) { - RuntimeExpression target = convert(statement.getTarget()); - RuntimeExpression message = convert(statement.getMessage()); - add(new SendMessageNode(target, message)); + return new SpellStructure( + visitor.statementsAccumulator, + visitor.functions.values() + ); } @Override - public void handleSendNbt(@NotNull SendNbtStatement statement) { - RuntimeExpression target = convert(statement.getTarget()); - RuntimeExpression name = convert(statement.getNbtName()); - RuntimeExpression value = convert(statement.getNbtValue()); - RuntimeExpression duration = convert(statement.getNbtDuration()); - add(new SendNbtNode(target, name, value, duration)); + public void handleDeclareVariable(@NotNull DeclareNewVariableStatement statement) { + String varName = statement.getVarName(); + Type type = statement.getCompiledType(); + RuntimeExpression expression = convert(statement.getExpression()); + add(new DeclareVarNode(varName, type, expression)); } @Override - public void handleDefine(@NotNull DefineStatement statement) { - String varName = statement.getVarName(); + public void handleAffectVariable(@NotNull AffectationStatement statement) { + RuntimeExpression holder = convert(statement.getValueHolder()); RuntimeExpression value = convert(statement.getExpression()); - add(new DefineNode(varName, value, statement.getExpression().getExpressionType())); + add(new AffectVarNode(holder, value)); } @Override - public void handleRunLater(@NotNull RunLaterStatement statement) { - RuntimeExpression duration = convert(statement.getDuration()); - RuntimeStatement child = convertOneStatement(statement.getChild()); - add(new RunLaterNode(duration, child)); - } + public void handleFunctionDeclaration(@NotNull FunctionDeclarationStatement statement) { + // Basics + String funcName = statement.getFunctionName(); + Type type = statement.getOutputType(); - @Override - public void handleRepeatRun(@NotNull RepeatStatement statement) { - RuntimeExpression period = convert(statement.getPeriod()); - RuntimeStatement child = convertOneStatement(statement.getChild()); - RuntimeExpression delay = convert(statement.getDelay().orElse(null)); - RuntimeExpression totalCount = convert(statement.getTotalCount()); - RuntimeExpression totalDuration = convert(statement.getTotalDuration()); - add(new RunRepeatNode(period, child, delay, totalCount, totalDuration)); + // Convert statements + pushQueue(); + for(StatementNode child : statement.getStatements()) { + child.visit(this); + } + List statements = List.copyOf(currentQueue); + popQueue(); + + // Register function + functions.put(funcName, new RuntimeFunctionDeclaration(funcName, type, statement.getParameters(), statements)); } @Override - public void handleSummon(@NotNull SummonStatement statement) { - RuntimeExpression type = convert(statement.getEntityType()); - RuntimeExpression source = convert(statement.getSource().orElse(null)); - RuntimeExpression duration = convert(statement.getDuration()); - RuntimeExpression properties = convert(statement.getProperties().orElse(null)); - String varName = statement.getVarName().orElse(null); - add(new SummonNode(type, source, duration, properties, varName)); + public void handleReturn(@NotNull ReturnStatement statement) { + RuntimeExpression exitCode = convert(statement.getExitCodeNode()); + add(new ReturnNode(exitCode)); } @Override @@ -130,69 +97,17 @@ public void handleBlock(@NotNull BlockStatement statement) { child.visit(this); } BlockNodes block = new BlockNodes(currentQueue); - popQueue(); add(block); } - @Override - public void handleIncrement(@NotNull IncrementStatement statement) { - String varName = statement.getVarName(); - boolean increments = statement.isPositive(); - add(new IncrementNode(varName, increments)); - } - - @Override - public void handleTeleport(@NotNull TeleportStatement statement) { - RuntimeExpression entity = convert(statement.getEntity()); - RuntimeExpression target = convert(statement.getTarget()); - add(new TeleportNode(entity, target)); - } - - @Override - public void handlePlay(@NotNull PlayStatement statement) { - RuntimeExpression location = convert(statement.getLocation()); - RuntimeExpression properties = convert(statement.getProperties()); - PlayNode node = switch (statement.getType()) { - case BLOCK -> new PlayBlockNode(location, properties); - case PARTICLE -> new PlayParticleNode(location, properties); - case SOUND -> new PlaySoundNode(location, properties); - case ANIMATION -> new PlayAnimationNode(location, properties); - }; - add(node); - } - - @Override - public void handleGive(@NotNull GiveStatement statement) { - RuntimeExpression target = convert(statement.getTarget()); - RuntimeExpression amount = convert(statement.getOptAmount()); - RuntimeExpression type = convert(statement.getOptType()); - RuntimeExpression properties = convert(statement.getOptProperties()); - add(new GiveNode(target, amount, type, properties)); - } - - @Override - public void handleCallback(@NotNull CallbackStatement statement) { - String varInput = statement.getListenVariableName(); - CallbackEvent type = statement.getCallbackType(); - String varArg = statement.getOutputVariable().orElse(null); - RuntimeStatement child = convertOneStatement(statement.getChild()); - add(new CallbackNode(varInput, type, varArg, child)); - } - @Override public void handleSimpleExpression(@NotNull SimpleExpressionStatement statement) { RuntimeExpression child = convert(statement.getChild()); add(new ExpressionWrapperNode(child)); } - @Override - public void handleMetadata(@NotNull MetadataStatement statement) { - String name = statement.getName(); - add(new MetadataNode(name, statement.getParams())); - } - @Override public void handleIf(@NotNull IfElseStatement statement) { RuntimeExpression condition = convert(statement.getCondition()); @@ -210,15 +125,6 @@ public void handleForLoop(@NotNull ForLoopStatement statement) { add(new ForLoopNode(init, condition, iteration, child)); } - @Override - public void handleForeachLoop(@NotNull ForeachLoopStatement statement) { - String varName = statement.getVariableName(); - RuntimeExpression source = convert(statement.getSource()); - RuntimeStatement child = convertOneStatement(statement.getChild()); - add(new ForeachLoopNode(varName, source, child)); - - } - @Override public void handleWhileLoop(@NotNull WhileLoopStatement statement) { RuntimeExpression condition = convert(statement.getCondition()); @@ -232,6 +138,7 @@ public void handleBreakContinue(@NotNull BreakContinueStatement statement) { add(new BreakContinueNode(statement.isContinue())); } + @Contract("null -> null; !null -> new") public RuntimeExpression convert(ExpressionNode expression) { if(expression == null) return null; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/builder/SpellStructure.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/builder/SpellStructure.java new file mode 100644 index 00000000..09eadf5b --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/builder/SpellStructure.java @@ -0,0 +1,20 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.builder; + +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; +import fr.jamailun.ultimatespellsystem.api.runner.functions.GlobalFunction; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.RuntimeFunctionDeclaration; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.List; + +/** + * Content of a spell. + * @param statements statements of the spell. + * @param functions functions registered inside the spell. + */ +public record SpellStructure( + @NotNull List statements, + @NotNull Collection functions +) { +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/functions/JavaFunctionCallNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/functions/JavaFunctionCallNode.java index 670cabaa..c97d7c4e 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/functions/JavaFunctionCallNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/functions/JavaFunctionCallNode.java @@ -4,7 +4,8 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import fr.jamailun.ultimatespellsystem.api.runner.functions.RunnableJavaFunction; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; import fr.jamailun.ultimatespellsystem.plugin.entities.BukkitSpellEntity; import lombok.RequiredArgsConstructor; import org.bukkit.entity.Entity; @@ -21,6 +22,7 @@ @RequiredArgsConstructor public class JavaFunctionCallNode extends RuntimeExpression { + private final TokenPosition pos; private final RunnableJavaFunction function; private final List arguments; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/blocks/CallbackNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/blocks/CallbackNode.java index e1493085..6a208275 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/blocks/CallbackNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/blocks/CallbackNode.java @@ -8,7 +8,7 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import fr.jamailun.ultimatespellsystem.api.runner.errors.InvalidTypeException; -import fr.jamailun.ultimatespellsystem.dsl.objects.CallbackEvent; +import fr.jamailun.ultimatespellsystem.dsl2.callbacks.CallbackEvent; import lombok.Getter; import org.jetbrains.annotations.NotNull; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/blocks/RunLaterNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/blocks/RunLaterNode.java index 5bb34b71..fd101b59 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/blocks/RunLaterNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/blocks/RunLaterNode.java @@ -2,7 +2,7 @@ import fr.jamailun.ultimatespellsystem.UssLogger; import fr.jamailun.ultimatespellsystem.api.UltimateSpellSystem; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/blocks/RunRepeatNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/blocks/RunRepeatNode.java index 57a4d707..e7f6da83 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/blocks/RunRepeatNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/blocks/RunRepeatNode.java @@ -3,8 +3,7 @@ import fr.jamailun.ultimatespellsystem.UssLogger; import fr.jamailun.ultimatespellsystem.api.UltimateSpellSystem; import fr.jamailun.ultimatespellsystem.api.runner.FlowState; -import fr.jamailun.ultimatespellsystem.dsl.nodes.statements.blocks.RepeatStatement; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; @@ -72,7 +71,7 @@ public void run() { } return; } - runtime.variables().set(RepeatStatement.INDEX_VARIABLE, count); + runtime.variables().set("_index", count); try { child.run(runtime); } catch (Exception t) { diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/EntityTypeLiteral.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/EntityTypeLiteral.java deleted file mode 100644 index 9422de4e..00000000 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/EntityTypeLiteral.java +++ /dev/null @@ -1,30 +0,0 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.expressions; - -import fr.jamailun.ultimatespellsystem.api.entities.UssEntityType; -import fr.jamailun.ultimatespellsystem.api.providers.EntityTypeProvider; -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; -import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral.EntityTypeExpression; -import org.jetbrains.annotations.NotNull; - -/** - * Literal for {@link UssEntityType} - */ -public class EntityTypeLiteral extends RuntimeExpression { - - private final String name; - - public EntityTypeLiteral(@NotNull EntityTypeExpression dsl) { - this.name = dsl.getRaw(); - } - - @Override - public UssEntityType evaluate(@NotNull SpellRuntime runtime) { - return EntityTypeProvider.instance().find(name); - } - - @Override - public String toString() { - return "EntityType." + name; - } -} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/PositionOfNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/PositionOfNode.java deleted file mode 100644 index 8652413c..00000000 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/PositionOfNode.java +++ /dev/null @@ -1,52 +0,0 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.expressions; - -import fr.jamailun.ultimatespellsystem.UssLogger; -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; -import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.api.runner.errors.InvalidTypeException; -import fr.jamailun.ultimatespellsystem.api.entities.SpellEntity; -import lombok.RequiredArgsConstructor; -import org.bukkit.Location; -import org.bukkit.entity.Entity; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.stream.Collectors; - -@RequiredArgsConstructor -public class PositionOfNode extends RuntimeExpression { - - private final RuntimeExpression entity; - private final boolean isCollection; - - @Override - public Object evaluate(@NotNull SpellRuntime runtime) { - if(isCollection) { - return runtime.safeEvaluateList(this.entity, Object.class).stream() - .map(PositionOfNode::getLocation) - .collect(Collectors.toCollection(ArrayList::new)); - } - Object entityRef = runtime.safeEvaluate(this.entity, Object.class); - Location location = getLocation(entityRef); - UssLogger.logDebug("PositionOf : " + entityRef + (entityRef==null?"":" = " +location)); - return location; - - } - - private static @Nullable Location getLocation(@Nullable Object object) { - return switch (object) { - case null -> null; - case Entity entity -> entity.getLocation(); - case SpellEntity spellEntity -> spellEntity.getLocation(); - case Location loc -> loc.clone(); - default -> throw new InvalidTypeException("position-of:entity", "entity", object); - }; - - } - - @Override - public String toString() { - return "position-of(" + entity + ")"; - } -} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/RawLiteral.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/RawLiteral.java index bb2aaa80..b5f39a7b 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/RawLiteral.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/RawLiteral.java @@ -1,6 +1,6 @@ package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.expressions; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.litteral.LiteralExpression; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.litteral.LiteralExpression; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import org.jetbrains.annotations.NotNull; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/AllAroundNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/_old/AllAroundNode.java similarity index 99% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/AllAroundNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/_old/AllAroundNode.java index f0bdc566..f65dc5a6 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/AllAroundNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/_old/AllAroundNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.expressions; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.expressions._old; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/SizeOfNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/_old/SizeOfNode.java similarity index 97% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/SizeOfNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/_old/SizeOfNode.java index 898eeff3..b62d6314 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/SizeOfNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/_old/SizeOfNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.expressions; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.expressions._old; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/DefineNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/DefineNode.java deleted file mode 100644 index 4dc0ec05..00000000 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/DefineNode.java +++ /dev/null @@ -1,45 +0,0 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions; - -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; -import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; - -/** - * A node that can define a variable to the runtime. - */ -@RequiredArgsConstructor -public class DefineNode extends RuntimeStatement { - - private final String varName; - private final RuntimeExpression expression; - private final Type type; - - @Override - public void run(@NotNull SpellRuntime runtime) { - if(type.is(TypePrimitive.NULL)) { - if(type.isCollection()) { - runtime.variables().set(varName, new ArrayList<>()); - } else { - runtime.variables().set(varName, null); - } - return; - } - - Class clazz = type.primitive().clazz; - if(clazz == null) - throw new RuntimeException("Cannot run a null-typed expression : " + runtime); - - runtime.variables().set(varName, expression.evaluate(runtime)); - } - - @Override - public String toString() { - return "DEFINE %" + varName + " = " + expression; - } -} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/RuntimeFunctionDeclaration.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/RuntimeFunctionDeclaration.java new file mode 100644 index 00000000..fb5488c1 --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/RuntimeFunctionDeclaration.java @@ -0,0 +1,81 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions; + +import fr.jamailun.ultimatespellsystem.api.runner.FlowState; +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; +import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; +import fr.jamailun.ultimatespellsystem.api.runner.functions.GlobalFunction; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionSignature; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.statements.FunctionDeclarationStatement; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +@RequiredArgsConstructor +public class RuntimeFunctionDeclaration implements GlobalFunction { + + private final @NotNull String name; + private final @NotNull Type type; + private final @NotNull List args; + private final @NotNull List statements; + + @Override + public @NotNull FunctionSignature getSignature() { + return new FunctionSignature(name, args.stream().map(fa -> Type.ofAny(fa.type())).toList()); + } + + @Override + public @Nullable Object call(@NotNull TokenPosition pos, @NotNull List arguments, @NotNull SpellRuntime runtimeParent) { + SpellRuntime runtime = runtimeParent.makeChild(true); + + // Handle params + for(MatchedParam param : matchParams(runtime, arguments)) { + runtime.variables().set(param.argName(), param.value()); + } + + // Execute statements + Object output = null; + for(RuntimeStatement statement : statements) { + statement.run(runtime); + + // 'Return' was used + if(runtime.getFlowState() == FlowState.STOPPED) { + output = runtime.getReturnedValue(); + break; + } + } + + //TODO match output type? + + return output; + } + + private record MatchedParam(@NotNull String argName, @Nullable Object value) { } + + private @NotNull List matchParams(@NotNull SpellRuntime runtime, List args) { + return matchParams(args.stream().map(a -> a.evaluate(runtime)).toList()); + } + private @NotNull List matchParams(@NotNull List params) { + List output = new ArrayList<>(args.size()); + for(int i = 0; i < args.size(); i++) { + FunctionDeclarationStatement.FunctionParameter arg = args.get(i); + + // Le paramètre N est manquant. + if(params.size() <= i) { + throw new RuntimeException("Missing args. f="+name+", args=" + params + ", but expected " + args); + } + + Object value = params.get(i); + //TODO match type + + output.add(new MatchedParam(arg.name(), value)); + } + return output; + } + +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/GiveNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/GiveNode.java similarity index 99% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/GiveNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/GiveNode.java index 0b59d3de..297943a4 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/GiveNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/GiveNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old; import fr.jamailun.ultimatespellsystem.api.UltimateSpellSystem; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/SendAttributeNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/SendAttributeNode.java similarity index 98% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/SendAttributeNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/SendAttributeNode.java index d1400598..e114e560 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/SendAttributeNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/SendAttributeNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old; import fr.jamailun.ultimatespellsystem.UssKeys; import fr.jamailun.ultimatespellsystem.api.UltimateSpellSystem; @@ -6,7 +6,7 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import lombok.RequiredArgsConstructor; import org.bukkit.Bukkit; import org.bukkit.attribute.Attributable; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/SendEffectNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/SendEffectNode.java similarity index 98% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/SendEffectNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/SendEffectNode.java index 9036b773..72966fa0 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/SendEffectNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/SendEffectNode.java @@ -1,9 +1,9 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old; import fr.jamailun.ultimatespellsystem.UssLogger; import fr.jamailun.ultimatespellsystem.api.entities.SpellEntity; import fr.jamailun.ultimatespellsystem.api.runner.errors.InvalidEnumValueException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/SendMessageNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/SendMessageNode.java similarity index 99% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/SendMessageNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/SendMessageNode.java index 6312c88e..7dc1c983 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/SendMessageNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/SendMessageNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/SendNbtNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/SendNbtNode.java similarity index 97% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/SendNbtNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/SendNbtNode.java index 485ef0c0..2e707b18 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/SendNbtNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/SendNbtNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old; import fr.jamailun.ultimatespellsystem.UssKeys; import fr.jamailun.ultimatespellsystem.UssLogger; @@ -7,7 +7,7 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.bukkit.NamespacedKey; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/SummonNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/SummonNode.java similarity index 97% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/SummonNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/SummonNode.java index bedab870..99c09c9d 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/SummonNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/SummonNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old; import fr.jamailun.ultimatespellsystem.UssLogger; import fr.jamailun.ultimatespellsystem.api.UltimateSpellSystem; @@ -9,7 +9,7 @@ import fr.jamailun.ultimatespellsystem.api.entities.SpellEntity; import fr.jamailun.ultimatespellsystem.plugin.entities.SummonAttributesImpl; import fr.jamailun.ultimatespellsystem.api.runner.errors.InvalidTypeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.bukkit.Location; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/TeleportNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/TeleportNode.java similarity index 99% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/TeleportNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/TeleportNode.java index 32eaedc2..150998cb 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/TeleportNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/TeleportNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/play/PlayAnimationNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/play/PlayAnimationNode.java similarity index 98% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/play/PlayAnimationNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/play/PlayAnimationNode.java index 17c9b779..fecb68e8 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/play/PlayAnimationNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/play/PlayAnimationNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.play; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old.play; import fr.jamailun.ultimatespellsystem.UssLogger; import fr.jamailun.ultimatespellsystem.api.UltimateSpellSystem; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/play/PlayBlockNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/play/PlayBlockNode.java similarity index 98% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/play/PlayBlockNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/play/PlayBlockNode.java index f41c6fce..4778134c 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/play/PlayBlockNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/play/PlayBlockNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.play; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old.play; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.plugin.utils.holders.BlockHolder; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/play/PlayNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/play/PlayNode.java similarity index 99% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/play/PlayNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/play/PlayNode.java index 0764d9f1..2d31a086 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/play/PlayNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/play/PlayNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.play; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old.play; import fr.jamailun.ultimatespellsystem.api.UltimateSpellSystem; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/play/PlayParticleNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/play/PlayParticleNode.java similarity index 98% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/play/PlayParticleNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/play/PlayParticleNode.java index e666287f..4f9f7987 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/play/PlayParticleNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/play/PlayParticleNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.play; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old.play; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.plugin.utils.holders.ParticleHolder; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/play/PlaySoundNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/play/PlaySoundNode.java similarity index 98% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/play/PlaySoundNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/play/PlaySoundNode.java index ea75fdc4..afea5bb2 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/play/PlaySoundNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/_old/play/PlaySoundNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.play; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old.play; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.plugin.utils.holders.SoundHolder; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/IncrementNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/IncrementNode.java index de7f6f80..81abf8d1 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/IncrementNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/IncrementNode.java @@ -1,29 +1,27 @@ package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators; -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import fr.jamailun.ultimatespellsystem.api.runner.errors.UnreachableRuntimeException; +import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; -public class IncrementNode extends RuntimeStatement { +@RequiredArgsConstructor +public class IncrementNode extends RuntimeExpression { - private final String varName; + private final @NotNull String varName; private final boolean increments; - - public IncrementNode(@NotNull String varName, boolean increments) { - this.varName = varName; - this.increments = increments; - } + private final boolean postFix; @Override - public void run(@NotNull SpellRuntime runtime) { + public Double evaluate(@NotNull SpellRuntime runtime) { Object value = runtime.variables().get(varName); - if(value instanceof Double d) { - double v = d + (increments ? 1 : -1); - runtime.variables().set(varName, v); - return; - } - throw new UnreachableRuntimeException("Invalid type for variable " + varName + " : " + value); - } + if(!(value instanceof Number num)) + throw new UnreachableRuntimeException("Invalid type for variable " + varName + " : " + value); + double input = num.doubleValue(); + double output = input + (increments ? 1 : -1); + runtime.variables().set(varName, output); + return postFix ? input : output; + } } diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunAddOpe.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunAddOpe.java index f5c98e3b..82f04e8c 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunAddOpe.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunAddOpe.java @@ -2,7 +2,7 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.errors.UnreachableRuntimeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.bukkit.Location; import org.bukkit.util.Vector; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunCompOpe.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunCompOpe.java index a89b78ed..65303e6f 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunCompOpe.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunCompOpe.java @@ -2,7 +2,7 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.errors.UnreachableRuntimeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; public final class RunCompOpe extends RuntimeBiOperator { diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunMathOpe.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunMathOpe.java deleted file mode 100644 index 662f1b4c..00000000 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunMathOpe.java +++ /dev/null @@ -1,52 +0,0 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators; - -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; -import fr.jamailun.ultimatespellsystem.api.runner.errors.UnreachableRuntimeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.operators.MonoOperator.MonoOpeType; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; - -/** - * Not-operator - */ -public final class RunMathOpe extends RuntimeMonoOperator { - - private final MonoOpeType type; - - /** - * Create a new mono-operator. - * @param child the child expression. - * @param type the type of operation. - */ - public RunMathOpe(@NotNull RuntimeExpression child, @NotNull MonoOpeType type) { - super(child); - this.type = type; - } - - @Override - protected @NotNull Object evaluate(@NotNull Object value) { - // A math function only handles numbers. - if(value instanceof List list) { - // evaluate for each element. - List output = new ArrayList<>(); - for(Object subValue : list) { - output.add(evaluate(subValue)); - } - return output; - } - - // If it's a number, accept it - if(value instanceof Number number) { - return type.function.apply(number); - } - - throw new UnreachableRuntimeException("Unexpected type for "+type+"-operator : " + value + " | " + value.getClass()); - } - - @Override - public @NotNull String toString() { - return "not(" + child + ")"; - } -} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunMulDivOpe.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunMulDivOpe.java index 5407c83f..8416778b 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunMulDivOpe.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunMulDivOpe.java @@ -2,7 +2,7 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.errors.UnreachableRuntimeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.bukkit.Location; import org.bukkit.util.Vector; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunSizeofOpe.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunSizeofOpe.java new file mode 100644 index 00000000..c97cfe42 --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunSizeofOpe.java @@ -0,0 +1,30 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators; + +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; +import fr.jamailun.ultimatespellsystem.api.runner.errors.UnreachableRuntimeException; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +/** + * Sizeof-operator + */ +public final class RunSizeofOpe extends RuntimeMonoOperator { + + public RunSizeofOpe(@NotNull RuntimeExpression child) { + super(child); + } + + @Override + protected @NotNull Object evaluate(@NotNull Object value) { + if(value instanceof Collection coll) { + return coll.size(); + } + throw new UnreachableRuntimeException("Unexpected type for SIZE_OF-operator : " + value + " | " + value.getClass()); + } + + @Override + public @NotNull String toString() { + return "size_of(" + child + ")"; + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunSubOpe.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunSubOpe.java index c9eb083c..6232f057 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunSubOpe.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/RunSubOpe.java @@ -2,7 +2,7 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.errors.UnreachableRuntimeException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.bukkit.Location; import org.bukkit.util.Vector; import org.jetbrains.annotations.Contract; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/ListAddRemOpe.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/ListAddRemOpe.java deleted file mode 100644 index 6937ee76..00000000 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/ListAddRemOpe.java +++ /dev/null @@ -1,54 +0,0 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list; - -import fr.jamailun.ultimatespellsystem.UssLogger; -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; -import fr.jamailun.ultimatespellsystem.api.runner.errors.UnreachableRuntimeException; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.RuntimeBiOperator; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * An 'append' or 'remove' on list, operator. - */ -public class ListAddRemOpe extends RuntimeBiOperator { - - private final boolean append; - - public ListAddRemOpe(@NotNull RuntimeExpression left, @NotNull RuntimeExpression right, boolean append) { - super(left, right); - this.append = append; - } - - @Override - protected Object evaluate(Object left, Object right) { - if(!(left instanceof List list)) - throw new UnreachableRuntimeException("Cannot have a left non-list: " + left); - - // Handle MONO and MULTI cases - Set allOthers; - if(right instanceof Collection coll) { - allOthers = new HashSet<>(coll); - } else { - allOthers = Set.of(right); - } - - List listObj = (List) list; - if(append) { - listObj.addAll(allOthers); - UssLogger.logDebug("[List:add] New list: " + listObj); - } else { - listObj.removeAll(allOthers); - UssLogger.logDebug("[List:rem] New list: " + listObj); - } - return listObj; - } - - @Override - public String toString() { - return leftExpression +(append?".add(":".remove(") + rightExpression + ")"; - } -} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/ListContainsOpe.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/ListContainsOpe.java deleted file mode 100644 index 63a6286c..00000000 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/ListContainsOpe.java +++ /dev/null @@ -1,41 +0,0 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list; - -import fr.jamailun.ultimatespellsystem.UssLogger; -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; -import fr.jamailun.ultimatespellsystem.api.runner.errors.UnreachableRuntimeException; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.RuntimeBiOperator; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * A "does list contains element" operation. - */ -public class ListContainsOpe extends RuntimeBiOperator { - - public ListContainsOpe(@NotNull RuntimeExpression left, @NotNull RuntimeExpression right) { - super(left, right); - } - - @Override - protected Object evaluate(Object left, Object right) { - if(!(left instanceof List list)) - throw new UnreachableRuntimeException("Cannot have a left non-list: " + left + "|" + left.getClass() + ". L = " + leftExpression + "; R = " + rightExpression); - // Better performance if we hash data. - Set hashedList = new HashSet<>(list); - - if(right instanceof Collection others) { - return hashedList.containsAll(new HashSet<>(others)); - } - UssLogger.logDebug("[List:contains] Contains ? " + list.contains(right)); - return list.contains(right); - } - - @Override - public String toString() { - return leftExpression + ".contains(" + rightExpression + ")"; - } -} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/ListOperator.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/ListOperator.java new file mode 100644 index 00000000..0e908d8c --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/ListOperator.java @@ -0,0 +1,54 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list; + +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; +import fr.jamailun.ultimatespellsystem.api.runner.errors.UnreachableRuntimeException; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.RuntimeBiOperator; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Specialized bi-operator for list. + */ +public abstract class ListOperator extends RuntimeBiOperator { + + public ListOperator(@NotNull RuntimeExpression left, @NotNull RuntimeExpression right) { + super(left, right); + } + + /** + * Evaluate with a list. + * @param collection list of objects. + * @param arg argument of the operator. + * @return something, according to the operator. + */ + protected abstract Object evaluateList(@NotNull Collection collection, Object arg); + + @Override + @SuppressWarnings("unchecked") + protected final Object evaluate(Object left, Object right) { + if(!(left instanceof Collection list)) + throw new UnreachableRuntimeException("Cannot have a left non-list: " + left); + + List listObj = (List) list; + return evaluateList(listObj, right); + } + + /** + * Transform a single element or a collection (or a {@code null} value into a collection). + * @param object object to handle. + * @return a non-null collection. + */ + protected @NotNull Collection elementAsCollection(@Nullable Object object) { + if(object instanceof Collection coll) { + return new HashSet<>(coll); + } + if(object == null) + return new HashSet<>(); + return Set.of(object); + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/ListRemIndexOpe.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/ListRemIndexOpe.java deleted file mode 100644 index 6e51dfe1..00000000 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/ListRemIndexOpe.java +++ /dev/null @@ -1,33 +0,0 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list; - -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; -import fr.jamailun.ultimatespellsystem.api.runner.errors.UnreachableRuntimeException; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.RuntimeBiOperator; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -/** - * A "remove at index" operation. - */ -public class ListRemIndexOpe extends RuntimeBiOperator { - - public ListRemIndexOpe(@NotNull RuntimeExpression left, @NotNull RuntimeExpression right) { - super(left, right); - } - - @Override - protected Object evaluate(Object left, Object right) { - if(!(left instanceof List list)) - throw new UnreachableRuntimeException("Cannot have a left non-list: " + left); - if(!(right instanceof Number index)) - throw new UnreachableRuntimeException("Cannot have a right non-number: " + right); - list.remove(index.intValue()); - return list; - } - - @Override - public String toString() { - return leftExpression + ".remove(" + rightExpression + ")"; - } -} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/RunListAddOpe.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/RunListAddOpe.java new file mode 100644 index 00000000..fa45b1dd --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/RunListAddOpe.java @@ -0,0 +1,31 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list; + +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +/** + * "Append" operation on a collection. + */ +public class RunListAddOpe extends ListOperator { + + public RunListAddOpe(@NotNull RuntimeExpression left, @NotNull RuntimeExpression right) { + super(left, right); + } + + @Override + protected Object evaluateList(@NotNull Collection collection, Object arg) { + // Can add either another collection or a single element. + Collection allOthers = elementAsCollection(arg); + + // Append values + collection.addAll(allOthers); + return collection; + } + + @Override + public String toString() { + return leftExpression +".add(" + rightExpression + ")"; + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/RunListContainsOpe.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/RunListContainsOpe.java new file mode 100644 index 00000000..230795aa --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/RunListContainsOpe.java @@ -0,0 +1,33 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list; + +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * Test if a collection contains an element. + */ +public class RunListContainsOpe extends ListOperator { + + public RunListContainsOpe(@NotNull RuntimeExpression left, @NotNull RuntimeExpression right) { + super(left, right); + } + + @Override + protected Object evaluateList(@NotNull Collection collection, Object arg) { + Set hashedList = new HashSet<>(collection); + + if(arg instanceof Collection others) { + return hashedList.containsAll(new HashSet<>(others)); + } + return hashedList.contains(arg); + } + + @Override + public String toString() { + return leftExpression + ".contains(" + rightExpression + ")"; + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/RunListRemIndexOpe.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/RunListRemIndexOpe.java new file mode 100644 index 00000000..067f35c2 --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/RunListRemIndexOpe.java @@ -0,0 +1,30 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list; + +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; +import fr.jamailun.ultimatespellsystem.api.runner.errors.UnreachableRuntimeException; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +/** + * "Remove" operation on a collection, by index. + */ +public class RunListRemIndexOpe extends ListOperator { + + public RunListRemIndexOpe(@NotNull RuntimeExpression left, @NotNull RuntimeExpression right) { + super(left, right); + } + + @Override + protected Object evaluateList(@NotNull Collection collection, Object arg) { + if(!(arg instanceof Number index)) + throw new UnreachableRuntimeException("Cannot have a right non-number: " + arg); + collection.remove(index.intValue()); + return arg; + } + + @Override + public String toString() { + return leftExpression + ".remove_idx(" + rightExpression + ")"; + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/RunListRemOpe.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/RunListRemOpe.java new file mode 100644 index 00000000..4ca7780a --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/RunListRemOpe.java @@ -0,0 +1,31 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list; + +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +/** + * "Remove" operation on a collection. + */ +public class RunListRemOpe extends ListOperator { + + public RunListRemOpe(@NotNull RuntimeExpression left, @NotNull RuntimeExpression right) { + super(left, right); + } + + @Override + protected Object evaluateList(@NotNull Collection collection, Object arg) { + // Can add either another collection or a single element. + Collection allOthers = elementAsCollection(arg); + + // Append values + collection.addAll(allOthers); + return collection; + } + + @Override + public String toString() { + return leftExpression +".remove(" + rightExpression + ")"; + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/ArrayGetNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/objects/ArrayGetNode.java similarity index 98% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/ArrayGetNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/objects/ArrayGetNode.java index f2ace184..b808cf02 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/list/ArrayGetNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/objects/ArrayGetNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.list; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.objects; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/objects/GlobalFunctionCallNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/objects/GlobalFunctionCallNode.java new file mode 100644 index 00000000..3f291917 --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/objects/GlobalFunctionCallNode.java @@ -0,0 +1,40 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.objects; + +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; +import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; +import fr.jamailun.ultimatespellsystem.api.runner.functions.GlobalFunction; +import fr.jamailun.ultimatespellsystem.dsl2.errors.UnknownFunctionException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionSignature; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * Getter on a field of an object. + */ +@RequiredArgsConstructor +public class GlobalFunctionCallNode extends RuntimeExpression { + + private final TokenPosition pos; + private final FunctionSignature signature; + private final List parameters; + + @Override + public @Nullable Object evaluate(@NotNull SpellRuntime runtime) { + // Find function + GlobalFunction function = runtime.functions().get(signature); + if(function == null) + throw new UnknownFunctionException(pos, signature.name()); + + // Call function + return function.call(pos, parameters, runtime); + } + + @Override + public @NotNull String toString() { + return signature.name() + "(" + parameters + ")"; + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/objects/StructFieldGetNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/objects/StructFieldGetNode.java new file mode 100644 index 00000000..06a051f5 --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/objects/StructFieldGetNode.java @@ -0,0 +1,39 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.objects; + +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; +import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; +import fr.jamailun.ultimatespellsystem.dsl2.library.StructDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import fr.jamailun.ultimatespellsystem.api.runner.structs.Struct; +import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Getter on a field of an object. + */ +@RequiredArgsConstructor +public class StructFieldGetNode extends RuntimeExpression { + + private final TokenPosition pos; + private final RuntimeExpression object; + private final StructDefinition objectStruct; + private final String fieldName; + + @Override + public @Nullable Object evaluate(@NotNull SpellRuntime runtime) { + Object target = object.evaluate(runtime); + + // "definition → instance", à partir de OBJECT + Struct struct = runtime.getStructOf(objectStruct.getName(), target); + if(struct == null) + throw new RuntimeException("Cannot get struct '" + objectStruct.getName() + "' from value " + target + "."); + + return struct.getField(pos, fieldName); + } + + @Override + public @NotNull String toString() { + return object + "." + fieldName; + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/objects/StructFunctionCallNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/objects/StructFunctionCallNode.java new file mode 100644 index 00000000..3a676f14 --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/operators/objects/StructFunctionCallNode.java @@ -0,0 +1,50 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.operators.objects; + +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; +import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; +import fr.jamailun.ultimatespellsystem.api.runner.structs.Struct; +import fr.jamailun.ultimatespellsystem.dsl2.library.StructDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +/** + * Getter on a field of an object. + */ +@RequiredArgsConstructor +public class StructFunctionCallNode extends RuntimeExpression { + + private final TokenPosition pos; + private final RuntimeExpression object; + private final StructDefinition objectStruct; + private final String functionName; + private final List parameters; + + @Override + public @Nullable Object evaluate(@NotNull SpellRuntime runtime) { + Object target = object.evaluate(runtime); + + // "definition → instance", à partir de OBJECT + Struct struct = runtime.getStructOf(objectStruct.getName(), target); + if(struct == null) + throw new RuntimeException("Cannot get struct '" + objectStruct.getName() + "' from value " + target + "."); + + // Handle params + List params = new ArrayList<>(parameters.size()); + for(RuntimeExpression expression : parameters) { + params.add(expression.evaluate(runtime)); + } + + // Call function + return struct.callFunction(pos, functionName, params); + } + + @Override + public @NotNull String toString() { + return object + "." + functionName + "(" + parameters + ")"; + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/statements/AffectVarNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/statements/AffectVarNode.java new file mode 100644 index 00000000..b39c67d3 --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/statements/AffectVarNode.java @@ -0,0 +1,22 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.statements; + +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; +import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +@Getter +@RequiredArgsConstructor +public class AffectVarNode extends RuntimeStatement { + + private final @NotNull RuntimeExpression holder; + private final @Nullable RuntimeExpression expression; + + @Override + public void run(@NotNull SpellRuntime runtime) { + //TODO + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/statements/DeclareVarNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/statements/DeclareVarNode.java new file mode 100644 index 00000000..bc31f65c --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/statements/DeclareVarNode.java @@ -0,0 +1,28 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.statements; + +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; +import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; +import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +@Getter +@RequiredArgsConstructor +public class DeclareVarNode extends RuntimeStatement { + + private final @NotNull String varName; + private final @NotNull Type type; + private final @Nullable RuntimeExpression expression; + + @Override + public void run(@NotNull SpellRuntime runtime) { + Object value = expression == null ? null : expression.evaluate(runtime); + if(value != null) { + //TODO match type ?! + } + runtime.variables().set(varName, value); + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/ExpressionWrapperNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/statements/ExpressionWrapperNode.java similarity index 90% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/ExpressionWrapperNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/statements/ExpressionWrapperNode.java index fb3a914c..2fc71fbb 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/expressions/ExpressionWrapperNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/statements/ExpressionWrapperNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.expressions; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.statements; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/StopNode.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/statements/ReturnNode.java similarity index 57% rename from plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/StopNode.java rename to plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/statements/ReturnNode.java index a43ac677..8d6e79e8 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/functions/StopNode.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/nodes/statements/ReturnNode.java @@ -1,4 +1,4 @@ -package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions; +package fr.jamailun.ultimatespellsystem.plugin.runner.nodes.statements; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; @@ -7,23 +7,27 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +/** + * A {@code return [expr]} node. + */ @RequiredArgsConstructor -public class StopNode extends RuntimeStatement { +public class ReturnNode extends RuntimeStatement { private final @Nullable RuntimeExpression exitCode; @Override public void run(@NotNull SpellRuntime runtime) { + Object output; if(exitCode == null) { - runtime.stop(0); + output = null; } else { - int code = runtime.safeEvaluate(exitCode, Double.class).intValue(); - runtime.stop(code); + output = exitCode.evaluate(runtime); } + runtime.statementReturn(output); } @Override - public String toString() { - return "STOP("+exitCode+")"; + public @NotNull String toString() { + return "RETURN" + (exitCode == null ? "" : " " + exitCode); } } diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/AbstractStructDefinition.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/AbstractStructDefinition.java new file mode 100644 index 00000000..8d812ad0 --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/AbstractStructDefinition.java @@ -0,0 +1,175 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.structs; + +import com.google.common.base.Preconditions; +import fr.jamailun.ultimatespellsystem.api.runner.structs.StructDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.errors.UnknownFieldException; +import fr.jamailun.ultimatespellsystem.dsl2.errors.UnknownFunctionException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.bukkit.Location; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Function; + +/** + * Internal abstract struct definition. + */ +@RequiredArgsConstructor(access = AccessLevel.PROTECTED) +public abstract class AbstractStructDefinition implements StructDefinition { + + private final Map> fields = new HashMap<>(); + private final Map> functions = new HashMap<>(); + + @Getter protected final String structName; + private fr.jamailun.ultimatespellsystem.dsl2.library.StructDefinition struct; + + @Override + public void registerField(@NotNull String name, @NotNull Type type, @NotNull Function getter, @Nullable BiConsumer setter) { + Preconditions.checkState(!fields.containsKey(name), "The field '" + name + " has already be defined in struct " + structName + "."); + fields.put(name, new FieldMetadata<>(name, type, getter, setter)); + dsl().registerField(name, type); + } + + @Override + public void registerFunction(@NotNull FunctionDefinition def, @NotNull BiFunction, T> impl) { + String name = def.id(); + Preconditions.checkState(!functions.containsKey(name), "The function '" + name + " has already be defined in struct " + structName + "."); + functions.put(name, new FunctionMetadata<>(def, impl)); + dsl().registerFunction(def); + } + + protected void registerNumber(@NotNull String name, @NotNull Function getter) { + registerField(name, Type.of(TypePrimitive.NUMBER), s -> getter.apply(s).doubleValue(), null); + } + + protected void registerLocation(@NotNull String name, @NotNull Function getter) { + registerField(name, Type.of(TypePrimitive.LOCATION), getter, null); + } + + protected void registerString(@NotNull String name, @NotNull Function getter) { + registerField(name, Type.of(TypePrimitive.STRING), getter, null); + } + + protected void registerNumber(@NotNull String name, @NotNull Function getter, @NotNull BiConsumer setter) { + registerField(name, Type.of(TypePrimitive.NUMBER), s -> getter.apply(s).doubleValue(), setter::accept); + } + + protected void registerNullFunc(@NotNull String name, @NotNull BiConsumer> impl, FunctionArgument... args) { + registerFunction( + FunctionDefinition.of(name, Type.NULL, args), + (s, params) -> { + impl.accept(s, params); + return null; + } + ); + } + + /** + * Compute the DSL holder for the first time. + * @return a non-null object. + */ + protected abstract @NotNull fr.jamailun.ultimatespellsystem.dsl2.library.StructDefinition computeDsl(); + + /** + * Get the DSL definition. + * @return the DSL definition of the object. + */ + protected final @NotNull fr.jamailun.ultimatespellsystem.dsl2.library.StructDefinition dsl() { + if(struct == null) { + struct = computeDsl(); + } + return struct; + } + + /** + * Get a value. + * @param object object to get the value from. + * @param pos token pos + * @param fieldName name of the field. + * @param parameter type. + * @return null if value not found. + */ + protected @Nullable T get(@NotNull S object, @NotNull TokenPosition pos, @NotNull String fieldName) { + FieldMetadata field = field(pos, fieldName); + return field.getter.apply(object); + } + + /** + * Set a value. + * @param object object to set the value of. + * @param pos token pos + * @param fieldName field name. + * @param value value to set. + * @param parameter type. + */ + protected void set(@NotNull S object, @NotNull TokenPosition pos, @NotNull String fieldName, @Nullable T value) { + FieldMetadata field = field(pos, fieldName); + Preconditions.checkState(field.setter != null, "The field '" + field + "' of " + structName + " is NOT mutable."); + field.setter.accept(object, value); + } + + /** + * Call a function. + * @param object object to call the function on. + * @param pos token pos. + * @param funcName function name. + * @param params list of parameters passed to the function. + * @return the output value. May be null. + * @param function-output parameter type. + */ + protected @Nullable T call(@NotNull S object, @NotNull TokenPosition pos, @NotNull String funcName, @NotNull List params) { + FunctionMetadata function = function(pos, funcName); + return function.implementation.apply(object, params); + } + + @SuppressWarnings("unchecked") + private @NotNull FieldMetadata field(@NotNull TokenPosition pos, @NotNull String fieldName) { + FieldMetadata field = (FieldMetadata) fields.get(fieldName); + if(field == null) + throw new UnknownFieldException(pos, structName, fieldName); + return field; + } + + @SuppressWarnings("unchecked") + private @NotNull FunctionMetadata function(@NotNull TokenPosition pos, @NotNull String funcName) { + FunctionMetadata func = (FunctionMetadata) functions.get(funcName); + if(func == null) + throw new UnknownFunctionException(pos, structName, funcName); + return func; + } + + @Override + public @NotNull String getName() { + return structName; + } + + /** + * Meta-data holder for types. + * @param type of the field. + */ + @RequiredArgsConstructor + private class FieldMetadata { + private final @NotNull String name; + private final @NotNull Type type; + private final @NotNull Function getter; + private final @Nullable BiConsumer setter; + } + + @RequiredArgsConstructor + private class FunctionMetadata { + private final @NotNull FunctionDefinition definition; + private final @NotNull BiFunction, T> implementation; + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/AbstractStructInstance.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/AbstractStructInstance.java new file mode 100644 index 00000000..3afc10f6 --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/AbstractStructInstance.java @@ -0,0 +1,42 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.structs; + +import fr.jamailun.ultimatespellsystem.api.runner.structs.Struct; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * Structure instance for an object. + */ +public abstract class AbstractStructInstance implements Struct { + + protected final AbstractStructDefinition definition; + protected final S object; + + /** + * Wraps an object inside this definition. + * @param definition definition definition to use. + * @param object object to handle. + */ + public AbstractStructInstance(@NotNull AbstractStructDefinition definition, S object) { + this.definition = definition; + this.object = object; + } + + @Override + public @Nullable Object getField(@NotNull TokenPosition pos, @NotNull String fieldName) { + return definition.get(object, pos, fieldName); + } + + @Override + public void setField(@NotNull TokenPosition pos, @NotNull String fieldName, @Nullable Object value) { + definition.set(object, pos, fieldName, value); + } + + @Override + public @Nullable Object callFunction(@NotNull TokenPosition pos, @NotNull String functionName, @NotNull List parameters) { + return definition.call(object, pos, functionName, parameters); + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/ConsoleDefinition.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/ConsoleDefinition.java new file mode 100644 index 00000000..51a70c30 --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/ConsoleDefinition.java @@ -0,0 +1,49 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.structs; + +import fr.jamailun.ultimatespellsystem.UssLogger; +import fr.jamailun.ultimatespellsystem.api.runner.structs.Struct; +import fr.jamailun.ultimatespellsystem.dsl2.library.StructDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.library.structs.ConsoleStruct; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.registries.ObjectsDefinitionRegistry; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; +import java.util.function.Consumer; + +/** + * Definition for the 'console' object. + */ +public class ConsoleDefinition extends AbstractStructDefinition { + + static final ConsoleDefinition INSTANCE = new ConsoleDefinition(); + + public ConsoleDefinition() { + super(ConsoleStruct.NAME); + // Functions + registerSend("send", UssLogger::logInfo); + registerSend("debug", UssLogger::logDebug); + registerSend("info", UssLogger::logInfo); + registerSend("warning", UssLogger::logWarning); + registerSend("error", UssLogger::logError); + } + + @Override + public @NotNull Struct instantiate(Object ignored) { + return new ConsoleInstance(); + } + + private void registerSend(String name, Consumer method) { + registerNullFunc( + name, + (x, args) -> method.accept((String) args.getFirst()), + FunctionArgument.of(TypePrimitive.STRING) + ); + } + + @Override + protected @NotNull StructDefinition computeDsl() { + return Objects.requireNonNull(ObjectsDefinitionRegistry.getDefaultStruct(getName()), "Console struct cannot be found in defaults."); + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/ConsoleInstance.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/ConsoleInstance.java new file mode 100644 index 00000000..237ff450 --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/ConsoleInstance.java @@ -0,0 +1,15 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.structs; + +/** + * Structure for the console. + */ +public class ConsoleInstance extends AbstractStructInstance { + + /** + * Create a new console instance. + */ + public ConsoleInstance() { + super(ConsoleDefinition.INSTANCE, null); + } + +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/EntityDefinition.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/EntityDefinition.java new file mode 100644 index 00000000..90bed182 --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/EntityDefinition.java @@ -0,0 +1,109 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.structs; + +import fr.jamailun.ultimatespellsystem.api.entities.SpellEntity; +import fr.jamailun.ultimatespellsystem.api.runner.structs.Struct; +import fr.jamailun.ultimatespellsystem.api.utils.StringTransformation; +import fr.jamailun.ultimatespellsystem.dsl2.library.StructDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.registries.ObjectsDefinitionRegistry; +import org.bukkit.Location; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; +import org.bukkit.entity.Damageable; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; +import java.util.function.Function; + +/** + * "Implements" the abstract {@link fr.jamailun.ultimatespellsystem.dsl2.library.structs.EntityStruct}. + */ +public class EntityDefinition extends AbstractStructDefinition { + + /** + * Create a new definition. + */ + public EntityDefinition() { + super("entity"); + loadFields(); + loadFunctions(); + } + + @Override + public @NotNull Struct instantiate(SpellEntity value) { + return new EntityInstance(value, this); + } + + private void loadFields() { + // Name + registerString("name", makeBukkitGetter(Entity::getName)); + // Locations + registerLocation("location", SpellEntity::getLocation); + registerLocation("position", SpellEntity::getLocation); + registerLocation("eye_location", SpellEntity::getEyeLocation); + registerLocation("eye_position", SpellEntity::getEyeLocation); + registerNumber("x", e -> e.getLocation().getX()); + registerNumber("y", e -> e.getLocation().getY()); + registerNumber("z", e -> e.getLocation().getZ()); + registerNumber("yaw", e -> e.getLocation().getYaw()); + registerNumber("pitch", e -> e.getLocation().getPitch()); + // Health + registerNumber("health", makeBukkitGetter(Damageable::getHealth, 0)); + // Attributes + registerNumber("max_health", makeAttribute(Attribute.GENERIC_MAX_HEALTH)); + registerNumber("armor", makeAttribute(Attribute.GENERIC_ARMOR)); + registerNumber("armor_toughness", makeAttribute(Attribute.GENERIC_ARMOR_TOUGHNESS)); + registerNumber("attack", makeAttribute(Attribute.GENERIC_ATTACK_DAMAGE)); + registerNumber("attack_damage", makeAttribute(Attribute.GENERIC_ATTACK_DAMAGE)); + registerNumber("damage", makeAttribute(Attribute.GENERIC_ATTACK_DAMAGE)); + registerNumber("speed", makeAttribute(Attribute.GENERIC_MOVEMENT_SPEED)); + registerNumber("knockback", makeAttribute(Attribute.GENERIC_ATTACK_KNOCKBACK)); + registerNumber("knockback_resistance", makeAttribute(Attribute.GENERIC_KNOCKBACK_RESISTANCE)); + } + + private void loadFunctions() { + registerNullFunc( + "teleport", + (se,a) -> se.teleport((Location) a.getFirst()), + FunctionArgument.of(TypePrimitive.LOCATION) + ); + registerNullFunc( + "send_message", + (se,a) -> se.sendMessage(StringTransformation.parse((String) a.getFirst())), + FunctionArgument.of(TypePrimitive.STRING) + ); + registerNullFunc( + "heal", + (se,a) -> se.getEntityAs(LivingEntity.class).ifPresent(le -> le.heal((Double)a.getFirst())), + FunctionArgument.of(TypePrimitive.NUMBER) + ); + } + + @Override + protected @NotNull StructDefinition computeDsl() { + return Objects.requireNonNull(ObjectsDefinitionRegistry.getDefaultStruct(getName()), "Entity struct cannot be found in defaults."); + } + + private static @NotNull Function makeBukkitGetter(@NotNull Function getter) { + return makeBukkitGetter(getter, null); + } + + private static @NotNull Function makeBukkitGetter(@NotNull Function getter, @Nullable T defaultValue) { + return se -> { + if(se.getBukkitEntity().orElse(null) instanceof LivingEntity le) + return getter.apply(le); + return defaultValue; + }; + } + + private static @NotNull Function makeAttribute(@NotNull Attribute attribute) { + return makeBukkitGetter(e -> { + AttributeInstance ai = e.getAttribute(attribute); + return ai == null ? 0 : ai.getValue(); + }); + } +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/EntityInstance.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/EntityInstance.java new file mode 100644 index 00000000..7fc932ef --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/EntityInstance.java @@ -0,0 +1,19 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.structs; + +import fr.jamailun.ultimatespellsystem.api.entities.SpellEntity; +import org.jetbrains.annotations.NotNull; + +/** + * Structure wrapper for an entity. + */ +public class EntityInstance extends AbstractStructInstance { + + /** + * Wraps a spell-entity inside this definition. + * @param entity the entity to use. + */ + public EntityInstance(@NotNull SpellEntity entity, @NotNull EntityDefinition definition) { + super(definition, entity); + } + +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/StructsLibrary.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/StructsLibrary.java new file mode 100644 index 00000000..d49e1b16 --- /dev/null +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/runner/structs/StructsLibrary.java @@ -0,0 +1,33 @@ +package fr.jamailun.ultimatespellsystem.plugin.runner.structs; + +import fr.jamailun.ultimatespellsystem.api.runner.structs.Struct; +import fr.jamailun.ultimatespellsystem.api.runner.structs.StructDefinition; +import fr.jamailun.ultimatespellsystem.dsl2.errors.TypeException; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenPosition; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +public class StructsLibrary { + + private final Map> definitions = new HashMap<>(); + + public @Nullable StructDefinition find(@NotNull String name) { + return definitions.get(name); + } + + public void register(@NotNull StructDefinition struct) { + definitions.put(struct.getName(), struct); + } + + @SuppressWarnings("unchecked") + public @NotNull Struct instantiate(@NotNull String structName, @NotNull S object) { + StructDefinition def = (StructDefinition) find(structName); + if(def == null) + throw new TypeException(TokenPosition.unknown(), "Could not find a definition for struct name '" + structName + "'."); + return def.instantiate(object); + } + +} diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/PropertiesValidator.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/PropertiesValidator.java index 8d9bd0b0..91693629 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/PropertiesValidator.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/PropertiesValidator.java @@ -6,7 +6,7 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.blocks.*; import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.expressions.PropertiesLiteral; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.SummonNode; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old.SummonNode; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/SpellDefinition.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/SpellDefinition.java index 1226aacc..7f9d01e9 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/SpellDefinition.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/SpellDefinition.java @@ -4,14 +4,16 @@ import fr.jamailun.ultimatespellsystem.api.entities.SpellEntity; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; +import fr.jamailun.ultimatespellsystem.api.runner.functions.GlobalFunction; import fr.jamailun.ultimatespellsystem.api.spells.SpellMetadata; import fr.jamailun.ultimatespellsystem.api.utils.MultivaluedMap; -import fr.jamailun.ultimatespellsystem.dsl.visitor.PrintingVisitor; -import fr.jamailun.ultimatespellsystem.dsl.UltimateSpellSystemDSL; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.validators.DslValidator; +import fr.jamailun.ultimatespellsystem.dsl2.visitor.PrintingVisitor; +import fr.jamailun.ultimatespellsystem.dsl2.UltimateSpellSystemDSL2; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.validators.DslValidator; import fr.jamailun.ultimatespellsystem.plugin.configuration.UssConfig; import fr.jamailun.ultimatespellsystem.plugin.runner.builder.SpellBuilderVisitor; +import fr.jamailun.ultimatespellsystem.plugin.runner.builder.SpellStructure; import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.MetadataNode; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,6 +28,7 @@ public class SpellDefinition extends AbstractSpell { private final File file; private final List steps = new ArrayList<>(); + private final Collection functions; private final MultivaluedMap metadata = new MultivaluedMap<>(); /** @@ -34,9 +37,10 @@ public class SpellDefinition extends AbstractSpell { * @param name the name of the spell. * @param steps the steps to run. */ - public SpellDefinition(@NotNull File file, @NotNull String name, @NotNull List steps) { + public SpellDefinition(@NotNull File file, @NotNull String name, @NotNull List steps, @NotNull Collection functions) { super(name); this.file = file; + this.functions = functions; // Metadata are already sorted (thanks to AST validation) for(RuntimeStatement statement : steps) { if(statement instanceof MetadataNode meta) { @@ -77,9 +81,9 @@ private void checkSpellWarnings() { */ public static @Nullable SpellDefinition loadFile(@NotNull String name, @NotNull File file) { try { - List dsl = UltimateSpellSystemDSL.parse(file); - List steps = load(dsl); - SpellDefinition spell = new SpellDefinition(file, name, steps); + List dsl = UltimateSpellSystemDSL2.parse(file); + SpellStructure structure = load(dsl); + SpellDefinition spell = new SpellDefinition(file, name, structure.statements(), structure.functions()); if(UssConfig.displaySummonWarnings()) spell.checkSpellWarnings(); return spell; @@ -92,7 +96,7 @@ private void checkSpellWarnings() { } } - public static @NotNull List load(@NotNull List dsl) { + public static @NotNull SpellStructure load(@NotNull List dsl) { DslValidator.validateDsl(dsl); return SpellBuilderVisitor.build(dsl); } @@ -101,7 +105,7 @@ private void checkSpellWarnings() { if(!file.exists()) return "file["+file+"] doesn't exist."; try { - List dsl = UltimateSpellSystemDSL.parse(file); + List dsl = UltimateSpellSystemDSL2.parse(file); DslValidator.validateDsl(dsl); return PrintingVisitor.toString(dsl); } catch(Exception e) { @@ -114,6 +118,9 @@ private void checkSpellWarnings() { protected boolean castSpell(@NotNull SpellEntity caster, @NotNull SpellRuntime runtime) { String prefix = "SpellRun-" + UUID.randomUUID().toString().substring(20) + " | "; + // Load functions + functions.forEach(runtime.functions()::register); + UssLogger.logDebug(prefix + " Casted on " + caster); for(RuntimeStatement statement : steps) { @@ -124,8 +131,8 @@ protected boolean castSpell(@NotNull SpellEntity caster, @NotNull SpellRuntime r break; } - boolean success = runtime.getFinalExitCode() == 0; - UssLogger.logDebug(prefix + "End of cast on " + caster + " with code " + runtime.getFinalExitCode() + ". Success = " + success); + boolean success = runtime.isReturnValueSuccess(); + UssLogger.logDebug(prefix + "End of cast on " + caster + " with " + runtime.getReturnedValue() + ". Success = " + success); return success; } diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/SpellsCooldowns.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/SpellsCooldowns.java index 59fdad03..e779b042 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/SpellsCooldowns.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/SpellsCooldowns.java @@ -1,6 +1,6 @@ package fr.jamailun.ultimatespellsystem.plugin.spells; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.jetbrains.annotations.NotNull; import java.time.Instant; @@ -9,11 +9,21 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; -public class SpellsCooldowns { +/** + * Static handler for cooldowns. + */ +public final class SpellsCooldowns { private SpellsCooldowns() {} private static final Map> COOLDOWNS = new ConcurrentHashMap<>(128); + /** + * Test if an entity can cast. + * @param caster UUID of the potential caster. + * @param spellId ID of the spell to use. + * @param duration cooldown duration to apply on the next cooldown. + * @return true if the caster can cast this specific spell at this instant. + */ public static boolean canCast(@NotNull UUID caster, @NotNull String spellId, @NotNull Duration duration) { Map data = COOLDOWNS.computeIfAbsent(caster, x -> new HashMap<>()); Instant next = data.get(spellId); @@ -24,6 +34,10 @@ public static boolean canCast(@NotNull UUID caster, @NotNull String spellId, @No return false; } + /** + * Clear the data related to one caster. + * @param caster UUID of the caster to clear the memory of. + */ public static void removeCaster(@NotNull UUID caster) { COOLDOWNS.remove(caster); } diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/external/ExternalExecutorImpl.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/external/ExternalExecutorImpl.java index 5c2dadcb..bc507dbe 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/external/ExternalExecutorImpl.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/external/ExternalExecutorImpl.java @@ -5,8 +5,8 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import fr.jamailun.ultimatespellsystem.api.spells.ExternalExecutor; -import fr.jamailun.ultimatespellsystem.dsl.nodes.ExpressionNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.ExpressionNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; import fr.jamailun.ultimatespellsystem.plugin.runner.SpellRuntimeImpl; import fr.jamailun.ultimatespellsystem.plugin.runner.builder.SpellBuilderVisitor; import fr.jamailun.ultimatespellsystem.plugin.spells.SpellDefinition; @@ -34,7 +34,7 @@ public class ExternalExecutorImpl implements ExternalExecutor { @Override public @NotNull @UnmodifiableView List handleImplementation(@NotNull List dsl) { - return Collections.unmodifiableList(SpellDefinition.load(dsl)); + return Collections.unmodifiableList(SpellDefinition.load(dsl).statements()); } @Override diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/functions/SpellFunction.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/functions/SpellFunction.java index 07076816..cbcf89a2 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/functions/SpellFunction.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/spells/functions/SpellFunction.java @@ -7,12 +7,12 @@ import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import fr.jamailun.ultimatespellsystem.api.runner.functions.RunnableJavaFunction; import fr.jamailun.ultimatespellsystem.api.utils.MultivaluedMap; -import fr.jamailun.ultimatespellsystem.dsl.UltimateSpellSystemDSL; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Type; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.UltimateSpellSystemDSL2; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.plugin.runner.builder.SpellStructure; import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.MetadataNode; import fr.jamailun.ultimatespellsystem.plugin.spells.SpellDefinition; import lombok.Getter; @@ -46,7 +46,7 @@ private void registerFunction() { // Definition new RunnableJavaFunction( name, - outputVar == null ? TypePrimitive.NULL.asType() : outputVar.type(), + outputVar == null ? Type.NULL : outputVar.type(), args ) { // Execution @@ -56,7 +56,7 @@ public Object compute(@NotNull List arguments, @NotNull Spell SpellRuntime childRuntime = runtime.makeChild(); for(int i = 0; i < args.size(); i++) { Object arg = arguments.get(i).evaluate(childRuntime); - childRuntime.variables().set(args.get(i).debugName(), arg); + childRuntime.variables().set(args.get(i).name(), arg); } // Execute return executeSteps(childRuntime); @@ -75,7 +75,7 @@ public Object executeSteps(@NotNull SpellRuntime runtime) { if(outputVar != null) { return runtime.variables().get(outputVar.name()); } - return runtime.getFinalExitCode(); + return runtime.getReturnedValue(); } public static @Nullable SpellFunction loadFile(@NotNull File file) { @@ -83,8 +83,9 @@ public Object executeSteps(@NotNull SpellRuntime runtime) { List steps = new ArrayList<>(); try { - List dsl = UltimateSpellSystemDSL.parse(file); - List rawStatements = SpellDefinition.load(dsl); + List dsl = UltimateSpellSystemDSL2.parse(file); + SpellStructure structure = SpellDefinition.load(dsl); + List rawStatements = structure.statements(); // Metadata are already sorted (thanks to AST validation) for(RuntimeStatement statement : rawStatements) { @@ -141,7 +142,7 @@ public Object executeSteps(@NotNull SpellRuntime runtime) { throw new InvalidMetadata(node, "unknown @param primitive: '" + varType + "'."); list.add(new FunctionArgument( - FunctionType.accept(type), + Type.of(type), varName, false )); diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/utils/DurationHelper.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/utils/DurationHelper.java index f096d514..f0692b3f 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/utils/DurationHelper.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/utils/DurationHelper.java @@ -1,7 +1,7 @@ package fr.jamailun.ultimatespellsystem.plugin.utils; import fr.jamailun.ultimatespellsystem.UssLogger; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/utils/holders/BlockHolder.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/utils/holders/BlockHolder.java index 3a9374c5..406d2305 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/utils/holders/BlockHolder.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/utils/holders/BlockHolder.java @@ -2,7 +2,7 @@ import fr.jamailun.ultimatespellsystem.UssLogger; import fr.jamailun.ultimatespellsystem.api.UltimateSpellSystem; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import fr.jamailun.ultimatespellsystem.plugin.utils.Pair; import org.bukkit.Location; import org.bukkit.Material; diff --git a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/utils/holders/PotionEffectHolder.java b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/utils/holders/PotionEffectHolder.java index 673f4dc7..e689537a 100644 --- a/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/utils/holders/PotionEffectHolder.java +++ b/plugin/src/main/java/fr/jamailun/ultimatespellsystem/plugin/utils/holders/PotionEffectHolder.java @@ -3,8 +3,8 @@ import fr.jamailun.ultimatespellsystem.UssLogger; import fr.jamailun.ultimatespellsystem.api.runner.errors.InvalidEnumValueException; import fr.jamailun.ultimatespellsystem.api.runner.errors.InvalidTypeException; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.SendEffectNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.Duration; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old.SendEffectNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Duration; import org.bukkit.entity.LivingEntity; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; diff --git a/plugin/src/test/java/fr/jamailun/ultimatespellsystem/extension/ExtensionParsingTests.java b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/extension/ExtensionParsingTests.java index 688f69c1..70438d3f 100644 --- a/plugin/src/test/java/fr/jamailun/ultimatespellsystem/extension/ExtensionParsingTests.java +++ b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/extension/ExtensionParsingTests.java @@ -1,19 +1,12 @@ package fr.jamailun.ultimatespellsystem.extension; -import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; -import fr.jamailun.ultimatespellsystem.dsl.errors.UssException; -import fr.jamailun.ultimatespellsystem.runner.framework.AssertException; -import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import java.io.File; -import java.util.List; - /** * Multiple tests for valid USS files. */ -public class ExtensionParsingTests extends ParseAndCompileTest { +class ExtensionParsingTests extends ParseAndCompileTest { @BeforeAll static void beforeAll() { @@ -35,31 +28,9 @@ void testEntityTypes() { testFolder("entities", false); } - @Test - void testLoops() { - testFolder("loops", true); - } - private void testFolder(@NotNull String folder, boolean run) { - for(File file : listTests(folder)) { - try { - List statements = parseAndVerify(file); - if(run) - cast(statements); - addOk(); - } catch (UssException e) { - e.printStackTrace(); - addFails(file, toString(e)); - } catch (AssertException e) { - System.err.println("Assertion exception ! " + e.getMessage()); - addFails(file, toString(e)); - } catch (Exception e) { - System.err.println("Unexpected error."); - e.printStackTrace(); - addFails(file, toString(e)); - } - } - printResults(); + @Override + protected String baseDir() { + return "extension"; } - } diff --git a/plugin/src/test/java/fr/jamailun/ultimatespellsystem/extension/ParseAndCompileTest.java b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/extension/ParseAndCompileTest.java index 9e983617..f9f06148 100644 --- a/plugin/src/test/java/fr/jamailun/ultimatespellsystem/extension/ParseAndCompileTest.java +++ b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/extension/ParseAndCompileTest.java @@ -1,14 +1,16 @@ package fr.jamailun.ultimatespellsystem.extension; import fr.jamailun.ultimatespellsystem.api.runner.RuntimeStatement; -import fr.jamailun.ultimatespellsystem.dsl.UltimateSpellSystemDSL; -import fr.jamailun.ultimatespellsystem.dsl.errors.UssException; -import fr.jamailun.ultimatespellsystem.dsl.nodes.StatementNode; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.variables.TypesContext; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.CharStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.TokenStream; -import fr.jamailun.ultimatespellsystem.dsl.tokenization.Tokenizer; +import fr.jamailun.ultimatespellsystem.dsl2.UltimateSpellSystemDSL2; +import fr.jamailun.ultimatespellsystem.dsl2.errors.UssException; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.StatementNode; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.variables.TypesContext; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.CharStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.TokenStream; +import fr.jamailun.ultimatespellsystem.dsl2.tokenization.Tokenizer; import fr.jamailun.ultimatespellsystem.plugin.runner.builder.SpellBuilderVisitor; +import fr.jamailun.ultimatespellsystem.plugin.runner.builder.SpellStructure; +import fr.jamailun.ultimatespellsystem.runner.framework.AssertException; import fr.jamailun.ultimatespellsystem.runner.framework.TestFramework; import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Assertions; @@ -22,10 +24,12 @@ */ abstract class ParseAndCompileTest extends TestFramework { - protected final File PARSINGS_FILE = new File("src/test/resources/extension-parsing"); + protected final File PARSINGS_FILE = new File("src/test/resources/spells"); + + protected abstract String baseDir(); protected @NotNull List listTests(@NotNull String subFolder) { - File directory = new File(PARSINGS_FILE, subFolder); + File directory = new File(new File(PARSINGS_FILE, baseDir()), subFolder); Assertions.assertTrue(directory.exists() && directory.isDirectory(), "Directory '" + subFolder + "' does not exist."); File[] children = directory.listFiles(); @@ -52,14 +56,37 @@ protected void addFails(@NotNull File test, @NotNull String error) { failures.put(test, error); } - protected List parseAndVerify(@NotNull File file) throws UssException { + protected void testFolder(@NotNull String folder, boolean run) { + for(File file : listTests(folder)) { + try { + SpellStructure structure = parseAndVerify(file); + List statements = structure.statements(); + if(run) + cast(statements); + addOk(); + } catch (UssException e) { + e.printStackTrace(); + addFails(file, toString(e)); + } catch (AssertException e) { + System.err.println("Assertion exception ! " + e.getMessage()); + addFails(file, toString(e)); + } catch (Exception e) { + System.err.println("Unexpected error."); + e.printStackTrace(); + addFails(file, toString(e)); + } + } + printResults(); + } + + protected SpellStructure parseAndVerify(@NotNull File file) throws UssException { System.out.println("\n\n ================[ " + file.getName() + "]================\n"); // Tokenize TokenStream tokens = Tokenizer.tokenize(CharStream.from(file)); System.out.println(tokens + "\n"); // Parse - List nodes = UltimateSpellSystemDSL.parse(tokens); + List nodes = UltimateSpellSystemDSL2.parse(tokens); System.out.println(" ----------------------- "); diff --git a/plugin/src/test/java/fr/jamailun/ultimatespellsystem/extension/VanillaParsingTests.java b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/extension/VanillaParsingTests.java new file mode 100644 index 00000000..6a227016 --- /dev/null +++ b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/extension/VanillaParsingTests.java @@ -0,0 +1,24 @@ +package fr.jamailun.ultimatespellsystem.extension; + +import org.junit.jupiter.api.Test; + +/** + * Multiple tests for valid USS files. + */ +class VanillaParsingTests extends ParseAndCompileTest { + + @Test + void testLoops() { + testFolder("loops", true); + } + + @Test + void testConsole() { + testFolder("console", true); + } + + @Override + protected String baseDir() { + return "vanilla"; + } +} diff --git a/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/SimpleTest.java b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/SimpleTest.java index d08cd634..ff032a3a 100644 --- a/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/SimpleTest.java +++ b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/SimpleTest.java @@ -3,7 +3,7 @@ import fr.jamailun.ultimatespellsystem.api.utils.StringTransformation; import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.expressions.RawLiteral; import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.expressions.VariableNode; -import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions.SendMessageNode; +import fr.jamailun.ultimatespellsystem.plugin.runner.nodes.functions._old.SendMessageNode; import fr.jamailun.ultimatespellsystem.runner.framework.TestFramework; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/TestFramework.java b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/TestFramework.java index f0f51973..0ac24cee 100644 --- a/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/TestFramework.java +++ b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/TestFramework.java @@ -22,7 +22,6 @@ import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; -import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.Mockito; @@ -63,11 +62,10 @@ static void initAll() { Mockito.when(fakePlugin.getScheduler()).thenReturn(Mockito.mock(Scheduler.class)); try { UltimateSpellSystem.setPlugin(fakePlugin); - - JavaFunctionProvider.instance().registerFunction(new AssertTrueFunction()); - JavaFunctionProvider.instance().registerFunction(new AssertNotCalledFunction()); - JavaFunctionProvider.instance().registerFunction(new PrintFunction()); } catch(IllegalStateException ignored) {} + JavaFunctionProvider.instance().registerFunction(new AssertTrueFunction()); + JavaFunctionProvider.instance().registerFunction(new AssertNotCalledFunction()); + JavaFunctionProvider.instance().registerFunction(new PrintFunction()); } @BeforeEach @@ -97,7 +95,7 @@ protected boolean cast(@NotNull List statements) { if(runtime.isStopped()) break; } - return runtime.getFinalExitCode() == 0; + return runtime.getReturnedValue() == null; } } diff --git a/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/functions/AssertNotCalledFunction.java b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/functions/AssertNotCalledFunction.java index d20c8eb8..4ad94280 100644 --- a/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/functions/AssertNotCalledFunction.java +++ b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/functions/AssertNotCalledFunction.java @@ -3,9 +3,9 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import fr.jamailun.ultimatespellsystem.api.runner.functions.RunnableJavaFunction; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import fr.jamailun.ultimatespellsystem.runner.framework.AssertException; import org.jetbrains.annotations.NotNull; @@ -15,14 +15,8 @@ public class AssertNotCalledFunction extends RunnableJavaFunction { public AssertNotCalledFunction() { super( "ASSERT_NOT_CALLED", - TypePrimitive.NULL.asType(), - List.of( - new FunctionArgument( - FunctionType.acceptOnlyMono(TypePrimitive.STRING), - "message", - false - ) - ) + Type.NULL, + List.of(FunctionArgument.of(TypePrimitive.STRING)) ); } diff --git a/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/functions/AssertTrueFunction.java b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/functions/AssertTrueFunction.java index 6128ece2..da038dbb 100644 --- a/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/functions/AssertTrueFunction.java +++ b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/functions/AssertTrueFunction.java @@ -3,9 +3,9 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import fr.jamailun.ultimatespellsystem.api.runner.functions.RunnableJavaFunction; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import fr.jamailun.ultimatespellsystem.runner.framework.AssertException; import org.jetbrains.annotations.NotNull; @@ -15,15 +15,15 @@ public class AssertTrueFunction extends RunnableJavaFunction { public AssertTrueFunction() { super( "ASSERT_TRUE", - TypePrimitive.NULL.asType(), + Type.NULL, List.of( new FunctionArgument( - FunctionType.acceptOnlyMono(TypePrimitive.BOOLEAN), + Type.of(TypePrimitive.BOOLEAN), "value", true ), new FunctionArgument( - FunctionType.acceptOnlyMono(TypePrimitive.STRING), + Type.of(TypePrimitive.STRING), "message", false ) diff --git a/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/functions/PrintFunction.java b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/functions/PrintFunction.java index 1f6ea2a9..cc516d71 100644 --- a/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/functions/PrintFunction.java +++ b/plugin/src/test/java/fr/jamailun/ultimatespellsystem/runner/framework/functions/PrintFunction.java @@ -3,9 +3,9 @@ import fr.jamailun.ultimatespellsystem.api.runner.RuntimeExpression; import fr.jamailun.ultimatespellsystem.api.runner.SpellRuntime; import fr.jamailun.ultimatespellsystem.api.runner.functions.RunnableJavaFunction; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionArgument; -import fr.jamailun.ultimatespellsystem.dsl.nodes.expressions.functions.FunctionType; -import fr.jamailun.ultimatespellsystem.dsl.nodes.type.TypePrimitive; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.expressions.functions.FunctionArgument; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.Type; +import fr.jamailun.ultimatespellsystem.dsl2.nodes.type.TypePrimitive; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -14,14 +14,8 @@ public class PrintFunction extends RunnableJavaFunction { public PrintFunction() { super( "PRINT", - TypePrimitive.NULL.asType(), - List.of( - new FunctionArgument( - FunctionType.acceptOnlyMono(TypePrimitive.STRING), - "value", - true - ) - ) + Type.NULL, + List.of(FunctionArgument.of(TypePrimitive.STRING)) ); } diff --git a/plugin/src/test/resources/extension-parsing/loops/basic_incr.uss b/plugin/src/test/resources/extension-parsing/loops/basic_incr.uss deleted file mode 100644 index 5c20e9e7..00000000 --- a/plugin/src/test/resources/extension-parsing/loops/basic_incr.uss +++ /dev/null @@ -1,7 +0,0 @@ -%val = 0; - -for(%i = 0; %i < 5; increment %i) { - increment %val; -} - -ASSERT_TRUE(%val == 5, "%val = " + %val + ", should be 5."); diff --git a/plugin/src/test/resources/extension-parsing/lists/basic_list.uss b/plugin/src/test/resources/old/lists/basic_list.uss similarity index 100% rename from plugin/src/test/resources/extension-parsing/lists/basic_list.uss rename to plugin/src/test/resources/old/lists/basic_list.uss diff --git a/plugin/src/test/resources/extension-parsing/lists/entity_contains.uss b/plugin/src/test/resources/old/lists/entity_contains.uss similarity index 100% rename from plugin/src/test/resources/extension-parsing/lists/entity_contains.uss rename to plugin/src/test/resources/old/lists/entity_contains.uss diff --git a/plugin/src/test/resources/old/loops/basic_incr.uss b/plugin/src/test/resources/old/loops/basic_incr.uss new file mode 100644 index 00000000..ba5f9501 --- /dev/null +++ b/plugin/src/test/resources/old/loops/basic_incr.uss @@ -0,0 +1,6 @@ +int val = 0; +for(int i = 0; i < 5; i++) { + ++val; +} + +ASSERT_TRUE(val == 5, "val = " + val + ", should be 5."); diff --git a/plugin/src/test/resources/extension-parsing/loops/for_break.uss b/plugin/src/test/resources/old/loops/for_break.uss similarity index 100% rename from plugin/src/test/resources/extension-parsing/loops/for_break.uss rename to plugin/src/test/resources/old/loops/for_break.uss diff --git a/plugin/src/test/resources/extension-parsing/loops/foreach_break.uss b/plugin/src/test/resources/old/loops/foreach_break.uss similarity index 100% rename from plugin/src/test/resources/extension-parsing/loops/foreach_break.uss rename to plugin/src/test/resources/old/loops/foreach_break.uss diff --git a/plugin/src/test/resources/extension-parsing/loops/repeat_breaks.uss b/plugin/src/test/resources/old/loops/repeat_breaks.uss similarity index 100% rename from plugin/src/test/resources/extension-parsing/loops/repeat_breaks.uss rename to plugin/src/test/resources/old/loops/repeat_breaks.uss diff --git a/plugin/src/test/resources/extension-parsing/loops/while_breaks.uss b/plugin/src/test/resources/old/loops/while_breaks.uss similarity index 100% rename from plugin/src/test/resources/extension-parsing/loops/while_breaks.uss rename to plugin/src/test/resources/old/loops/while_breaks.uss diff --git a/plugin/src/test/resources/extension-parsing/entities/summon-orb.uss b/plugin/src/test/resources/spells/extension/entities/summon-orb.uss similarity index 100% rename from plugin/src/test/resources/extension-parsing/entities/summon-orb.uss rename to plugin/src/test/resources/spells/extension/entities/summon-orb.uss diff --git a/plugin/src/test/resources/extension-parsing/various/damage.uss b/plugin/src/test/resources/spells/extension/various/damage.uss similarity index 100% rename from plugin/src/test/resources/extension-parsing/various/damage.uss rename to plugin/src/test/resources/spells/extension/various/damage.uss diff --git a/plugin/src/test/resources/extension-parsing/various/entity_set_unset.uss b/plugin/src/test/resources/spells/extension/various/entity_set_unset.uss similarity index 100% rename from plugin/src/test/resources/extension-parsing/various/entity_set_unset.uss rename to plugin/src/test/resources/spells/extension/various/entity_set_unset.uss diff --git a/plugin/src/test/resources/extension-parsing/various/operators.uss b/plugin/src/test/resources/spells/extension/various/operators.uss similarity index 100% rename from plugin/src/test/resources/extension-parsing/various/operators.uss rename to plugin/src/test/resources/spells/extension/various/operators.uss diff --git a/plugin/src/test/resources/extension-parsing/various/repeat.uss b/plugin/src/test/resources/spells/extension/various/repeat.uss similarity index 100% rename from plugin/src/test/resources/extension-parsing/various/repeat.uss rename to plugin/src/test/resources/spells/extension/various/repeat.uss diff --git a/plugin/src/test/resources/extension-parsing/various/strike.uss b/plugin/src/test/resources/spells/extension/various/strike.uss similarity index 100% rename from plugin/src/test/resources/extension-parsing/various/strike.uss rename to plugin/src/test/resources/spells/extension/various/strike.uss diff --git a/plugin/src/test/resources/spells/vanilla/console/console.uss b/plugin/src/test/resources/spells/vanilla/console/console.uss new file mode 100644 index 00000000..2471d51f --- /dev/null +++ b/plugin/src/test/resources/spells/vanilla/console/console.uss @@ -0,0 +1 @@ +console.info("test"); \ No newline at end of file diff --git a/plugin/src/test/resources/spells/vanilla/loops/basic_incr.uss b/plugin/src/test/resources/spells/vanilla/loops/basic_incr.uss new file mode 100644 index 00000000..ba5f9501 --- /dev/null +++ b/plugin/src/test/resources/spells/vanilla/loops/basic_incr.uss @@ -0,0 +1,6 @@ +int val = 0; +for(int i = 0; i < 5; i++) { + ++val; +} + +ASSERT_TRUE(val == 5, "val = " + val + ", should be 5."); diff --git a/plugin/src/test/resources/spells/vanilla/loops/for_break.uss b/plugin/src/test/resources/spells/vanilla/loops/for_break.uss new file mode 100644 index 00000000..697b6e22 --- /dev/null +++ b/plugin/src/test/resources/spells/vanilla/loops/for_break.uss @@ -0,0 +1,11 @@ +for(int i = 0; i < 5; ++i) { + if(i >= 0) + break; + ASSERT_NOT_CALLED("FOR::Break should work."); +} + +for(int i = 0; i < 5; i++) { + if(i >= 0) + continue; + ASSERT_NOT_CALLED("FOR::Continue should work."); +} diff --git a/plugin/src/test/resources/spells/vanilla/loops/while_breaks.uss b/plugin/src/test/resources/spells/vanilla/loops/while_breaks.uss new file mode 100644 index 00000000..383e4977 --- /dev/null +++ b/plugin/src/test/resources/spells/vanilla/loops/while_breaks.uss @@ -0,0 +1,14 @@ +int i = 0; +while(i < 5) { + i++; + if(i >= 0) + break; + ASSERT_NOT_CALLED("WHILE::Break should work."); +} + +do { + --i; + if(i >= 0) + continue; + ASSERT_NOT_CALLED("WHILE::Continue should work."); +} while(i > 0); diff --git a/pom.xml b/pom.xml index 1d4aff4a..cf7b96bf 100644 --- a/pom.xml +++ b/pom.xml @@ -6,14 +6,15 @@ fr.jamailun.paper ultimate-spell-system - 2.6.1-SNAPSHOT + 3.0.0-SNAPSHOT pom Ultimate Spell System Spells in Minecraft with a custom DSL. - dsl + + dsl2 api plugin