| summaryrefslogtreecommitdiff |
diff options
| author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2020-07-19 17:58:58 +0200 |
|---|---|---|
| committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2020-07-19 17:58:58 +0200 |
| commit | 99171d9707c58c4f9841a00bf6fd22c4660a81e4 (patch) | |
| tree | 99c78e3efe7f2b8535ff9d52d457af5dbb44520b | |
| parent | bfb30cba47d4f1a0429799bd358d371c760c4245 (diff) | |
Adds/modifies references and macros.
18 files changed, 1023 insertions, 133 deletions
diff --git a/data/examples/the_thief/include/characters.fate b/data/examples/the_thief/include/characters.fate index 386d0de..37dea7d 100644 --- a/data/examples/the_thief/include/characters.fate +++ b/data/examples/the_thief/include/characters.fate @@ -11,48 +11,53 @@ (require include/locations.fate) (set_fields + (variable oscar) + (name Oscar) (agility 50) (perception 50) (money 20) (location room0) - (variable oscar) ) (set_fields + (variable carla) + (name Carla) (agility 75) (perception 35) (money 7) (location room1) - (variable carla) ) (set_fields + (variable simon) + (name Simon) (agility 35) (perception 75) (money 80) (location room1) - (variable simon) ) (set_fields + (variable julie) + (name Julie) (agility 60) (perception 60) (money 90) (location room2) - (variable julie) ) (set_fields + (variable statue) + (name ( A oddly human shaped statue, with clothes adorned )) (agility 0) (perception 0) (money 30) (location corridor) - (variable statue) ) ;; Alright, but we clearly need to be able to point to variables using a type. diff --git a/src/core/src/tonkadur/fate/v1/error/NotInAMacroException.java b/src/core/src/tonkadur/fate/v1/error/NotInAMacroException.java new file mode 100644 index 0000000..2bb1ed2 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/error/NotInAMacroException.java @@ -0,0 +1,41 @@ +package tonkadur.fate.v1.error; + +import tonkadur.error.ErrorLevel; + +import tonkadur.parser.Origin; +import tonkadur.parser.ParsingError; + +public class NotInAMacroException extends ParsingError +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + public NotInAMacroException (final Origin origin) + { + super + ( + ErrorLevel.ERROR, + ErrorCategory.INVALID_USE, + origin + ); + } + + @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("This can only be done/used in a macro."); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/error/UnknownExtensionContentException.java b/src/core/src/tonkadur/fate/v1/error/UnknownExtensionContentException.java new file mode 100644 index 0000000..350b1ee --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/error/UnknownExtensionContentException.java @@ -0,0 +1,50 @@ +package tonkadur.fate.v1.error; + +import tonkadur.error.ErrorLevel; + +import tonkadur.parser.Origin; +import tonkadur.parser.ParsingError; + +public class UnknownExtensionContentException extends ParsingError +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final String function_name; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + public UnknownExtensionContentException + ( + final Origin origin, + final String function_name + ) + { + super + ( + ErrorLevel.ERROR, + ErrorCategory.UNKNOWN, + origin + ); + + this.function_name = function_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 extension content '"); + sb.append(function_name); + sb.append("'. "); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/error/UnknownParameterException.java b/src/core/src/tonkadur/fate/v1/error/UnknownParameterException.java new file mode 100644 index 0000000..6e09bee --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/error/UnknownParameterException.java @@ -0,0 +1,68 @@ +package tonkadur.fate.v1.error; + +import tonkadur.error.ErrorLevel; + +import tonkadur.parser.Origin; +import tonkadur.parser.ParsingError; + +import tonkadur.fate.v1.lang.meta.TypedEntryList; + +public class UnknownParameterException extends ParsingError +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final TypedEntryList available_parameters; + protected final String parameter_name; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + public UnknownParameterException + ( + final Origin origin, + final String parameter_name, + final TypedEntryList available_parameters + ) + { + super + ( + ErrorLevel.ERROR, + ErrorCategory.UNKNOWN, + origin + ); + + this.parameter_name = parameter_name; + this.available_parameters = available_parameters; + } + + @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 parameter '"); + sb.append(parameter_name); + sb.append("'. "); + sb.append(System.lineSeparator()); + sb.append("Available parameters:'"); + + for + ( + final TypedEntryList.TypedEntry param: + available_parameters.get_entries() + ) + { + sb.append(System.lineSeparator()); + sb.append("- "); + sb.append(param.get_name()); + } + + 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 new file mode 100644 index 0000000..7834bfc --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/Macro.java @@ -0,0 +1,90 @@ +package tonkadur.fate.v1.lang; + +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; + +public class Macro extends DeclaredEntity +{ + @Override + public /* static */ String get_type_name () + { + return "Macro"; + } + + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final InstructionNode root; + protected final TypedEntryList parameters; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + + /**** Constructors *********************************************************/ + public Macro + ( + final Origin origin, + final InstructionNode root, + final TypedEntryList parameters, + final String name + ) + { + super(origin, name); + + this.root = root; + this.parameters = parameters; + } + + /**** Accessors ************************************************************/ + public TypedEntryList get_parameters () + { + return parameters; + } + + public InstructionNode get_root () + { + return root; + } + + /**** Compatibility ********************************************************/ + + /* + * 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) + { + return null; + } + + + /**** Misc. ****************************************************************/ + @Override + public boolean is_incompatible_with_declaration (final DeclaredEntity de) + { + return true; + } + + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append("(Macro "); + sb.append(name); + sb.append(")"); + + return sb.toString(); + } + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ +} diff --git a/src/core/src/tonkadur/fate/v1/lang/World.java b/src/core/src/tonkadur/fate/v1/lang/World.java index 930d84d..3afd60a 100644 --- a/src/core/src/tonkadur/fate/v1/lang/World.java +++ b/src/core/src/tonkadur/fate/v1/lang/World.java @@ -17,6 +17,8 @@ import tonkadur.parser.Origin; import tonkadur.fate.v1.error.UnknownSequenceException; import tonkadur.fate.v1.lang.meta.DeclarationCollection; +import tonkadur.fate.v1.lang.meta.ExtensionInstruction; +import tonkadur.fate.v1.lang.meta.ExtensionValueNode; import tonkadur.fate.v1.lang.meta.InstructionNode; import tonkadur.fate.v1.lang.type.Type; @@ -30,9 +32,13 @@ public class World protected final Set<String> required_extensions; protected final Map<String, List<Origin>> sequence_calls; + protected final Map<String, ExtensionValueNode> extension_value_nodes; + protected final Map<String, ExtensionInstruction> extension_instructions; + protected final Map<String, ExtensionInstruction> + extension_first_level_instructions; protected final DeclarationCollection<Event> event_collection; -// protected final DeclarationCollection<Macro> macros; + protected final DeclarationCollection<Macro> macro_collection; protected final DeclarationCollection<Sequence> sequence_collection; protected final DeclarationCollection<TextEffect> text_effect_collection; protected final DeclarationCollection<Type> type_collection; @@ -49,11 +55,16 @@ public class World { loaded_files = new HashSet<String>(); required_extensions = new HashSet<String>(); + sequence_calls = new HashMap<String, List<Origin>>(); + extension_value_nodes = new HashMap<String, ExtensionValueNode>(); + extension_instructions = new HashMap<String, ExtensionInstruction>(); + extension_first_level_instructions = + new HashMap<String, ExtensionInstruction>(); event_collection = new DeclarationCollection<Event>(Event.value_on_missing()); - //macros = new DeclarationCollection<Macro>(); + macro_collection = new DeclarationCollection<Macro>(null); sequence_collection = new DeclarationCollection<Sequence>(null); text_effect_collection = @@ -118,12 +129,37 @@ public class World list_of_calls.add(origin); } + /**** Extension Stuff ****/ + public Map<String, ExtensionInstruction> extension_instructions () + { + return extension_instructions; + } + + public Map<String, ExtensionInstruction> extension_first_level_instructions + ( + ) + { + return extension_first_level_instructions; + } + + public Map<String, ExtensionValueNode> extension_value_nodes + ( + ) + { + return extension_value_nodes; + } + /**** Collections ****/ public DeclarationCollection<Event> events () { return event_collection; } + public DeclarationCollection<Macro> macros () + { + return macro_collection; + } + public DeclarationCollection<Sequence> sequences () { return sequence_collection; diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/CondInstruction.java b/src/core/src/tonkadur/fate/v1/lang/instruction/CondInstruction.java index 71a6a69..0118ba1 100644 --- a/src/core/src/tonkadur/fate/v1/lang/instruction/CondInstruction.java +++ b/src/core/src/tonkadur/fate/v1/lang/instruction/CondInstruction.java @@ -51,7 +51,7 @@ public class CondInstruction extends InstructionNode { for (final Cons<ValueNode, InstructionNode> branch: branches) { - if (branch.get_car().get_type().get_base_type().equals(Type.BOOLEAN)) + if (!branch.get_car().get_type().get_base_type().equals(Type.BOOLEAN)) { ErrorManager.handle ( diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/SetValue.java b/src/core/src/tonkadur/fate/v1/lang/instruction/SetValue.java new file mode 100644 index 0000000..9b50b47 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/instruction/SetValue.java @@ -0,0 +1,123 @@ +package tonkadur.fate.v1.lang.instruction; + +import tonkadur.error.ErrorManager; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.error.ConflictingTypeException; +import tonkadur.fate.v1.error.IncomparableTypeException; +import tonkadur.fate.v1.error.InvalidTypeException; + +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.meta.InstructionNode; +import tonkadur.fate.v1.lang.meta.ValueNode; + +public class SetValue extends InstructionNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final ValueNode element; + protected final ValueNode value_reference; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + protected SetValue + ( + final Origin origin, + final ValueNode element, + final ValueNode value_reference + ) + { + super(origin); + + this.value_reference = value_reference; + this.element = element; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public static SetValue build + ( + final Origin origin, + final ValueNode element, + final ValueNode value_reference + ) + throws + InvalidTypeException, + ConflictingTypeException, + IncomparableTypeException + { + final Type hint; + final Type value_reference_type; + + value_reference_type = value_reference.get_type(); + + if (element.get_type().can_be_used_as(value_reference_type)) + { + return new SetValue(origin, element, value_reference); + } + + ErrorManager.handle + ( + new ConflictingTypeException + ( + element.get_origin(), + element.get_type(), + value_reference_type + ) + ); + + hint = + (Type) element.get_type().generate_comparable_to + ( + value_reference_type + ); + + if (hint.equals(Type.ANY)) + { + ErrorManager.handle + ( + new IncomparableTypeException + ( + element.get_origin(), + element.get_type(), + value_reference_type + ) + ); + } + + return new SetValue(origin, element, value_reference); + } + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(origin.toString()); + sb.append("(SetValue"); + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + + sb.append("element:"); + sb.append(System.lineSeparator()); + sb.append(element.toString()); + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + + sb.append("value_reference:"); + sb.append(System.lineSeparator()); + sb.append(value_reference.toString()); + + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/meta/ExtensionInstruction.java b/src/core/src/tonkadur/fate/v1/lang/meta/ExtensionInstruction.java new file mode 100644 index 0000000..349731f --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/meta/ExtensionInstruction.java @@ -0,0 +1,35 @@ +package tonkadur.fate.v1.lang.meta; + +import java.util.List; + +import tonkadur.parser.Context; +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.World; + +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.meta.InstructionNode; + +public class ExtensionInstruction extends InstructionNode +{ + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public ExtensionInstruction (final Origin origin) + { + super(origin); + } + + public ExtensionInstruction build + ( + final World world, + final Context context, + final Origin origin, + final List<InstructionNode> parameters + ) + { + return new ExtensionInstruction(Origin.BASE_LANGUAGE); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/meta/ExtensionValueNode.java b/src/core/src/tonkadur/fate/v1/lang/meta/ExtensionValueNode.java new file mode 100644 index 0000000..57addaf --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/meta/ExtensionValueNode.java @@ -0,0 +1,39 @@ +package tonkadur.fate.v1.lang.meta; + +import java.util.List; + +import tonkadur.parser.Context; +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.World; + +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.meta.ValueNode; + +public class ExtensionValueNode extends ValueNode +{ + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + protected ExtensionValueNode + ( + final Origin origin, + final Type result_type + ) + { + super(origin, result_type); + } + + public ExtensionValueNode build + ( + final World world, + final Context context, + final Origin origin, + final List<ValueNode> parameters + ) + { + return new ExtensionValueNode(Origin.BASE_LANGUAGE, Type.ANY); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/meta/Reference.java b/src/core/src/tonkadur/fate/v1/lang/meta/Reference.java new file mode 100644 index 0000000..285dac7 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/meta/Reference.java @@ -0,0 +1,48 @@ +package tonkadur.fate.v1.lang.meta; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.type.Type; + +public abstract class Reference extends ValueNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final String name; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + protected Reference (final Origin origin, final Type type, final String name) + { + super(origin, type); + + this.name = name; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Accessors ************************************************************/ + public String get_name () + { + return name; + } + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append("("); + sb.append(type.get_name()); + sb.append(" Reference "); + sb.append(name); + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/meta/TypedEntryList.java b/src/core/src/tonkadur/fate/v1/lang/meta/TypedEntryList.java index 7692e38..0002449 100644 --- a/src/core/src/tonkadur/fate/v1/lang/meta/TypedEntryList.java +++ b/src/core/src/tonkadur/fate/v1/lang/meta/TypedEntryList.java @@ -15,13 +15,13 @@ import tonkadur.fate.v1.lang.type.Type; public class TypedEntryList { - protected final Map<String, Origin> entry_origins; - protected final List<TypedEntry> entries; + protected final Map<String, TypedEntry> as_map; + protected final List<TypedEntry> as_list; public TypedEntryList () { - entry_origins = new HashMap<String, Origin>(); - entries = new ArrayList<TypedEntry>(); + as_map = new HashMap<String, TypedEntry>(); + as_list = new ArrayList<TypedEntry>(); } public void add @@ -32,25 +32,37 @@ public class TypedEntryList ) throws DuplicateFieldException { - final Origin previous_origin; + TypedEntry previous_entry; - previous_origin = entry_origins.get(name); + previous_entry = as_map.get(name); - if (previous_origin != null) + if (previous_entry != null) { ErrorManager.handle ( - new DuplicateFieldException(origin, previous_origin, name) + new DuplicateFieldException + ( + origin, + previous_entry.get_origin(), + name + ) ); } - entry_origins.put(name, origin); - entries.add(new TypedEntry(origin, type, name)); + previous_entry = new TypedEntry(origin, type, name); + + as_map.put(name, previous_entry); + as_list.add(previous_entry); } public List<TypedEntry> get_entries () { - return entries; + return as_list; + } + + public Map<String, TypedEntry> as_map () + { + return as_map; } public static class TypedEntry diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/AtReference.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/AtReference.java new file mode 100644 index 0000000..e483100 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/AtReference.java @@ -0,0 +1,101 @@ +package tonkadur.fate.v1.lang.valued_node; + +import java.util.Collections; + +import tonkadur.parser.Origin; + +import tonkadur.error.ErrorManager; + +import tonkadur.fate.v1.error.InvalidTypeException; +import tonkadur.fate.v1.error.UnknownDictionaryFieldException; + +import tonkadur.fate.v1.lang.Variable; + +import tonkadur.fate.v1.lang.meta.Reference; + +import tonkadur.fate.v1.lang.type.RefType; +import tonkadur.fate.v1.lang.type.Type; + +public class AtReference extends Reference +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final Reference parent; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + protected AtReference + ( + final Origin origin, + final Type reported_type, + final Reference parent + ) + { + super(origin, reported_type, ("(At " + parent.get_name() + ")")); + + this.parent = parent; + } + /**** Constructors *********************************************************/ + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public static AtReference build + ( + final Origin origin, + final Reference parent + ) + throws + InvalidTypeException + { + Type current_type; + + current_type = parent.get_type(); + + if (!(current_type instanceof RefType)) + { + ErrorManager.handle + ( + new InvalidTypeException + ( + origin, + current_type, + Collections.singleton(Type.REF), + parent.get_name() + ) + ); + + current_type = Type.ANY; + } + else + { + current_type = ((RefType) current_type).get_referenced_type(); + } + + return new AtReference(origin, current_type, parent); + } + + /**** Accessors ************************************************************/ + public Reference get_parent () + { + return parent; + } + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append("(AtReference ("); + sb.append(type.get_name()); + sb.append(") "); + sb.append(parent.get_name()); + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/VariableFieldReference.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/FieldReference.java index 17a99fa..70813d3 100644 --- a/src/core/src/tonkadur/fate/v1/lang/valued_node/VariableFieldReference.java +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/FieldReference.java @@ -1,6 +1,6 @@ package tonkadur.fate.v1.lang.valued_node; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import tonkadur.parser.Origin; @@ -10,97 +10,118 @@ import tonkadur.error.ErrorManager; import tonkadur.fate.v1.error.InvalidTypeException; import tonkadur.fate.v1.error.UnknownDictionaryFieldException; -import tonkadur.fate.v1.lang.Variable; - -import tonkadur.fate.v1.lang.meta.ValueNode; +import tonkadur.fate.v1.lang.meta.Reference; import tonkadur.fate.v1.lang.type.DictType; import tonkadur.fate.v1.lang.type.Type; -public class VariableFieldReference extends VariableReference +public class FieldReference extends Reference { /***************************************************************************/ /**** MEMBERS **************************************************************/ /***************************************************************************/ - final List<String> field_accesses; + protected final Reference parent; + protected final String field_name; /***************************************************************************/ /**** PROTECTED ************************************************************/ /***************************************************************************/ /**** Constructors *********************************************************/ - protected VariableFieldReference + protected FieldReference ( final Origin origin, - final Variable variable, + final Reference parent, final Type type, - final List<String> field_accesses + final String field_name ) { - super(origin, type, variable); + super(origin, type, (parent.get_name() + "." + field_name)); - this.field_accesses = field_accesses; + this.parent = parent; + this.field_name = field_name; } /***************************************************************************/ /**** PUBLIC ***************************************************************/ /***************************************************************************/ /**** Constructors *********************************************************/ - public static VariableFieldReference build + public static FieldReference build ( final Origin origin, - final Variable variable, - final List<String> field_accesses + Reference parent, + final String field ) throws InvalidTypeException, UnknownDictionaryFieldException { - final StringBuilder sb; Type current_type; - sb = new StringBuilder(); - - current_type = variable.get_type(); + current_type = parent.get_type(); - for (final String field_access: field_accesses) + if (current_type.get_base_type().equals(Type.REF)) { - sb.append("."); - sb.append(field_access); - - if (!(current_type instanceof DictType)) - { - ErrorManager.handle - ( - new InvalidTypeException - ( - origin, - current_type, - Arrays.asList(new Type[]{Type.DICT}), - (variable.get_name() + "." + sb.toString()) - ) - ); - - break; - } - - current_type = - ((DictType) current_type).get_field_type(origin, field_access); + parent = AtReference.build(origin, parent); + current_type = parent.get_type(); } - return - new VariableFieldReference + if (!(current_type instanceof DictType)) + { + ErrorManager.handle ( - origin, - variable, - current_type, - field_accesses + new InvalidTypeException + ( + origin, + current_type, + Collections.singleton(Type.DICT), + parent.get_name() + ) ); + + current_type = Type.ANY; + } + else + { + current_type = ((DictType) current_type).get_field_type(origin, field); + } + + return new FieldReference(origin, parent, current_type, field); + } + + public static FieldReference build + ( + final Origin origin, + Reference parent, + final List<String> field_sequence + ) + throws + InvalidTypeException, + UnknownDictionaryFieldException + { + for (final String field: field_sequence) + { + parent = build(origin, parent, field); + } + + if (parent instanceof FieldReference) + { + return (FieldReference) parent; + } + else + { + return null; + } } /**** Accessors ************************************************************/ - public List<String> get_field_accesses () + public String get_field_name () + { + return field_name; + } + + public Reference get_parent () { - return field_accesses; + return parent; } /**** Misc. ****************************************************************/ @@ -109,18 +130,10 @@ public class VariableFieldReference extends VariableReference { final StringBuilder sb = new StringBuilder(); - sb.append(origin.toString()); - sb.append("(VariableFieldReference ("); + sb.append("(FieldReference ("); sb.append(type.get_name()); sb.append(") "); - sb.append(variable.get_name()); - - for (final String field: field_accesses) - { - sb.append("."); - sb.append(field); - } - + sb.append(name); sb.append(")"); return sb.toString(); diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/ParameterReference.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/ParameterReference.java new file mode 100644 index 0000000..38e59ee --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/ParameterReference.java @@ -0,0 +1,44 @@ +package tonkadur.fate.v1.lang.valued_node; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.meta.Reference; + +import tonkadur.fate.v1.lang.type.Type; + +public class ParameterReference extends Reference +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public ParameterReference + ( + final Origin origin, + final Type reported_type, + final String parameter_name + ) + { + super(origin, reported_type, parameter_name); + } + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(origin.toString()); + sb.append("(ParameterReference ("); + sb.append(type.get_name()); + sb.append(") "); + sb.append(name); + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/valued_node/VariableReference.java b/src/core/src/tonkadur/fate/v1/lang/valued_node/VariableReference.java index 1423b31..18c2549 100644 --- a/src/core/src/tonkadur/fate/v1/lang/valued_node/VariableReference.java +++ b/src/core/src/tonkadur/fate/v1/lang/valued_node/VariableReference.java @@ -4,11 +4,11 @@ import tonkadur.parser.Origin; import tonkadur.fate.v1.lang.Variable; -import tonkadur.fate.v1.lang.meta.ValueNode; +import tonkadur.fate.v1.lang.meta.Reference; import tonkadur.fate.v1.lang.type.Type; -public class VariableReference extends ValueNode +public class VariableReference extends Reference { /***************************************************************************/ /**** MEMBERS **************************************************************/ @@ -25,7 +25,7 @@ public class VariableReference extends ValueNode final Variable variable ) { - super(origin, reported_type); + super(origin, reported_type, variable.get_name()); this.variable = variable; } /**** Constructors *********************************************************/ @@ -40,7 +40,7 @@ public class VariableReference extends ValueNode final Variable variable ) { - super(origin, variable.get_type()); + super(origin, variable.get_type(), variable.get_name()); this.variable = variable; } diff --git a/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 index 26350ec..8d6dd29 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 @@ -16,6 +16,7 @@ ADD_KW: L_PAREN 'add'; ADD_VARIABLE_ATTRIBUTE_KW: L_PAREN 'add_variable_attribute'; AND_KW: L_PAREN ('and'|'/\\'); ASSERT_KW: L_PAREN 'assert'; +AT_KW: L_PAREN 'at'; CAST_KW: L_PAREN 'cast'; CLEAR_KW: L_PAREN 'clear'; COND_KW: L_PAREN 'cond'; @@ -39,6 +40,7 @@ EXTENSION_INSTRUCTION_KW: L_PAREN '#'; EXTENSION_VALUE_KW: L_PAREN '$'; FALSE_KW: L_PAREN 'false)'; FATE_VERSION_KW: L_PAREN 'fate_version'; +FIELD_KW: L_PAREN 'field'; GREATER_EQUAL_THAN_KW: L_PAREN ('greater_equal_than'|'>='); GREATER_THAN_KW: L_PAREN ('greater_than'|'>'); IF_ELSE_KW: L_PAREN 'if_else'; diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 index 4778cc3..1efccd1 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 @@ -26,6 +26,9 @@ options import tonkadur.fate.v1.Utils; import tonkadur.fate.v1.error.IllegalReferenceNameException; + import tonkadur.fate.v1.error.NotInAMacroException; + import tonkadur.fate.v1.error.UnknownExtensionContentException; + import tonkadur.fate.v1.error.UnknownParameterException; import tonkadur.fate.v1.error.UnknownVariableScopeException; import tonkadur.fate.v1.lang.*; @@ -39,6 +42,7 @@ options { Context CONTEXT; World WORLD; + TypedEntryList PARAMETERS; } /******************************************************************************/ @@ -49,6 +53,7 @@ fate_file [Context context, World world] { CONTEXT = context; WORLD = world; + PARAMETERS = null; } : WS* FATE_VERSION_KW WS+ WORD WS* R_PAREN WS* @@ -424,29 +429,70 @@ first_level_fate_instr: WS+ new_reference_name WS* - L_PAREN WS+ typed_entry_list WS* R_PAREN + ( + L_PAREN WS+ typed_entry_list WS* R_PAREN + { + PARAMETERS=($typed_entry_list.result); + } + ) WS* general_fate_sequence WS* R_PAREN { - /* TODO */ + final Origin origin; + final Macro new_macro; + + PARAMETERS = null; + + origin = + CONTEXT.get_origin_at + ( + ($DEFINE_MACRO_KW.getLine()), + ($DEFINE_MACRO_KW.getCharPositionInLine()) + ); + + new_macro = + new Macro + ( + origin, + new InstructionList + ( + origin, + ($general_fate_sequence.result) + ), + ($typed_entry_list.result), + ($new_reference_name.result) + ); + + WORLD.macros().add(new_macro); } | EXTENSION_FIRST_LEVEL_KW WORD WS+ general_fate_sequence WS* R_PAREN { - /* TODO */ + final Origin origin; + final ExtensionInstruction instr; - /* Extension stuff */ - System.out.println("Using extension FLI " + ($WORD.text)); - } + origin = + CONTEXT.get_origin_at + ( + ($WORD.getLine()), + ($WORD.getCharPositionInLine()) + ); - | EXTENSION_FIRST_LEVEL_KW WORD WS* R_PAREN - { - /* TODO */ + instr = WORLD.extension_first_level_instructions().get(($WORD.text)); - /* Extension stuff */ - System.out.println("Using extension FLI " + ($WORD.text)); + if (instr == null) + { + ErrorManager.handle + ( + new UnknownExtensionContentException(origin, ($WORD.text)) + ); + } + else + { + instr.build(WORLD, CONTEXT, origin, ($general_fate_sequence.result)); + } } ; catch [final Throwable e] @@ -532,12 +578,20 @@ returns [InstructionNode result] | SET_KW WS+ value WS+ value_reference WS* R_PAREN { - /* TODO */ - - $result = null; + $result = + SetValue.build + ( + CONTEXT.get_origin_at + ( + ($SET_KW.getLine()), + ($SET_KW.getCharPositionInLine()) + ), + ($value.result), + ($value_reference.result) + ); } - | SET_FIELDS_KW WS+ field_value_list WS* value_reference WS* R_PAREN + | SET_FIELDS_KW WS+ value_reference WS * field_value_list WS* R_PAREN { /* TODO */ @@ -656,11 +710,36 @@ returns [InstructionNode result] | EXTENSION_INSTRUCTION_KW WORD WS+ general_fate_sequence WS* R_PAREN { - /* TODO */ + final Origin origin; + final ExtensionInstruction instr; - /* Extension stuff */ - System.out.println("Using extension instruction " + ($WORD.text)); - $result = null; + origin = + CONTEXT.get_origin_at + ( + ($WORD.getLine()), + ($WORD.getCharPositionInLine()) + ); + + instr = WORLD.extension_instructions().get(($WORD.text)); + + if (instr == null) + { + ErrorManager.handle + ( + new UnknownExtensionContentException(origin, ($WORD.text)) + ); + } + else + { + $result = + instr.build + ( + WORLD, + CONTEXT, + origin, + ($general_fate_sequence.result) + ); + } } | paragraph @@ -1611,18 +1690,38 @@ returns [ValueNode result] ); } - | EXTENSION_VALUE_KW WORD WS+ general_fate_sequence WS* R_PAREN + | EXTENSION_VALUE_KW WORD WS+ value_list WS* R_PAREN { - /* TODO */ - /* Extension stuff */ - System.out.println("Using extension value " + ($WORD.text)); - } + final Origin origin; + final ExtensionValueNode value; - | EXTENSION_VALUE_KW WORD WS* R_PAREN - { - /* TODO */ - /* Extension stuff */ - System.out.println("Using extension value " + ($WORD.text)); + origin = + CONTEXT.get_origin_at + ( + ($WORD.getLine()), + ($WORD.getCharPositionInLine()) + ); + + value = WORLD.extension_value_nodes().get(($WORD.text)); + + if (value == null) + { + ErrorManager.handle + ( + new UnknownExtensionContentException(origin, ($WORD.text)) + ); + } + else + { + $result = + value.build + ( + WORLD, + CONTEXT, + origin, + ($value_list.result) + ); + } } | value_reference @@ -1636,9 +1735,38 @@ catch [final Throwable e] } value_reference -returns [VariableReference result] +returns [Reference result] : - VARIABLE_KW WS+ WORD WS* R_PAREN + AT_KW WS+ value_reference WS* R_PAREN + { + $result = + AtReference.build + ( + CONTEXT.get_origin_at + ( + ($AT_KW.getLine()), + ($AT_KW.getCharPositionInLine()) + ), + ($value_reference.result) + ); + } + + | FIELD_KW WS+ value_reference WORD R_PAREN + { + $result = + FieldReference.build + ( + CONTEXT.get_origin_at + ( + ($FIELD_KW.getLine()), + ($FIELD_KW.getCharPositionInLine()) + ), + ($value_reference.result), + ($WORD.text) + ); + } + + | VARIABLE_KW WS+ WORD WS* R_PAREN { final Origin target_var_origin; final Variable target_var; @@ -1655,20 +1783,18 @@ returns [VariableReference result] target_var = WORLD.variables().get(target_var_origin, subrefs[0]); - if (subrefs.length == 1) - { - $result = - new VariableReference + $result = + new VariableReference + ( + CONTEXT.get_origin_at ( - CONTEXT.get_origin_at - ( - ($VARIABLE_KW.getLine()), - ($VARIABLE_KW.getCharPositionInLine()) - ), - target_var - ); - } - else + ($VARIABLE_KW.getLine()), + ($VARIABLE_KW.getCharPositionInLine()) + ), + target_var + ); + + if (subrefs.length > 1) { final List<String> subrefs_list; @@ -1677,14 +1803,10 @@ returns [VariableReference result] subrefs_list.remove(0); $result = - VariableFieldReference.build + FieldReference.build ( - CONTEXT.get_origin_at - ( - ($VARIABLE_KW.getLine()), - ($VARIABLE_KW.getCharPositionInLine()) - ), - target_var, + target_var_origin, + ($result), subrefs_list ); } @@ -1692,7 +1814,68 @@ returns [VariableReference result] | PARAMETER_KW WS+ WORD WS* R_PAREN { - $result = null; + final Origin origin; + + origin = + CONTEXT.get_origin_at + ( + ($PARAMETER_KW.getLine()), + ($PARAMETER_KW.getCharPositionInLine()) + ); + + if (PARAMETERS == null) + { + ErrorManager.handle + ( + new NotInAMacroException(origin) + ); + } + else + { + final TypedEntryList.TypedEntry param; + final String[] subrefs; + + subrefs = ($WORD.text).split("\\."); + + param = PARAMETERS.as_map().get(subrefs[0]); + + if (param == null) + { + ErrorManager.handle + ( + new UnknownParameterException(origin, subrefs[0], PARAMETERS) + ); + + $result = new ParameterReference(origin, Type.ANY, ($WORD.text)); + } + else + { + $result = + new ParameterReference + ( + origin, + param.get_type(), + ($WORD.text) + ); + + if (subrefs.length > 1) + { + final List<String> subrefs_list; + + subrefs_list = new ArrayList(Arrays.asList(subrefs)); + + subrefs_list.remove(0); + + $result = + FieldReference.build + ( + origin, + ($result), + subrefs_list + ); + } + } + } } ; catch [final Throwable e] |


