summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/src/tonkadur/Main.java8
-rw-r--r--src/core/src/tonkadur/fate/v1/Utils.java1
-rw-r--r--src/core/src/tonkadur/fate/v1/error/ConflictingDeclarationException.java64
-rw-r--r--src/core/src/tonkadur/fate/v1/error/DuplicateDeclarationException.java (renamed from src/core/src/tonkadur/fate/v1/error/TypeAlreadyDeclaredException.java)20
-rw-r--r--src/core/src/tonkadur/fate/v1/error/ErrorCategory.java4
-rw-r--r--src/core/src/tonkadur/fate/v1/error/IncompatibleDeclarationException.java64
-rw-r--r--src/core/src/tonkadur/fate/v1/error/MissingDeclarationException.java47
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/Event.java147
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/Type.java69
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/World.java92
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/meta/DeclarationCollection.java119
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/meta/DeclaredEntity.java88
-rw-r--r--src/core/src/tonkadur/fate/v1/parser/FateParser.g44
-rw-r--r--src/core/src/tonkadur/functional/Merge.java46
14 files changed, 686 insertions, 87 deletions
diff --git a/src/core/src/tonkadur/Main.java b/src/core/src/tonkadur/Main.java
index 76790e9..c8f8f1b 100644
--- a/src/core/src/tonkadur/Main.java
+++ b/src/core/src/tonkadur/Main.java
@@ -2,6 +2,8 @@ package tonkadur;
import java.io.IOException;
+import tonkadur.fate.v1.lang.World;
+
import tonkadur.fate.v1.Utils;
public class Main
@@ -12,6 +14,10 @@ public class Main
public static void main (final String[] args)
throws IOException
{
- Utils.parse_file(args[0]);
+ final World world;
+
+ world = new World();
+
+ Utils.add_file_content(args[0], world);
}
}
diff --git a/src/core/src/tonkadur/fate/v1/Utils.java b/src/core/src/tonkadur/fate/v1/Utils.java
index 048b3f2..562adee 100644
--- a/src/core/src/tonkadur/fate/v1/Utils.java
+++ b/src/core/src/tonkadur/fate/v1/Utils.java
@@ -29,6 +29,7 @@ public class Utils
lexer = new FateLexer(CharStreams.fromFileName(filename));
tokens = new CommonTokenStream(lexer);
parser = new FateParser(tokens);
+
parser.fate_file(world);
}
}
diff --git a/src/core/src/tonkadur/fate/v1/error/ConflictingDeclarationException.java b/src/core/src/tonkadur/fate/v1/error/ConflictingDeclarationException.java
new file mode 100644
index 0000000..d0837a7
--- /dev/null
+++ b/src/core/src/tonkadur/fate/v1/error/ConflictingDeclarationException.java
@@ -0,0 +1,64 @@
+package tonkadur.fate.v1.error;
+
+import tonkadur.error.ErrorLevel;
+
+import tonkadur.parser.Origin;
+import tonkadur.parser.ParsingError;
+
+import tonkadur.fate.v1.lang.meta.DeclaredEntity;
+
+public class ConflictingDeclarationException extends ParsingError
+{
+ /***************************************************************************/
+ /**** MEMBERS **************************************************************/
+ /***************************************************************************/
+ protected final DeclaredEntity new_declaration;
+ protected final DeclaredEntity original_declaration;
+
+ /***************************************************************************/
+ /**** PUBLIC ***************************************************************/
+ /***************************************************************************/
+ public ConflictingDeclarationException
+ (
+ final DeclaredEntity new_declaration,
+ final DeclaredEntity original_declaration
+ )
+ {
+ super
+ (
+ ErrorLevel.ERROR,
+ ErrorCategory.CONFLICTING_DECLARATION,
+ new_declaration.get_origin()
+ );
+
+ this.new_declaration = new_declaration;
+ this.original_declaration = original_declaration;
+ }
+
+ @Override
+ public String toString ()
+ {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append(origin.get_context().toString());
+ sb.append("Declaration for ");
+ sb.append(original_declaration.get_type_name());
+ sb.append(" '");
+ sb.append(original_declaration.get_name());
+ sb.append("' at ");
+ sb.append(origin.get_location().toString());
+ sb.append(" conflicts with its declaration at ");
+ sb.append(original_declaration.get_origin().get_location().toString());
+ sb.append(".");
+ sb.append(System.lineSeparator());
+ sb.append("Previous declaration was ");
+ sb.append(original_declaration.toString());
+ sb.append(".");
+ sb.append(System.lineSeparator());
+ sb.append("New declaration is ");
+ sb.append(new_declaration.toString());
+ sb.append(".");
+
+ return sb.toString();
+ }
+}
diff --git a/src/core/src/tonkadur/fate/v1/error/TypeAlreadyDeclaredException.java b/src/core/src/tonkadur/fate/v1/error/DuplicateDeclarationException.java
index 4050d1e..066bbe6 100644
--- a/src/core/src/tonkadur/fate/v1/error/TypeAlreadyDeclaredException.java
+++ b/src/core/src/tonkadur/fate/v1/error/DuplicateDeclarationException.java
@@ -5,26 +5,26 @@ import tonkadur.error.ErrorLevel;
import tonkadur.parser.Origin;
import tonkadur.parser.ParsingError;
-import tonkadur.fate.v1.lang.Type;
+import tonkadur.fate.v1.lang.meta.DeclaredEntity;
-public class TypeAlreadyDeclaredException extends ParsingError
+public class DuplicateDeclarationException extends ParsingError
{
/***************************************************************************/
/**** MEMBERS **************************************************************/
/***************************************************************************/
- protected final Type original_type;
+ protected final DeclaredEntity original_declaration;
/***************************************************************************/
/**** PUBLIC ***************************************************************/
/***************************************************************************/
- public TypeAlreadyDeclaredException
+ public DuplicateDeclarationException
(
final Origin origin,
- final Type original_type
+ final DeclaredEntity original_declaration
)
{
super(ErrorLevel.WARNING, ErrorCategory.DUPLICATE_DECLARATION, origin);
- this.original_type = original_type;
+ this.original_declaration = original_declaration;
}
@Override
@@ -33,12 +33,14 @@ public class TypeAlreadyDeclaredException extends ParsingError
final StringBuilder sb = new StringBuilder();
sb.append(origin.get_context().toString());
- sb.append("Declaration for type '");
- sb.append(original_type.get_name());
+ sb.append("Declaration for ");
+ sb.append(original_declaration.get_type_name());
+ sb.append(" '");
+ sb.append(original_declaration.get_name());
sb.append("' at ");
sb.append(origin.get_location().toString());
sb.append(" when it was already declared at ");
- sb.append(original_type.get_origin().get_location().toString());
+ sb.append(original_declaration.get_origin().get_location().toString());
sb.append(".");
return sb.toString();
diff --git a/src/core/src/tonkadur/fate/v1/error/ErrorCategory.java b/src/core/src/tonkadur/fate/v1/error/ErrorCategory.java
index f56b6d5..ef1396e 100644
--- a/src/core/src/tonkadur/fate/v1/error/ErrorCategory.java
+++ b/src/core/src/tonkadur/fate/v1/error/ErrorCategory.java
@@ -4,7 +4,7 @@ class ErrorCategory extends tonkadur.error.ErrorCategory
{
public static final ErrorCategory DUPLICATE_DECLARATION;
public static final ErrorCategory CONFLICTING_DECLARATION;
- public static final ErrorCategory UNDECLARED;
+ public static final ErrorCategory MISSING_DECLARATION;
public static final ErrorCategory UNKNOWN_SEQUENCE;
public static final ErrorCategory INCORRECT_TYPE;
public static final ErrorCategory INCOMPATIBLE_TYPE;
@@ -13,7 +13,7 @@ class ErrorCategory extends tonkadur.error.ErrorCategory
{
DUPLICATE_DECLARATION = new ErrorCategory("duplicate_declaration");
CONFLICTING_DECLARATION = new ErrorCategory("conflicting_declaration");
- UNDECLARED = new ErrorCategory("undeclared");
+ MISSING_DECLARATION = new ErrorCategory("missing_declaration");
UNKNOWN_SEQUENCE = new ErrorCategory("unknown_sequence");
INCORRECT_TYPE = new ErrorCategory("incorrect_type");
INCOMPATIBLE_TYPE = new ErrorCategory("incompatible_type");
diff --git a/src/core/src/tonkadur/fate/v1/error/IncompatibleDeclarationException.java b/src/core/src/tonkadur/fate/v1/error/IncompatibleDeclarationException.java
new file mode 100644
index 0000000..582f593
--- /dev/null
+++ b/src/core/src/tonkadur/fate/v1/error/IncompatibleDeclarationException.java
@@ -0,0 +1,64 @@
+package tonkadur.fate.v1.error;
+
+import tonkadur.error.ErrorLevel;
+
+import tonkadur.parser.Origin;
+import tonkadur.parser.ParsingError;
+
+import tonkadur.fate.v1.lang.meta.DeclaredEntity;
+
+public class IncompatibleDeclarationException extends ParsingError
+{
+ /***************************************************************************/
+ /**** MEMBERS **************************************************************/
+ /***************************************************************************/
+ protected final DeclaredEntity new_declaration;
+ protected final DeclaredEntity original_declaration;
+
+ /***************************************************************************/
+ /**** PUBLIC ***************************************************************/
+ /***************************************************************************/
+ public IncompatibleDeclarationException
+ (
+ final DeclaredEntity new_declaration,
+ final DeclaredEntity original_declaration
+ )
+ {
+ super
+ (
+ ErrorLevel.ERROR,
+ ErrorCategory.CONFLICTING_DECLARATION,
+ new_declaration.get_origin()
+ );
+
+ this.new_declaration = new_declaration;
+ this.original_declaration = original_declaration;
+ }
+
+ @Override
+ public String toString ()
+ {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append(origin.get_context().toString());
+ sb.append("Declaration for ");
+ sb.append(original_declaration.get_type_name());
+ sb.append(" '");
+ sb.append(original_declaration.get_name());
+ sb.append("' at ");
+ sb.append(origin.get_location().toString());
+ sb.append(" is incompatible with its declaration at ");
+ sb.append(original_declaration.get_origin().get_location().toString());
+ sb.append(".");
+ sb.append(System.lineSeparator());
+ sb.append("Previous declaration was ");
+ sb.append(original_declaration.toString());
+ sb.append(".");
+ sb.append(System.lineSeparator());
+ sb.append("New declaration is ");
+ sb.append(new_declaration.toString());
+ sb.append(".");
+
+ return sb.toString();
+ }
+}
diff --git a/src/core/src/tonkadur/fate/v1/error/MissingDeclarationException.java b/src/core/src/tonkadur/fate/v1/error/MissingDeclarationException.java
new file mode 100644
index 0000000..f564fbe
--- /dev/null
+++ b/src/core/src/tonkadur/fate/v1/error/MissingDeclarationException.java
@@ -0,0 +1,47 @@
+package tonkadur.fate.v1.error;
+
+import tonkadur.error.ErrorLevel;
+
+import tonkadur.parser.Origin;
+import tonkadur.parser.ParsingError;
+
+public class MissingDeclarationException extends ParsingError
+{
+ /***************************************************************************/
+ /**** MEMBERS **************************************************************/
+ /***************************************************************************/
+ protected final String type_name;
+ protected final String name;
+
+ /***************************************************************************/
+ /**** PUBLIC ***************************************************************/
+ /***************************************************************************/
+ public MissingDeclarationException
+ (
+ final Origin origin,
+ final String type_name,
+ final String name
+ )
+ {
+ super(ErrorLevel.ERROR, ErrorCategory.MISSING_DECLARATION, origin);
+ this.type_name = type_name;
+ this.name = name;
+ }
+
+ @Override
+ public String toString ()
+ {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append(origin.get_context().toString());
+ sb.append("Unknown ");
+ sb.append(type_name);
+ sb.append(" '");
+ sb.append(name);
+ sb.append("' at ");
+ sb.append(origin.get_location().toString());
+ sb.append(".");
+
+ 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
new file mode 100644
index 0000000..38b3210
--- /dev/null
+++ b/src/core/src/tonkadur/fate/v1/lang/Event.java
@@ -0,0 +1,147 @@
+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 Event extends DeclaredEntity
+{
+ protected static final Event ANY;
+
+ static
+ {
+ ANY =
+ new Event
+ (
+ new Origin(new Context(""), Location.BASE_LANGUAGE),
+ new ArrayList<Type>(),
+ /*
+ * Use of a space necessary to avoid conflicting with a user created
+ * type.
+ */
+ "undetermined event"
+ );
+ }
+
+ public static Event value_on_missing ()
+ {
+ return ANY;
+ }
+
+ @Override
+ public /* static */ String get_type_name ()
+ {
+ return "Event";
+ }
+
+
+ /***************************************************************************/
+ /**** MEMBERS **************************************************************/
+ /***************************************************************************/
+ protected final List<Type> signature;
+
+ /***************************************************************************/
+ /**** PUBLIC ***************************************************************/
+ /***************************************************************************/
+
+ /**** Constructors *********************************************************/
+ public Event
+ (
+ final Origin origin,
+ final List<Type> signature,
+ final String name
+ )
+ {
+ super(origin, name);
+
+ this.signature = signature;
+ }
+
+ /**** Accessors ************************************************************/
+ public List<Type> get_signature ()
+ {
+ return signature;
+ }
+
+ /**** Misc. ****************************************************************/
+ @Override
+ public boolean is_incompatible_with_declaration (final DeclaredEntity de)
+ {
+ if (de instanceof Event)
+ {
+ final Event e;
+
+ e = (Event) de;
+
+ if (signature.size() == e.signature.size())
+ {
+ final List<Boolean> compatibility_result;
+
+ /*
+ * Basically, the events are compatible if, and only if, the old
+ * signature is as least as restrictive as the new one.
+ */
+ compatibility_result =
+ (
+ new Merge<Type,Type,Boolean>()
+ {
+ @Override
+ protected Boolean merge_fun (final Type a, final Type b)
+ {
+ return
+ new Boolean(a.is_incompatible_with_declaration(b));
+ }
+ }.merge(signature, e.signature)
+ );
+
+ return compatibility_result.contains(Boolean.TRUE);
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public String toString ()
+ {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append(name);
+
+ if (!signature.isEmpty())
+ {
+ boolean first_argument;
+
+ sb.append(": ");
+
+ first_argument = true;
+
+ for (final Type type: signature)
+ {
+ if (first_argument)
+ {
+ first_argument = false;
+ }
+ else
+ {
+ sb.append(" -> ");
+ }
+
+ sb.append(type.get_name());
+ }
+ }
+
+ return sb.toString();
+ }
+
+ /***************************************************************************/
+ /**** PROTECTED ************************************************************/
+ /***************************************************************************/
+}
diff --git a/src/core/src/tonkadur/fate/v1/lang/Type.java b/src/core/src/tonkadur/fate/v1/lang/Type.java
index 2990dc0..269e011 100644
--- a/src/core/src/tonkadur/fate/v1/lang/Type.java
+++ b/src/core/src/tonkadur/fate/v1/lang/Type.java
@@ -1,14 +1,44 @@
package tonkadur.fate.v1.lang;
+import tonkadur.parser.Context;
+import tonkadur.parser.Location;
import tonkadur.parser.Origin;
-public class Type
+import tonkadur.fate.v1.lang.meta.DeclaredEntity;
+
+public class Type extends DeclaredEntity
{
+ protected static final Type ANY;
+
+ static
+ {
+ ANY =
+ new Type
+ (
+ new Origin(new Context(""), Location.BASE_LANGUAGE),
+ null,
+ /*
+ * Use of a space necessary to avoid conflicting with a user created
+ * type.
+ */
+ "undetermined type"
+ );
+ }
+
+ public static Type value_on_missing ()
+ {
+ return ANY;
+ }
+
+ @Override
+ public /* static */ String get_type_name ()
+ {
+ return "Type";
+ }
+
/***************************************************************************/
/**** MEMBERS **************************************************************/
/***************************************************************************/
- protected final Origin origin;
- protected final String name;
protected final Type true_type;
protected final Type parent;
@@ -24,6 +54,8 @@ public class Type
final String name
)
{
+ super(origin, name);
+
if (parent == null)
{
true_type = this;
@@ -33,21 +65,10 @@ public class Type
true_type = parent.true_type;
}
- this.origin = origin;
this.parent = parent;
- this.name = name;
}
/**** Accessors ************************************************************/
- public String get_name ()
- {
- return name;
- }
-
- public Origin get_origin ()
- {
- return origin;
- }
public Type get_true_type ()
{
@@ -72,24 +93,22 @@ public class Type
/**** Misc. ****************************************************************/
@Override
- public boolean equals (final Object o)
+ public boolean is_incompatible_with_declaration (final DeclaredEntity de)
{
- if (o instanceof Type)
+ if (de instanceof Type)
{
final Type t;
- t = (Type) o;
+ t = (Type) de;
- return name.equals(t.name);
+ /*
+ * If the previous type cannot be used when the new one will do, the
+ * new declaration cannot safely stand.
+ */
+ return !can_be_used_as(t);
}
- return false;
- }
-
- @Override
- public int hashCode ()
- {
- return name.hashCode();
+ return true;
}
@Override
diff --git a/src/core/src/tonkadur/fate/v1/lang/World.java b/src/core/src/tonkadur/fate/v1/lang/World.java
index cd42f55..e6bf2d6 100644
--- a/src/core/src/tonkadur/fate/v1/lang/World.java
+++ b/src/core/src/tonkadur/fate/v1/lang/World.java
@@ -1,9 +1,14 @@
package tonkadur.fate.v1.lang;
-import tonkadur.fate.v1.error.EventAlreadyDeclaredException;
-import tonkadur.fate.v1.error.TypeAlreadyDeclaredException;
-import tonkadur.fate.v1.error.TextEffectAlreadyDeclaredException;
-import tonkadur.fate.v1.error.UnknownTypeException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+import tonkadur.parser.Context;
+import tonkadur.parser.Location;
+import tonkadur.parser.Origin;
+
+import tonkadur.fate.v1.lang.meta.DeclarationCollection;
public class World
{
@@ -11,12 +16,12 @@ public class World
/**** MEMBERS **************************************************************/
/***************************************************************************/
protected final Collection<String> loaded_files;
- protected final Map<String, Event> events;
- protected final Map<String, Macro> macros;
- protected final Map<String, Sequence> sequences;
- protected final Map<String, TextEffect> text_effects;
- protected final Map<String, Type> types;
- protected final Map<String, Variable> variables;
+ protected final DeclarationCollection<Event> event_collection;
+// protected final DeclarationCollection<Macro> macros;
+// protected final DeclarationCollection<Sequence> sequences;
+// protected final DeclarationCollection<TextEffect> text_effects;
+ protected final DeclarationCollection<Type> type_collection;
+// protected final DeclarationCollection<Variable> variables;
/***************************************************************************/
/**** PUBLIC ***************************************************************/
@@ -27,12 +32,14 @@ public class World
{
loaded_files = new HashSet<String>();
- events = new HashMap<String, Event>();
- macros = new HashMap<String, Macro>();
- sequences = new HashMap<String, Sequence>();
- text_effects = new HashMap<String, TextEffect>();
- types = new HashMap<String, Type>();
- variables = new HashMap<String, Variable>();
+ event_collection =
+ new DeclarationCollection<Event>(Event.value_on_missing());
+ //macros = new DeclarationCollection<Macro>();
+ //sequences = new DeclarationCollection<Sequence>();
+ //text_effects = new DeclarationCollection<TextEffect>();
+ type_collection =
+ new DeclarationCollection<Type>(Type.value_on_missing());
+ //variables = new DeclarationCollection<Variable>();
add_base_types();
}
@@ -41,7 +48,7 @@ public class World
/**** Loaded Files ****/
public Collection<String> get_loaded_files ()
{
- return loaded_files.clone();
+ return loaded_files;
}
public boolean has_loaded_file (final String name)
@@ -54,36 +61,14 @@ public class World
loaded_files.add(name);
}
- /**** Events ****/
- public Collection<Event> get_events ()
+ public DeclarationCollection<Type> types()
{
- return events.values();
+ return type_collection;
}
- public boolean has_event (final String name)
+ public DeclarationCollection<Event> events()
{
- return events.containsKey(name);
- }
-
- public void add_event
- (
- final Origin origin,
- final String name,
- final List<Type> parameter_types
- )
- throws EventAlreadyDeclaredException, UnknownTypeException
- {
- if (has_event(name))
- {
-
- }
- for (final Type t: parameter_types)
- {
- if (!has_type(t))
- {
- throw new UnknownTypeException()
- }
- }
+ return event_collection;
}
/**** Misc. ****************************************************************/
@@ -97,11 +82,20 @@ public class World
base = new Origin(new Context(""), Location.BASE_LANGUAGE);
- add_type(base, null, "dict");
- add_type(base, null, "float");
- add_type(base, null, "int");
- add_type(base, null, "list");
- add_type(base, null, "set");
- add_type(base, null, "string");
+ try
+ {
+ type_collection.add(new Type(base, null, "dict"));
+ type_collection.add(new Type(base, null, "float"));
+ type_collection.add(new Type(base, null, "int"));
+ type_collection.add(new Type(base, null, "list"));
+ type_collection.add(new Type(base, null, "set"));
+ type_collection.add(new Type(base, null, "string"));
+ }
+ catch (final Throwable t)
+ {
+ System.err.println("Unable to add base types:" + t.toString());
+ System.exit(-1);
+ }
+
}
}
diff --git a/src/core/src/tonkadur/fate/v1/lang/meta/DeclarationCollection.java b/src/core/src/tonkadur/fate/v1/lang/meta/DeclarationCollection.java
new file mode 100644
index 0000000..838d109
--- /dev/null
+++ b/src/core/src/tonkadur/fate/v1/lang/meta/DeclarationCollection.java
@@ -0,0 +1,119 @@
+package tonkadur.fate.v1.lang.meta;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import tonkadur.error.ErrorManager;
+
+import tonkadur.parser.Origin;
+
+import tonkadur.fate.v1.error.MissingDeclarationException;
+import tonkadur.fate.v1.error.DuplicateDeclarationException;
+import tonkadur.fate.v1.error.ConflictingDeclarationException;
+import tonkadur.fate.v1.error.IncompatibleDeclarationException;
+
+public class DeclarationCollection <Declared extends DeclaredEntity>
+{
+ protected final Map<String, Declared> collection;
+ protected final Declared value_on_missing;
+
+ public DeclarationCollection (final Declared value_on_missing)
+ {
+ collection = new HashMap<String, Declared>();
+ this.value_on_missing = value_on_missing;
+ }
+
+ public Collection<Declared> get_all ()
+ {
+ return collection.values();
+ }
+
+ public boolean has (final String name)
+ {
+ return collection.containsKey(name);
+ }
+
+ public void add (final Declared entity)
+ throws
+ DuplicateDeclarationException,
+ ConflictingDeclarationException,
+ IncompatibleDeclarationException
+ {
+ assert_entity_can_be_added(entity);
+ collection.put(entity.get_name(), entity);
+ }
+
+ public Declared get (final Origin call_origin, final String name)
+ throws MissingDeclarationException
+ {
+ final Declared result;
+
+ result = collection.get(name);
+
+ if (result == null)
+ {
+ ErrorManager.handle
+ (
+ new MissingDeclarationException
+ (
+ call_origin,
+ value_on_missing.get_type_name(),
+ name
+ )
+ );
+
+ return value_on_missing;
+ }
+
+ return result;
+ }
+
+ /***************************************************************************/
+ /**** PROTECTED ************************************************************/
+ /***************************************************************************/
+ protected void assert_entity_can_be_added (final Declared new_version)
+ throws
+ DuplicateDeclarationException,
+ ConflictingDeclarationException,
+ IncompatibleDeclarationException
+ {
+ final Declared previous_version;
+
+ previous_version = collection.get(new_version.get_name());
+
+ if (previous_version == null)
+ {
+ return;
+ }
+
+ ErrorManager.handle
+ (
+ new DuplicateDeclarationException
+ (
+ new_version.get_origin(),
+ previous_version
+ )
+ );
+
+ if (!previous_version.conflicts_with_declaration(new_version))
+ {
+ return;
+ }
+
+ ErrorManager.handle
+ (
+ new ConflictingDeclarationException(new_version, previous_version)
+ );
+
+ if (!previous_version.is_incompatible_with_declaration(new_version))
+ {
+ return;
+ }
+
+ ErrorManager.handle
+ (
+ new IncompatibleDeclarationException(new_version, previous_version)
+ );
+ }
+}
diff --git a/src/core/src/tonkadur/fate/v1/lang/meta/DeclaredEntity.java b/src/core/src/tonkadur/fate/v1/lang/meta/DeclaredEntity.java
new file mode 100644
index 0000000..5748391
--- /dev/null
+++ b/src/core/src/tonkadur/fate/v1/lang/meta/DeclaredEntity.java
@@ -0,0 +1,88 @@
+package tonkadur.fate.v1.lang.meta;
+
+import tonkadur.parser.Origin;
+
+public abstract class DeclaredEntity
+{
+ /***************************************************************************/
+ /**** STATIC ***************************************************************/
+ /***************************************************************************/
+ /* I wish it could be static, but it can't, because of Java limitations. */
+ public /* static */ String get_type_name ()
+ {
+ return "Declared Entity";
+ }
+
+ /***************************************************************************/
+ /**** MEMBERS **************************************************************/
+ /***************************************************************************/
+ protected final Origin origin;
+ protected final String name;
+
+ /***************************************************************************/
+ /**** PROTECTED ************************************************************/
+ /***************************************************************************/
+
+ /**** Constructors *********************************************************/
+ protected DeclaredEntity
+ (
+ final Origin origin,
+ final String name
+ )
+ {
+ this.origin = origin;
+ this.name = name;
+ }
+
+ /***************************************************************************/
+ /**** PUBLIC ***************************************************************/
+ /***************************************************************************/
+
+ /**** Accessors ************************************************************/
+ public String get_name ()
+ {
+ return name;
+ }
+
+ public Origin get_origin ()
+ {
+ return origin;
+ }
+
+ public boolean conflicts_with_declaration (final DeclaredEntity de)
+ {
+ return !equals(de);
+ }
+
+ public boolean is_incompatible_with_declaration (final DeclaredEntity de)
+ {
+ return !equals(de);
+ }
+
+ @Override
+ public boolean equals (final Object o)
+ {
+ if (o instanceof DeclaredEntity)
+ {
+ final DeclaredEntity de;
+
+ de = (DeclaredEntity) o;
+
+ return toString().equals(de.toString());
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode ()
+ {
+ return toString().hashCode();
+ }
+
+ @Override
+ public String toString ()
+ {
+ return name;
+ }
+}
diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
index 408d71d..273722f 100644
--- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
+++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
@@ -8,6 +8,8 @@ options
@header
{
package tonkadur.fate.v1.parser;
+
+ import tonkadur.fate.v1.lang.World;
}
@members
@@ -18,7 +20,7 @@ options
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
-fate_file:
+fate_file [World world]:
WS* FATE_VERSION_KW WORD L_PAREN WS*
(
(first_level_fate_instr|general_fate_instr)
diff --git a/src/core/src/tonkadur/functional/Merge.java b/src/core/src/tonkadur/functional/Merge.java
new file mode 100644
index 0000000..68bb0e7
--- /dev/null
+++ b/src/core/src/tonkadur/functional/Merge.java
@@ -0,0 +1,46 @@
+package tonkadur.functional;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * I am not a fan of how Java implemented functional programming, so here is
+ * some alternative.
+ **/
+
+public class Merge <Input0, Input1, Output>
+{
+ public List<Output> merge (final List<Input0> i0, final List<Input1> i1)
+ {
+ 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
+ (
+ merge_fun
+ (
+ it0.hasNext() ? it0.next() : null,
+ it1.hasNext() ? it1.next() : null
+ )
+ );
+ }
+
+ return output;
+ }
+
+ protected Output merge_fun (final Input0 i0, final Input1 i1)
+ {
+ return null;
+ }
+}