summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2020-07-05 13:36:24 +0200
committerNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2020-07-05 13:36:24 +0200
commit1737cb747199beac1879aa0867423bd634113333 (patch)
tree541f557f85e44f60eaa1176e3c619f2758549a10
parentf6cd96ae24b458a5b4875f8e151758c11c45dbcd (diff)
Adds DictType, guards for SetType, hints.
-rw-r--r--src/core/src/tonkadur/fate/v1/error/IncompatibleDeclarationException.java29
-rw-r--r--src/core/src/tonkadur/fate/v1/error/UnknownDictionaryFieldException.java63
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/DictType.java178
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/Operator.java24
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/SetType.java45
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/Type.java19
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/meta/DeclarationCollection.java30
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;
}
}