| summaryrefslogtreecommitdiff | 
diff options
| author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2020-07-20 00:51:37 +0200 | 
|---|---|---|
| committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2020-07-20 00:51:37 +0200 | 
| commit | 39fc3eb50f3984bb128439a2cf190e51267529d9 (patch) | |
| tree | b8a36bad9b60a480c1b6fafcbd73200cd498e354 /src/core | |
| parent | 99171d9707c58c4f9841a00bf6fd22c4660a81e4 (diff) | |
Simplifies refs, adds remaining missing stuff.
Diffstat (limited to 'src/core')
24 files changed, 1058 insertions, 57 deletions
| diff --git a/src/core/src/tonkadur/Main.java b/src/core/src/tonkadur/Main.java index 21bc077..23666dd 100644 --- a/src/core/src/tonkadur/Main.java +++ b/src/core/src/tonkadur/Main.java @@ -14,7 +14,6 @@ public class Main     private Main () {};     public static void main (final String[] args) -   throws IOException     {        final World world;        final Context context; @@ -22,9 +21,18 @@ public class Main        world = new World();        context = Context.build(args[0]); -      Utils.add_file_content(context.get_current_file(), context, world); - -      System.out.println("Parsing completed."); -      System.out.println(world.toString()); +      try +      { +         Utils.add_file_content(context.get_current_file(), context, world); + +         System.out.println("Parsing completed."); +         System.out.println(world.toString()); +      } +      catch (final Exception e) +      { +         System.err.println("Parsing failed."); +         System.err.println(world.toString()); +         e.printStackTrace(); +      }     }  } diff --git a/src/core/src/tonkadur/fate/v1/error/ConflictingTypeException.java b/src/core/src/tonkadur/fate/v1/error/ConflictingTypeException.java index 5a1d06e..3b49861 100644 --- a/src/core/src/tonkadur/fate/v1/error/ConflictingTypeException.java +++ b/src/core/src/tonkadur/fate/v1/error/ConflictingTypeException.java @@ -47,10 +47,10 @@ public class ConflictingTypeException extends ParsingError        sb.append(System.lineSeparator());        sb.append("Resulting type '"); -      sb.append(given_type.get_name()); +      sb.append(given_type.toString());        sb.append("' ");        sb.append(" conflicts with the expected one ('"); -      sb.append(expected_type.get_name()); +      sb.append(expected_type.toString());        sb.append("').");        return sb.toString(); diff --git a/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java b/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java index 6ada2c3..20ab742 100644 --- a/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java +++ b/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java @@ -79,7 +79,7 @@ public class IncompatibleTypeException extends ParsingError        {           sb.append(System.lineSeparator());           sb.append("Recommended compatible type: "); -         sb.append(hint.get_name()); +         sb.append(hint.toString());        }        return sb.toString(); diff --git a/src/core/src/tonkadur/fate/v1/error/NotAValueMacroException.java b/src/core/src/tonkadur/fate/v1/error/NotAValueMacroException.java new file mode 100644 index 0000000..b235ad9 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/error/NotAValueMacroException.java @@ -0,0 +1,53 @@ +package tonkadur.fate.v1.error; + +import tonkadur.error.ErrorLevel; + +import tonkadur.parser.Origin; +import tonkadur.parser.ParsingError; + +public class NotAValueMacroException extends ParsingError +{ +   /***************************************************************************/ +   /**** MEMBERS **************************************************************/ +   /***************************************************************************/ +   protected final String macro_name; + +   /***************************************************************************/ +   /**** PUBLIC ***************************************************************/ +   /***************************************************************************/ +   public NotAValueMacroException (final Origin origin, final String macro_name) +   { +      super +      ( +         ErrorLevel.ERROR, +         ErrorCategory.INVALID_USE, +         origin +      ); + +      this.macro_name = macro_name; +   } + +   @Override +   public String toString () +   { +      final StringBuilder sb = new StringBuilder(); + +      sb.append(origin.toString()); +      sb.append(" "); +      sb.append(error_category.toString()); +      sb.append(System.lineSeparator()); + +      sb.append("Macro '"); +      sb.append(macro_name); +      sb.append +      ( +         "' is not defined as a single value and thus cannot be used as one." +      ); +      sb.append(System.lineSeparator()); +      sb.append("Does it contain instructions?"); +      sb.append(System.lineSeparator()); +      sb.append("Is it a sequence of multiple values?"); + +      return sb.toString(); +   } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/Macro.java b/src/core/src/tonkadur/fate/v1/lang/Macro.java index 7834bfc..6030663 100644 --- a/src/core/src/tonkadur/fate/v1/lang/Macro.java +++ b/src/core/src/tonkadur/fate/v1/lang/Macro.java @@ -1,10 +1,22 @@  package tonkadur.fate.v1.lang; +import java.util.ArrayList; +import java.util.List; +  import tonkadur.parser.Origin;  import tonkadur.fate.v1.lang.meta.DeclaredEntity;  import tonkadur.fate.v1.lang.meta.InstructionNode;  import tonkadur.fate.v1.lang.meta.TypedEntryList; +import tonkadur.fate.v1.lang.meta.ValueNode; + +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.instruction.Display; +import tonkadur.fate.v1.lang.instruction.InstructionList; + +import tonkadur.fate.v1.lang.valued_node.Cast; +import tonkadur.fate.v1.lang.valued_node.ValueToText;  public class Macro extends DeclaredEntity  { @@ -50,6 +62,71 @@ public class Macro extends DeclaredEntity        return root;     } +   public List<Type> get_signature () +   { +      final List<Type> result; + +      result = new ArrayList<Type>(); + +      for (final TypedEntryList.TypedEntry entry: parameters.get_entries()) +      { +         result.add(entry.get_type()); +      } + +      return result; +   } + +   public ValueNode get_value_node_representation () +   { +      final Cast result_cast; +      InstructionList root_as_il; +      InstructionNode instr; +      ValueNode result; + +      if (!(root instanceof InstructionList)) +      { +         return null; +      } + +      root_as_il = (InstructionList) root; + +      if (root_as_il.get_instructions().size() != 1) +      { +         return null; +      } + +      instr = root_as_il.get_instructions().get(0); + +      if (!(instr instanceof Display)) +      { +         return null; +      } + +      result = ((Display) instr).get_content(); + +      if (!(result instanceof ValueToText)) +      { +         return result; +      } + +      result = ((ValueToText) result).get_value(); + +      if (!(result instanceof Cast)) +      { +         return result; +      } + +      result_cast = (Cast) result; + +      if (result_cast.is_autogenerated()) +      { +         return result_cast.get_parent(); +      } +      else +      { +         return result; +      } +   }     /**** Compatibility ********************************************************/     /* diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/AddElement.java b/src/core/src/tonkadur/fate/v1/lang/instruction/AddElement.java index 9cc9b3b..775fa63 100644 --- a/src/core/src/tonkadur/fate/v1/lang/instruction/AddElement.java +++ b/src/core/src/tonkadur/fate/v1/lang/instruction/AddElement.java @@ -81,7 +81,12 @@ public class AddElement extends InstructionNode        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)) +      if +      ( +         element.get_type().can_be_used_as(collection_element_type) +         || +         (element.get_type().try_merging_with(collection_element_type) != null) +      )        {           return new AddElement(origin, element, collection);        } diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/EventCall.java b/src/core/src/tonkadur/fate/v1/lang/instruction/EventCall.java new file mode 100644 index 0000000..8706f9c --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/instruction/EventCall.java @@ -0,0 +1,167 @@ +package tonkadur.fate.v1.lang.instruction; + +import java.util.ArrayList; +import java.util.List; + +import tonkadur.parser.Origin; +import tonkadur.parser.ParsingError; + +import tonkadur.functional.Merge; + +import tonkadur.error.ErrorManager; + +import tonkadur.fate.v1.error.IncompatibleTypeException; +import tonkadur.fate.v1.error.IncomparableTypeException; +import tonkadur.fate.v1.error.InvalidArityException; + +import tonkadur.fate.v1.lang.Event; + +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.meta.InstructionNode; +import tonkadur.fate.v1.lang.meta.ValueNode; + +public class EventCall extends InstructionNode +{ +   /***************************************************************************/ +   /**** MEMBERS **************************************************************/ +   /***************************************************************************/ +   protected final Event event; +   protected final List<ValueNode> parameters; + +   /***************************************************************************/ +   /**** PROTECTED ************************************************************/ +   /***************************************************************************/ +   /**** Constructors *********************************************************/ +   protected EventCall +   ( +      final Origin origin, +      final Event event, +      final List<ValueNode> parameters +   ) +   { +      super(origin); + +      this.event = event; +      this.parameters = parameters; +   } + +   /***************************************************************************/ +   /**** PUBLIC ***************************************************************/ +   /***************************************************************************/ +   /**** Constructors *********************************************************/ +   public static EventCall build +   ( +      final Origin origin, +      final Event event, +      final List<ValueNode> parameters +   ) +   throws Throwable +   { +      final List<Boolean> type_checks; +      final List<Type> signature; + +      signature = event.get_signature(); + +      if (parameters.size() != signature.size()) +      { +         ErrorManager.handle +         ( +            new InvalidArityException +            ( +               origin, +               parameters.size(), +               signature.size(), +               signature.size() +            ) +         ); +      } + +      (new Merge<Type, ValueNode, Boolean>() +      { +         @Override +         public Boolean risky_lambda (final Type t, final ValueNode p) +         throws ParsingError +         { +            if ((t == null) || (p == null)) +            { +               return Boolean.FALSE; +            } +            else +            { +               final Type hint; + +               if (p.get_type().can_be_used_as(t)) +               { +                  return Boolean.TRUE; +               } + +               if (p.get_type().try_merging_with(t) != null) +               { +                  return Boolean.TRUE; +               } + +               ErrorManager.handle +               ( +                  new IncompatibleTypeException +                  ( +                     p.get_origin(), +                     p.get_type(), +                     t +                  ) +               ); + +               hint = (Type) p.get_type().generate_comparable_to(t); + +               if (hint.equals(Type.ANY)) +               { +                  ErrorManager.handle +                  ( +                     new IncomparableTypeException +                     ( +                        p.get_origin(), +                        p.get_type(), +                        t +                     ) +                  ); +               } + +               return Boolean.FALSE; +            } +         } +      }).risky_merge(signature, parameters); + +      return new EventCall(origin, event, parameters); +   } + +   /**** Accessors ************************************************************/ +   public Event get_event () +   { +      return event; +   } + +   public List<ValueNode> get_parameters () +   { +      return parameters; +   } + +   /**** Misc. ****************************************************************/ +   @Override +   public String toString () +   { +      final StringBuilder sb = new StringBuilder(); + +      sb.append("(EventCall ("); +      sb.append(event.get_name()); + +      for (final ValueNode param: parameters) +      { +         sb.append(" "); +         sb.append(param.toString()); +      } + +      sb.append("))"); + +      return sb.toString(); +   } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/MacroCall.java b/src/core/src/tonkadur/fate/v1/lang/instruction/MacroCall.java new file mode 100644 index 0000000..f00c9f2 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/instruction/MacroCall.java @@ -0,0 +1,167 @@ +package tonkadur.fate.v1.lang.instruction; + +import java.util.ArrayList; +import java.util.List; + +import tonkadur.parser.Origin; +import tonkadur.parser.ParsingError; + +import tonkadur.functional.Merge; + +import tonkadur.error.ErrorManager; + +import tonkadur.fate.v1.error.IncompatibleTypeException; +import tonkadur.fate.v1.error.IncomparableTypeException; +import tonkadur.fate.v1.error.InvalidArityException; + +import tonkadur.fate.v1.lang.Macro; + +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.meta.InstructionNode; +import tonkadur.fate.v1.lang.meta.ValueNode; + +public class MacroCall extends InstructionNode +{ +   /***************************************************************************/ +   /**** MEMBERS **************************************************************/ +   /***************************************************************************/ +   protected final Macro macro; +   protected final List<ValueNode> parameters; + +   /***************************************************************************/ +   /**** PROTECTED ************************************************************/ +   /***************************************************************************/ +   /**** Constructors *********************************************************/ +   protected MacroCall +   ( +      final Origin origin, +      final Macro macro, +      final List<ValueNode> parameters +   ) +   { +      super(origin); + +      this.macro = macro; +      this.parameters = parameters; +   } + +   /***************************************************************************/ +   /**** PUBLIC ***************************************************************/ +   /***************************************************************************/ +   /**** Constructors *********************************************************/ +   public static MacroCall build +   ( +      final Origin origin, +      final Macro macro, +      final List<ValueNode> parameters +   ) +   throws Throwable +   { +      final List<Boolean> type_checks; +      final List<Type> signature; + +      signature = macro.get_signature(); + +      if (parameters.size() != signature.size()) +      { +         ErrorManager.handle +         ( +            new InvalidArityException +            ( +               origin, +               parameters.size(), +               signature.size(), +               signature.size() +            ) +         ); +      } + +      (new Merge<Type, ValueNode, Boolean>() +      { +         @Override +         public Boolean risky_lambda (final Type t, final ValueNode p) +         throws ParsingError +         { +            if ((t == null) || (p == null)) +            { +               return Boolean.FALSE; +            } +            else +            { +               final Type hint; + +               if (p.get_type().can_be_used_as(t)) +               { +                  return Boolean.TRUE; +               } + +               if (p.get_type().try_merging_with(t) != null) +               { +                  return Boolean.TRUE; +               } + +               ErrorManager.handle +               ( +                  new IncompatibleTypeException +                  ( +                     p.get_origin(), +                     p.get_type(), +                     t +                  ) +               ); + +               hint = (Type) p.get_type().generate_comparable_to(t); + +               if (hint.equals(Type.ANY)) +               { +                  ErrorManager.handle +                  ( +                     new IncomparableTypeException +                     ( +                        p.get_origin(), +                        p.get_type(), +                        t +                     ) +                  ); +               } + +               return Boolean.FALSE; +            } +         } +      }).risky_merge(signature, parameters); + +      return new MacroCall(origin, macro, parameters); +   } + +   /**** Accessors ************************************************************/ +   public Macro get_macro () +   { +      return macro; +   } + +   public List<ValueNode> get_parameters () +   { +      return parameters; +   } + +   /**** Misc. ****************************************************************/ +   @Override +   public String toString () +   { +      final StringBuilder sb = new StringBuilder(); + +      sb.append("(MacroCall ("); +      sb.append(macro.get_name()); + +      for (final ValueNode param: parameters) +      { +         sb.append(" "); +         sb.append(param.toString()); +      } + +      sb.append("))"); + +      return sb.toString(); +   } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/RemoveAllOfElement.java b/src/core/src/tonkadur/fate/v1/lang/instruction/RemoveAllOfElement.java index 937138c..0f6aba5 100644 --- a/src/core/src/tonkadur/fate/v1/lang/instruction/RemoveAllOfElement.java +++ b/src/core/src/tonkadur/fate/v1/lang/instruction/RemoveAllOfElement.java @@ -81,7 +81,12 @@ public class RemoveAllOfElement extends InstructionNode        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)) +      if +      ( +         element.get_type().can_be_used_as(collection_element_type) +         || +         (element.get_type().try_merging_with(collection_element_type) != null) +      )        {           return new RemoveAllOfElement(origin, element, collection);        } diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/RemoveElement.java b/src/core/src/tonkadur/fate/v1/lang/instruction/RemoveElement.java index c05ed5e..136524b 100644 --- a/src/core/src/tonkadur/fate/v1/lang/instruction/RemoveElement.java +++ b/src/core/src/tonkadur/fate/v1/lang/instruction/RemoveElement.java @@ -81,7 +81,12 @@ public class RemoveElement extends InstructionNode        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)) +      if +      ( +         element.get_type().can_be_used_as(collection_element_type) +         || +         (element.get_type().try_merging_with(collection_element_type) != null) +      )        {           return new RemoveElement(origin, element, collection);        } diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/SetValue.java b/src/core/src/tonkadur/fate/v1/lang/instruction/SetValue.java index 9b50b47..efee224 100644 --- a/src/core/src/tonkadur/fate/v1/lang/instruction/SetValue.java +++ b/src/core/src/tonkadur/fate/v1/lang/instruction/SetValue.java @@ -58,11 +58,17 @@ public class SetValue extends InstructionNode        value_reference_type = value_reference.get_type(); -      if (element.get_type().can_be_used_as(value_reference_type)) +      if +      ( +         element.get_type().can_be_used_as(value_reference_type) +         || +         (element.get_type().try_merging_with(value_reference_type) != null) +      )        {           return new SetValue(origin, element, value_reference);        } +        ErrorManager.handle        (           new ConflictingTypeException diff --git a/src/core/src/tonkadur/fate/v1/lang/type/Type.java b/src/core/src/tonkadur/fate/v1/lang/type/Type.java index 87ef5fe..ec961d8 100644 --- a/src/core/src/tonkadur/fate/v1/lang/type/Type.java +++ b/src/core/src/tonkadur/fate/v1/lang/type/Type.java @@ -124,6 +124,26 @@ public class Type extends DeclaredEntity        return (parent == null);     } +   public Type try_merging_with (final Type t) +   { +      if (t.get_base_type() != get_base_type()) +      { +         return null; +      } + +      if (t.is_base_type()) +      { +         return this; +      } + +      if (is_base_type()) +      { +         return t; +      } + +      return null; +   } +     /**** Compatibility ********************************************************/     public boolean can_be_used_as (final Type t)     { 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 index 62a258f..9a084ce 100644 --- a/src/core/src/tonkadur/fate/v1/lang/valued_node/Cast.java +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/Cast.java @@ -83,6 +83,7 @@ public class Cast extends ValueNode     /**** MEMBERS **************************************************************/     /***************************************************************************/     protected final ValueNode value; +   protected final boolean is_autogenerated;     /***************************************************************************/     /**** PROTECTED ************************************************************/ @@ -92,11 +93,13 @@ public class Cast extends ValueNode     (        final Origin origin,        final Type to, -      final ValueNode value +      final ValueNode value, +      final boolean is_autogenerated     )     {        super(origin, to);        this.value = value; +      this.is_autogenerated = is_autogenerated;     }     /***************************************************************************/ @@ -107,7 +110,8 @@ public class Cast extends ValueNode     (        final Origin origin,        final Type to, -      final ValueNode value +      final ValueNode value, +      final boolean is_autogenerated     )     throws        IncompatibleTypeException, @@ -131,7 +135,7 @@ public class Cast extends ValueNode           )        )        { -         return new Cast(origin, to, value); +         return new Cast(origin, to, value, is_autogenerated);        }        hint = (Type) value.get_type().generate_comparable_to(to); @@ -156,11 +160,21 @@ public class Cast extends ValueNode           );        } -      return new Cast(origin, hint, value); +      return new Cast(origin, hint, value, is_autogenerated);     }     /**** Accessors ************************************************************/ +   public ValueNode get_parent () +   { +      return value; +   } + +   public boolean is_autogenerated () +   { +      return is_autogenerated; +   } +     /**** Misc. ****************************************************************/     @Override     public String 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 index fa8dcaf..0cdb45e 100644 --- a/src/core/src/tonkadur/fate/v1/lang/valued_node/CondValue.java +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/CondValue.java @@ -55,7 +55,7 @@ public class CondValue extends ValueNode        IncomparableTypeException     {        final Type first_type; -      Type hint; +      Type candidate_hint, hint;        first_type = branches.get(0).get_cdr().get_type();        hint = first_type; @@ -80,6 +80,15 @@ public class CondValue extends ValueNode              continue;           } +         candidate_hint = entry.get_cdr().get_type().try_merging_with(hint); + +         if (candidate_hint != null) +         { +            hint = candidate_hint; + +            continue; +         } +           ErrorManager.handle           (              new ConflictingTypeException 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 index 7eacc40..3b7787c 100644 --- a/src/core/src/tonkadur/fate/v1/lang/valued_node/CountOperator.java +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/CountOperator.java @@ -80,7 +80,12 @@ public class CountOperator extends ValueNode        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)) +      if +      ( +         element.get_type().can_be_used_as(collection_element_type) +         || +         (element.get_type().try_merging_with(collection_element_type) != null) +      )        {           return new CountOperator(origin, element, collection);        } 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 index 1b40f73..a54c1b6 100644 --- a/src/core/src/tonkadur/fate/v1/lang/valued_node/IfElseValue.java +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/IfElseValue.java @@ -59,7 +59,7 @@ public class IfElseValue extends ValueNode        ConflictingTypeException,        IncomparableTypeException     { -      final Type hint; +      Type hint;        final Type if_true_type;        final Type if_false_type; @@ -85,6 +85,13 @@ public class IfElseValue extends ValueNode              new IfElseValue(origin, if_true_type, condition, if_true, if_false);        } +      hint = if_true_type.try_merging_with(if_false_type); + +      if (hint != null) +      { +         return new IfElseValue(origin, hint, condition, if_true, if_false); +      } +        ErrorManager.handle        (           new ConflictingTypeException 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 index 7701614..b0c8fa8 100644 --- a/src/core/src/tonkadur/fate/v1/lang/valued_node/IsMemberOperator.java +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/IsMemberOperator.java @@ -80,7 +80,12 @@ public class IsMemberOperator extends ValueNode        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)) +      if +      ( +         element.get_type().can_be_used_as(collection_element_type) +         || +         (element.get_type().try_merging_with(collection_element_type) != null) +      )        {           return new IsMemberOperator(origin, element, collection);        } diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/MacroValueCall.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/MacroValueCall.java new file mode 100644 index 0000000..1405e6f --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/MacroValueCall.java @@ -0,0 +1,185 @@ +package tonkadur.fate.v1.lang.valued_node; + +import java.util.ArrayList; +import java.util.List; + +import tonkadur.parser.Origin; +import tonkadur.parser.ParsingError; + +import tonkadur.functional.Merge; + +import tonkadur.error.ErrorManager; + +import tonkadur.fate.v1.error.IncompatibleTypeException; +import tonkadur.fate.v1.error.IncomparableTypeException; +import tonkadur.fate.v1.error.InvalidArityException; +import tonkadur.fate.v1.error.NotAValueMacroException; + +import tonkadur.fate.v1.lang.Macro; + +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.meta.ValueNode; + +public class MacroValueCall extends ValueNode +{ +   /***************************************************************************/ +   /**** MEMBERS **************************************************************/ +   /***************************************************************************/ +   protected final Macro macro; +   protected final ValueNode act_as; +   protected final List<ValueNode> parameters; + +   /***************************************************************************/ +   /**** PROTECTED ************************************************************/ +   /***************************************************************************/ +   /**** Constructors *********************************************************/ +   protected MacroValueCall +   ( +      final Origin origin, +      final Macro macro, +      final List<ValueNode> parameters, +      final ValueNode act_as +   ) +   { +      super(origin, act_as.get_type()); + +      this.macro = macro; +      this.parameters = parameters; +      this.act_as = act_as; +   } + +   /***************************************************************************/ +   /**** PUBLIC ***************************************************************/ +   /***************************************************************************/ +   /**** Constructors *********************************************************/ +   public static MacroValueCall build +   ( +      final Origin origin, +      final Macro macro, +      final List<ValueNode> parameters +   ) +   throws Throwable +   { +      ValueNode act_as; +      final List<Type> signature; + +      act_as = macro.get_value_node_representation(); + +      if (act_as == null) +      { +         ErrorManager.handle +         ( +            new NotAValueMacroException(origin, macro.get_name()) +         ); +      } + +      signature = macro.get_signature(); + +      if (parameters.size() != signature.size()) +      { +         ErrorManager.handle +         ( +            new InvalidArityException +            ( +               origin, +               parameters.size(), +               signature.size(), +               signature.size() +            ) +         ); +      } + +      (new Merge<Type, ValueNode, Boolean>() +      { +         @Override +         public Boolean risky_lambda (final Type t, final ValueNode p) +         throws ParsingError +         { +            if ((t == null) || (p == null)) +            { +               return Boolean.FALSE; +            } +            else +            { +               final Type hint; + +               if (p.get_type().can_be_used_as(t)) +               { +                  return Boolean.TRUE; +               } + +               if (p.get_type().try_merging_with(t) != null) +               { +                  return Boolean.TRUE; +               } + +               ErrorManager.handle +               ( +                  new IncompatibleTypeException +                  ( +                     p.get_origin(), +                     p.get_type(), +                     t +                  ) +               ); + +               hint = (Type) p.get_type().generate_comparable_to(t); + +               if (hint.equals(Type.ANY)) +               { +                  ErrorManager.handle +                  ( +                     new IncomparableTypeException +                     ( +                        p.get_origin(), +                        p.get_type(), +                        t +                     ) +                  ); +               } + +               return Boolean.FALSE; +            } +         } +      }).risky_merge(signature, parameters); + +      return new MacroValueCall(origin, macro, parameters, act_as); +   } + +   /**** Accessors ************************************************************/ +   public Macro get_macro () +   { +      return macro; +   } + +   public ValueNode get_actual_value_node () +   { +      return act_as; +   } + +   public List<ValueNode> get_parameters () +   { +      return parameters; +   } + +   /**** Misc. ****************************************************************/ +   @Override +   public String toString () +   { +      final StringBuilder sb = new StringBuilder(); + +      sb.append("(MacroValueCall ("); +      sb.append(macro.get_name()); + +      for (final ValueNode param: parameters) +      { +         sb.append(" "); +         sb.append(param.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 index 87ea676..8b7e2b2 100644 --- a/src/core/src/tonkadur/fate/v1/lang/valued_node/Operation.java +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/Operation.java @@ -127,19 +127,26 @@ public class Operation extends ValueNode              continue;           } +         previous_computed_type = computed_type; +         computed_type = computed_type.try_merging_with(operand_type); + +         if (computed_type != null) +         { +            continue; +         } +           ErrorManager.handle           (              new IncompatibleTypeException              (                 operand.get_origin(),                 operand_type, -               computed_type +               previous_computed_type              )           ); -         previous_computed_type = computed_type;           computed_type = -            (Type) computed_type.generate_comparable_to(operand_type); +            (Type) previous_computed_type.generate_comparable_to(operand_type);           if (computed_type.equals(Type.ANY))           { 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 index e6d03b2..d99bb76 100644 --- a/src/core/src/tonkadur/fate/v1/lang/valued_node/RefOperator.java +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/RefOperator.java @@ -2,10 +2,9 @@ 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.Reference;  import tonkadur.fate.v1.lang.meta.ValueNode;  public class RefOperator extends ValueNode @@ -13,16 +12,16 @@ public class RefOperator extends ValueNode     /***************************************************************************/     /**** MEMBERS **************************************************************/     /***************************************************************************/ -   protected final Variable variable; +   protected final Reference referred;     /***************************************************************************/     /**** PROTECTED ************************************************************/     /***************************************************************************/     /**** Constructors *********************************************************/ -   public RefOperator (final Origin origin, final Variable variable) +   public RefOperator (final Origin origin, final Reference referred)     { -      super(origin, new RefType(origin, variable.get_type(), "auto generated")); -      this.variable = variable; +      super(origin, new RefType(origin, referred.get_type(), "auto generated")); +      this.referred = referred;     }     /***************************************************************************/ @@ -40,7 +39,7 @@ public class RefOperator extends ValueNode        sb.append(origin.toString());        sb.append("(Ref "); -      sb.append(variable.get_name()); +      sb.append(referred.get_name());        sb.append(") ");        return sb.toString(); diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/TextWithEffect.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/TextWithEffect.java index 705ef64..b1fd88a 100644 --- a/src/core/src/tonkadur/fate/v1/lang/valued_node/TextWithEffect.java +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/TextWithEffect.java @@ -4,6 +4,15 @@ import java.util.ArrayList;  import java.util.List;  import tonkadur.parser.Origin; +import tonkadur.parser.ParsingError; + +import tonkadur.functional.Merge; + +import tonkadur.error.ErrorManager; + +import tonkadur.fate.v1.error.IncompatibleTypeException; +import tonkadur.fate.v1.error.IncomparableTypeException; +import tonkadur.fate.v1.error.InvalidArityException;  import tonkadur.fate.v1.lang.TextEffect; @@ -44,20 +53,6 @@ public class TextWithEffect extends TextNode     /**** PUBLIC ***************************************************************/     /***************************************************************************/     /**** Constructors *********************************************************/ -   public TextWithEffect -   ( -      final Origin origin, -      final TextEffect effect, -      final TextNode text -   ) -   { -      super(origin); - -      this.effect = effect; -      this.parameters = new ArrayList<ValueNode>(); -      this.text = text; -   } -     public static TextWithEffect build     (        final Origin origin, @@ -65,8 +60,80 @@ public class TextWithEffect extends TextNode        final List<ValueNode> parameters,        final TextNode text     ) +   throws Throwable     { -      /* TODO: Checks */ +      final List<Type> signature; + +      signature = effect.get_signature(); + +      if (parameters.size() != signature.size()) +      { +         ErrorManager.handle +         ( +            new InvalidArityException +            ( +               origin, +               parameters.size(), +               signature.size(), +               signature.size() +            ) +         ); +      } + +      (new Merge<Type,ValueNode,Boolean>() +      { +         @Override +         public Boolean risky_lambda (final Type t, final ValueNode p) +         throws ParsingError +         { +            if ((t == null) || (p == null)) +            { +               return Boolean.FALSE; +            } +            else +            { +               final Type hint; + +               if (p.get_type().can_be_used_as(t)) +               { +                  return Boolean.TRUE; +               } + +               if (p.get_type().try_merging_with(t) != null) +               { +                  return Boolean.TRUE; +               } + +               ErrorManager.handle +               ( +                  new IncompatibleTypeException +                  ( +                     p.get_origin(), +                     p.get_type(), +                     t +                  ) +               ); + +               hint = (Type) p.get_type().generate_comparable_to(t); + +               if (hint.equals(Type.ANY)) +               { +                  ErrorManager.handle +                  ( +                     new IncomparableTypeException +                     ( +                        p.get_origin(), +                        p.get_type(), +                        t +                     ) +                  ); +               } + +               return Boolean.FALSE; +            } +         } +      }).risky_merge(signature, parameters); +        return new TextWithEffect(origin, effect, parameters, text);     } diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/ValueToText.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/ValueToText.java index fcfac27..ec69776 100644 --- a/src/core/src/tonkadur/fate/v1/lang/valued_node/ValueToText.java +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/ValueToText.java @@ -49,11 +49,12 @@ public class ValueToText extends TextNode        return           new ValueToText           ( -            new Cast +            Cast.build              (                 value.get_origin(),                 Type.STRING, -               value +               value, +               true              )           );     } diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 index 1efccd1..3ec977a 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 @@ -591,25 +591,89 @@ returns [InstructionNode result]           );     } -   | SET_FIELDS_KW WS+ value_reference WS * field_value_list WS* R_PAREN +   | SET_FIELDS_KW WS+ value_reference WS* field_value_list WS* R_PAREN     { -      /* TODO */ +      final Origin origin; +      final List<InstructionNode> operations; + +      origin = +         CONTEXT.get_origin_at +         ( +            ($SET_FIELDS_KW.getLine()), +            ($SET_FIELDS_KW.getCharPositionInLine()) +         ); + +      operations = new ArrayList<InstructionNode>(); + +      for +      ( +         final Cons<Origin, Cons<String, ValueNode>> entry: +            ($field_value_list.result) +      ) +      { +         operations.add +         ( +            SetValue.build +            ( +               entry.get_car(), +               entry.get_cdr().get_cdr(), +               FieldReference.build +               ( +                  entry.get_car(), +                  ($value_reference.result), +                  entry.get_cdr().get_car() +               ) +            ) +         ); +      } -      $result = null; +      $result = new InstructionList(origin, operations);     }     | EVENT_KW WS+ WORD WS+ value_list WS* R_PAREN     { -      /* TODO */ +      final Origin origin; +      final Event event; -      $result = null; +      origin = +         CONTEXT.get_origin_at +         ( +            ($EVENT_KW.getLine()), +            ($EVENT_KW.getCharPositionInLine()) +         ); + +      event = WORLD.events().get(origin, ($WORD.text)); + +      $result = +         EventCall.build +         ( +            origin, +            event, +            ($value_list.result) +         );     }     | MACRO_KW WS+ WORD WS+ value_list WS* R_PAREN     { -      /* TODO */ +      final Origin origin; +      final Macro macro; + +      origin = +         CONTEXT.get_origin_at +         ( +            ($MACRO_KW.getLine()), +            ($MACRO_KW.getCharPositionInLine()) +         ); + +      macro = WORLD.macros().get(origin, ($WORD.text)); -      $result = null; +      $result = +         MacroCall.build +         ( +            origin, +            macro, +            ($value_list.result) +         );     }     | SEQUENCE_KW WS+ WORD WS* R_PAREN @@ -956,7 +1020,7 @@ returns [TextNode result]:           );        $result = -         new TextWithEffect +         TextWithEffect.build           (              CONTEXT.get_origin_at              ( @@ -964,6 +1028,7 @@ returns [TextNode result]:                 ($WORD.getCharPositionInLine())              ),              effect, +            new ArrayList<ValueNode>(),              ($paragraph.result)           );     } @@ -1550,7 +1615,7 @@ returns [ValueNode result]           );        $result = -         new TextWithEffect +         TextWithEffect.build           (              CONTEXT.get_origin_at              ( @@ -1558,6 +1623,7 @@ returns [ValueNode result]                 ($WORD.getCharPositionInLine())              ),              effect, +            new ArrayList<ValueNode>(),              ($paragraph.result)           );     } @@ -1663,6 +1729,20 @@ returns [ValueNode result]        $result = ($math_expression.result);     } +   | REF_KW WS+ value_reference WS* R_PAREN +   { +      $result = +         new RefOperator +         ( +            CONTEXT.get_origin_at +            ( +               ($REF_KW.getLine()), +               ($REF_KW.getCharPositionInLine()) +            ), +            ($value_reference.result) +         ); +   } +     | CAST_KW WS+ WORD WS+ value WS* R_PAREN     {        final Origin target_type_origin; @@ -1686,7 +1766,8 @@ returns [ValueNode result]                 ($CAST_KW.getCharPositionInLine())              ),              target_type, -            ($value.result) +            ($value.result), +            false           );     } @@ -1724,6 +1805,29 @@ returns [ValueNode result]        }     } +   | MACRO_KW WS+ WORD WS+ value_list WS* R_PAREN +   { +      final Origin origin; +      final Macro macro; + +      origin = +         CONTEXT.get_origin_at +         ( +            ($MACRO_KW.getLine()), +            ($MACRO_KW.getCharPositionInLine()) +         ); + +      macro = WORLD.macros().get(origin, ($WORD.text)); + +      $result = +         MacroValueCall.build +         ( +            origin, +            macro, +            ($value_list.result) +         ); +   } +     | value_reference     {        $result = ($value_reference.result); @@ -1877,6 +1981,52 @@ returns [Reference result]           }        }     } + +   | WORD +   { +      final Origin target_var_origin; +      final Variable target_var; +      final String[] subrefs; + +      subrefs = ($WORD.text).split("\\."); + +      target_var_origin = +         CONTEXT.get_origin_at +         ( +            ($WORD.getLine()), +            ($WORD.getCharPositionInLine()) +         ); + +      target_var = WORLD.variables().get(target_var_origin, subrefs[0]); + +      $result = +         new VariableReference +         ( +            CONTEXT.get_origin_at +            ( +               ($WORD.getLine()), +               ($WORD.getCharPositionInLine()) +            ), +            target_var +         ); + +      if (subrefs.length > 1) +      { +         final List<String> subrefs_list; + +         subrefs_list = new ArrayList(Arrays.asList(subrefs)); + +         subrefs_list.remove(0); + +         $result = +            FieldReference.build +            ( +               target_var_origin, +               ($result), +               subrefs_list +            ); +      } +   }  ;  catch [final Throwable e]  { diff --git a/src/core/src/tonkadur/functional/Merge.java b/src/core/src/tonkadur/functional/Merge.java index 29d37c5..5d5dcb8 100644 --- a/src/core/src/tonkadur/functional/Merge.java +++ b/src/core/src/tonkadur/functional/Merge.java @@ -39,8 +39,47 @@ public class Merge <Input0, Input1, Output>        return output;     } +   public List<Output> risky_merge +   ( +      final List<Input0> i0, +      final List<Input1> i1 +   ) +   throws Throwable +   { +      final int result_size; +      final List<Output> output; +      final Iterator<Input0> it0; +      final Iterator<Input1> it1; + +      result_size = Math.max(i0.size(), i1.size()); +      output = new ArrayList<Output>(result_size); + +      it0 = i0.iterator(); +      it1 = i1.iterator(); + +      for (int i = 0; i < result_size; ++i) +      { +         output.add +         ( +            risky_lambda +            ( +               it0.hasNext() ? it0.next() : null, +               it1.hasNext() ? it1.next() : null +            ) +         ); +      } + +      return output; +   } +     protected Output lambda (final Input0 i0, final Input1 i1)     {        return null;     } + +   protected Output risky_lambda (final Input0 i0, final Input1 i1) +   throws Throwable +   { +      return null; +   }  } | 


