From ca36b9f2ae93d989aeacf0b7267e19ed6913a4fe Mon Sep 17 00:00:00 2001 From: Nathanael Sensfelder Date: Fri, 17 Jul 2020 21:20:50 +0200 Subject: Sorting stuff... --- .../fate/v1/error/ConflictingTypeException.java | 2 +- .../fate/v1/error/IncomparableTypeException.java | 2 +- .../fate/v1/error/IncompatibleTypeException.java | 2 +- .../fate/v1/error/InvalidTypeException.java | 2 +- .../v1/error/UnknownDictionaryFieldException.java | 4 +- src/core/src/tonkadur/fate/v1/lang/Cast.java | 170 ------------- .../src/tonkadur/fate/v1/lang/CollectionType.java | 151 ------------ src/core/src/tonkadur/fate/v1/lang/CondValue.java | 138 ----------- src/core/src/tonkadur/fate/v1/lang/Constant.java | 91 ------- .../src/tonkadur/fate/v1/lang/CountOperator.java | 144 ----------- src/core/src/tonkadur/fate/v1/lang/DictType.java | 178 -------------- src/core/src/tonkadur/fate/v1/lang/Event.java | 2 + .../src/tonkadur/fate/v1/lang/IfElseValue.java | 148 ----------- .../src/tonkadur/fate/v1/lang/InstructionList.java | 57 ----- .../tonkadur/fate/v1/lang/IsMemberOperator.java | 144 ----------- src/core/src/tonkadur/fate/v1/lang/Operation.java | 160 ------------ src/core/src/tonkadur/fate/v1/lang/Operator.java | 141 ----------- .../src/tonkadur/fate/v1/lang/RefOperator.java | 44 ---- src/core/src/tonkadur/fate/v1/lang/RefType.java | 91 ------- .../src/tonkadur/fate/v1/lang/SequenceCall.java | 43 ---- src/core/src/tonkadur/fate/v1/lang/TextEffect.java | 2 + src/core/src/tonkadur/fate/v1/lang/Type.java | 271 --------------------- src/core/src/tonkadur/fate/v1/lang/Variable.java | 2 + .../fate/v1/lang/VariableFieldReference.java | 123 ---------- .../tonkadur/fate/v1/lang/VariableReference.java | 64 ----- src/core/src/tonkadur/fate/v1/lang/World.java | 1 + .../fate/v1/lang/instruction/AddElement.java | 148 +++++++++++ .../fate/v1/lang/instruction/InstructionList.java | 57 +++++ .../fate/v1/lang/instruction/SequenceCall.java | 43 ++++ .../tonkadur/fate/v1/lang/meta/TypedEntryList.java | 2 +- .../src/tonkadur/fate/v1/lang/meta/ValueNode.java | 2 +- .../tonkadur/fate/v1/lang/type/CollectionType.java | 151 ++++++++++++ .../src/tonkadur/fate/v1/lang/type/DictType.java | 178 ++++++++++++++ .../src/tonkadur/fate/v1/lang/type/RefType.java | 91 +++++++ src/core/src/tonkadur/fate/v1/lang/type/Type.java | 271 +++++++++++++++++++++ .../tonkadur/fate/v1/lang/valued_node/Cast.java | 172 +++++++++++++ .../fate/v1/lang/valued_node/CondValue.java | 140 +++++++++++ .../fate/v1/lang/valued_node/Constant.java | 93 +++++++ .../fate/v1/lang/valued_node/CountOperator.java | 147 +++++++++++ .../fate/v1/lang/valued_node/IfElseValue.java | 150 ++++++++++++ .../fate/v1/lang/valued_node/IsMemberOperator.java | 147 +++++++++++ .../fate/v1/lang/valued_node/Operation.java | 162 ++++++++++++ .../fate/v1/lang/valued_node/Operator.java | 143 +++++++++++ .../fate/v1/lang/valued_node/RefOperator.java | 48 ++++ .../lang/valued_node/VariableFieldReference.java | 128 ++++++++++ .../v1/lang/valued_node/VariableReference.java | 68 ++++++ src/core/src/tonkadur/fate/v1/parser/FateParser.g4 | 3 + 47 files changed, 2355 insertions(+), 2166 deletions(-) delete mode 100644 src/core/src/tonkadur/fate/v1/lang/Cast.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/CollectionType.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/CondValue.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/Constant.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/CountOperator.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/DictType.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/IfElseValue.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/InstructionList.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/IsMemberOperator.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/Operation.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/Operator.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/RefOperator.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/RefType.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/SequenceCall.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/Type.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/VariableFieldReference.java delete mode 100644 src/core/src/tonkadur/fate/v1/lang/VariableReference.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/instruction/AddElement.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/instruction/InstructionList.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/instruction/SequenceCall.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/type/CollectionType.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/type/DictType.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/type/RefType.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/type/Type.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/valued_node/Cast.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/valued_node/CondValue.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/valued_node/Constant.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/valued_node/CountOperator.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/valued_node/IfElseValue.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/valued_node/IsMemberOperator.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/valued_node/Operation.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/valued_node/Operator.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/valued_node/RefOperator.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/valued_node/VariableFieldReference.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/valued_node/VariableReference.java diff --git a/src/core/src/tonkadur/fate/v1/error/ConflictingTypeException.java b/src/core/src/tonkadur/fate/v1/error/ConflictingTypeException.java index f084ea9..5a1d06e 100644 --- a/src/core/src/tonkadur/fate/v1/error/ConflictingTypeException.java +++ b/src/core/src/tonkadur/fate/v1/error/ConflictingTypeException.java @@ -5,7 +5,7 @@ import tonkadur.error.ErrorLevel; import tonkadur.parser.Origin; import tonkadur.parser.ParsingError; -import tonkadur.fate.v1.lang.Type; +import tonkadur.fate.v1.lang.type.Type; public class ConflictingTypeException extends ParsingError { diff --git a/src/core/src/tonkadur/fate/v1/error/IncomparableTypeException.java b/src/core/src/tonkadur/fate/v1/error/IncomparableTypeException.java index b3fa548..8169825 100644 --- a/src/core/src/tonkadur/fate/v1/error/IncomparableTypeException.java +++ b/src/core/src/tonkadur/fate/v1/error/IncomparableTypeException.java @@ -5,7 +5,7 @@ import tonkadur.error.ErrorLevel; import tonkadur.parser.Origin; import tonkadur.parser.ParsingError; -import tonkadur.fate.v1.lang.Type; +import tonkadur.fate.v1.lang.type.Type; public class IncomparableTypeException extends ParsingError { diff --git a/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java b/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java index d1827d3..6ada2c3 100644 --- a/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java +++ b/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java @@ -5,7 +5,7 @@ import tonkadur.error.ErrorLevel; import tonkadur.parser.Origin; import tonkadur.parser.ParsingError; -import tonkadur.fate.v1.lang.Type; +import tonkadur.fate.v1.lang.type.Type; public class IncompatibleTypeException extends ParsingError { diff --git a/src/core/src/tonkadur/fate/v1/error/InvalidTypeException.java b/src/core/src/tonkadur/fate/v1/error/InvalidTypeException.java index fcee1ef..a2745d9 100644 --- a/src/core/src/tonkadur/fate/v1/error/InvalidTypeException.java +++ b/src/core/src/tonkadur/fate/v1/error/InvalidTypeException.java @@ -7,7 +7,7 @@ import tonkadur.error.ErrorLevel; import tonkadur.parser.Origin; import tonkadur.parser.ParsingError; -import tonkadur.fate.v1.lang.Type; +import tonkadur.fate.v1.lang.type.Type; public class InvalidTypeException extends ParsingError { diff --git a/src/core/src/tonkadur/fate/v1/error/UnknownDictionaryFieldException.java b/src/core/src/tonkadur/fate/v1/error/UnknownDictionaryFieldException.java index aa1ff70..f5e67f2 100644 --- a/src/core/src/tonkadur/fate/v1/error/UnknownDictionaryFieldException.java +++ b/src/core/src/tonkadur/fate/v1/error/UnknownDictionaryFieldException.java @@ -7,8 +7,8 @@ import tonkadur.error.ErrorLevel; import tonkadur.parser.Origin; import tonkadur.parser.ParsingError; -import tonkadur.fate.v1.lang.DictType; -import tonkadur.fate.v1.lang.Type; +import tonkadur.fate.v1.lang.type.DictType; +import tonkadur.fate.v1.lang.type.Type; public class UnknownDictionaryFieldException extends ParsingError { diff --git a/src/core/src/tonkadur/fate/v1/lang/Cast.java b/src/core/src/tonkadur/fate/v1/lang/Cast.java deleted file mode 100644 index f8b4a75..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/Cast.java +++ /dev/null @@ -1,170 +0,0 @@ -package tonkadur.fate.v1.lang; - -import java.util.Set; -import java.util.Map; -import java.util.HashMap; -import java.util.Collections; - -import tonkadur.error.ErrorManager; - -import tonkadur.parser.Origin; - -import tonkadur.fate.v1.lang.meta.ValueNode; - -import tonkadur.fate.v1.error.IncompatibleTypeException; -import tonkadur.fate.v1.error.IncomparableTypeException; - -public class Cast extends ValueNode -{ - protected static final Map> allowed_type_changes; - - static - { - allowed_type_changes = new HashMap>(); - - allowed_type_changes.put - ( - Type.INT, - Type.NUMBER_TYPES - ); - - allowed_type_changes.put - ( - Type.FLOAT, - Type.NUMBER_TYPES - ); - - allowed_type_changes.put - ( - Type.DICT, - Collections.emptySet() - ); - - allowed_type_changes.put - ( - Type.SET, - Collections.emptySet() - ); - - allowed_type_changes.put - ( - Type.LIST, - Collections.emptySet() - ); - - allowed_type_changes.put - ( - Type.BOOLEAN, - Collections.emptySet() - ); - - allowed_type_changes.put - ( - Type.ANY, - Collections.singleton(Type.ANY) - ); - - allowed_type_changes.put - ( - Type.STRING, - Type.SIMPLE_BASE_TYPES - ); - } - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final ValueNode value; - - /***************************************************************************/ - /**** PROTECTED ************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - protected Cast - ( - final Origin origin, - final Type to, - final ValueNode value - ) - { - super(origin, to); - this.value = value; - } - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - public static Cast build - ( - final Origin origin, - final Type to, - final ValueNode value - ) - throws - IncompatibleTypeException, - IncomparableTypeException - { - final Type hint; - - if - ( - (value.get_type().can_be_used_as(to)) - || - ( - (to.is_base_type()) - && - ( - allowed_type_changes.get(to).contains - ( - value.get_type().get_base_type() - ) - ) - ) - ) - { - return new Cast(origin, to, value); - } - - hint = (Type) value.get_type().generate_comparable_to(to); - - if (hint.equals(Type.ANY)) - { - ErrorManager.handle - ( - new IncompatibleTypeException(origin, value.get_type(), to) - ); - - ErrorManager.handle - ( - new IncomparableTypeException(origin, value.get_type(), to) - ); - } - else - { - ErrorManager.handle - ( - new IncompatibleTypeException(origin, value.get_type(), to, hint) - ); - } - - return new Cast(origin, hint, value); - } - - /**** Accessors ************************************************************/ - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - sb.append(origin.toString()); - sb.append("(Cast ("); - sb.append(type.get_name()); - sb.append(") "); - sb.append(value.toString()); - sb.append(")"); - - return sb.toString(); - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/CollectionType.java b/src/core/src/tonkadur/fate/v1/lang/CollectionType.java deleted file mode 100644 index 0fc52d0..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/CollectionType.java +++ /dev/null @@ -1,151 +0,0 @@ -package tonkadur.fate.v1.lang; - -import tonkadur.error.ErrorManager; - -import tonkadur.parser.Origin; - -import tonkadur.fate.v1.error.InvalidTypeException; - -import tonkadur.fate.v1.lang.meta.DeclaredEntity; - -public class CollectionType extends Type -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final Type content_type; - protected final boolean is_set; - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - - /**** Constructors *********************************************************/ - public static CollectionType build - ( - final Origin origin, - final Type content_type, - final boolean is_set, - final String name - ) - throws InvalidTypeException - { - if - ( - !Type.SIMPLE_BASE_TYPES.contains - ( - content_type.get_base_type() - ) - ) - { - ErrorManager.handle - ( - new InvalidTypeException - ( - origin, - content_type, - Type.SIMPLE_BASE_TYPES - ) - ); - } - - return new CollectionType(origin, content_type, is_set, name); - } - - - /**** Accessors ************************************************************/ - public Type get_content_type () - { - return true_type; - } - - /**** Compatibility ********************************************************/ - @Override - public boolean can_be_used_as (final Type t) - { - if (t instanceof CollectionType) - { - final CollectionType ct; - - ct = (CollectionType) t; - - return - ( - (!ct.is_set || is_set) - && content_type.can_be_used_as(ct.content_type) - ); - } - - return false; - } - - /* - * This is for the very special case where a type is used despite not being - * even a sub-type of the expected one. Using this rather expensive function, - * the most restrictive shared type will be returned. If no such type exists, - * the ANY time is returned. - */ - @Override - public DeclaredEntity generate_comparable_to (final DeclaredEntity de) - { - final CollectionType ct; - - if (!(de instanceof CollectionType)) - { - return Type.ANY; - } - - ct = (CollectionType) de; - - return - new CollectionType - ( - get_origin(), - ((Type) content_type.generate_comparable_to (ct.content_type)), - (ct.is_set || is_set), - name - ); - } - - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - if (is_set) - { - sb.append("(Set "); - } - else - { - sb.append("(List "); - } - - sb.append(content_type.toString()); - sb.append(")::"); - sb.append(name); - - return sb.toString(); - } - - /***************************************************************************/ - /**** PROTECTED ************************************************************/ - /***************************************************************************/ - - /**** Constructors *********************************************************/ - protected CollectionType - ( - final Origin origin, - final Type content_type, - final boolean is_set, - final String name - ) - { - super(origin, (is_set ? Type.SET : Type.LIST), name); - - this.is_set = is_set; - this.content_type = content_type; - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/CondValue.java b/src/core/src/tonkadur/fate/v1/lang/CondValue.java deleted file mode 100644 index cb0bf7c..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/CondValue.java +++ /dev/null @@ -1,138 +0,0 @@ -package tonkadur.fate.v1.lang; - -import java.util.List; -import java.util.Collections; - -import tonkadur.functional.Cons; - -import tonkadur.error.ErrorManager; - -import tonkadur.parser.Origin; - -import tonkadur.fate.v1.lang.meta.ValueNode; - -import tonkadur.fate.v1.error.ConflictingTypeException; -import tonkadur.fate.v1.error.IncomparableTypeException; -import tonkadur.fate.v1.error.InvalidTypeException; - -public class CondValue extends ValueNode -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final List> branches; - - /***************************************************************************/ - /**** PROTECTED ************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - protected CondValue - ( - final Origin origin, - final Type return_type, - final List> branches - ) - { - super(origin, return_type); - - this.branches = branches; - } - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - public static CondValue build - ( - final Origin origin, - final List> branches - ) - throws - InvalidTypeException, - ConflictingTypeException, - IncomparableTypeException - { - final Type first_type; - Type hint; - - first_type = branches.get(0).get_cdr().get_type(); - hint = first_type; - - for (final Cons entry: branches) - { - if (!entry.get_car().get_type().can_be_used_as(Type.BOOLEAN)) - { - ErrorManager.handle - ( - new InvalidTypeException - ( - entry.get_car().get_origin(), - entry.get_car().get_type(), - Collections.singleton(Type.BOOLEAN) - ) - ); - } - - if (entry.get_cdr().get_type().equals(hint)) - { - continue; - } - - ErrorManager.handle - ( - new ConflictingTypeException - ( - entry.get_cdr().get_origin(), - entry.get_cdr().get_type(), - first_type - ) - ); - - hint = (Type) hint.generate_comparable_to(entry.get_cdr().get_type()); - - if (hint.equals(Type.ANY)) - { - ErrorManager.handle - ( - new IncomparableTypeException - ( - entry.get_cdr().get_origin(), - entry.get_cdr().get_type(), - first_type - ) - ); - } - } - - return new CondValue(origin, hint, branches); - } - - /**** Accessors ************************************************************/ - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - sb.append(origin.toString()); - sb.append("(CondValue"); - sb.append(System.lineSeparator()); - - for (final Cons entry: branches) - { - sb.append(System.lineSeparator()); - sb.append("Condition:"); - sb.append(System.lineSeparator()); - sb.append(entry.get_car().toString()); - sb.append(System.lineSeparator()); - sb.append("Value:"); - sb.append(entry.get_cdr().toString()); - sb.append(System.lineSeparator()); - } - - sb.append(")"); - - return sb.toString(); - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/Constant.java b/src/core/src/tonkadur/fate/v1/lang/Constant.java deleted file mode 100644 index 9c13b1f..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/Constant.java +++ /dev/null @@ -1,91 +0,0 @@ -package tonkadur.fate.v1.lang; - -import tonkadur.parser.Origin; - -import tonkadur.fate.v1.lang.meta.ValueNode; - -public class Constant extends ValueNode -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final String as_string; - - /***************************************************************************/ - /**** PROTECTED ************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - protected Constant - ( - final Origin origin, - final Type result_type, - final String as_string - ) - { - super(origin, result_type); - - this.as_string = as_string; - } - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - public static Constant build_boolean - ( - final Origin origin, - final boolean value - ) - { - return new Constant(origin, Type.BOOLEAN, value ? "true" : "false"); - } - - public static Constant build (final Origin origin, final String as_string) - { - try - { - Integer.valueOf(as_string); - - return new Constant(origin, Type.INT, as_string); - } - catch (final NumberFormatException nfe) - { - /* That's fine, we're just testing... */ - } - - try - { - Float.valueOf(as_string); - - return new Constant(origin, Type.FLOAT, as_string); - } - catch (final NumberFormatException nfe) - { - /* That's fine, we're just testing... */ - } - - return new Constant(origin, Type.STRING, as_string); - } - - /**** Accessors ************************************************************/ - public String get_value_as_string () - { - return as_string; - } - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - sb.append(origin.toString()); - sb.append("("); - sb.append(type.get_name()); - sb.append(" Constant "); - sb.append(as_string); - sb.append(")"); - - return sb.toString(); - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/CountOperator.java b/src/core/src/tonkadur/fate/v1/lang/CountOperator.java deleted file mode 100644 index eabbe5c..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/CountOperator.java +++ /dev/null @@ -1,144 +0,0 @@ -package tonkadur.fate.v1.lang; - -import tonkadur.error.ErrorManager; - -import tonkadur.parser.Origin; - -import tonkadur.fate.v1.lang.meta.ValueNode; - -import tonkadur.fate.v1.error.ConflictingTypeException; -import tonkadur.fate.v1.error.IncomparableTypeException; -import tonkadur.fate.v1.error.InvalidTypeException; - -public class CountOperator extends ValueNode -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final ValueNode element; - protected final ValueNode collection; - - /***************************************************************************/ - /**** PROTECTED ************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - protected CountOperator - ( - final Origin origin, - final ValueNode element, - final ValueNode collection - ) - { - super(origin, Type.INT); - - this.collection = collection; - this.element = element; - } - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - public static CountOperator build - ( - final Origin origin, - final ValueNode element, - final ValueNode collection - ) - throws - InvalidTypeException, - ConflictingTypeException, - IncomparableTypeException - { - final Type hint; - final Type collection_type; - final CollectionType collection_true_type; - final Type collection_element_type; - - collection_type = collection.get_type(); - - if - ( - !Type.COLLECTION_TYPES.contains(collection_type.get_base_type()) - || !(collection_type instanceof CollectionType) - ) - { - ErrorManager.handle - ( - new InvalidTypeException - ( - collection.get_origin(), - collection.get_type(), - Type.COLLECTION_TYPES - ) - ); - } - - collection_true_type = (CollectionType) collection_type; - collection_element_type = collection_true_type.get_content_type(); - - if (element.get_type().can_be_used_as(collection_element_type)) - { - return new CountOperator(origin, element, collection); - } - - ErrorManager.handle - ( - new ConflictingTypeException - ( - element.get_origin(), - element.get_type(), - collection_element_type - ) - ); - - hint = - (Type) element.get_type().generate_comparable_to - ( - collection_element_type - ); - - if (hint.equals(Type.ANY)) - { - ErrorManager.handle - ( - new IncomparableTypeException - ( - element.get_origin(), - element.get_type(), - collection_element_type - ) - ); - } - - return new CountOperator(origin, element, collection); - } - - /**** Accessors ************************************************************/ - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - sb.append(origin.toString()); - sb.append("(CountOperator"); - sb.append(System.lineSeparator()); - sb.append(System.lineSeparator()); - - sb.append("element:"); - sb.append(System.lineSeparator()); - sb.append(element.toString()); - sb.append(System.lineSeparator()); - sb.append(System.lineSeparator()); - - sb.append("collection:"); - sb.append(System.lineSeparator()); - sb.append(collection.toString()); - - sb.append(")"); - - return sb.toString(); - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/DictType.java b/src/core/src/tonkadur/fate/v1/lang/DictType.java deleted file mode 100644 index 0b1d138..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/DictType.java +++ /dev/null @@ -1,178 +0,0 @@ -package tonkadur.fate.v1.lang; - -import java.util.Map; -import java.util.HashSet; -import java.util.HashMap; -import java.util.Set; - -import tonkadur.parser.Origin; - -import tonkadur.error.ErrorManager; - -import tonkadur.fate.v1.error.UnknownDictionaryFieldException; - -import tonkadur.fate.v1.lang.meta.DeclaredEntity; - -public class DictType extends Type -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final Map field_types; - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - - /**** Constructors *********************************************************/ - public DictType - ( - final Origin origin, - final Map field_types, - final String name - ) - { - super(origin, Type.DICT, name); - - this.field_types = field_types; - } - - /**** Accessors ************************************************************/ - public Type get_field_type (final Origin call_origin, final String t) - throws UnknownDictionaryFieldException - { - final Type result; - - result = field_types.get(t); - - if (result == null) - { - ErrorManager.handle - ( - new UnknownDictionaryFieldException(call_origin, t, this) - ); - - return Type.ANY; - } - - return result; - } - - public Set> get_fields () - { - return field_types.entrySet(); - } - - /**** Compatibility ********************************************************/ - @Override - public boolean can_be_used_as (final Type t) - { - if (t instanceof DictType) - { - final DictType dt; - - dt = (DictType) t; - - for (final Map.Entry own_field: get_fields()) - { - final Type dt_field_t; - - dt_field_t = dt.field_types.get(own_field.getKey()); - - if - ( - (dt_field_t == null) - || !(own_field.getValue().can_be_used_as(dt_field_t)) - ) - { - return false; - } - } - - return true; - - } - - return false; - } - - /* - * This is for the very special case where a type is used despite not being - * even a sub-type of the expected one. Using this rather expensive function, - * the most restrictive shared type will be returned. If no such type exists, - * the ANY time is returned. - */ - @Override - public DeclaredEntity generate_comparable_to (final DeclaredEntity de) - { - final Map result_field_types; - final Set result_field_names; - final DictType dt; - - if (!(de instanceof DictType)) - { - return Type.ANY; - } - - dt = (DictType) de; - - result_field_names = new HashSet(); - result_field_types = new HashMap(); - - result_field_names.addAll(field_types.keySet()); - result_field_names.addAll(dt.field_types.keySet()); - - for (final String field_name: result_field_names) - { - final Type this_type; - final Type other_type; - Type result_field_type; - - this_type = field_types.get(field_name); - other_type = dt.field_types.get(field_name); - - if (this_type == null) - { - result_field_type = other_type; - } - else if (other_type == null) - { - result_field_type = this_type; - } - else - { - result_field_type = - (Type) this_type.generate_comparable_to(other_type); - } - - result_field_types.put(field_name, result_field_type); - } - - return new DictType(get_origin(), result_field_types, name); - } - - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - sb.append("(Dict "); - - for (final Map.Entry field: get_fields()) - { - sb.append(System.lineSeparator()); - sb.append("(field "); - sb.append(field.getKey()); - sb.append(" "); - sb.append(field.getValue().toString()); - sb.append(")"); - } - sb.append(System.lineSeparator()); - sb.append(")::"); - sb.append(name); - - return sb.toString(); - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/Event.java b/src/core/src/tonkadur/fate/v1/lang/Event.java index fe667af..55b8c62 100644 --- a/src/core/src/tonkadur/fate/v1/lang/Event.java +++ b/src/core/src/tonkadur/fate/v1/lang/Event.java @@ -11,6 +11,8 @@ import tonkadur.parser.Origin; import tonkadur.fate.v1.lang.meta.DeclaredEntity; +import tonkadur.fate.v1.lang.type.Type; + public class Event extends DeclaredEntity { protected static final Event ANY; diff --git a/src/core/src/tonkadur/fate/v1/lang/IfElseValue.java b/src/core/src/tonkadur/fate/v1/lang/IfElseValue.java deleted file mode 100644 index d54e164..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/IfElseValue.java +++ /dev/null @@ -1,148 +0,0 @@ -package tonkadur.fate.v1.lang; - -import java.util.Collections; - -import tonkadur.error.ErrorManager; - -import tonkadur.parser.Origin; - -import tonkadur.fate.v1.lang.meta.ValueNode; - -import tonkadur.fate.v1.error.ConflictingTypeException; -import tonkadur.fate.v1.error.IncomparableTypeException; -import tonkadur.fate.v1.error.InvalidTypeException; - -public class IfElseValue extends ValueNode -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final ValueNode condition; - protected final ValueNode if_true; - protected final ValueNode if_false; - - /***************************************************************************/ - /**** PROTECTED ************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - protected IfElseValue - ( - final Origin origin, - final Type return_type, - final ValueNode condition, - final ValueNode if_true, - final ValueNode if_false - ) - { - super(origin, return_type); - - this.condition = condition; - this.if_true = if_true; - this.if_false = if_false; - } - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - public static IfElseValue build - ( - final Origin origin, - final ValueNode condition, - final ValueNode if_true, - final ValueNode if_false - ) - throws - InvalidTypeException, - ConflictingTypeException, - IncomparableTypeException - { - final Type hint; - final Type if_true_type; - final Type if_false_type; - - if (!condition.get_type().can_be_used_as(Type.BOOLEAN)) - { - ErrorManager.handle - ( - new InvalidTypeException - ( - condition.get_origin(), - condition.get_type(), - Collections.singleton(Type.BOOLEAN) - ) - ); - } - - if_true_type = if_true.get_type(); - if_false_type = if_false.get_type(); - - if (if_true_type.equals(if_false_type)) - { - return - new IfElseValue(origin, if_true_type, condition, if_true, if_false); - } - - ErrorManager.handle - ( - new ConflictingTypeException - ( - if_false.get_origin(), - if_false_type, - if_true_type - ) - ); - - hint = - (Type) if_false_type.generate_comparable_to(if_true_type); - - if (hint.equals(Type.ANY)) - { - ErrorManager.handle - ( - new IncomparableTypeException - ( - if_false.get_origin(), - if_false_type, - if_true_type - ) - ); - } - - return new IfElseValue(origin, hint, condition, if_true, if_false); - } - - /**** Accessors ************************************************************/ - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - sb.append(origin.toString()); - sb.append("(IfElseValue"); - sb.append(System.lineSeparator()); - sb.append(System.lineSeparator()); - - sb.append("Condition:"); - sb.append(System.lineSeparator()); - sb.append(condition.toString()); - - sb.append(System.lineSeparator()); - sb.append(System.lineSeparator()); - sb.append("If true:"); - sb.append(System.lineSeparator()); - sb.append(if_true.toString()); - - sb.append(System.lineSeparator()); - sb.append(System.lineSeparator()); - sb.append("If false:"); - sb.append(System.lineSeparator()); - sb.append(if_false.toString()); - - sb.append(")"); - - return sb.toString(); - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/InstructionList.java b/src/core/src/tonkadur/fate/v1/lang/InstructionList.java deleted file mode 100644 index ee85120..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/InstructionList.java +++ /dev/null @@ -1,57 +0,0 @@ -package tonkadur.fate.v1.lang; - -import java.util.List; - -import tonkadur.parser.Origin; - -import tonkadur.fate.v1.lang.meta.InstructionNode; - -public class InstructionList extends InstructionNode -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final List instructions; - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - public InstructionList - ( - final Origin origin, - final List instructions - ) - { - super(origin); - - this.instructions = instructions; - } - - /**** Accessors ************************************************************/ - public List get_instructions () - { - return instructions; - } - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - sb.append("(InstructionList "); - - sb.append(System.lineSeparator()); - - for (final InstructionNode instruction: instructions) - { - sb.append(instruction.toString()); - sb.append(System.lineSeparator()); - } - - sb.append(")"); - - return sb.toString(); - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/IsMemberOperator.java b/src/core/src/tonkadur/fate/v1/lang/IsMemberOperator.java deleted file mode 100644 index 3120c6c..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/IsMemberOperator.java +++ /dev/null @@ -1,144 +0,0 @@ -package tonkadur.fate.v1.lang; - -import tonkadur.error.ErrorManager; - -import tonkadur.parser.Origin; - -import tonkadur.fate.v1.lang.meta.ValueNode; - -import tonkadur.fate.v1.error.ConflictingTypeException; -import tonkadur.fate.v1.error.IncomparableTypeException; -import tonkadur.fate.v1.error.InvalidTypeException; - -public class IsMemberOperator extends ValueNode -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final ValueNode element; - protected final ValueNode collection; - - /***************************************************************************/ - /**** PROTECTED ************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - protected IsMemberOperator - ( - final Origin origin, - final ValueNode element, - final ValueNode collection - ) - { - super(origin, Type.BOOLEAN); - - this.collection = collection; - this.element = element; - } - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - public static IsMemberOperator build - ( - final Origin origin, - final ValueNode element, - final ValueNode collection - ) - throws - InvalidTypeException, - ConflictingTypeException, - IncomparableTypeException - { - final Type hint; - final Type collection_type; - final CollectionType collection_true_type; - final Type collection_element_type; - - collection_type = collection.get_type(); - - if - ( - !Type.COLLECTION_TYPES.contains(collection_type.get_base_type()) - || !(collection_type instanceof CollectionType) - ) - { - ErrorManager.handle - ( - new InvalidTypeException - ( - collection.get_origin(), - collection.get_type(), - Type.COLLECTION_TYPES - ) - ); - } - - collection_true_type = (CollectionType) collection_type; - collection_element_type = collection_true_type.get_content_type(); - - if (element.get_type().can_be_used_as(collection_element_type)) - { - return new IsMemberOperator(origin, element, collection); - } - - ErrorManager.handle - ( - new ConflictingTypeException - ( - element.get_origin(), - element.get_type(), - collection_element_type - ) - ); - - hint = - (Type) element.get_type().generate_comparable_to - ( - collection_element_type - ); - - if (hint.equals(Type.ANY)) - { - ErrorManager.handle - ( - new IncomparableTypeException - ( - element.get_origin(), - element.get_type(), - collection_element_type - ) - ); - } - - return new IsMemberOperator(origin, element, collection); - } - - /**** Accessors ************************************************************/ - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - sb.append(origin.toString()); - sb.append("(IsMemberOperator"); - sb.append(System.lineSeparator()); - sb.append(System.lineSeparator()); - - sb.append("element:"); - sb.append(System.lineSeparator()); - sb.append(element.toString()); - sb.append(System.lineSeparator()); - sb.append(System.lineSeparator()); - - sb.append("collection:"); - sb.append(System.lineSeparator()); - sb.append(collection.toString()); - - sb.append(")"); - - return sb.toString(); - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/Operation.java b/src/core/src/tonkadur/fate/v1/lang/Operation.java deleted file mode 100644 index b3549e6..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/Operation.java +++ /dev/null @@ -1,160 +0,0 @@ -package tonkadur.fate.v1.lang; - -import java.util.Collection; -import java.util.List; - -import tonkadur.error.ErrorManager; - -import tonkadur.parser.Origin; - -//import tonkadur.fate.v1.error.ConflictingTypeException; -import tonkadur.fate.v1.error.IncomparableTypeException; -import tonkadur.fate.v1.error.IncompatibleTypeException; -import tonkadur.fate.v1.error.InvalidArityException; -import tonkadur.fate.v1.error.InvalidTypeException; - -import tonkadur.fate.v1.lang.meta.ValueNode; - -public class Operation extends ValueNode -{ - protected final Operator operator; - protected final List operands; - - protected Operation - ( - final Origin origin, - final Type result_type, - final Operator operator, - final List operands - ) - { - super(origin, result_type); - - this.operator = operator; - this.operands = operands; - } - - public static Operation build - ( - final Origin origin, - final Operator operator, - final List operands - ) - throws - //ConflictingTypeException, - IncomparableTypeException, - IncompatibleTypeException, - InvalidArityException, - InvalidTypeException - { - final Collection allowed_base_types; - final int operator_max_arity; - final int operator_min_arity; - final int operands_size; - Type computed_type, previous_computed_type; - - allowed_base_types = operator.get_allowed_base_types(); - operator_max_arity = operator.get_maximum_arity(); - operator_min_arity = operator.get_minimum_arity(); - operands_size = operands.size(); - - if - ( - (operands_size < operator_min_arity) - || - ( - (operator_max_arity != 0) - && (operator_max_arity < operands_size) - ) - ) - { - ErrorManager.handle - ( - new InvalidArityException - ( - origin, - operands_size, - operator_min_arity, - operator_max_arity - ) - ); - } - - computed_type = operands.get(0).get_type(); - - for (final ValueNode operand: operands) - { - final Type operand_type; - - operand_type = operand.get_type(); - - if (!allowed_base_types.contains(operand_type.get_base_type())) - { - ErrorManager.handle - ( - new InvalidTypeException - ( - operand.get_origin(), - operand_type, - allowed_base_types - ) - ); - } - - /* - - if (computed_type.equals(operand_type)) - { - continue; - } - - ErrorManager.handle - ( - new ConflictingTypeException - ( - operand.get_origin(), - operand_type, - computed_type - ) - ); - - */ - - if (operand_type.can_be_used_as(computed_type)) - { - continue; - } - - ErrorManager.handle - ( - new IncompatibleTypeException - ( - operand.get_origin(), - operand_type, - computed_type - ) - ); - - previous_computed_type = computed_type; - computed_type = - (Type) computed_type.generate_comparable_to(operand_type); - - if (computed_type.equals(Type.ANY)) - { - ErrorManager.handle - ( - new IncomparableTypeException - ( - operand.get_origin(), - operand_type, - previous_computed_type - ) - ); - } - } - - computed_type = operator.transform_type(computed_type); - - return new Operation(origin, computed_type, operator, operands); - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/Operator.java b/src/core/src/tonkadur/fate/v1/lang/Operator.java deleted file mode 100644 index 5a8f303..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/Operator.java +++ /dev/null @@ -1,141 +0,0 @@ -package tonkadur.fate.v1.lang; - -import java.util.Collections; -import java.util.Set; - -/* - * Yes, it *could* have been an enum. In fact, it used to be one. Except that - * unless you want to ensure coverage of all cases in a switch, Java enums are - * clearly inferior to classes in everyway. Having this be a class will, at - * the very least, let you extend it to add new operators in extensions. - */ -public class Operator -{ - public static final Operator PLUS; - public static final Operator MINUS; - public static final Operator TIMES; - public static final Operator DIVIDE; - public static final Operator POWER; - public static final Operator RANDOM; - - public static final Operator AND; - public static final Operator OR; - public static final Operator NOT; - public static final Operator IMPLIES; - public static final Operator ONE_IN; - - public static final Operator EQUALS; - - public static final Operator LOWER_THAN; - public static final Operator LOWER_EQUAL_THAN; - public static final Operator GREATER_EQUAL_THAN; - public static final Operator GREATER_THAN; - - - static - { - PLUS = new Operator("+", 2, 0, Type.NUMBER_TYPES, null); - MINUS = new Operator("-", 2, 0, Type.NUMBER_TYPES, null); - TIMES = new Operator("*", 2, 0, Type.NUMBER_TYPES, null); - DIVIDE = new Operator("/", 2, 2, Type.NUMBER_TYPES, null); - POWER = new Operator("^", 2, 2, Type.NUMBER_TYPES, null); - RANDOM = - new Operator("rand", 2, 2, Collections.singleton(Type.INT), null); - - AND = - new Operator("and", 2, 0, Collections.singleton(Type.BOOLEAN), null); - OR = - new Operator("or", 2, 0, Collections.singleton(Type.BOOLEAN), null); - NOT = - new Operator("not", 1, 1, Collections.singleton(Type.BOOLEAN), null); - IMPLIES = - new Operator - ( - "implies", - 2, - 2, - Collections.singleton(Type.BOOLEAN), - null - ); - ONE_IN = - new Operator - ( - "one_in", - 1, - 0, - Collections.singleton(Type.BOOLEAN), - null - ); - - EQUALS = - new Operator - ( - "equals", - 2, - 0, - Type.SIMPLE_BASE_TYPES, - Type.BOOLEAN - ); - - LOWER_THAN = new Operator("<", 2, 2, Type.NUMBER_TYPES, Type.BOOLEAN); - LOWER_EQUAL_THAN = - new Operator("=<", 2, 2, Type.NUMBER_TYPES, Type.BOOLEAN); - GREATER_EQUAL_THAN = - new Operator(">=", 2, 2, Type.NUMBER_TYPES, Type.BOOLEAN); - GREATER_THAN = new Operator(">", 2, 2, Type.NUMBER_TYPES, Type.BOOLEAN); - } - - final protected String name; - final protected int min_arity; - final protected int max_arity; - final protected Set valid_input_types; - final protected Type output_type_transform; - - protected Operator - ( - final String name, - final int min_arity, - final int max_arity, - final Set valid_input_types, - final Type output_type_transform - ) - { - this.name = name; - this.min_arity = min_arity; - this.max_arity = max_arity; - this.valid_input_types = valid_input_types; - - this.output_type_transform = output_type_transform; - } - - public Set get_allowed_base_types () - { - return valid_input_types; - } - - public int get_minimum_arity () - { - return min_arity; - } - - public int get_maximum_arity () - { - return max_arity; - } - - public Type transform_type (final Type in) - { - if (output_type_transform == null) - { - return in; - } - - return output_type_transform; - } - - @Override - public String toString () - { - return name; - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/RefOperator.java b/src/core/src/tonkadur/fate/v1/lang/RefOperator.java deleted file mode 100644 index f55be22..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/RefOperator.java +++ /dev/null @@ -1,44 +0,0 @@ -package tonkadur.fate.v1.lang; - -import tonkadur.parser.Origin; - -import tonkadur.fate.v1.lang.meta.ValueNode; - -public class RefOperator extends ValueNode -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final Variable variable; - - /***************************************************************************/ - /**** PROTECTED ************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - public RefOperator (final Origin origin, final Variable variable) - { - super(origin, new RefType(origin, variable.get_type(), "auto generated")); - this.variable = variable; - } - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - - /**** Accessors ************************************************************/ - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - sb.append(origin.toString()); - sb.append("(Ref "); - sb.append(variable.get_name()); - sb.append(") "); - - return sb.toString(); - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/RefType.java b/src/core/src/tonkadur/fate/v1/lang/RefType.java deleted file mode 100644 index 423f695..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/RefType.java +++ /dev/null @@ -1,91 +0,0 @@ -package tonkadur.fate.v1.lang; - -import tonkadur.parser.Origin; - -import tonkadur.fate.v1.lang.meta.DeclaredEntity; - -public class RefType extends Type -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final Type referenced_type; - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - - /**** Constructors *********************************************************/ - public RefType - ( - final Origin origin, - final Type referenced_type, - final String name - ) - { - super(origin, Type.REF, name); - - this.referenced_type = referenced_type; - } - - /**** Accessors ************************************************************/ - public Type get_referenced_type () - { - return referenced_type; - } - - /**** Compatibility ********************************************************/ - @Override - public boolean can_be_used_as (final Type t) - { - if (t instanceof RefType) - { - final RefType dt; - - dt = (RefType) t; - - return referenced_type.can_be_used_as(dt.referenced_type); - } - - return false; - } - - /* - * This is for the very special case where a type is used despite not being - * even a sub-type of the expected one. Using this rather expensive function, - * the most restrictive shared type will be returned. If no such type exists, - * the ANY time is returned. - */ - @Override - public DeclaredEntity generate_comparable_to (final DeclaredEntity de) - { - final Type resulting_referenced_type; - final RefType dt; - - if (!(de instanceof RefType)) - { - return Type.ANY; - } - - dt = (RefType) de; - resulting_referenced_type = - (Type) referenced_type.generate_comparable_to(dt.referenced_type); - - return new RefType(get_origin(), resulting_referenced_type, name); - } - - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - sb.append("(Ref to "); - sb.append(referenced_type.toString()); - sb.append(")::"); - sb.append(name); - - return sb.toString(); - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/SequenceCall.java b/src/core/src/tonkadur/fate/v1/lang/SequenceCall.java deleted file mode 100644 index 5b0df50..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/SequenceCall.java +++ /dev/null @@ -1,43 +0,0 @@ -package tonkadur.fate.v1.lang; - -import tonkadur.parser.Origin; - -import tonkadur.fate.v1.lang.meta.InstructionNode; - -public class SequenceCall extends InstructionNode -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final String sequence_name; - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - public SequenceCall (final Origin origin, final String sequence_name) - { - super(origin); - - this.sequence_name = sequence_name; - } - - /**** Accessors ************************************************************/ - public String get_sequence_name () - { - return sequence_name; - } - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - sb.append("(SequenceCall "); - sb.append(sequence_name); - sb.append(")"); - - return sb.toString(); - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/TextEffect.java b/src/core/src/tonkadur/fate/v1/lang/TextEffect.java index db29da1..dde0cfd 100644 --- a/src/core/src/tonkadur/fate/v1/lang/TextEffect.java +++ b/src/core/src/tonkadur/fate/v1/lang/TextEffect.java @@ -11,6 +11,8 @@ import tonkadur.parser.Origin; import tonkadur.fate.v1.lang.meta.DeclaredEntity; +import tonkadur.fate.v1.lang.type.Type; + public class TextEffect extends Event { protected static final TextEffect ANY; diff --git a/src/core/src/tonkadur/fate/v1/lang/Type.java b/src/core/src/tonkadur/fate/v1/lang/Type.java deleted file mode 100644 index cbbeb42..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/Type.java +++ /dev/null @@ -1,271 +0,0 @@ -package tonkadur.fate.v1.lang; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import tonkadur.error.ErrorManager; - -import tonkadur.parser.Context; -import tonkadur.parser.Location; -import tonkadur.parser.Origin; - -import tonkadur.fate.v1.error.InvalidTypeException; - -import tonkadur.fate.v1.lang.meta.DeclaredEntity; - -public class Type extends DeclaredEntity -{ - public static final Type ANY; - public static final Type BOOLEAN; - public static final Type DICT; - public static final Type FLOAT; - public static final Type INT; - public static final Type LIST; - public static final Type SET; - public static final Type REF; - public static final Type STRING; - - public static final Set NUMBER_TYPES; - public static final Set SIMPLE_BASE_TYPES; - public static final Set COLLECTION_TYPES; - - static - { - final Origin base; - - base = new Origin(new Context(""), Location.BASE_LANGUAGE); - - /* - * Use of a space necessary to avoid conflicting with a user created type. - */ - ANY = new Type(base, null, "undetermined type"); - - BOOLEAN = new Type(base, null, "boolean"); - DICT = new Type(base, null, "dict"); - FLOAT = new Type(base, null, "float"); - INT = new Type(base, null, "int"); - LIST = new Type(base, null, "list"); - SET = new Type(base, null, "set"); - REF = new Type(base, null, "ref"); - STRING = new Type(base, null, "string"); - - NUMBER_TYPES = new HashSet(); - NUMBER_TYPES.add(FLOAT); - NUMBER_TYPES.add(INT); - - SIMPLE_BASE_TYPES = new HashSet(); - - SIMPLE_BASE_TYPES.add(FLOAT); - SIMPLE_BASE_TYPES.add(INT); - SIMPLE_BASE_TYPES.add(STRING); - SIMPLE_BASE_TYPES.add(BOOLEAN); - SIMPLE_BASE_TYPES.add(REF); - - COLLECTION_TYPES = new HashSet(); - - COLLECTION_TYPES.add(SET); - COLLECTION_TYPES.add(LIST); - } - - public static Type value_on_missing () - { - return ANY; - } - - @Override - public /* static */ String get_type_name () - { - return "Type"; - } - - - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final Type true_type; - protected final Type parent; - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - - /**** Constructors *********************************************************/ - public static Type build - ( - final Origin origin, - final Type parent, - final String name - ) - throws InvalidTypeException - { - if (!SIMPLE_BASE_TYPES.contains(parent.get_base_type())) - { - ErrorManager.handle - ( - new InvalidTypeException(origin, parent, SIMPLE_BASE_TYPES) - ); - } - - return new Type(origin, parent, name); - } - - /**** Accessors ************************************************************/ - public Type get_base_type () - { - return true_type; - } - - public boolean is_base_type () - { - return (parent == null); - } - - /**** Compatibility ********************************************************/ - public boolean can_be_used_as (final Type t) - { - if (!true_type.equals(t.true_type)) - { - return false; - } - - return this_or_parent_equals(t); - } - - /* - * This is for the very special case where a type is used despite not being - * even a sub-type of the expected one. Using this rather expensive function, - * the most restrictive shared type will be returned. If no such type exists, - * the ANY time is returned. - */ - @Override - public DeclaredEntity generate_comparable_to (final DeclaredEntity de) - { - final Iterator it0, it1; - Type result, candidate; - - if (!(de instanceof Type)) - { - return ANY; - } - - it0 = ((Type) de).compute_full_type_chain().iterator(); - it1 = compute_full_type_chain().iterator(); - - result = Type.ANY; - - while (it0.hasNext() && it1.hasNext()) - { - candidate = it0.next(); - - if (!candidate.name.equals(it1.next().name)) - { - break; - } - - result = candidate; - } - - return new Type(origin, result, name); - } - - - /**** Misc. ****************************************************************/ - @Override - public boolean is_incompatible_with_declaration (final DeclaredEntity de) - { - if (de instanceof Type) - { - final Type t; - - t = (Type) de; - - /* - * If the previous type cannot be used when the new one will do, the - * new declaration cannot safely stand. - */ - return !can_be_used_as(t); - } - - return true; - } - - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - if (parent != null) - { - sb.append(parent.toString()); - sb.append("::"); - } - - sb.append(name); - - return sb.toString(); - } - - /***************************************************************************/ - /**** PROTECTED ************************************************************/ - /***************************************************************************/ - protected Type - ( - final Origin origin, - final Type parent, - final String name - ) - { - super(origin, name); - - if (parent == null) - { - true_type = this; - } - else - { - true_type = parent.true_type; - } - - this.parent = parent; - } - - protected boolean this_or_parent_equals (final Type t) - { - if (equals(t)) - { - return true; - } - - if (parent == null) - { - return false; - } - - return parent.this_or_parent_equals(t); - } - - protected List compute_full_type_chain () - { - final List result; - Type t; - - result = new ArrayList(); - - t = this; - - while (t != null) - { - result.add(t); - - t = t.parent; - } - - Collections.reverse(result); - - return result; - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/Variable.java b/src/core/src/tonkadur/fate/v1/lang/Variable.java index 3e17d61..0b6bba5 100644 --- a/src/core/src/tonkadur/fate/v1/lang/Variable.java +++ b/src/core/src/tonkadur/fate/v1/lang/Variable.java @@ -11,6 +11,8 @@ import tonkadur.parser.Origin; import tonkadur.fate.v1.lang.meta.DeclaredEntity; +import tonkadur.fate.v1.lang.type.Type; + public class Variable extends DeclaredEntity { protected static final Variable ANY; diff --git a/src/core/src/tonkadur/fate/v1/lang/VariableFieldReference.java b/src/core/src/tonkadur/fate/v1/lang/VariableFieldReference.java deleted file mode 100644 index 767a56b..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/VariableFieldReference.java +++ /dev/null @@ -1,123 +0,0 @@ -package tonkadur.fate.v1.lang; - -import java.util.Arrays; -import java.util.List; - -import tonkadur.parser.Origin; - -import tonkadur.error.ErrorManager; - -import tonkadur.fate.v1.lang.meta.ValueNode; - -import tonkadur.fate.v1.error.InvalidTypeException; -import tonkadur.fate.v1.error.UnknownDictionaryFieldException; - -public class VariableFieldReference extends VariableReference -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - final List field_accesses; - - /***************************************************************************/ - /**** PROTECTED ************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - protected VariableFieldReference - ( - final Origin origin, - final Variable variable, - final Type type, - final List field_accesses - ) - { - super(origin, type, variable); - - this.field_accesses = field_accesses; - } - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - public static VariableFieldReference build - ( - final Origin origin, - final Variable variable, - final List field_accesses - ) - throws - InvalidTypeException, - UnknownDictionaryFieldException - { - final StringBuilder sb; - Type current_type; - - sb = new StringBuilder(); - - current_type = variable.get_type(); - - for (final String field_access: field_accesses) - { - sb.append("."); - sb.append(field_access); - - if (!(current_type instanceof DictType)) - { - ErrorManager.handle - ( - new InvalidTypeException - ( - origin, - current_type, - Arrays.asList(new Type[]{Type.DICT}), - (variable.get_name() + "." + sb.toString()) - ) - ); - - break; - } - - current_type = - ((DictType) current_type).get_field_type(origin, field_access); - } - - return - new VariableFieldReference - ( - origin, - variable, - current_type, - field_accesses - ); - } - - /**** Accessors ************************************************************/ - public List get_field_accesses () - { - return field_accesses; - } - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - sb.append(origin.toString()); - sb.append("(VariableFieldReference ("); - sb.append(type.get_name()); - sb.append(") "); - sb.append(variable.get_name()); - - for (final String field: field_accesses) - { - sb.append("."); - sb.append(field); - } - - sb.append(")"); - - return sb.toString(); - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/VariableReference.java b/src/core/src/tonkadur/fate/v1/lang/VariableReference.java deleted file mode 100644 index 5a08483..0000000 --- a/src/core/src/tonkadur/fate/v1/lang/VariableReference.java +++ /dev/null @@ -1,64 +0,0 @@ -package tonkadur.fate.v1.lang; - -import tonkadur.parser.Origin; - -import tonkadur.fate.v1.lang.meta.ValueNode; - -public class VariableReference extends ValueNode -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final Variable variable; - - /***************************************************************************/ - /**** PROTECTED ************************************************************/ - /***************************************************************************/ - protected VariableReference - ( - final Origin origin, - final Type reported_type, - final Variable variable - ) - { - super(origin, reported_type); - this.variable = variable; - } - /**** Constructors *********************************************************/ - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - /**** Constructors *********************************************************/ - public VariableReference - ( - final Origin origin, - final Variable variable - ) - { - super(origin, variable.get_type()); - this.variable = variable; - } - - /**** Accessors ************************************************************/ - public Variable get_variable () - { - return variable; - } - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - sb.append(origin.toString()); - sb.append("(VariableReference ("); - sb.append(type.get_name()); - sb.append(") "); - sb.append(variable.get_name()); - sb.append(")"); - - return sb.toString(); - } -} diff --git a/src/core/src/tonkadur/fate/v1/lang/World.java b/src/core/src/tonkadur/fate/v1/lang/World.java index 76b7805..eb87c45 100644 --- a/src/core/src/tonkadur/fate/v1/lang/World.java +++ b/src/core/src/tonkadur/fate/v1/lang/World.java @@ -18,6 +18,7 @@ import tonkadur.fate.v1.error.UnknownSequenceException; import tonkadur.fate.v1.lang.meta.DeclarationCollection; +import tonkadur.fate.v1.lang.type.Type; public class World { diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/AddElement.java b/src/core/src/tonkadur/fate/v1/lang/instruction/AddElement.java new file mode 100644 index 0000000..9cc9b3b --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/instruction/AddElement.java @@ -0,0 +1,148 @@ +package tonkadur.fate.v1.lang.instruction; + +import tonkadur.error.ErrorManager; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.error.ConflictingTypeException; +import tonkadur.fate.v1.error.IncomparableTypeException; +import tonkadur.fate.v1.error.InvalidTypeException; + +import tonkadur.fate.v1.lang.type.CollectionType; +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.meta.InstructionNode; +import tonkadur.fate.v1.lang.meta.ValueNode; + +public class AddElement extends InstructionNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final ValueNode element; + protected final ValueNode collection; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + protected AddElement + ( + final Origin origin, + final ValueNode element, + final ValueNode collection + ) + { + super(origin); + + this.collection = collection; + this.element = element; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public static AddElement build + ( + final Origin origin, + final ValueNode element, + final ValueNode collection + ) + throws + InvalidTypeException, + ConflictingTypeException, + IncomparableTypeException + { + final Type hint; + final Type collection_type; + final CollectionType collection_true_type; + final Type collection_element_type; + + collection_type = collection.get_type(); + + if + ( + !Type.COLLECTION_TYPES.contains(collection_type.get_base_type()) + || !(collection_type instanceof CollectionType) + ) + { + ErrorManager.handle + ( + new InvalidTypeException + ( + collection.get_origin(), + collection.get_type(), + Type.COLLECTION_TYPES + ) + ); + } + + collection_true_type = (CollectionType) collection_type; + collection_element_type = collection_true_type.get_content_type(); + + if (element.get_type().can_be_used_as(collection_element_type)) + { + return new AddElement(origin, element, collection); + } + + ErrorManager.handle + ( + new ConflictingTypeException + ( + element.get_origin(), + element.get_type(), + collection_element_type + ) + ); + + hint = + (Type) element.get_type().generate_comparable_to + ( + collection_element_type + ); + + if (hint.equals(Type.ANY)) + { + ErrorManager.handle + ( + new IncomparableTypeException + ( + element.get_origin(), + element.get_type(), + collection_element_type + ) + ); + } + + return new AddElement(origin, element, collection); + } + + /**** Accessors ************************************************************/ + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(origin.toString()); + sb.append("(AddElement"); + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + + sb.append("element:"); + sb.append(System.lineSeparator()); + sb.append(element.toString()); + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + + sb.append("collection:"); + sb.append(System.lineSeparator()); + sb.append(collection.toString()); + + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/InstructionList.java b/src/core/src/tonkadur/fate/v1/lang/instruction/InstructionList.java new file mode 100644 index 0000000..47d0c35 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/instruction/InstructionList.java @@ -0,0 +1,57 @@ +package tonkadur.fate.v1.lang.instruction; + +import java.util.List; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.meta.InstructionNode; + +public class InstructionList extends InstructionNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final List instructions; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public InstructionList + ( + final Origin origin, + final List instructions + ) + { + super(origin); + + this.instructions = instructions; + } + + /**** Accessors ************************************************************/ + public List get_instructions () + { + return instructions; + } + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append("(InstructionList "); + + sb.append(System.lineSeparator()); + + for (final InstructionNode instruction: instructions) + { + sb.append(instruction.toString()); + sb.append(System.lineSeparator()); + } + + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/SequenceCall.java b/src/core/src/tonkadur/fate/v1/lang/instruction/SequenceCall.java new file mode 100644 index 0000000..03b7453 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/instruction/SequenceCall.java @@ -0,0 +1,43 @@ +package tonkadur.fate.v1.lang.instruction; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.meta.InstructionNode; + +public class SequenceCall extends InstructionNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final String sequence_name; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public SequenceCall (final Origin origin, final String sequence_name) + { + super(origin); + + this.sequence_name = sequence_name; + } + + /**** Accessors ************************************************************/ + public String get_sequence_name () + { + return sequence_name; + } + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append("(SequenceCall "); + sb.append(sequence_name); + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/meta/TypedEntryList.java b/src/core/src/tonkadur/fate/v1/lang/meta/TypedEntryList.java index b8ad468..7692e38 100644 --- a/src/core/src/tonkadur/fate/v1/lang/meta/TypedEntryList.java +++ b/src/core/src/tonkadur/fate/v1/lang/meta/TypedEntryList.java @@ -11,7 +11,7 @@ import tonkadur.error.ErrorManager; import tonkadur.fate.v1.error.DuplicateFieldException; -import tonkadur.fate.v1.lang.Type; +import tonkadur.fate.v1.lang.type.Type; public class TypedEntryList { diff --git a/src/core/src/tonkadur/fate/v1/lang/meta/ValueNode.java b/src/core/src/tonkadur/fate/v1/lang/meta/ValueNode.java index 6670855..f1a8b64 100644 --- a/src/core/src/tonkadur/fate/v1/lang/meta/ValueNode.java +++ b/src/core/src/tonkadur/fate/v1/lang/meta/ValueNode.java @@ -2,7 +2,7 @@ package tonkadur.fate.v1.lang.meta; import tonkadur.parser.Origin; -import tonkadur.fate.v1.lang.Type; +import tonkadur.fate.v1.lang.type.Type; public abstract class ValueNode extends Node { diff --git a/src/core/src/tonkadur/fate/v1/lang/type/CollectionType.java b/src/core/src/tonkadur/fate/v1/lang/type/CollectionType.java new file mode 100644 index 0000000..04c02f2 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/type/CollectionType.java @@ -0,0 +1,151 @@ +package tonkadur.fate.v1.lang.type; + +import tonkadur.error.ErrorManager; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.error.InvalidTypeException; + +import tonkadur.fate.v1.lang.meta.DeclaredEntity; + +public class CollectionType extends Type +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final Type content_type; + protected final boolean is_set; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + + /**** Constructors *********************************************************/ + public static CollectionType build + ( + final Origin origin, + final Type content_type, + final boolean is_set, + final String name + ) + throws InvalidTypeException + { + if + ( + !Type.SIMPLE_BASE_TYPES.contains + ( + content_type.get_base_type() + ) + ) + { + ErrorManager.handle + ( + new InvalidTypeException + ( + origin, + content_type, + Type.SIMPLE_BASE_TYPES + ) + ); + } + + return new CollectionType(origin, content_type, is_set, name); + } + + + /**** Accessors ************************************************************/ + public Type get_content_type () + { + return true_type; + } + + /**** Compatibility ********************************************************/ + @Override + public boolean can_be_used_as (final Type t) + { + if (t instanceof CollectionType) + { + final CollectionType ct; + + ct = (CollectionType) t; + + return + ( + (!ct.is_set || is_set) + && content_type.can_be_used_as(ct.content_type) + ); + } + + return false; + } + + /* + * This is for the very special case where a type is used despite not being + * even a sub-type of the expected one. Using this rather expensive function, + * the most restrictive shared type will be returned. If no such type exists, + * the ANY time is returned. + */ + @Override + public DeclaredEntity generate_comparable_to (final DeclaredEntity de) + { + final CollectionType ct; + + if (!(de instanceof CollectionType)) + { + return Type.ANY; + } + + ct = (CollectionType) de; + + return + new CollectionType + ( + get_origin(), + ((Type) content_type.generate_comparable_to (ct.content_type)), + (ct.is_set || is_set), + name + ); + } + + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + if (is_set) + { + sb.append("(Set "); + } + else + { + sb.append("(List "); + } + + sb.append(content_type.toString()); + sb.append(")::"); + sb.append(name); + + return sb.toString(); + } + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + + /**** Constructors *********************************************************/ + protected CollectionType + ( + final Origin origin, + final Type content_type, + final boolean is_set, + final String name + ) + { + super(origin, (is_set ? Type.SET : Type.LIST), name); + + this.is_set = is_set; + this.content_type = content_type; + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/type/DictType.java b/src/core/src/tonkadur/fate/v1/lang/type/DictType.java new file mode 100644 index 0000000..93b9106 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/type/DictType.java @@ -0,0 +1,178 @@ +package tonkadur.fate.v1.lang.type; + +import java.util.Map; +import java.util.HashSet; +import java.util.HashMap; +import java.util.Set; + +import tonkadur.parser.Origin; + +import tonkadur.error.ErrorManager; + +import tonkadur.fate.v1.error.UnknownDictionaryFieldException; + +import tonkadur.fate.v1.lang.meta.DeclaredEntity; + +public class DictType extends Type +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final Map field_types; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + + /**** Constructors *********************************************************/ + public DictType + ( + final Origin origin, + final Map field_types, + final String name + ) + { + super(origin, Type.DICT, name); + + this.field_types = field_types; + } + + /**** Accessors ************************************************************/ + public Type get_field_type (final Origin call_origin, final String t) + throws UnknownDictionaryFieldException + { + final Type result; + + result = field_types.get(t); + + if (result == null) + { + ErrorManager.handle + ( + new UnknownDictionaryFieldException(call_origin, t, this) + ); + + return Type.ANY; + } + + return result; + } + + public Set> get_fields () + { + return field_types.entrySet(); + } + + /**** Compatibility ********************************************************/ + @Override + public boolean can_be_used_as (final Type t) + { + if (t instanceof DictType) + { + final DictType dt; + + dt = (DictType) t; + + for (final Map.Entry own_field: get_fields()) + { + final Type dt_field_t; + + dt_field_t = dt.field_types.get(own_field.getKey()); + + if + ( + (dt_field_t == null) + || !(own_field.getValue().can_be_used_as(dt_field_t)) + ) + { + return false; + } + } + + return true; + + } + + return false; + } + + /* + * This is for the very special case where a type is used despite not being + * even a sub-type of the expected one. Using this rather expensive function, + * the most restrictive shared type will be returned. If no such type exists, + * the ANY time is returned. + */ + @Override + public DeclaredEntity generate_comparable_to (final DeclaredEntity de) + { + final Map result_field_types; + final Set result_field_names; + final DictType dt; + + if (!(de instanceof DictType)) + { + return Type.ANY; + } + + dt = (DictType) de; + + result_field_names = new HashSet(); + result_field_types = new HashMap(); + + result_field_names.addAll(field_types.keySet()); + result_field_names.addAll(dt.field_types.keySet()); + + for (final String field_name: result_field_names) + { + final Type this_type; + final Type other_type; + Type result_field_type; + + this_type = field_types.get(field_name); + other_type = dt.field_types.get(field_name); + + if (this_type == null) + { + result_field_type = other_type; + } + else if (other_type == null) + { + result_field_type = this_type; + } + else + { + result_field_type = + (Type) this_type.generate_comparable_to(other_type); + } + + result_field_types.put(field_name, result_field_type); + } + + return new DictType(get_origin(), result_field_types, name); + } + + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append("(Dict "); + + for (final Map.Entry field: get_fields()) + { + sb.append(System.lineSeparator()); + sb.append("(field "); + sb.append(field.getKey()); + sb.append(" "); + sb.append(field.getValue().toString()); + sb.append(")"); + } + sb.append(System.lineSeparator()); + sb.append(")::"); + sb.append(name); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/type/RefType.java b/src/core/src/tonkadur/fate/v1/lang/type/RefType.java new file mode 100644 index 0000000..277e369 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/type/RefType.java @@ -0,0 +1,91 @@ +package tonkadur.fate.v1.lang.type; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.meta.DeclaredEntity; + +public class RefType extends Type +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final Type referenced_type; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + + /**** Constructors *********************************************************/ + public RefType + ( + final Origin origin, + final Type referenced_type, + final String name + ) + { + super(origin, Type.REF, name); + + this.referenced_type = referenced_type; + } + + /**** Accessors ************************************************************/ + public Type get_referenced_type () + { + return referenced_type; + } + + /**** Compatibility ********************************************************/ + @Override + public boolean can_be_used_as (final Type t) + { + if (t instanceof RefType) + { + final RefType dt; + + dt = (RefType) t; + + return referenced_type.can_be_used_as(dt.referenced_type); + } + + return false; + } + + /* + * This is for the very special case where a type is used despite not being + * even a sub-type of the expected one. Using this rather expensive function, + * the most restrictive shared type will be returned. If no such type exists, + * the ANY time is returned. + */ + @Override + public DeclaredEntity generate_comparable_to (final DeclaredEntity de) + { + final Type resulting_referenced_type; + final RefType dt; + + if (!(de instanceof RefType)) + { + return Type.ANY; + } + + dt = (RefType) de; + resulting_referenced_type = + (Type) referenced_type.generate_comparable_to(dt.referenced_type); + + return new RefType(get_origin(), resulting_referenced_type, name); + } + + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append("(Ref to "); + sb.append(referenced_type.toString()); + sb.append(")::"); + sb.append(name); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/type/Type.java b/src/core/src/tonkadur/fate/v1/lang/type/Type.java new file mode 100644 index 0000000..4d3ad1d --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/type/Type.java @@ -0,0 +1,271 @@ +package tonkadur.fate.v1.lang.type; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import tonkadur.error.ErrorManager; + +import tonkadur.parser.Context; +import tonkadur.parser.Location; +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.error.InvalidTypeException; + +import tonkadur.fate.v1.lang.meta.DeclaredEntity; + +public class Type extends DeclaredEntity +{ + public static final Type ANY; + public static final Type BOOLEAN; + public static final Type DICT; + public static final Type FLOAT; + public static final Type INT; + public static final Type LIST; + public static final Type SET; + public static final Type REF; + public static final Type STRING; + + public static final Set NUMBER_TYPES; + public static final Set SIMPLE_BASE_TYPES; + public static final Set COLLECTION_TYPES; + + static + { + final Origin base; + + base = new Origin(new Context(""), Location.BASE_LANGUAGE); + + /* + * Use of a space necessary to avoid conflicting with a user created type. + */ + ANY = new Type(base, null, "undetermined type"); + + BOOLEAN = new Type(base, null, "boolean"); + DICT = new Type(base, null, "dict"); + FLOAT = new Type(base, null, "float"); + INT = new Type(base, null, "int"); + LIST = new Type(base, null, "list"); + SET = new Type(base, null, "set"); + REF = new Type(base, null, "ref"); + STRING = new Type(base, null, "string"); + + NUMBER_TYPES = new HashSet(); + NUMBER_TYPES.add(FLOAT); + NUMBER_TYPES.add(INT); + + SIMPLE_BASE_TYPES = new HashSet(); + + SIMPLE_BASE_TYPES.add(FLOAT); + SIMPLE_BASE_TYPES.add(INT); + SIMPLE_BASE_TYPES.add(STRING); + SIMPLE_BASE_TYPES.add(BOOLEAN); + SIMPLE_BASE_TYPES.add(REF); + + COLLECTION_TYPES = new HashSet(); + + COLLECTION_TYPES.add(SET); + COLLECTION_TYPES.add(LIST); + } + + public static Type value_on_missing () + { + return ANY; + } + + @Override + public /* static */ String get_type_name () + { + return "Type"; + } + + + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final Type true_type; + protected final Type parent; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + + /**** Constructors *********************************************************/ + public static Type build + ( + final Origin origin, + final Type parent, + final String name + ) + throws InvalidTypeException + { + if (!SIMPLE_BASE_TYPES.contains(parent.get_base_type())) + { + ErrorManager.handle + ( + new InvalidTypeException(origin, parent, SIMPLE_BASE_TYPES) + ); + } + + return new Type(origin, parent, name); + } + + /**** Accessors ************************************************************/ + public Type get_base_type () + { + return true_type; + } + + public boolean is_base_type () + { + return (parent == null); + } + + /**** Compatibility ********************************************************/ + public boolean can_be_used_as (final Type t) + { + if (!true_type.equals(t.true_type)) + { + return false; + } + + return this_or_parent_equals(t); + } + + /* + * This is for the very special case where a type is used despite not being + * even a sub-type of the expected one. Using this rather expensive function, + * the most restrictive shared type will be returned. If no such type exists, + * the ANY time is returned. + */ + @Override + public DeclaredEntity generate_comparable_to (final DeclaredEntity de) + { + final Iterator it0, it1; + Type result, candidate; + + if (!(de instanceof Type)) + { + return ANY; + } + + it0 = ((Type) de).compute_full_type_chain().iterator(); + it1 = compute_full_type_chain().iterator(); + + result = Type.ANY; + + while (it0.hasNext() && it1.hasNext()) + { + candidate = it0.next(); + + if (!candidate.name.equals(it1.next().name)) + { + break; + } + + result = candidate; + } + + return new Type(origin, result, name); + } + + + /**** Misc. ****************************************************************/ + @Override + public boolean is_incompatible_with_declaration (final DeclaredEntity de) + { + if (de instanceof Type) + { + final Type t; + + t = (Type) de; + + /* + * If the previous type cannot be used when the new one will do, the + * new declaration cannot safely stand. + */ + return !can_be_used_as(t); + } + + return true; + } + + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + if (parent != null) + { + sb.append(parent.toString()); + sb.append("::"); + } + + sb.append(name); + + return sb.toString(); + } + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + protected Type + ( + final Origin origin, + final Type parent, + final String name + ) + { + super(origin, name); + + if (parent == null) + { + true_type = this; + } + else + { + true_type = parent.true_type; + } + + this.parent = parent; + } + + protected boolean this_or_parent_equals (final Type t) + { + if (equals(t)) + { + return true; + } + + if (parent == null) + { + return false; + } + + return parent.this_or_parent_equals(t); + } + + protected List compute_full_type_chain () + { + final List result; + Type t; + + result = new ArrayList(); + + t = this; + + while (t != null) + { + result.add(t); + + t = t.parent; + } + + Collections.reverse(result); + + return result; + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/Cast.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/Cast.java new file mode 100644 index 0000000..afc2c0e --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/Cast.java @@ -0,0 +1,172 @@ +package tonkadur.fate.v1.lang.valued_node; + +import java.util.Set; +import java.util.Map; +import java.util.HashMap; +import java.util.Collections; + +import tonkadur.error.ErrorManager; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.error.IncompatibleTypeException; +import tonkadur.fate.v1.error.IncomparableTypeException; + +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.meta.ValueNode; + +public class Cast extends ValueNode +{ + protected static final Map> allowed_type_changes; + + static + { + allowed_type_changes = new HashMap>(); + + allowed_type_changes.put + ( + Type.INT, + Type.NUMBER_TYPES + ); + + allowed_type_changes.put + ( + Type.FLOAT, + Type.NUMBER_TYPES + ); + + allowed_type_changes.put + ( + Type.DICT, + Collections.emptySet() + ); + + allowed_type_changes.put + ( + Type.SET, + Collections.emptySet() + ); + + allowed_type_changes.put + ( + Type.LIST, + Collections.emptySet() + ); + + allowed_type_changes.put + ( + Type.BOOLEAN, + Collections.emptySet() + ); + + allowed_type_changes.put + ( + Type.ANY, + Collections.singleton(Type.ANY) + ); + + allowed_type_changes.put + ( + Type.STRING, + Type.SIMPLE_BASE_TYPES + ); + } + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final ValueNode value; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + protected Cast + ( + final Origin origin, + final Type to, + final ValueNode value + ) + { + super(origin, to); + this.value = value; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public static Cast build + ( + final Origin origin, + final Type to, + final ValueNode value + ) + throws + IncompatibleTypeException, + IncomparableTypeException + { + final Type hint; + + if + ( + (value.get_type().can_be_used_as(to)) + || + ( + (to.is_base_type()) + && + ( + allowed_type_changes.get(to).contains + ( + value.get_type().get_base_type() + ) + ) + ) + ) + { + return new Cast(origin, to, value); + } + + hint = (Type) value.get_type().generate_comparable_to(to); + + if (hint.equals(Type.ANY)) + { + ErrorManager.handle + ( + new IncompatibleTypeException(origin, value.get_type(), to) + ); + + ErrorManager.handle + ( + new IncomparableTypeException(origin, value.get_type(), to) + ); + } + else + { + ErrorManager.handle + ( + new IncompatibleTypeException(origin, value.get_type(), to, hint) + ); + } + + return new Cast(origin, hint, value); + } + + /**** Accessors ************************************************************/ + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(origin.toString()); + sb.append("(Cast ("); + sb.append(type.get_name()); + sb.append(") "); + sb.append(value.toString()); + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/CondValue.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/CondValue.java new file mode 100644 index 0000000..fa8dcaf --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/CondValue.java @@ -0,0 +1,140 @@ +package tonkadur.fate.v1.lang.valued_node; + +import java.util.List; +import java.util.Collections; + +import tonkadur.functional.Cons; + +import tonkadur.error.ErrorManager; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.error.ConflictingTypeException; +import tonkadur.fate.v1.error.IncomparableTypeException; +import tonkadur.fate.v1.error.InvalidTypeException; + +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.meta.ValueNode; + +public class CondValue extends ValueNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final List> branches; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + protected CondValue + ( + final Origin origin, + final Type return_type, + final List> branches + ) + { + super(origin, return_type); + + this.branches = branches; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public static CondValue build + ( + final Origin origin, + final List> branches + ) + throws + InvalidTypeException, + ConflictingTypeException, + IncomparableTypeException + { + final Type first_type; + Type hint; + + first_type = branches.get(0).get_cdr().get_type(); + hint = first_type; + + for (final Cons entry: branches) + { + if (!entry.get_car().get_type().can_be_used_as(Type.BOOLEAN)) + { + ErrorManager.handle + ( + new InvalidTypeException + ( + entry.get_car().get_origin(), + entry.get_car().get_type(), + Collections.singleton(Type.BOOLEAN) + ) + ); + } + + if (entry.get_cdr().get_type().equals(hint)) + { + continue; + } + + ErrorManager.handle + ( + new ConflictingTypeException + ( + entry.get_cdr().get_origin(), + entry.get_cdr().get_type(), + first_type + ) + ); + + hint = (Type) hint.generate_comparable_to(entry.get_cdr().get_type()); + + if (hint.equals(Type.ANY)) + { + ErrorManager.handle + ( + new IncomparableTypeException + ( + entry.get_cdr().get_origin(), + entry.get_cdr().get_type(), + first_type + ) + ); + } + } + + return new CondValue(origin, hint, branches); + } + + /**** Accessors ************************************************************/ + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(origin.toString()); + sb.append("(CondValue"); + sb.append(System.lineSeparator()); + + for (final Cons entry: branches) + { + sb.append(System.lineSeparator()); + sb.append("Condition:"); + sb.append(System.lineSeparator()); + sb.append(entry.get_car().toString()); + sb.append(System.lineSeparator()); + sb.append("Value:"); + sb.append(entry.get_cdr().toString()); + sb.append(System.lineSeparator()); + } + + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/Constant.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/Constant.java new file mode 100644 index 0000000..f99f375 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/Constant.java @@ -0,0 +1,93 @@ +package tonkadur.fate.v1.lang.valued_node; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.meta.ValueNode; + +public class Constant extends ValueNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final String as_string; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + protected Constant + ( + final Origin origin, + final Type result_type, + final String as_string + ) + { + super(origin, result_type); + + this.as_string = as_string; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public static Constant build_boolean + ( + final Origin origin, + final boolean value + ) + { + return new Constant(origin, Type.BOOLEAN, value ? "true" : "false"); + } + + public static Constant build (final Origin origin, final String as_string) + { + try + { + Integer.valueOf(as_string); + + return new Constant(origin, Type.INT, as_string); + } + catch (final NumberFormatException nfe) + { + /* That's fine, we're just testing... */ + } + + try + { + Float.valueOf(as_string); + + return new Constant(origin, Type.FLOAT, as_string); + } + catch (final NumberFormatException nfe) + { + /* That's fine, we're just testing... */ + } + + return new Constant(origin, Type.STRING, as_string); + } + + /**** Accessors ************************************************************/ + public String get_value_as_string () + { + return as_string; + } + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(origin.toString()); + sb.append("("); + sb.append(type.get_name()); + sb.append(" Constant "); + sb.append(as_string); + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/CountOperator.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/CountOperator.java new file mode 100644 index 0000000..7eacc40 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/CountOperator.java @@ -0,0 +1,147 @@ +package tonkadur.fate.v1.lang.valued_node; + +import tonkadur.error.ErrorManager; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.error.ConflictingTypeException; +import tonkadur.fate.v1.error.IncomparableTypeException; +import tonkadur.fate.v1.error.InvalidTypeException; + +import tonkadur.fate.v1.lang.type.CollectionType; +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.meta.ValueNode; + +public class CountOperator extends ValueNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final ValueNode element; + protected final ValueNode collection; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + protected CountOperator + ( + final Origin origin, + final ValueNode element, + final ValueNode collection + ) + { + super(origin, Type.INT); + + this.collection = collection; + this.element = element; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public static CountOperator build + ( + final Origin origin, + final ValueNode element, + final ValueNode collection + ) + throws + InvalidTypeException, + ConflictingTypeException, + IncomparableTypeException + { + final Type hint; + final Type collection_type; + final CollectionType collection_true_type; + final Type collection_element_type; + + collection_type = collection.get_type(); + + if + ( + !Type.COLLECTION_TYPES.contains(collection_type.get_base_type()) + || !(collection_type instanceof CollectionType) + ) + { + ErrorManager.handle + ( + new InvalidTypeException + ( + collection.get_origin(), + collection.get_type(), + Type.COLLECTION_TYPES + ) + ); + } + + collection_true_type = (CollectionType) collection_type; + collection_element_type = collection_true_type.get_content_type(); + + if (element.get_type().can_be_used_as(collection_element_type)) + { + return new CountOperator(origin, element, collection); + } + + ErrorManager.handle + ( + new ConflictingTypeException + ( + element.get_origin(), + element.get_type(), + collection_element_type + ) + ); + + hint = + (Type) element.get_type().generate_comparable_to + ( + collection_element_type + ); + + if (hint.equals(Type.ANY)) + { + ErrorManager.handle + ( + new IncomparableTypeException + ( + element.get_origin(), + element.get_type(), + collection_element_type + ) + ); + } + + return new CountOperator(origin, element, collection); + } + + /**** Accessors ************************************************************/ + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(origin.toString()); + sb.append("(CountOperator"); + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + + sb.append("element:"); + sb.append(System.lineSeparator()); + sb.append(element.toString()); + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + + sb.append("collection:"); + sb.append(System.lineSeparator()); + sb.append(collection.toString()); + + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/IfElseValue.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/IfElseValue.java new file mode 100644 index 0000000..1b40f73 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/IfElseValue.java @@ -0,0 +1,150 @@ +package tonkadur.fate.v1.lang.valued_node; + +import java.util.Collections; + +import tonkadur.error.ErrorManager; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.error.ConflictingTypeException; +import tonkadur.fate.v1.error.IncomparableTypeException; +import tonkadur.fate.v1.error.InvalidTypeException; + +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.meta.ValueNode; + +public class IfElseValue extends ValueNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final ValueNode condition; + protected final ValueNode if_true; + protected final ValueNode if_false; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + protected IfElseValue + ( + final Origin origin, + final Type return_type, + final ValueNode condition, + final ValueNode if_true, + final ValueNode if_false + ) + { + super(origin, return_type); + + this.condition = condition; + this.if_true = if_true; + this.if_false = if_false; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public static IfElseValue build + ( + final Origin origin, + final ValueNode condition, + final ValueNode if_true, + final ValueNode if_false + ) + throws + InvalidTypeException, + ConflictingTypeException, + IncomparableTypeException + { + final Type hint; + final Type if_true_type; + final Type if_false_type; + + if (!condition.get_type().can_be_used_as(Type.BOOLEAN)) + { + ErrorManager.handle + ( + new InvalidTypeException + ( + condition.get_origin(), + condition.get_type(), + Collections.singleton(Type.BOOLEAN) + ) + ); + } + + if_true_type = if_true.get_type(); + if_false_type = if_false.get_type(); + + if (if_true_type.equals(if_false_type)) + { + return + new IfElseValue(origin, if_true_type, condition, if_true, if_false); + } + + ErrorManager.handle + ( + new ConflictingTypeException + ( + if_false.get_origin(), + if_false_type, + if_true_type + ) + ); + + hint = + (Type) if_false_type.generate_comparable_to(if_true_type); + + if (hint.equals(Type.ANY)) + { + ErrorManager.handle + ( + new IncomparableTypeException + ( + if_false.get_origin(), + if_false_type, + if_true_type + ) + ); + } + + return new IfElseValue(origin, hint, condition, if_true, if_false); + } + + /**** Accessors ************************************************************/ + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(origin.toString()); + sb.append("(IfElseValue"); + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + + sb.append("Condition:"); + sb.append(System.lineSeparator()); + sb.append(condition.toString()); + + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + sb.append("If true:"); + sb.append(System.lineSeparator()); + sb.append(if_true.toString()); + + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + sb.append("If false:"); + sb.append(System.lineSeparator()); + sb.append(if_false.toString()); + + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/IsMemberOperator.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/IsMemberOperator.java new file mode 100644 index 0000000..7701614 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/IsMemberOperator.java @@ -0,0 +1,147 @@ +package tonkadur.fate.v1.lang.valued_node; + +import tonkadur.error.ErrorManager; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.error.ConflictingTypeException; +import tonkadur.fate.v1.error.IncomparableTypeException; +import tonkadur.fate.v1.error.InvalidTypeException; + +import tonkadur.fate.v1.lang.type.CollectionType; +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.meta.ValueNode; + +public class IsMemberOperator extends ValueNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final ValueNode element; + protected final ValueNode collection; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + protected IsMemberOperator + ( + final Origin origin, + final ValueNode element, + final ValueNode collection + ) + { + super(origin, Type.BOOLEAN); + + this.collection = collection; + this.element = element; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public static IsMemberOperator build + ( + final Origin origin, + final ValueNode element, + final ValueNode collection + ) + throws + InvalidTypeException, + ConflictingTypeException, + IncomparableTypeException + { + final Type hint; + final Type collection_type; + final CollectionType collection_true_type; + final Type collection_element_type; + + collection_type = collection.get_type(); + + if + ( + !Type.COLLECTION_TYPES.contains(collection_type.get_base_type()) + || !(collection_type instanceof CollectionType) + ) + { + ErrorManager.handle + ( + new InvalidTypeException + ( + collection.get_origin(), + collection.get_type(), + Type.COLLECTION_TYPES + ) + ); + } + + collection_true_type = (CollectionType) collection_type; + collection_element_type = collection_true_type.get_content_type(); + + if (element.get_type().can_be_used_as(collection_element_type)) + { + return new IsMemberOperator(origin, element, collection); + } + + ErrorManager.handle + ( + new ConflictingTypeException + ( + element.get_origin(), + element.get_type(), + collection_element_type + ) + ); + + hint = + (Type) element.get_type().generate_comparable_to + ( + collection_element_type + ); + + if (hint.equals(Type.ANY)) + { + ErrorManager.handle + ( + new IncomparableTypeException + ( + element.get_origin(), + element.get_type(), + collection_element_type + ) + ); + } + + return new IsMemberOperator(origin, element, collection); + } + + /**** Accessors ************************************************************/ + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(origin.toString()); + sb.append("(IsMemberOperator"); + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + + sb.append("element:"); + sb.append(System.lineSeparator()); + sb.append(element.toString()); + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + + sb.append("collection:"); + sb.append(System.lineSeparator()); + sb.append(collection.toString()); + + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/Operation.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/Operation.java new file mode 100644 index 0000000..87ea676 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/Operation.java @@ -0,0 +1,162 @@ +package tonkadur.fate.v1.lang.valued_node; + +import java.util.Collection; +import java.util.List; + +import tonkadur.error.ErrorManager; + +import tonkadur.parser.Origin; + +//import tonkadur.fate.v1.error.ConflictingTypeException; +import tonkadur.fate.v1.error.IncomparableTypeException; +import tonkadur.fate.v1.error.IncompatibleTypeException; +import tonkadur.fate.v1.error.InvalidArityException; +import tonkadur.fate.v1.error.InvalidTypeException; + +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.meta.ValueNode; + +public class Operation extends ValueNode +{ + protected final Operator operator; + protected final List operands; + + protected Operation + ( + final Origin origin, + final Type result_type, + final Operator operator, + final List operands + ) + { + super(origin, result_type); + + this.operator = operator; + this.operands = operands; + } + + public static Operation build + ( + final Origin origin, + final Operator operator, + final List operands + ) + throws + //ConflictingTypeException, + IncomparableTypeException, + IncompatibleTypeException, + InvalidArityException, + InvalidTypeException + { + final Collection allowed_base_types; + final int operator_max_arity; + final int operator_min_arity; + final int operands_size; + Type computed_type, previous_computed_type; + + allowed_base_types = operator.get_allowed_base_types(); + operator_max_arity = operator.get_maximum_arity(); + operator_min_arity = operator.get_minimum_arity(); + operands_size = operands.size(); + + if + ( + (operands_size < operator_min_arity) + || + ( + (operator_max_arity != 0) + && (operator_max_arity < operands_size) + ) + ) + { + ErrorManager.handle + ( + new InvalidArityException + ( + origin, + operands_size, + operator_min_arity, + operator_max_arity + ) + ); + } + + computed_type = operands.get(0).get_type(); + + for (final ValueNode operand: operands) + { + final Type operand_type; + + operand_type = operand.get_type(); + + if (!allowed_base_types.contains(operand_type.get_base_type())) + { + ErrorManager.handle + ( + new InvalidTypeException + ( + operand.get_origin(), + operand_type, + allowed_base_types + ) + ); + } + + /* + + if (computed_type.equals(operand_type)) + { + continue; + } + + ErrorManager.handle + ( + new ConflictingTypeException + ( + operand.get_origin(), + operand_type, + computed_type + ) + ); + + */ + + if (operand_type.can_be_used_as(computed_type)) + { + continue; + } + + ErrorManager.handle + ( + new IncompatibleTypeException + ( + operand.get_origin(), + operand_type, + computed_type + ) + ); + + previous_computed_type = computed_type; + computed_type = + (Type) computed_type.generate_comparable_to(operand_type); + + if (computed_type.equals(Type.ANY)) + { + ErrorManager.handle + ( + new IncomparableTypeException + ( + operand.get_origin(), + operand_type, + previous_computed_type + ) + ); + } + } + + computed_type = operator.transform_type(computed_type); + + return new Operation(origin, computed_type, operator, operands); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/Operator.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/Operator.java new file mode 100644 index 0000000..7f1db14 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/Operator.java @@ -0,0 +1,143 @@ +package tonkadur.fate.v1.lang.valued_node; + +import java.util.Collections; +import java.util.Set; + +import tonkadur.fate.v1.lang.type.Type; + +/* + * Yes, it *could* have been an enum. In fact, it used to be one. Except that + * unless you want to ensure coverage of all cases in a switch, Java enums are + * clearly inferior to classes in everyway. Having this be a class will, at + * the very least, let you extend it to add new operators in extensions. + */ +public class Operator +{ + public static final Operator PLUS; + public static final Operator MINUS; + public static final Operator TIMES; + public static final Operator DIVIDE; + public static final Operator POWER; + public static final Operator RANDOM; + + public static final Operator AND; + public static final Operator OR; + public static final Operator NOT; + public static final Operator IMPLIES; + public static final Operator ONE_IN; + + public static final Operator EQUALS; + + public static final Operator LOWER_THAN; + public static final Operator LOWER_EQUAL_THAN; + public static final Operator GREATER_EQUAL_THAN; + public static final Operator GREATER_THAN; + + + static + { + PLUS = new Operator("+", 2, 0, Type.NUMBER_TYPES, null); + MINUS = new Operator("-", 2, 0, Type.NUMBER_TYPES, null); + TIMES = new Operator("*", 2, 0, Type.NUMBER_TYPES, null); + DIVIDE = new Operator("/", 2, 2, Type.NUMBER_TYPES, null); + POWER = new Operator("^", 2, 2, Type.NUMBER_TYPES, null); + RANDOM = + new Operator("rand", 2, 2, Collections.singleton(Type.INT), null); + + AND = + new Operator("and", 2, 0, Collections.singleton(Type.BOOLEAN), null); + OR = + new Operator("or", 2, 0, Collections.singleton(Type.BOOLEAN), null); + NOT = + new Operator("not", 1, 1, Collections.singleton(Type.BOOLEAN), null); + IMPLIES = + new Operator + ( + "implies", + 2, + 2, + Collections.singleton(Type.BOOLEAN), + null + ); + ONE_IN = + new Operator + ( + "one_in", + 1, + 0, + Collections.singleton(Type.BOOLEAN), + null + ); + + EQUALS = + new Operator + ( + "equals", + 2, + 0, + Type.SIMPLE_BASE_TYPES, + Type.BOOLEAN + ); + + LOWER_THAN = new Operator("<", 2, 2, Type.NUMBER_TYPES, Type.BOOLEAN); + LOWER_EQUAL_THAN = + new Operator("=<", 2, 2, Type.NUMBER_TYPES, Type.BOOLEAN); + GREATER_EQUAL_THAN = + new Operator(">=", 2, 2, Type.NUMBER_TYPES, Type.BOOLEAN); + GREATER_THAN = new Operator(">", 2, 2, Type.NUMBER_TYPES, Type.BOOLEAN); + } + + final protected String name; + final protected int min_arity; + final protected int max_arity; + final protected Set valid_input_types; + final protected Type output_type_transform; + + protected Operator + ( + final String name, + final int min_arity, + final int max_arity, + final Set valid_input_types, + final Type output_type_transform + ) + { + this.name = name; + this.min_arity = min_arity; + this.max_arity = max_arity; + this.valid_input_types = valid_input_types; + + this.output_type_transform = output_type_transform; + } + + public Set get_allowed_base_types () + { + return valid_input_types; + } + + public int get_minimum_arity () + { + return min_arity; + } + + public int get_maximum_arity () + { + return max_arity; + } + + public Type transform_type (final Type in) + { + if (output_type_transform == null) + { + return in; + } + + return output_type_transform; + } + + @Override + public String toString () + { + return name; + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/RefOperator.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/RefOperator.java new file mode 100644 index 0000000..e6d03b2 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/RefOperator.java @@ -0,0 +1,48 @@ +package tonkadur.fate.v1.lang.valued_node; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.Variable; + +import tonkadur.fate.v1.lang.type.RefType; + +import tonkadur.fate.v1.lang.meta.ValueNode; + +public class RefOperator extends ValueNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final Variable variable; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public RefOperator (final Origin origin, final Variable variable) + { + super(origin, new RefType(origin, variable.get_type(), "auto generated")); + this.variable = variable; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + + /**** Accessors ************************************************************/ + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(origin.toString()); + sb.append("(Ref "); + sb.append(variable.get_name()); + sb.append(") "); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/VariableFieldReference.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/VariableFieldReference.java new file mode 100644 index 0000000..17a99fa --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/VariableFieldReference.java @@ -0,0 +1,128 @@ +package tonkadur.fate.v1.lang.valued_node; + +import java.util.Arrays; +import java.util.List; + +import tonkadur.parser.Origin; + +import tonkadur.error.ErrorManager; + +import tonkadur.fate.v1.error.InvalidTypeException; +import tonkadur.fate.v1.error.UnknownDictionaryFieldException; + +import tonkadur.fate.v1.lang.Variable; + +import tonkadur.fate.v1.lang.meta.ValueNode; + +import tonkadur.fate.v1.lang.type.DictType; +import tonkadur.fate.v1.lang.type.Type; + +public class VariableFieldReference extends VariableReference +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + final List field_accesses; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + protected VariableFieldReference + ( + final Origin origin, + final Variable variable, + final Type type, + final List field_accesses + ) + { + super(origin, type, variable); + + this.field_accesses = field_accesses; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public static VariableFieldReference build + ( + final Origin origin, + final Variable variable, + final List field_accesses + ) + throws + InvalidTypeException, + UnknownDictionaryFieldException + { + final StringBuilder sb; + Type current_type; + + sb = new StringBuilder(); + + current_type = variable.get_type(); + + for (final String field_access: field_accesses) + { + sb.append("."); + sb.append(field_access); + + if (!(current_type instanceof DictType)) + { + ErrorManager.handle + ( + new InvalidTypeException + ( + origin, + current_type, + Arrays.asList(new Type[]{Type.DICT}), + (variable.get_name() + "." + sb.toString()) + ) + ); + + break; + } + + current_type = + ((DictType) current_type).get_field_type(origin, field_access); + } + + return + new VariableFieldReference + ( + origin, + variable, + current_type, + field_accesses + ); + } + + /**** Accessors ************************************************************/ + public List get_field_accesses () + { + return field_accesses; + } + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(origin.toString()); + sb.append("(VariableFieldReference ("); + sb.append(type.get_name()); + sb.append(") "); + sb.append(variable.get_name()); + + for (final String field: field_accesses) + { + sb.append("."); + sb.append(field); + } + + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/VariableReference.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/VariableReference.java new file mode 100644 index 0000000..1423b31 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/VariableReference.java @@ -0,0 +1,68 @@ +package tonkadur.fate.v1.lang.valued_node; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.Variable; + +import tonkadur.fate.v1.lang.meta.ValueNode; + +import tonkadur.fate.v1.lang.type.Type; + +public class VariableReference extends ValueNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final Variable variable; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + protected VariableReference + ( + final Origin origin, + final Type reported_type, + final Variable variable + ) + { + super(origin, reported_type); + this.variable = variable; + } + /**** Constructors *********************************************************/ + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public VariableReference + ( + final Origin origin, + final Variable variable + ) + { + super(origin, variable.get_type()); + this.variable = variable; + } + + /**** Accessors ************************************************************/ + public Variable get_variable () + { + return variable; + } + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(origin.toString()); + sb.append("(VariableReference ("); + sb.append(type.get_name()); + sb.append(") "); + sb.append(variable.get_name()); + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 index 8f84217..fbb1d2d 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 @@ -28,7 +28,10 @@ options import tonkadur.fate.v1.error.UnknownVariableScopeException; import tonkadur.fate.v1.lang.*; + import tonkadur.fate.v1.lang.instruction.*; import tonkadur.fate.v1.lang.meta.*; + import tonkadur.fate.v1.lang.type.*; + import tonkadur.fate.v1.lang.valued_node.*; } @members -- cgit v1.2.3-70-g09d2