summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2020-07-05 21:47:43 +0200
committerNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2020-07-05 21:47:43 +0200
commit30906df3bc34e70f5be5add5d4c4e55437a0326d (patch)
tree29a8c15da8d9accd93b35243c80c1b7aca93016b
parent7b053964589d4eebb7fc4d600c8762501ec36f21 (diff)
Adds Variable declaration.
-rw-r--r--src/core/src/tonkadur/fate/v1/error/UnknownDictionaryFieldException.java5
-rw-r--r--src/core/src/tonkadur/fate/v1/error/UnknownVariableScopeException.java55
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/Event.java6
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/Variable.java136
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/VariableScope.java88
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/World.java20
-rw-r--r--src/core/src/tonkadur/fate/v1/parser/FateParser.g423
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