| summaryrefslogtreecommitdiff | 
diff options
| author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2020-07-05 19:38:24 +0200 | 
|---|---|---|
| committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2020-07-05 19:38:24 +0200 | 
| commit | 3803f236f97b9149ddead5218c3585097245c600 (patch) | |
| tree | 7e9050309c6cf87cb9956dccbdcdf8979abe59d0 /src/core | |
| parent | 8a78ec95b126ef653a2990161e541f97eab0ed88 (diff) | |
Adds Cast.
Diffstat (limited to 'src/core')
6 files changed, 257 insertions, 31 deletions
| diff --git a/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java b/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java index b79f293..d1827d3 100644 --- a/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java +++ b/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java @@ -14,6 +14,7 @@ public class IncompatibleTypeException extends ParsingError     /***************************************************************************/     protected final Type given_type;     protected final Type expected_type; +   protected final Type hint;     /***************************************************************************/     /**** PUBLIC ***************************************************************/ @@ -34,6 +35,27 @@ public class IncompatibleTypeException extends ParsingError        this.given_type = given_type;        this.expected_type = expected_type; +      this.hint = null; +   } + +   public IncompatibleTypeException +   ( +      final Origin call_origin, +      final Type given_type, +      final Type expected_type, +      final Type hint +   ) +   { +      super +      ( +         ErrorLevel.ERROR, +         ErrorCategory.INCOMPATIBLE, +         call_origin +      ); + +      this.given_type = given_type; +      this.expected_type = expected_type; +      this.hint = hint;     }     @Override @@ -53,6 +75,13 @@ public class IncompatibleTypeException extends ParsingError        sb.append(expected_type.toString());        sb.append("')."); +      if (hint != null) +      { +         sb.append(System.lineSeparator()); +         sb.append("Recommended compatible type: "); +         sb.append(hint.get_name()); +      } +        return sb.toString();     }  } diff --git a/src/core/src/tonkadur/fate/v1/lang/Cast.java b/src/core/src/tonkadur/fate/v1/lang/Cast.java new file mode 100644 index 0000000..482d203 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/Cast.java @@ -0,0 +1,170 @@ +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<Type,Set<Type>> allowed_type_changes; + +   static +   { +      allowed_type_changes = new HashMap<Type,Set<Type>>(); + +      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.COLLECTION_COMPATIBLE_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_true_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/Operation.java b/src/core/src/tonkadur/fate/v1/lang/Operation.java index 4b05a68..d7efc6c 100644 --- a/src/core/src/tonkadur/fate/v1/lang/Operation.java +++ b/src/core/src/tonkadur/fate/v1/lang/Operation.java @@ -7,7 +7,7 @@ import tonkadur.error.ErrorManager;  import tonkadur.parser.Origin; -import tonkadur.fate.v1.error.ConflictingTypeException; +//import tonkadur.fate.v1.error.ConflictingTypeException;  import tonkadur.fate.v1.error.IncomparableTypeException;  import tonkadur.fate.v1.error.IncompatibleTypeException;  import tonkadur.fate.v1.error.InvalidArityException; @@ -41,7 +41,7 @@ public class Operation extends ValueNode        final List<ValueNode> operands     )     throws -      ConflictingTypeException, +      //ConflictingTypeException,        IncomparableTypeException,        IncompatibleTypeException,        InvalidArityException, @@ -101,6 +101,8 @@ public class Operation extends ValueNode              );           } +         /* +           if (computed_type.equals(operand_type))           {              continue; @@ -116,6 +118,8 @@ public class Operation extends ValueNode              )           ); +         */ +           if (operand_type.can_be_used_as(computed_type))           {              continue; 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 81767e9..376befe 100644 --- a/src/core/src/tonkadur/fate/v1/lang/meta/DeclarationCollection.java +++ b/src/core/src/tonkadur/fate/v1/lang/meta/DeclarationCollection.java @@ -160,7 +160,7 @@ public class DeclarationCollection <Declared extends DeclaredEntity>           System.exit(-1);        } -      if (new_version.equals(value_on_missing)) +      if (hint.equals(value_on_missing))        {           ErrorManager.handle           ( diff --git a/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 index 6f03d0c..4240c1b 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 @@ -13,7 +13,6 @@ L_PAREN: WS* '(';  R_PAREN: WS* ')';  ADD_KW: L_PAREN 'add' WS*; -ADD_TO_ENUM_TYPE_KW: L_PAREN 'add_to_enum_type' WS*;  ADD_VARIABLE_ATTRIBUTE_KW: L_PAREN 'add_variable_attribute' WS*;  AND_KW: L_PAREN ('and'|'/\\') WS*;  ASSERT_KW: L_PAREN 'assert' WS*; @@ -23,7 +22,6 @@ COND_KW: L_PAREN 'cond' WS*;  COUNT_KW: L_PAREN 'count' WS*;  DECLARE_ALIAS_TYPE_KW: L_PAREN 'declare_subtype' WS*;  DECLARE_DICT_TYPE_KW: L_PAREN 'declare_dict_type' WS*; -DECLARE_ENUM_TYPE_KW: L_PAREN 'declare_enum_type' WS*;  DECLARE_EVENT_TYPE_KW: L_PAREN 'declare_event_type' WS*;  DECLARE_TEXT_EFFECT: L_PAREN 'declare_text_effect' WS*;  DECLARE_TEXT_EFFECT_KW: L_PAREN 'declare_text_effect' WS*; @@ -36,6 +34,8 @@ EQUALS_KW: L_PAREN ('equals'|'='|'==') WS*;  EVENT_KW: L_PAREN 'event' WS*;  FALSE_KW: L_PAREN 'false)';  FATE_VERSION_KW: L_PAREN 'fate_version' WS*; +GET_KW: L_PAREN 'get' WS*; +SET_FIELD_KW: L_PAREN 'set_field' WS*;  GREATER_EQUAL_THAN_KW: L_PAREN ('greater_equal_than'|'>=') WS*;  GREATER_THAN_KW: L_PAREN ('greater_than'|'>') WS*;  IF_ELSE_KW: L_PAREN 'if_else' WS*; @@ -57,6 +57,7 @@ POWER_KW: L_PAREN ('power'|'^'|'**') WS*;  RANDOM_KW: L_PAREN ('random'|'rand') WS*;  REMOVE_ALL_KW: L_PAREN 'remove_all' WS*;  REMOVE_ONE_KW: L_PAREN 'remove_one' WS*; +REQUIRE_EXTENSION_KW: L_PAREN 'require_extension' WS*;  REQUIRE_KW: L_PAREN 'require' WS*;  SEQUENCE_KW: L_PAREN 'sequence' WS*;  SET_EXPRESSION_KW: L_PAREN 'set_expression' WS*; diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 index ccc46db..2585948 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 @@ -117,6 +117,10 @@ first_level_fate_instr:     {     } +   | REQUIRE_EXTENSION_KW name=WORD R_PAREN +   { +   } +     | DECLARE_ALIAS_TYPE_KW parent=WORD WS+ name=WORD R_PAREN     {        final Origin start_origin, parent_origin; @@ -147,15 +151,19 @@ first_level_fate_instr:     {     } -   | DECLARE_ENUM_TYPE_KW name=WORD R_PAREN +   | ADD_KW value WS+ value_reference R_PAREN     {     } -   | DECLARE_EVENT_TYPE_KW name=WORD WS+ word_list R_PAREN +   | REMOVE_ONE_KW value WS+ value_reference R_PAREN +   { +   } + +   | REMOVE_ALL_KW value WS+ value_reference R_PAREN     {     } -   | ADD_TO_ENUM_TYPE_KW entry=WORD WS+ name=WORD R_PAREN +   | DECLARE_EVENT_TYPE_KW name=WORD WS+ word_list R_PAREN     {     } @@ -188,8 +196,13 @@ general_fate_instr:     {     } +   | SET_FIELD_KW WORD WS+ value WS+ value_reference R_PAREN +   { +   } +     | SET_EXPRESSION_KW value WS+ value_reference R_PAREN     { +      /* that one isn't resolved until the value is referenced */     }     | EVENT_KW WORD WS+ value_list R_PAREN @@ -609,20 +622,6 @@ catch [final Throwable e]     throw new ParseCancellationException(e);  } -bag_expression: -   | ADD_KW value WS+ value_reference R_PAREN -   { -   } - -   | REMOVE_ONE_KW value WS+ value_reference R_PAREN -   { -   } - -   | REMOVE_ALL_KW value WS+ value_reference R_PAREN -   { -   } -; -  value  returns [ValueNode result]  : @@ -677,24 +676,43 @@ returns [ValueNode result]        $result = ($math_expression.result);     } -   | CAST_KW WORD WORD value R_PAREN +   | CAST_KW WORD value R_PAREN     { -      /* TODO */ -      $result = null; -   } +      final Origin target_type_origin; +      final Type target_type; -   | value_reference -   { -      /* TODO */ -      $result = null; +      target_type_origin = +         CONTEXT.get_origin_at +         ( +            ($WORD.getLine()), +            ($WORD.getCharPositionInLine()) +         ); + +      target_type = WORLD.types().get(target_type_origin, ($WORD.text)); + +      $result = +         Cast.build +         ( +            CONTEXT.get_origin_at +            ( +               ($WORD.getLine()), +               ($WORD.getCharPositionInLine()) +            ), +            target_type, +            ($value.result) +         );     } -   | SET_KW value WS+ value_reference R_PAREN +   | value_reference     {        /* TODO */        $result = null;     }  ; +catch [final Throwable e] +{ +   throw new ParseCancellationException(e); +}  value_reference:     VARIABLE_KW WORD R_PAREN @@ -704,6 +722,10 @@ value_reference:     | PARAMETER_KW WORD R_PAREN     {     } + +   | GET_KW value_reference R_PAREN +   { +   }  ;  value_cond_list: | 


