summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/computation/Cast.java2
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/computation/CondValue.java74
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/type/FutureType.java226
3 files changed, 300 insertions, 2 deletions
diff --git a/src/core/src/tonkadur/fate/v1/lang/computation/Cast.java b/src/core/src/tonkadur/fate/v1/lang/computation/Cast.java
index 8e283c9..a14bf27 100644
--- a/src/core/src/tonkadur/fate/v1/lang/computation/Cast.java
+++ b/src/core/src/tonkadur/fate/v1/lang/computation/Cast.java
@@ -107,6 +107,8 @@ public class Cast extends Computation
{
final Type hint;
+ value.expect_string();
+
if
(
(value.get_type().can_be_used_as(to))
diff --git a/src/core/src/tonkadur/fate/v1/lang/computation/CondValue.java b/src/core/src/tonkadur/fate/v1/lang/computation/CondValue.java
index 91f6b6b..cf4395d 100644
--- a/src/core/src/tonkadur/fate/v1/lang/computation/CondValue.java
+++ b/src/core/src/tonkadur/fate/v1/lang/computation/CondValue.java
@@ -49,13 +49,43 @@ public class CondValue extends Computation
{
Type hint;
- hint = branches.get(0).get_cdr().get_type();
+ hint = null;
for (final Cons<Computation, Computation> entry: branches)
{
+ if (entry.get_cdr().get_type().can_be_used_as(Type.STRING))
+ {
+ expect_string = 1;
+
+ hint = Type.STRING;
+
+ break;
+ }
+ else if (entry.get_cdr().get_type() != Type.ANY)
+ {
+ expect_string = 0;
+
+ hint = entry.get_cdr().get_type();
+
+ break;
+ }
+ }
+
+ for (final Cons<Computation, Computation> entry: branches)
+ {
+ entry.get_car().expect_non_string();
+
RecurrentChecks.assert_can_be_used_as(entry.get_car(), Type.BOOL);
- hint = RecurrentChecks.assert_can_be_used_as(entry.get_cdr(), hint);
+ if (hint != null)
+ {
+ hint = RecurrentChecks.assert_can_be_used_as(entry.get_cdr(), hint);
+ }
+ }
+
+ if (hint == null)
+ {
+ hint = new FutureType(origin, new ArrayList<Type>());
}
return new CondValue(origin, hint, branches);
@@ -63,6 +93,46 @@ public class CondValue extends Computation
/**** Accessors ************************************************************/
@Override
+ public void expect_non_string ()
+ {
+ if (get_type() instanceof FutureType)
+ {
+ Type hint;
+
+ hint = branches.get(0).get_cdr().expect_non_string();
+
+ for (final Cons<Computation, Computation> entry: branches)
+ {
+ entry.get_cdr().expect_non_string();
+
+ hint = RecurrentChecks.assert_can_be_used_as(entry.get_cdr(), hint);
+ }
+
+ ((FutureType) get_type()).resolve_to(hint);
+ }
+ }
+
+ @Override
+ public void expect_string ()
+ {
+ if (get_type() instanceof FutureType)
+ {
+ Type hint;
+
+ hint = branches.get(0).get_cdr().expect_string();
+
+ for (final Cons<Computation, Computation> entry: branches)
+ {
+ entry.get_cdr().expect_non_string();
+
+ hint = RecurrentChecks.assert_can_be_used_as(entry.get_cdr(), hint);
+ }
+
+ ((FutureType) get_type()).resolve_to(hint);
+ }
+ }
+
+ @Override
public void get_visited_by (final ComputationVisitor cv)
throws Throwable
{
diff --git a/src/core/src/tonkadur/fate/v1/lang/type/FutureType.java b/src/core/src/tonkadur/fate/v1/lang/type/FutureType.java
new file mode 100644
index 0000000..2eadd4f
--- /dev/null
+++ b/src/core/src/tonkadur/fate/v1/lang/type/FutureType.java
@@ -0,0 +1,226 @@
+package tonkadur.fate.v1.lang.type;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import tonkadur.error.ErrorManager;
+
+import tonkadur.parser.Context;
+import tonkadur.parser.Location;
+import tonkadur.parser.Origin;
+
+public class FutureType extends Type
+{
+ public static final Collection<FutureType> FUTURE_TYPES;
+
+ static
+ {
+ FUTURE_TYPES = new ArrayList<FutureType>();
+ }
+
+ /***************************************************************************/
+ /**** MEMBERS **************************************************************/
+ /***************************************************************************/
+ protected Type resolved_type;
+
+ protected void assert_is_resolved ()
+ {
+ if (resolved_type == null)
+ {
+ // TODO: proper error handling
+ //
+ System.err.println
+ (
+ "[F] Future Type from "
+ + get_origin().toString()
+ + " used prior to resolution."
+ );
+
+ System.exit(-1);
+ }
+ }
+
+ public static Collection<FutureType> get_unresolved_types ()
+ {
+ final Collection<FutureType> result;
+
+ result = new ArraList<FutureType>();
+
+ for (final FutureType t: FUTURE_TYPES)
+ {
+ if (t.resolved_type == null)
+ {
+ result.add(t);
+ }
+ }
+
+ return result;
+ }
+
+ /***************************************************************************/
+ /**** PUBLIC ***************************************************************/
+ /***************************************************************************/
+ public FutureType
+ (
+ final Origin origin,
+ final List<Type> parameters
+ )
+ {
+ super(origin, null, "Future Type", parameters);
+
+ FUTURE_TYPES.add(this);
+ }
+
+
+ /**** Accessors ************************************************************/
+ public Type get_base_type ()
+ {
+ assert_is_resolved();
+
+ return resolved_type.get_base_type();
+ }
+
+ public Type get_act_as_type ()
+ {
+ assert_is_resolved();
+
+ return resolved_type.get_act_as_type();
+ }
+
+ public boolean is_base_type ()
+ {
+ assert_is_resolved();
+
+ return resolved_type.is_base_type();
+ }
+
+ public Type try_merging_with (final Type t)
+ {
+ assert_is_resolved();
+
+ return resolved_type.try_merging_with(t);
+ }
+
+ /**** Compatibility ********************************************************/
+ public boolean can_be_used_as (final Type t)
+ {
+ assert_is_resolved();
+
+ return resolved_type.can_be_used_as(t);
+ }
+
+ @Override
+ public DeclaredEntity generate_comparable_to (final DeclaredEntity de)
+ {
+ assert_is_resolved();
+
+ return resolved_type.generate_comparable_to(de);
+ }
+
+
+ /**** Misc. ****************************************************************/
+ @Override
+ public Type generate_alias (final Origin origin, final String name)
+ {
+ // FutureType won't work as a stand in for non-basic types, since
+ // the casts performed on such classes won't be allowed.
+ final FutureType result;
+
+ result = new FutureType(origin, parameters);
+
+ result.resolve_to(this);
+
+ return result;
+ }
+
+ @Override
+ public boolean is_incompatible_with_declaration (final DeclaredEntity de)
+ {
+ assert_is_resolved();
+
+ return resolved_type.is_incompatible_with_declaration(de);
+ }
+
+ @Override
+ public String toString ()
+ {
+ if (resolved_type == null)
+ {
+ return "Unresolved Future Type";
+ }
+ else
+ {
+ return resolved_type.toString();
+ }
+ }
+
+ @Override
+ public Type generate_variant
+ (
+ final Origin origin,
+ final List<Type> parameters
+ )
+ throws Throwable
+ {
+ assert_is_resolved();
+
+ return resolved_type.generate_variant(parameters);
+ }
+
+ public Type get_resolved_type ()
+ {
+ if
+ (
+ (resolved_type != null)
+ && (resolved_type instanceof FutureType)
+ )
+ {
+ return ((FutureType) resolved_type).get_resolved_type();
+ }
+ else
+ {
+ return resolved_type;
+ }
+ }
+
+ public void resolve_to (final Type t)
+ {
+ if (resolved_type == null)
+ {
+ resolved_type = t;
+ }
+ }
+
+ /***************************************************************************/
+ /**** PROTECTED ************************************************************/
+ /***************************************************************************/
+ @Override
+ protected boolean this_or_parent_equals (final Type t)
+ {
+ assert_is_resolved();
+
+ return resolved_type.this_or_parent_equals(t);
+ }
+
+ @Override
+ protected List<Type> compute_full_type_chain ()
+ {
+ final List<Type> result;
+ Type t;
+
+ result = new ArrayList<Type>();
+
+ t = this;
+
+ while (t != null)
+ {
+ result.add(t);
+
+ t = t.parent;
+ }
+
+ Collections.reverse(result);
+
+ return result;
+ }
+}