[vala/staging] vala: Allow unscoped enum values where possible



commit 33c91a04f758c89f0402994a6df894e6c2032def
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Sun Nov 19 20:17:07 2017 +0100

    vala: Allow unscoped enum values where possible
    
    If the scope for an enumeration value can be determined from current context
    it is possible to omit the enum's scope.
    
    Based on patch by Timo Kluck
    
    https://bugzilla.gnome.org/show_bug.cgi?id=666035

 tests/Makefile.am              |    1 +
 tests/enums/bug666035.vala     |   58 ++++++++++++++++++++++++++++++++++++++++
 vala/valabinaryexpression.vala |   18 ++++++++++++
 vala/valamemberaccess.vala     |   11 +++++++
 vala/valaswitchlabel.vala      |   16 ++++++++++-
 5 files changed, 103 insertions(+), 1 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 86bc2c4..c64a2cd 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -120,6 +120,7 @@ TESTS = \
        enums/enum_only.vala \
        enums/enums.vala \
        enums/flags.vala \
+       enums/bug666035.vala \
        enums/bug673879.vala \
        enums/bug763831.vala \
        enums/bug780050.vala \
diff --git a/tests/enums/bug666035.vala b/tests/enums/bug666035.vala
new file mode 100644
index 0000000..16c65d1
--- /dev/null
+++ b/tests/enums/bug666035.vala
@@ -0,0 +1,58 @@
+enum FooEnum {
+       FOO,
+       BAR,
+       MAM;
+}
+
+[Flags]
+enum FooFlag {
+       FOO = 1 << 0,
+       BAR = 1 << 1,
+       MAM = 1 << 2;
+}
+
+struct FooStruct {
+       public FooEnum f;
+}
+
+FooEnum takes_enum (FooEnum foo) {
+       return foo;
+}
+
+FooEnum gives_enum () {
+       return MAM;
+}
+
+FooFlag takes_flag (FooFlag foo) {
+       return foo;
+}
+
+FooFlag gives_flag () {
+       return MAM | BAR;
+}
+
+void main () {
+       if (takes_enum (BAR) == BAR)
+               return;
+
+       assert (takes_enum (BAR) == BAR);
+       //TODO assert (MAM == gives_enum ());
+
+       assert (takes_flag (BAR | MAM) == (BAR | MAM));
+       //TODO assert (FOO == takes_flag (BAR & MAM | FOO));
+       assert (gives_flag () == (BAR | MAM));
+
+       FooEnum[] foo_array = { FOO, BAR, FOO };
+       foo_array[1] = MAM;
+       assert (foo_array[1] == MAM);
+
+       FooStruct foo_struct = { BAR };
+       assert (foo_struct.f == BAR);
+
+       FooEnum foo_enum = BAR;
+       switch (foo_enum) {
+               default:
+               case FOO: assert (false); break;
+               case BAR: break;
+       }
+}
diff --git a/vala/valabinaryexpression.vala b/vala/valabinaryexpression.vala
index 19287da..afdc756 100644
--- a/vala/valabinaryexpression.vala
+++ b/vala/valabinaryexpression.vala
@@ -279,6 +279,24 @@ public class Vala.BinaryExpression : Expression {
                        return true;
                }
 
+               // enum-type inference
+               if (target_type != null && target_type.data_type is Enum
+                   && (operator == BinaryOperator.BITWISE_AND || operator == BinaryOperator.BITWISE_OR)) {
+                       left.target_type = target_type.copy ();
+                       right.target_type = target_type.copy ();
+               }
+               left.check (context);
+               if (left.value_type != null && left.value_type.data_type is Enum
+                   && (operator == BinaryOperator.EQUALITY || operator == BinaryOperator.INEQUALITY)) {
+                       right.target_type = left.value_type.copy ();
+               }
+               right.check (context);
+               if (right.value_type != null && right.value_type.data_type is Enum
+                   && (operator == BinaryOperator.EQUALITY || operator == BinaryOperator.INEQUALITY)) {
+                       left.target_type = right.value_type.copy ();
+                       //TODO bug 666035 -- re-check left how?
+               }
+
                if (!left.check (context) || !right.check (context)) {
                        /* if there were any errors in inner expressions, skip type check */
                        error = true;
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index c00f5fc..3014353 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -452,6 +452,17 @@ public class Vala.MemberAccess : Expression {
                        }
                }
 
+               // enum-type inference
+               if (symbol_reference == null && target_type != null && target_type.data_type is Enum) {
+                       var enum_type = (Enum) target_type.data_type;
+                       foreach (var val in enum_type.get_values ()) {
+                               if (member_name == val.name) {
+                                       symbol_reference = val;
+                                       break;
+                               }
+                       }
+               }
+
                if (symbol_reference == null) {
                        error = true;
 
diff --git a/vala/valaswitchlabel.vala b/vala/valaswitchlabel.vala
index 9468b0e..99fbb4a 100644
--- a/vala/valaswitchlabel.vala
+++ b/vala/valaswitchlabel.vala
@@ -69,9 +69,23 @@ public class Vala.SwitchLabel : CodeNode {
        
        public override bool check (CodeContext context) {
                if (expression != null) {
+                       var switch_statement = (SwitchStatement) section.parent_node;
+
+                       // enum-type inference
+                       var condition_target_type = switch_statement.expression.target_type;
+                       if (expression.symbol_reference == null && condition_target_type != null && 
condition_target_type.data_type is Enum) {
+                               var enum_type = (Enum) condition_target_type.data_type;
+                               foreach (var val in enum_type.get_values ()) {
+                                       if (expression.to_string () == val.name) {
+                                               expression.target_type = condition_target_type.copy ();
+                                               expression.symbol_reference = val;
+                                               break;
+                                       }
+                               }
+                       }
+
                        expression.check (context);
 
-                       var switch_statement = (SwitchStatement) section.parent_node;
                        if (!expression.is_constant ()) {
                                error = true;
                                Report.error (expression.source_reference, "Expression must be constant");


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]