| summaryrefslogtreecommitdiff | 
diff options
| author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2020-07-05 13:36:24 +0200 | 
|---|---|---|
| committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2020-07-05 13:36:24 +0200 | 
| commit | 1737cb747199beac1879aa0867423bd634113333 (patch) | |
| tree | 541f557f85e44f60eaa1176e3c619f2758549a10 /src | |
| parent | f6cd96ae24b458a5b4875f8e151758c11c45dbcd (diff) | |
Adds DictType, guards for SetType, hints.
Diffstat (limited to 'src')
7 files changed, 357 insertions, 31 deletions
| diff --git a/src/core/src/tonkadur/fate/v1/error/IncompatibleDeclarationException.java b/src/core/src/tonkadur/fate/v1/error/IncompatibleDeclarationException.java index f1f1be6..ce8792a 100644 --- a/src/core/src/tonkadur/fate/v1/error/IncompatibleDeclarationException.java +++ b/src/core/src/tonkadur/fate/v1/error/IncompatibleDeclarationException.java @@ -14,6 +14,7 @@ public class IncompatibleDeclarationException extends ParsingError     /***************************************************************************/     protected final DeclaredEntity new_declaration;     protected final DeclaredEntity original_declaration; +   protected final DeclaredEntity correction_hint;     /***************************************************************************/     /**** PUBLIC ***************************************************************/ @@ -33,6 +34,26 @@ public class IncompatibleDeclarationException extends ParsingError        this.new_declaration = new_declaration;        this.original_declaration = original_declaration; +      this.correction_hint = null; +   } + +   public IncompatibleDeclarationException +   ( +      final DeclaredEntity new_declaration, +      final DeclaredEntity original_declaration, +      final DeclaredEntity correction_hint +   ) +   { +      super +      ( +         ErrorLevel.ERROR, +         ErrorCategory.INCOMPATIBLE, +         new_declaration.get_origin() +      ); + +      this.new_declaration = new_declaration; +      this.original_declaration = original_declaration; +      this.correction_hint = correction_hint;     }     @Override @@ -60,6 +81,14 @@ public class IncompatibleDeclarationException extends ParsingError        sb.append(new_declaration.toString());        sb.append("."); +      if (correction_hint != null) +      { +         sb.append(System.lineSeparator()); +         sb.append("Recommended compatible declaration: "); +         sb.append(correction_hint.toString()); +         sb.append("."); +      } +        return sb.toString();     }  } diff --git a/src/core/src/tonkadur/fate/v1/error/UnknownDictionaryFieldException.java b/src/core/src/tonkadur/fate/v1/error/UnknownDictionaryFieldException.java new file mode 100644 index 0000000..a624fb8 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/error/UnknownDictionaryFieldException.java @@ -0,0 +1,63 @@ +package tonkadur.fate.v1.error; + +import java.util.Map; + +import tonkadur.error.ErrorLevel; + +import tonkadur.parser.Origin; +import tonkadur.parser.ParsingError; + +import tonkadur.fate.v1.lang.DictType; +import tonkadur.fate.v1.lang.Type; + +public class UnknownDictionaryFieldException extends ParsingError +{ +   /***************************************************************************/ +   /**** MEMBERS **************************************************************/ +   /***************************************************************************/ +   protected final String field_name; +   protected final DictType dict; + +   /***************************************************************************/ +   /**** PUBLIC ***************************************************************/ +   /***************************************************************************/ +   public UnknownDictionaryFieldException +   ( +      final Origin origin, +      final String field_name, +      final DictType dict +   ) +   { +      super(ErrorLevel.ERROR, ErrorCategory.INVALID_USE, origin); +      this.field_name = field_name; +      this.dict = dict; +   } + +   @Override +   public String toString () +   { +      final StringBuilder sb = new StringBuilder(); + +      sb.append(origin.get_context().toString()); +      sb.append(error_category.toString()); +      sb.append(" Unknown field '"); +      sb.append(field_name); +      sb.append("' for dictionary type '"); +      sb.append(dict.get_name()); +      sb.append("' at "); +      sb.append(origin.get_location().toString()); +      sb.append("."); +      sb.append(System.lineSeparator()); +      sb.append("Available fields are:"); + +      for (final Map.Entry<String, Type> field: dict.get_fields()) +      { +         sb.append("- "); +         sb.append(field.getKey()); +         sb.append(": "); +         sb.append(field.getValue().get_name()); +      } + +      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 new file mode 100644 index 0000000..0b1d138 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/DictType.java @@ -0,0 +1,178 @@ +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<String, Type> field_types; + +   /***************************************************************************/ +   /**** PUBLIC ***************************************************************/ +   /***************************************************************************/ + +   /**** Constructors *********************************************************/ +   public DictType +   ( +      final Origin origin, +      final Map<String, Type> 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<Map.Entry<String, Type>> 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<String, Type> 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<String, Type> result_field_types; +      final Set<String> result_field_names; +      final DictType dt; + +      if (!(de instanceof DictType)) +      { +         return Type.ANY; +      } + +      dt = (DictType) de; + +      result_field_names = new HashSet<String>(); +      result_field_types = new HashMap<String, Type>(); + +      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<String, Type> 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/Operator.java b/src/core/src/tonkadur/fate/v1/lang/Operator.java index f8fb8ff..9e2e522 100644 --- a/src/core/src/tonkadur/fate/v1/lang/Operator.java +++ b/src/core/src/tonkadur/fate/v1/lang/Operator.java @@ -1,8 +1,7 @@  package tonkadur.fate.v1.lang; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; +import java.util.Collections; +import java.util.Set;  public enum Operator  { @@ -11,12 +10,12 @@ public enum Operator     TIMES("*", 0, Type.NUMBER_TYPES, null),     DIVIDED("/", 0, Type.NUMBER_TYPES, null),     POWER("^", 2, Type.NUMBER_TYPES, null), -   RANDOM("rand", 2, (new Type[]{Type.INT}), null), +   RANDOM("rand", 2, Collections.singleton(Type.INT), null), -   AND("and", 0, (new Type[]{Type.BOOLEAN}), null), -   OR("or", 0, (new Type[]{Type.BOOLEAN}), null), -   NOT("not", 1, (new Type[]{Type.BOOLEAN}), null), -   IMPLIES("implies", 1, (new Type[]{Type.BOOLEAN}), null), +   AND("and", 0, Collections.singleton(Type.BOOLEAN), null), +   OR("or", 0, Collections.singleton(Type.BOOLEAN), null), +   NOT("not", 1, Collections.singleton(Type.BOOLEAN), null), +   IMPLIES("implies", 1, Collections.singleton(Type.BOOLEAN), null),     LOWER_THAN("<", 2, Type.NUMBER_TYPES, Type.BOOLEAN),     LOWER_EQUAL_THAN("=<", 2, Type.NUMBER_TYPES, Type.BOOLEAN), @@ -25,26 +24,25 @@ public enum Operator     final private String name;     final private int arity; -   final private Collection<Type> valid_input_types; +   final private Set<Type> valid_input_types;     final private Type output_type_transform;     private Operator     (        final String name,        final int arity, -      final Type[] valid_input_types, +      final Set<Type> valid_input_types,        final Type output_type_transform     )     {        this.name = name;        this.arity = arity; -      this.valid_input_types = -         new HashSet<Type>(Arrays.asList(valid_input_types)); +      this.valid_input_types = valid_input_types;        this.output_type_transform = output_type_transform;     } -   public Collection<Type> get_allowed_base_types () +   public Set<Type> get_allowed_base_types ()     {        return valid_input_types;     } diff --git a/src/core/src/tonkadur/fate/v1/lang/SetType.java b/src/core/src/tonkadur/fate/v1/lang/SetType.java index ccb5bf3..2b30139 100644 --- a/src/core/src/tonkadur/fate/v1/lang/SetType.java +++ b/src/core/src/tonkadur/fate/v1/lang/SetType.java @@ -1,9 +1,11 @@  package tonkadur.fate.v1.lang; -import java.util.Iterator; +import tonkadur.error.ErrorManager;  import tonkadur.parser.Origin; +import tonkadur.fate.v1.error.InvalidTypeException; +  import tonkadur.fate.v1.lang.meta.DeclaredEntity;  public class SetType extends Type @@ -18,18 +20,31 @@ public class SetType extends Type     /***************************************************************************/     /**** Constructors *********************************************************/ -   public SetType +   public static SetType build     (        final Origin origin,        final Type content_type,        final String name     ) +   throws InvalidTypeException     { -      super(origin, Type.SET, name); +      if (!Type.SET_COMPATIBLE_TYPES.contains(content_type.get_true_type())) +      { +         ErrorManager.handle +         ( +            new InvalidTypeException +            ( +               origin, +               content_type, +               Type.SET_COMPATIBLE_TYPES +            ) +         ); +      } -      this.content_type = content_type; +      return new SetType(origin, content_type, name);     } +     /**** Accessors ************************************************************/     public Type get_content_type ()     { @@ -65,7 +80,7 @@ public class SetType extends Type        return           new SetType           ( -            de.get_origin(), +            get_origin(),              (                 (Type) content_type.generate_comparable_to                 ( @@ -85,8 +100,26 @@ public class SetType extends Type        sb.append("(Set ");        sb.append(content_type.toString()); -      sb.append(")"); +      sb.append(")::"); +      sb.append(name);        return sb.toString();     } + +   /***************************************************************************/ +   /**** PROTECTED ************************************************************/ +   /***************************************************************************/ + +   /**** Constructors *********************************************************/ +   protected SetType +   ( +      final Origin origin, +      final Type content_type, +      final String name +   ) +   { +      super(origin, Type.SET, name); + +      this.content_type = content_type; +   }  } diff --git a/src/core/src/tonkadur/fate/v1/lang/Type.java b/src/core/src/tonkadur/fate/v1/lang/Type.java index ad49268..b5438e5 100644 --- a/src/core/src/tonkadur/fate/v1/lang/Type.java +++ b/src/core/src/tonkadur/fate/v1/lang/Type.java @@ -1,10 +1,11 @@  package tonkadur.fate.v1.lang;  import java.util.ArrayList; -import java.util.Collection;  import java.util.Collections; +import java.util.HashSet;  import java.util.Iterator;  import java.util.List; +import java.util.Set;  import tonkadur.parser.Context;  import tonkadur.parser.Location; @@ -23,7 +24,8 @@ public class Type extends DeclaredEntity     public static final Type SET;     public static final Type STRING; -   public static final Type[] NUMBER_TYPES; +   public static final Set<Type> NUMBER_TYPES; +   public static final Set<Type> SET_COMPATIBLE_TYPES;     static     { @@ -44,7 +46,16 @@ public class Type extends DeclaredEntity        SET = new Type(base, null, "set");        STRING = new Type(base, null, "string"); -      NUMBER_TYPES = new Type[]{FLOAT, INT}; +      NUMBER_TYPES = new HashSet<Type>(); +      NUMBER_TYPES.add(FLOAT); +      NUMBER_TYPES.add(INT); + +      SET_COMPATIBLE_TYPES = new HashSet<Type>(); + +      SET_COMPATIBLE_TYPES.add(FLOAT); +      SET_COMPATIBLE_TYPES.add(INT); +      SET_COMPATIBLE_TYPES.add(STRING); +      SET_COMPATIBLE_TYPES.add(BOOLEAN);     }     public static Type value_on_missing () @@ -147,7 +158,7 @@ public class Type extends DeclaredEntity           result = candidate;        } -      return result; +      return new Type(origin, result, name);     } diff --git a/src/core/src/tonkadur/fate/v1/lang/meta/DeclarationCollection.java b/src/core/src/tonkadur/fate/v1/lang/meta/DeclarationCollection.java index 7bcaaa1..04bbfa9 100644 --- a/src/core/src/tonkadur/fate/v1/lang/meta/DeclarationCollection.java +++ b/src/core/src/tonkadur/fate/v1/lang/meta/DeclarationCollection.java @@ -83,7 +83,7 @@ public class DeclarationCollection <Declared extends DeclaredEntity>     /***************************************************************************/     /**** PROTECTED ************************************************************/     /***************************************************************************/ -   protected Declared assert_entity_can_be_added (Declared new_version) +   protected Declared assert_entity_can_be_added (final Declared new_version)     throws        DuplicateDeclarationException,        ConflictingDeclarationException, @@ -92,6 +92,7 @@ public class DeclarationCollection <Declared extends DeclaredEntity>     {        final DeclaredEntity de;        final Declared previous_version; +      Declared hint;        previous_version = collection.get(new_version.get_name()); @@ -124,19 +125,15 @@ public class DeclarationCollection <Declared extends DeclaredEntity>           return new_version;        } -      ErrorManager.handle -      ( -         new IncompatibleDeclarationException(new_version, previous_version) -      ); -        de = new_version.generate_comparable_to(previous_version);        try        { -         new_version = (Declared) de; +         hint = (Declared) de;        }        catch (final ClassCastException e)        { +         hint = null;           e.printStackTrace();           System.exit(-1); @@ -146,10 +143,27 @@ public class DeclarationCollection <Declared extends DeclaredEntity>        {           ErrorManager.handle           ( +            new IncompatibleDeclarationException(new_version, previous_version) +         ); + +         ErrorManager.handle +         (              new IncomparableDeclarationException(new_version, previous_version)           );        } +      else +      { +         ErrorManager.handle +         ( +            new IncompatibleDeclarationException +            ( +               new_version, +               previous_version, +               hint +            ) +         ); +      } -      return new_version; +      return hint;     }  } | 


