| summaryrefslogtreecommitdiff | 
diff options
Diffstat (limited to 'src')
7 files changed, 315 insertions, 18 deletions
| diff --git a/src/core/src/tonkadur/fate/v1/error/UnknownDictionaryFieldException.java b/src/core/src/tonkadur/fate/v1/error/UnknownDictionaryFieldException.java index dd3e67d..aa1ff70 100644 --- a/src/core/src/tonkadur/fate/v1/error/UnknownDictionaryFieldException.java +++ b/src/core/src/tonkadur/fate/v1/error/UnknownDictionaryFieldException.java @@ -47,14 +47,13 @@ public class UnknownDictionaryFieldException extends ParsingError        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("'.");        sb.append(System.lineSeparator());        sb.append("Available fields are:");        for (final Map.Entry<String, Type> field: dict.get_fields())        { +         sb.append(System.lineSeparator());           sb.append("- ");           sb.append(field.getKey());           sb.append(": "); diff --git a/src/core/src/tonkadur/fate/v1/error/UnknownVariableScopeException.java b/src/core/src/tonkadur/fate/v1/error/UnknownVariableScopeException.java new file mode 100644 index 0000000..129a789 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/error/UnknownVariableScopeException.java @@ -0,0 +1,55 @@ +package tonkadur.fate.v1.error; + +import tonkadur.error.ErrorLevel; + +import tonkadur.parser.Origin; +import tonkadur.parser.ParsingError; + +import tonkadur.fate.v1.lang.VariableScope; + +public class UnknownVariableScopeException extends ParsingError +{ +   /***************************************************************************/ +   /**** MEMBERS **************************************************************/ +   /***************************************************************************/ +   protected final String name; + +   /***************************************************************************/ +   /**** PUBLIC ***************************************************************/ +   /***************************************************************************/ +   public UnknownVariableScopeException +   ( +      final Origin origin, +      final String name +   ) +   { +      super(ErrorLevel.ERROR, ErrorCategory.INVALID_USE, origin); +      this.name = 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("Unknown variable scope '"); +      sb.append(name); +      sb.append("'."); +      sb.append(System.lineSeparator()); +      sb.append("Available fields are:"); + +      for (final String scope: VariableScope.get_available_scopes()) +      { +         sb.append(System.lineSeparator()); +         sb.append("- "); +         sb.append(scope); +      } + +      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 b917ebf..d762c71 100644 --- a/src/core/src/tonkadur/fate/v1/lang/Event.java +++ b/src/core/src/tonkadur/fate/v1/lang/Event.java @@ -127,7 +127,7 @@ public class Event extends DeclaredEntity                       protected Boolean lambda (final Type a, final Type b)                       {                          return -                           new Boolean(a.is_incompatible_with_declaration(b)); +                           new Boolean(a.can_be_used_as(b));                       }                    }.merge(signature, e.signature)                 ); @@ -171,8 +171,4 @@ public class Event extends DeclaredEntity        return sb.toString();     } - -   /***************************************************************************/ -   /**** PROTECTED ************************************************************/ -   /***************************************************************************/  } diff --git a/src/core/src/tonkadur/fate/v1/lang/Variable.java b/src/core/src/tonkadur/fate/v1/lang/Variable.java new file mode 100644 index 0000000..3e17d61 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/Variable.java @@ -0,0 +1,136 @@ +package tonkadur.fate.v1.lang; + +import java.util.ArrayList; +import java.util.List; + +import tonkadur.functional.Merge; + +import tonkadur.parser.Context; +import tonkadur.parser.Location; +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.meta.DeclaredEntity; + +public class Variable extends DeclaredEntity +{ +   protected static final Variable ANY; + +   static +   { +      ANY = +         new Variable +         ( +            new Origin(new Context(""), Location.BASE_LANGUAGE), +            VariableScope.ANY, +            Type.ANY, +            /* +             * Use of a space necessary to avoid conflicting with a user created +             * type. +             */ +            "undetermined variable" +         ); +   } + +   public static Variable value_on_missing () +   { +      return ANY; +   } + +   @Override +   public /* static */ String get_type_name () +   { +      return "Variable"; +   } + + +   /***************************************************************************/ +   /**** MEMBERS **************************************************************/ +   /***************************************************************************/ +   protected final VariableScope scope; +   protected final Type type; + +   /***************************************************************************/ +   /**** PUBLIC ***************************************************************/ +   /***************************************************************************/ + +   /**** Constructors *********************************************************/ +   public Variable +   ( +      final Origin origin, +      final VariableScope scope, +      final Type type, +      final String name +   ) +   { +      super(origin, name); + +      this.scope = scope; +      this.type = type; +   } + +   /**** Accessors ************************************************************/ +   public Type get_type () +   { +      return type; +   } + +   @Override +   public DeclaredEntity generate_comparable_to (final DeclaredEntity de) +   { +      final VariableScope new_scope; +      final Type new_type; +      final Variable v; + +      if (!(de instanceof Variable)) +      { +         return ANY; +      } + +      v = (Variable) de; + +      new_scope = scope.generate_compatible_with(v.scope); +      new_type = (Type) type.generate_comparable_to(v.type); + +      return new Variable(origin, new_scope, new_type, name); +   } + +   /**** Misc. ****************************************************************/ +   @Override +   public boolean is_incompatible_with_declaration (final DeclaredEntity de) +   { +      if (de instanceof Variable) +      { +         final Variable v; + +         v = (Variable) de; + +         return +            ( +               (!scope.equals(v.scope)) +               || !type.can_be_used_as(v.type) +            ); +      } + +      return true; +   } + +   @Override +   public String toString () +   { +      final StringBuilder sb = new StringBuilder(); + +      sb.append("("); +      sb.append(scope.toString()); +      sb.append(" "); +      sb.append(type.get_name()); +      sb.append(" Variable "); +      sb.append(name); +      sb.append(")"); + +      return sb.toString(); +   } + +   /***************************************************************************/ +   /**** PROTECTED ************************************************************/ +   /***************************************************************************/ +} diff --git a/src/core/src/tonkadur/fate/v1/lang/VariableScope.java b/src/core/src/tonkadur/fate/v1/lang/VariableScope.java new file mode 100644 index 0000000..7f42fa6 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/VariableScope.java @@ -0,0 +1,88 @@ +package tonkadur.fate.v1.lang; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.HashSet; + +/* + * Yes, it *could* have been an enum. Except that you can't extend enums, making + * them inadequate for anything that has even the slightest chance of needing to + * be extended at some point in the future. In other words, they're inadequate + * for anything but very rare corner cases (days in week, for example). + * Tonkadur wants extension support, ergo, no enums in Tonkadur. + * + * The use of a collection to decode them stems from the same reason (can't + * override static methods). + */ +public class VariableScope +{ +   public static final VariableScope ANY; + +   protected static final Map<String, VariableScope> from_name; +   public static final VariableScope LOCAL; +   public static final VariableScope GLOBAL; + +   static +   { +      from_name = new HashMap<String, VariableScope>(); + +      ANY = new VariableScope("unknown scope", null); +      GLOBAL = new VariableScope("global", null); +      LOCAL = new VariableScope("local", GLOBAL); +   } + +   public static VariableScope value_of (final String string) +   { +      return from_name.get(string); +   } + +   public static Set<String> get_available_scopes () +   { +      return from_name.keySet(); +   } + +   protected final String name; +   protected final Set<VariableScope> more_restrictive_than; + +   protected VariableScope (final String name, final VariableScope parent) +   { +      this.name = name; + +      more_restrictive_than = new HashSet<VariableScope>(); + +      if (parent != null) +      { +         more_restrictive_than.addAll(parent.more_restrictive_than); +         more_restrictive_than.add(parent); +      } + +      from_name.put(name, this); +   } + +   public VariableScope generate_compatible_with (final VariableScope other) +   { +      if (other.equals(this)) +      { +         return this; +      } + +      if (other.more_restrictive_than.contains(this)) +      { +         if (this.more_restrictive_than.contains(other)) +         { +            return ANY; +         } + +         return other; +      } + +      return this; +   } + +   @Override +   public String toString () +   { +      return name; +   } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/World.java b/src/core/src/tonkadur/fate/v1/lang/World.java index 43feb5f..8419b06 100644 --- a/src/core/src/tonkadur/fate/v1/lang/World.java +++ b/src/core/src/tonkadur/fate/v1/lang/World.java @@ -21,7 +21,7 @@ public class World  //   protected final DeclarationCollection<Sequence> sequences;  //   protected final DeclarationCollection<TextEffect> text_effects;     protected final DeclarationCollection<Type> type_collection; -//   protected final DeclarationCollection<Variable> variables; +   protected final DeclarationCollection<Variable> variable_collection;     /***************************************************************************/     /**** PUBLIC ***************************************************************/ @@ -39,7 +39,8 @@ public class World        //text_effects = new DeclarationCollection<TextEffect>();        type_collection =           new DeclarationCollection<Type>(Type.value_on_missing()); -      //variables = new DeclarationCollection<Variable>(); +      variable_collection = +         new DeclarationCollection<Variable>(Variable.value_on_missing());        add_base_types();     } @@ -61,16 +62,21 @@ public class World        loaded_files.add(name);     } -   public DeclarationCollection<Type> types() +   public DeclarationCollection<Type> types ()     {        return type_collection;     } -   public DeclarationCollection<Event> events() +   public DeclarationCollection<Event> events ()     {        return event_collection;     } +   public DeclarationCollection<Variable> variables () +   { +      return variable_collection; +   } +     /**** Misc. ****************************************************************/     @Override     public String toString () @@ -103,6 +109,12 @@ public class World        sb.append(System.lineSeparator());        sb.append(System.lineSeparator()); +      sb.append("Variable: "); +      sb.append(System.lineSeparator()); +      sb.append(variable_collection.toString()); +      sb.append(System.lineSeparator()); +      sb.append(System.lineSeparator()); +        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 27ff773..9d30b0f 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 @@ -9,11 +9,13 @@ options  {     package tonkadur.fate.v1.parser; -   import tonkadur.error.Error; +   import tonkadur.error.ErrorManager;     import tonkadur.parser.Context;     import tonkadur.parser.Origin; +   import tonkadur.fate.v1.error.UnknownVariableScopeException; +     import tonkadur.fate.v1.lang.*;     import tonkadur.fate.v1.lang.meta.*;  } @@ -71,11 +73,10 @@ first_level_fate_instr:     | DECLARE_VARIABLE_KW scope=WORD WS+ type=WORD WS+ name=WORD R_PAREN     { -   /*        final Origin start_origin, scope_origin, type_origin; -      final VariableScope variable_scope;        final Type variable_type;        final Variable new_variable; +      VariableScope variable_scope;        start_origin =           CONTEXT.get_origin_at @@ -98,8 +99,19 @@ first_level_fate_instr:              ($type.getCharPositionInLine())           ); -      variable_scope = VariableScope.value_of(scope_origin, ($scope.text)); -      variable_type = WORLD.types().get(($type.text)); +      variable_scope = VariableScope.value_of(($scope.text)); + +      if (variable_scope == null) +      { +         ErrorManager.handle +         ( +            new UnknownVariableScopeException(scope_origin, ($scope.text)) +         ); + +         variable_scope = VariableScope.ANY; +      } + +      variable_type = WORLD.types().get(type_origin, ($type.text));        new_variable =           new Variable           ( @@ -110,7 +122,6 @@ first_level_fate_instr:           );        WORLD.variables().add(new_variable); -   */     }     | DECLARE_TEXT_EFFECT_KW params=word_list name=WORD R_PAREN | 


