summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java29
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/Cast.java170
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/Operation.java8
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/meta/DeclarationCollection.java2
-rw-r--r--src/core/src/tonkadur/fate/v1/parser/FateLexer.g45
-rw-r--r--src/core/src/tonkadur/fate/v1/parser/FateParser.g474
6 files changed, 257 insertions, 31 deletions
diff --git a/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java b/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java
index b79f293..d1827d3 100644
--- a/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java
+++ b/src/core/src/tonkadur/fate/v1/error/IncompatibleTypeException.java
@@ -14,6 +14,7 @@ public class IncompatibleTypeException extends ParsingError
/***************************************************************************/
protected final Type given_type;
protected final Type expected_type;
+ protected final Type hint;
/***************************************************************************/
/**** PUBLIC ***************************************************************/
@@ -34,6 +35,27 @@ public class IncompatibleTypeException extends ParsingError
this.given_type = given_type;
this.expected_type = expected_type;
+ this.hint = null;
+ }
+
+ public IncompatibleTypeException
+ (
+ final Origin call_origin,
+ final Type given_type,
+ final Type expected_type,
+ final Type hint
+ )
+ {
+ super
+ (
+ ErrorLevel.ERROR,
+ ErrorCategory.INCOMPATIBLE,
+ call_origin
+ );
+
+ this.given_type = given_type;
+ this.expected_type = expected_type;
+ this.hint = hint;
}
@Override
@@ -53,6 +75,13 @@ public class IncompatibleTypeException extends ParsingError
sb.append(expected_type.toString());
sb.append("').");
+ if (hint != null)
+ {
+ sb.append(System.lineSeparator());
+ sb.append("Recommended compatible type: ");
+ sb.append(hint.get_name());
+ }
+
return sb.toString();
}
}
diff --git a/src/core/src/tonkadur/fate/v1/lang/Cast.java b/src/core/src/tonkadur/fate/v1/lang/Cast.java
new file mode 100644
index 0000000..482d203
--- /dev/null
+++ b/src/core/src/tonkadur/fate/v1/lang/Cast.java
@@ -0,0 +1,170 @@
+package tonkadur.fate.v1.lang;
+
+import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Collections;
+
+import tonkadur.error.ErrorManager;
+
+import tonkadur.parser.Origin;
+
+import tonkadur.fate.v1.lang.meta.ValueNode;
+
+import tonkadur.fate.v1.error.IncompatibleTypeException;
+import tonkadur.fate.v1.error.IncomparableTypeException;
+
+public class Cast extends ValueNode
+{
+ protected static final Map<Type,Set<Type>> allowed_type_changes;
+
+ static
+ {
+ allowed_type_changes = new HashMap<Type,Set<Type>>();
+
+ allowed_type_changes.put
+ (
+ Type.INT,
+ Type.NUMBER_TYPES
+ );
+
+ allowed_type_changes.put
+ (
+ Type.FLOAT,
+ Type.NUMBER_TYPES
+ );
+
+ allowed_type_changes.put
+ (
+ Type.DICT,
+ Collections.emptySet()
+ );
+
+ allowed_type_changes.put
+ (
+ Type.SET,
+ Collections.emptySet()
+ );
+
+ allowed_type_changes.put
+ (
+ Type.LIST,
+ Collections.emptySet()
+ );
+
+ allowed_type_changes.put
+ (
+ Type.BOOLEAN,
+ Collections.emptySet()
+ );
+
+ allowed_type_changes.put
+ (
+ Type.ANY,
+ Collections.singleton(Type.ANY)
+ );
+
+ allowed_type_changes.put
+ (
+ Type.STRING,
+ Type.COLLECTION_COMPATIBLE_TYPES
+ );
+ }
+ /***************************************************************************/
+ /**** MEMBERS **************************************************************/
+ /***************************************************************************/
+ protected final ValueNode value;
+
+ /***************************************************************************/
+ /**** PROTECTED ************************************************************/
+ /***************************************************************************/
+ /**** Constructors *********************************************************/
+ protected Cast
+ (
+ final Origin origin,
+ final Type to,
+ final ValueNode value
+ )
+ {
+ super(origin, to);
+ this.value = value;
+ }
+
+ /***************************************************************************/
+ /**** PUBLIC ***************************************************************/
+ /***************************************************************************/
+ /**** Constructors *********************************************************/
+ public static Cast build
+ (
+ final Origin origin,
+ final Type to,
+ final ValueNode value
+ )
+ throws
+ IncompatibleTypeException,
+ IncomparableTypeException
+ {
+ final Type hint;
+
+ if
+ (
+ (value.get_type().can_be_used_as(to))
+ ||
+ (
+ (to.is_base_type())
+ &&
+ (
+ allowed_type_changes.get(to).contains
+ (
+ value.get_type().get_true_type()
+ )
+ )
+ )
+ )
+ {
+ return new Cast(origin, to, value);
+ }
+
+ hint = (Type) value.get_type().generate_comparable_to(to);
+
+ if (hint.equals(Type.ANY))
+ {
+ ErrorManager.handle
+ (
+ new IncompatibleTypeException(origin, value.get_type(), to)
+ );
+
+ ErrorManager.handle
+ (
+ new IncomparableTypeException(origin, value.get_type(), to)
+ );
+ }
+ else
+ {
+ ErrorManager.handle
+ (
+ new IncompatibleTypeException(origin, value.get_type(), to, hint)
+ );
+ }
+
+ return new Cast(origin, hint, value);
+ }
+
+ /**** Accessors ************************************************************/
+
+ /**** Misc. ****************************************************************/
+ @Override
+ public String toString ()
+ {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append(origin.toString());
+ sb.append("(Cast (");
+ sb.append(type.get_name());
+ sb.append(") ");
+ sb.append(value.toString());
+ sb.append(")");
+
+ return sb.toString();
+ }
+}
diff --git a/src/core/src/tonkadur/fate/v1/lang/Operation.java b/src/core/src/tonkadur/fate/v1/lang/Operation.java
index 4b05a68..d7efc6c 100644
--- a/src/core/src/tonkadur/fate/v1/lang/Operation.java
+++ b/src/core/src/tonkadur/fate/v1/lang/Operation.java
@@ -7,7 +7,7 @@ import tonkadur.error.ErrorManager;
import tonkadur.parser.Origin;
-import tonkadur.fate.v1.error.ConflictingTypeException;
+//import tonkadur.fate.v1.error.ConflictingTypeException;
import tonkadur.fate.v1.error.IncomparableTypeException;
import tonkadur.fate.v1.error.IncompatibleTypeException;
import tonkadur.fate.v1.error.InvalidArityException;
@@ -41,7 +41,7 @@ public class Operation extends ValueNode
final List<ValueNode> operands
)
throws
- ConflictingTypeException,
+ //ConflictingTypeException,
IncomparableTypeException,
IncompatibleTypeException,
InvalidArityException,
@@ -101,6 +101,8 @@ public class Operation extends ValueNode
);
}
+ /*
+
if (computed_type.equals(operand_type))
{
continue;
@@ -116,6 +118,8 @@ public class Operation extends ValueNode
)
);
+ */
+
if (operand_type.can_be_used_as(computed_type))
{
continue;
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 81767e9..376befe 100644
--- a/src/core/src/tonkadur/fate/v1/lang/meta/DeclarationCollection.java
+++ b/src/core/src/tonkadur/fate/v1/lang/meta/DeclarationCollection.java
@@ -160,7 +160,7 @@ public class DeclarationCollection <Declared extends DeclaredEntity>
System.exit(-1);
}
- if (new_version.equals(value_on_missing))
+ if (hint.equals(value_on_missing))
{
ErrorManager.handle
(
diff --git a/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4
index 6f03d0c..4240c1b 100644
--- a/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4
+++ b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4
@@ -13,7 +13,6 @@ L_PAREN: WS* '(';
R_PAREN: WS* ')';
ADD_KW: L_PAREN 'add' WS*;
-ADD_TO_ENUM_TYPE_KW: L_PAREN 'add_to_enum_type' WS*;
ADD_VARIABLE_ATTRIBUTE_KW: L_PAREN 'add_variable_attribute' WS*;
AND_KW: L_PAREN ('and'|'/\\') WS*;
ASSERT_KW: L_PAREN 'assert' WS*;
@@ -23,7 +22,6 @@ COND_KW: L_PAREN 'cond' WS*;
COUNT_KW: L_PAREN 'count' WS*;
DECLARE_ALIAS_TYPE_KW: L_PAREN 'declare_subtype' WS*;
DECLARE_DICT_TYPE_KW: L_PAREN 'declare_dict_type' WS*;
-DECLARE_ENUM_TYPE_KW: L_PAREN 'declare_enum_type' WS*;
DECLARE_EVENT_TYPE_KW: L_PAREN 'declare_event_type' WS*;
DECLARE_TEXT_EFFECT: L_PAREN 'declare_text_effect' WS*;
DECLARE_TEXT_EFFECT_KW: L_PAREN 'declare_text_effect' WS*;
@@ -36,6 +34,8 @@ EQUALS_KW: L_PAREN ('equals'|'='|'==') WS*;
EVENT_KW: L_PAREN 'event' WS*;
FALSE_KW: L_PAREN 'false)';
FATE_VERSION_KW: L_PAREN 'fate_version' WS*;
+GET_KW: L_PAREN 'get' WS*;
+SET_FIELD_KW: L_PAREN 'set_field' WS*;
GREATER_EQUAL_THAN_KW: L_PAREN ('greater_equal_than'|'>=') WS*;
GREATER_THAN_KW: L_PAREN ('greater_than'|'>') WS*;
IF_ELSE_KW: L_PAREN 'if_else' WS*;
@@ -57,6 +57,7 @@ POWER_KW: L_PAREN ('power'|'^'|'**') WS*;
RANDOM_KW: L_PAREN ('random'|'rand') WS*;
REMOVE_ALL_KW: L_PAREN 'remove_all' WS*;
REMOVE_ONE_KW: L_PAREN 'remove_one' WS*;
+REQUIRE_EXTENSION_KW: L_PAREN 'require_extension' WS*;
REQUIRE_KW: L_PAREN 'require' WS*;
SEQUENCE_KW: L_PAREN 'sequence' WS*;
SET_EXPRESSION_KW: L_PAREN 'set_expression' WS*;
diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
index ccc46db..2585948 100644
--- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
+++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
@@ -117,6 +117,10 @@ first_level_fate_instr:
{
}
+ | REQUIRE_EXTENSION_KW name=WORD R_PAREN
+ {
+ }
+
| DECLARE_ALIAS_TYPE_KW parent=WORD WS+ name=WORD R_PAREN
{
final Origin start_origin, parent_origin;
@@ -147,15 +151,19 @@ first_level_fate_instr:
{
}
- | DECLARE_ENUM_TYPE_KW name=WORD R_PAREN
+ | ADD_KW value WS+ value_reference R_PAREN
{
}
- | DECLARE_EVENT_TYPE_KW name=WORD WS+ word_list R_PAREN
+ | REMOVE_ONE_KW value WS+ value_reference R_PAREN
+ {
+ }
+
+ | REMOVE_ALL_KW value WS+ value_reference R_PAREN
{
}
- | ADD_TO_ENUM_TYPE_KW entry=WORD WS+ name=WORD R_PAREN
+ | DECLARE_EVENT_TYPE_KW name=WORD WS+ word_list R_PAREN
{
}
@@ -188,8 +196,13 @@ general_fate_instr:
{
}
+ | SET_FIELD_KW WORD WS+ value WS+ value_reference R_PAREN
+ {
+ }
+
| SET_EXPRESSION_KW value WS+ value_reference R_PAREN
{
+ /* that one isn't resolved until the value is referenced */
}
| EVENT_KW WORD WS+ value_list R_PAREN
@@ -609,20 +622,6 @@ catch [final Throwable e]
throw new ParseCancellationException(e);
}
-bag_expression:
- | ADD_KW value WS+ value_reference R_PAREN
- {
- }
-
- | REMOVE_ONE_KW value WS+ value_reference R_PAREN
- {
- }
-
- | REMOVE_ALL_KW value WS+ value_reference R_PAREN
- {
- }
-;
-
value
returns [ValueNode result]
:
@@ -677,24 +676,43 @@ returns [ValueNode result]
$result = ($math_expression.result);
}
- | CAST_KW WORD WORD value R_PAREN
+ | CAST_KW WORD value R_PAREN
{
- /* TODO */
- $result = null;
- }
+ final Origin target_type_origin;
+ final Type target_type;
- | value_reference
- {
- /* TODO */
- $result = null;
+ target_type_origin =
+ CONTEXT.get_origin_at
+ (
+ ($WORD.getLine()),
+ ($WORD.getCharPositionInLine())
+ );
+
+ target_type = WORLD.types().get(target_type_origin, ($WORD.text));
+
+ $result =
+ Cast.build
+ (
+ CONTEXT.get_origin_at
+ (
+ ($WORD.getLine()),
+ ($WORD.getCharPositionInLine())
+ ),
+ target_type,
+ ($value.result)
+ );
}
- | SET_KW value WS+ value_reference R_PAREN
+ | value_reference
{
/* TODO */
$result = null;
}
;
+catch [final Throwable e]
+{
+ throw new ParseCancellationException(e);
+}
value_reference:
VARIABLE_KW WORD R_PAREN
@@ -704,6 +722,10 @@ value_reference:
| PARAMETER_KW WORD R_PAREN
{
}
+
+ | GET_KW value_reference R_PAREN
+ {
+ }
;
value_cond_list: