use IntegerType, FloatingType, and rank attributes to analyze arithmetic
authorJürg Billeter <j@bitron.ch>
Sat, 2 Sep 2006 11:04:24 +0000 (11:04 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Sat, 2 Sep 2006 11:04:24 +0000 (11:04 +0000)
2006-09-02  Jürg Billeter  <j@bitron.ch>

* vala/valasemanticanalyzer.vala: use IntegerType, FloatingType, and
  rank attributes to analyze arithmetic operations
* vala/valacodegenerator.vala: generate C casts for explicit value-type
  casts
* vala/valastruct.vala: add is_integer_type, is_floating_type, and
  get_rank methods, add IntegerType and FloatingType attributes
* vala/valasemanticanalyzer.vala, vala/valacastexpression.vala,
  vala/valainstancecast.vala, ccode/valaccodecastexpression.vala: fix
  typos
* vapi/glib-2.0.vala: add int16, uint16, int32, uint32, use IntegerType
  and FloatingType attributes

svn path=/trunk/; revision=117

vala/ChangeLog
vala/ccode/valaccodecastexpression.vala
vala/vala/valacastexpression.vala
vala/vala/valacodegenerator.vala
vala/vala/valainstancecast.vala
vala/vala/valasemanticanalyzer.vala
vala/vala/valastruct.vala
vala/vapi/glib-2.0.vala

index a11a708..3c2ace7 100644 (file)
@@ -1,5 +1,19 @@
 2006-09-02  Jürg Billeter  <j@bitron.ch>
 
+       * vala/valasemanticanalyzer.vala: use IntegerType, FloatingType, and
+         rank attributes to analyze arithmetic operations
+       * vala/valacodegenerator.vala: generate C casts for explicit value-type
+         casts
+       * vala/valastruct.vala: add is_integer_type, is_floating_type, and
+         get_rank methods, add IntegerType and FloatingType attributes
+       * vala/valasemanticanalyzer.vala, vala/valacastexpression.vala,
+         vala/valainstancecast.vala, ccode/valaccodecastexpression.vala: fix
+         typos
+       * vapi/glib-2.0.vala: add int16, uint16, int32, uint32, use IntegerType
+         and FloatingType attributes
+
+2006-09-02  Jürg Billeter  <j@bitron.ch>
+
        * vala/parser.y: set accessibility for constants
        * vala/valasemanticanalyzer.vala: set return type in property set
          accessors to void
index 756e5c8..00b630a 100644 (file)
@@ -27,7 +27,7 @@ using GLib;
  */
 public class Vala.CCodeCastExpression : CCodeExpression {
        /**
-        * The expression to be casted.
+        * The expression to be cast.
         */
        public CCodeExpression! inner { get; set construct; }
        
index a41b873..d848262 100644 (file)
@@ -27,7 +27,7 @@ using GLib;
  */
 public class Vala.CastExpression : Expression {
        /**
-        * The expression to be casted.
+        * The expression to be cast.
         */
        public Expression! inner { get; set construct; }
        
@@ -39,7 +39,7 @@ public class Vala.CastExpression : Expression {
        /**
         * Creates a new cast expression.
         *
-        * @param inner expression to be casted
+        * @param inner expression to be cast
         * @param type  target type
         * @return      newly created cast expression
         */
index d70e001..eee2ac4 100644 (file)
@@ -1367,6 +1367,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                            && decl.initializer.static_type.data_type != null
                            && decl.type_reference.data_type.is_reference_type ()
                            && decl.initializer.static_type.data_type != decl.type_reference.data_type) {
+                               // FIXME: use C cast if debugging disabled
                                rhs = new InstanceCast (rhs, decl.type_reference.data_type);
                        }
                } else if (decl.type_reference.data_type != null && decl.type_reference.data_type.is_reference_type ()) {
@@ -1899,6 +1900,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                        if (f.instance) {
                                ref CCodeExpression typed_inst;
                                if (f.symbol.parent_symbol.node != base_type) {
+                                       // FIXME: use C cast if debugging disabled
                                        typed_inst = new CCodeFunctionCall (new CCodeIdentifier (((DataType) f.symbol.parent_symbol.node).get_upper_case_cname (null)));
                                        ((CCodeFunctionCall) typed_inst).add_argument (pub_inst);
                                } else {
@@ -1935,6 +1937,7 @@ public class Vala.CodeGenerator : CodeVisitor {
 
                                /* cast if necessary */
                                if (cl != base_type) {
+                                       // FIXME: use C cast if debugging disabled
                                        var ccast = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null)));
                                        ccast.add_argument (pub_inst);
                                        typed_pub_inst = ccast;
@@ -1999,6 +2002,7 @@ public class Vala.CodeGenerator : CodeVisitor {
 
                                /* cast if necessary */
                                if (cl != base_type) {
+                                       // FIXME: use C cast if debugging disabled
                                        var ccast = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null)));
                                        ccast.add_argument (pub_inst);
                                        typed_pub_inst = ccast;
@@ -2009,6 +2013,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                        } else {
                                var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
 
+                               // FIXME: use C cast if debugging disabled
                                var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT"));
                                ccast.add_argument (pub_inst);
                                ccall.add_argument (ccast);
@@ -2129,6 +2134,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                        }
                        
                        if (req_cast && ((DataType) m.symbol.parent_symbol.node).is_reference_type ()) {
+                               // FIXME: use C cast if debugging disabled
                                var ccall = new CCodeFunctionCall (new CCodeIdentifier (((DataType) base_method.symbol.parent_symbol.node).get_upper_case_cname (null)));
                                ccall.add_argument (instance);
                                instance = ccall;
@@ -2161,6 +2167,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                                                }
                                        }
                                        if (param.type_reference.data_type != arg.static_type.data_type) {
+                                               // FIXME: use C cast if debugging disabled
                                                var ccall = new CCodeFunctionCall (new CCodeIdentifier (param.type_reference.data_type.get_upper_case_cname (null)));
                                                ccall.add_argument (cexpr);
                                                cexpr = ccall;
@@ -2360,6 +2367,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                                            && param.type_reference.data_type.is_reference_type ()
                                            && arg.static_type.data_type != null
                                            && param.type_reference.data_type != arg.static_type.data_type) {
+                                               // FIXME: use C cast if debugging disabled
                                                var ccall = new CCodeFunctionCall (new CCodeIdentifier (param.type_reference.data_type.get_upper_case_cname (null)));
                                                ccall.add_argument (cexpr);
                                                cexpr = ccall;
@@ -2438,8 +2446,9 @@ public class Vala.CodeGenerator : CodeVisitor {
 
        public override void visit_cast_expression (CastExpression! expr) {
                if (expr.type_reference.data_type is Struct || expr.type_reference.data_type is Enum || expr.type_reference.data_type is Flags) {
-                       expr.ccodenode = expr.inner.ccodenode;
+                       expr.ccodenode = new CCodeCastExpression ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.get_cname ());
                } else {
+                       // GObject cast
                        expr.ccodenode = new InstanceCast ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.data_type);
                }
                
index 0c76417..7d1ec9b 100644 (file)
@@ -32,7 +32,7 @@ public class Vala.InstanceCast : CCodeFunctionCall {
        public DataType! type_reference { get; set construct; }
        
        /**
-        * The expression to be casted.
+        * The expression to be cast.
         */
        public CCodeExpression! inner { get; set construct; }
        
index 0eda76d..4f463c4 100644 (file)
@@ -783,7 +783,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        return (expression_type.data_type == null && expected_type.type_parameter == null);
                }
 
-               /* null can be casted to any reference or array type */
+               /* null can be cast to any reference or array type */
                if (expression_type.data_type == null &&
                    (expected_type.type_parameter != null ||
                     expected_type.data_type.is_reference_type () ||
@@ -807,54 +807,21 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        return true;
                }
                
-               /* int may be implicitly casted to long */
-               if (expression_type.data_type == root_symbol.lookup ("int").node && expected_type.data_type == root_symbol.lookup ("long").node) {
-                       return true;
-               }
-               
-               /* int may be implicitly casted to ulong */
-               if (expression_type.data_type == root_symbol.lookup ("int").node && expected_type.data_type == root_symbol.lookup ("ulong").node) {
-                       return true;
-               }
-               
-               /* uint may be implicitly casted to long */
-               if (expression_type.data_type == root_symbol.lookup ("uint").node && expected_type.data_type == root_symbol.lookup ("long").node) {
-                       return true;
-               }
-               
-               /* uint may be implicitly casted to ulong */
-               if (expression_type.data_type == root_symbol.lookup ("uint").node && expected_type.data_type == root_symbol.lookup ("ulong").node) {
-                       return true;
-               }
-               
-               /* int may be implicitly casted to uint */
-               if (expression_type.data_type == root_symbol.lookup ("int").node && expected_type.data_type == root_symbol.lookup ("uint").node) {
-                       return true;
-               }
-               
-               /* uint may be implicitly casted to int */
-               if (expression_type.data_type == root_symbol.lookup ("uint").node && expected_type.data_type == root_symbol.lookup ("int").node) {
-                       return true;
-               }
-               
-               /* long may be implicitly casted to ulong */
-               if (expression_type.data_type == root_symbol.lookup ("long").node && expected_type.data_type == root_symbol.lookup ("ulong").node) {
-                       return true;
-               }
-               
-               /* ulong may be implicitly casted to long */
-               if (expression_type.data_type == root_symbol.lookup ("ulong").node && expected_type.data_type == root_symbol.lookup ("long").node) {
-                       return true;
-               }
-               
-               /* int may be implicitly casted to double */
-               if (expression_type.data_type == root_symbol.lookup ("int").node && expected_type.data_type == root_symbol.lookup ("double").node) {
-                       return true;
-               }
-               
-               /* char may be implicitly casted to unichar */
-               if (expression_type.data_type == root_symbol.lookup ("char").node && expected_type.data_type == root_symbol.lookup ("unichar").node) {
-                       return true;
+               if (expression_type.data_type is Struct && expected_type.data_type is Struct) {
+                       var expr_struct = (Struct) expression_type.data_type;
+                       var expect_struct = (Struct) expected_type.data_type;
+
+                       /* integer types may be implicitly cast to floating point types */
+                       if (expr_struct.is_integer_type () && expect_struct.is_floating_type ()) {
+                               return true;
+                       }
+
+                       if ((expr_struct.is_integer_type () && expect_struct.is_integer_type ()) ||
+                           (expr_struct.is_floating_type () && expect_struct.is_floating_type ())) {
+                               if (expr_struct.get_rank () <= expect_struct.get_rank ()) {
+                                       return true;
+                               }
+                       }
                }
                
                return expression_type.data_type.is_subtype_of (expected_type.data_type);
@@ -1157,6 +1124,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        /* if type resolving didn't succeed, skip this check */
                        return;
                }
+               
+               // FIXME: check whether cast is allowed
        
                current_source_file.add_symbol_dependency (expr.type_reference.data_type.symbol, SourceFileDependencyType.SOURCE);
 
@@ -1172,6 +1141,38 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                return true;
        }
        
+       private ref TypeReference get_arithmetic_result_type (TypeReference! left_type, TypeReference! right_type) {
+                if (!(left_type.data_type is Struct) || !(right_type.data_type is Struct)) {
+                       // at least one operand not struct
+                       return null;
+                }
+                
+                var left = (Struct) left_type.data_type;
+                var right = (Struct) right_type.data_type;
+                
+                if ((!left.is_floating_type () && !left.is_integer_type ()) ||
+                    (!right.is_floating_type () && !right.is_integer_type ())) {
+                       // at least one operand not numeric
+                       return null;
+                }
+
+                if (left.is_floating_type () == right.is_floating_type ()) {
+                       // both operands integer or floating type
+                       if (left.get_rank () >= right.get_rank ()) {
+                               return left_type;
+                       } else {
+                               return right_type;
+                       }
+                } else {
+                       // one integer and one floating type operand
+                       if (left.is_floating_type ()) {
+                               return left_type;
+                       } else {
+                               return right_type;
+                       }
+                }
+       }
+       
        public override void visit_binary_expression (BinaryExpression! expr) {
                if (expr.left.error || expr.right.error) {
                        /* if there were any errors in inner expressions, skip type check */
@@ -1192,26 +1193,24 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                           || expr.operator == BinaryOperator.MINUS
                           || expr.operator == BinaryOperator.MUL
                           || expr.operator == BinaryOperator.DIV) {
-                       // TODO: check for integer or floating point type in expr.left
+                       expr.static_type = get_arithmetic_result_type (expr.left.static_type, expr.right.static_type);
 
-                       if (!check_binary_type (expr, "Arithmetic operation")) {
+                       if (expr.static_type == null) {
                                expr.error = true;
+                               Report.error (expr.source_reference, "Arithmetic operation not supported for types `%s' and `%s'".printf (expr.left.static_type.to_string (), expr.right.static_type.to_string ()));
                                return;
                        }
-
-                       expr.static_type = expr.left.static_type;
                } else if (expr.operator == BinaryOperator.MOD
                           || expr.operator == BinaryOperator.SHIFT_LEFT
                           || expr.operator == BinaryOperator.SHIFT_RIGHT
                           || expr.operator == BinaryOperator.BITWISE_XOR) {
-                       // TODO: check for integer type in expr.left
+                       expr.static_type = get_arithmetic_result_type (expr.left.static_type, expr.right.static_type);
 
-                       if (!check_binary_type (expr, "Arithmetic operation")) {
+                       if (expr.static_type == null) {
                                expr.error = true;
+                               Report.error (expr.source_reference, "Arithmetic operation not supported for types `%s' and `%s'".printf (expr.left.static_type.to_string (), expr.right.static_type.to_string ()));
                                return;
                        }
-
-                       expr.static_type = expr.left.static_type;
                } else if (expr.operator == BinaryOperator.LESS_THAN
                           || expr.operator == BinaryOperator.GREATER_THAN
                           || expr.operator == BinaryOperator.LESS_THAN_OR_EQUAL
index 1dc270c..3c52234 100644 (file)
@@ -26,21 +26,24 @@ using GLib;
  * Represents a struct declaration in the source code.
  */
 public class Vala.Struct : DataType {
-       List<TypeParameter> type_parameters;
-       List<Constant> constants;
-       List<Field> fields;
-       List<Method> methods;
+       private List<TypeParameter> type_parameters;
+       private List<Constant> constants;
+       private List<Field> fields;
+       private List<Method> methods;
 
        private List<TypeReference> base_types;
        
-       string cname;
-       string dup_function;
-       string free_function;
-       string type_id;
-       string lower_case_cprefix;
-       string lower_case_csuffix;
-       bool reference_type;
-       string marshaller_type_name;
+       private string cname;
+       private string dup_function;
+       private string free_function;
+       private string type_id;
+       private string lower_case_cprefix;
+       private string lower_case_csuffix;
+       private bool reference_type;
+       private bool integer_type;
+       private bool floating_type;
+       private int rank;
+       private string marshaller_type_name;
        
        /**
         * Specifies the default construction method.
@@ -183,6 +186,33 @@ public class Vala.Struct : DataType {
        }
        
        /**
+        * Returns whether this is an integer type.
+        *
+        * @return true if this is an integer type, false otherwise
+        */
+       public bool is_integer_type () {
+               return integer_type;
+       }
+       
+       /**
+        * Returns whether this is a floating point type.
+        *
+        * @return true if this is a floating point type, false otherwise
+        */
+       public bool is_floating_type () {
+               return floating_type;
+       }
+       
+       /**
+        * Returns the rank of this integer or floating point type.
+        *
+        * @return the rank if this is an integer or floating point type
+        */
+       public int get_rank () {
+               return rank;
+       }
+       
+       /**
         * Sets whether this data type has value or reference type semantics.
         *
         * @param ref_type true if this data type has reference type semantics
@@ -263,6 +293,36 @@ public class Vala.Struct : DataType {
                }
        }
        
+       private void process_integer_type_attribute (Attribute! a) {
+               integer_type = true;
+               foreach (NamedArgument arg in a.args) {
+                       if (arg.name == "rank") {
+                               /* this will already be checked during semantic analysis */
+                               if (arg.argument is LiteralExpression) {
+                                       var lit = ((LiteralExpression) arg.argument).literal;
+                                       if (lit is IntegerLiteral) {
+                                               rank = ((IntegerLiteral) lit).value.to_int ();
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       private void process_floating_type_attribute (Attribute! a) {
+               floating_type = true;
+               foreach (NamedArgument arg in a.args) {
+                       if (arg.name == "rank") {
+                               /* this will already be checked during semantic analysis */
+                               if (arg.argument is LiteralExpression) {
+                                       var lit = ((LiteralExpression) arg.argument).literal;
+                                       if (lit is IntegerLiteral) {
+                                               rank = ((IntegerLiteral) lit).value.to_int ();
+                                       }
+                               }
+                       }
+               }
+       }
+       
        /**
         * Process all associated attributes.
         */
@@ -272,6 +332,10 @@ public class Vala.Struct : DataType {
                                process_ccode_attribute (a);
                        } else if (a.name == "ReferenceType") {
                                process_ref_type_attribute (a);
+                       } else if (a.name == "IntegerType") {
+                               process_integer_type_attribute (a);
+                       } else if (a.name == "FloatingType") {
+                               process_floating_type_attribute (a);
                        }
                }
        }
index d4f3d76..d7e91b3 100644 (file)
@@ -29,6 +29,7 @@ public struct pointer {
 }
 
 [CCode (cheader_filename = "glib.h", type_id = "G_TYPE_CHAR", marshaller_type_name = "CHAR")]
+[IntegerType (rank = 1)]
 public struct char {
        [InstanceLast ()]
        [CCode (cname = "g_strdup_printf")]
@@ -36,6 +37,7 @@ public struct char {
 }
 
 [CCode (cname = "unsigned char", cheader_filename = "glib.h", type_id = "G_TYPE_UCHAR", marshaller_type_name = "UCHAR")]
+[IntegerType (rank = 2)]
 public struct uchar {
        [InstanceLast ()]
        [CCode (cname = "g_strdup_printf")]
@@ -43,6 +45,7 @@ public struct uchar {
 }
 
 [CCode (cheader_filename = "glib.h", type_id = "G_TYPE_INT", marshaller_type_name = "INT")]
+[IntegerType (rank = 7)]
 public struct int {
        [InstanceLast ()]
        [CCode (cname = "g_strdup_printf")]
@@ -50,6 +53,7 @@ public struct int {
 }
 
 [CCode (cname = "unsigned int", cheader_filename = "glib.h", type_id = "G_TYPE_UINT", marshaller_type_name = "UINT")]
+[IntegerType (rank = 8)]
 public struct uint {
        [InstanceLast ()]
        [CCode (cname = "g_strdup_printf")]
@@ -57,6 +61,7 @@ public struct uint {
 }
 
 [CCode (cheader_filename = "glib.h")]
+[IntegerType (rank = 3)]
 public struct short {
        [InstanceLast ()]
        [CCode (cname = "g_strdup_printf")]
@@ -64,6 +69,7 @@ public struct short {
 }
 
 [CCode (cname = "unsigned short", cheader_filename = "glib.h")]
+[IntegerType (rank = 4)]
 public struct ushort {
        [InstanceLast ()]
        [CCode (cname = "g_strdup_printf")]
@@ -71,6 +77,7 @@ public struct ushort {
 }
 
 [CCode (cheader_filename = "glib.h", type_id = "G_TYPE_LONG", marshaller_type_name = "LONG")]
+[IntegerType (rank = 12)]
 public struct long {
        [InstanceLast ()]
        [CCode (cname = "g_strdup_printf")]
@@ -78,29 +85,55 @@ public struct long {
 }
 
 [CCode (cname = "unsigned long", cheader_filename = "glib.h", type_id = "G_TYPE_ULONG", marshaller_type_name = "ULONG")]
+[IntegerType (rank = 13)]
 public struct ulong {
        [InstanceLast ()]
        [CCode (cname = "g_strdup_printf")]
        public ref string! to_string (string! format = "%lu");
 }
 
+[CCode (cname = "gint16", cheader_filename = "glib.h")]
+[IntegerType (rank = 5)]
+public struct int16 {
+}
+
+[CCode (cname = "guint16", cheader_filename = "glib.h")]
+[IntegerType (rank = 6)]
+public struct uint16 {
+}
+
+[CCode (cname = "gint32", cheader_filename = "glib.h")]
+[IntegerType (rank = 9)]
+public struct int32 {
+}
+
+[CCode (cname = "guint32", cheader_filename = "glib.h")]
+[IntegerType (rank = 10)]
+public struct uint32 {
+}
+
 [CCode (cname = "gint64", cheader_filename = "glib.h", type_id = "G_TYPE_INT64", marshaller_type_name = "INT64")]
+[IntegerType (rank = 14)]
 public struct int64 {
 }
 
 [CCode (cname = "guint64", cheader_filename = "glib.h", type_id = "G_TYPE_UINT64", marshaller_type_name = "UINT64")]
+[IntegerType (rank = 15)]
 public struct uint64 {
 }
 
 [CCode (cname = "float", cheader_filename = "glib.h", type_id = "G_TYPE_FLOAT", marshaller_type_name = "FLOAT")]
+[FloatingType (rank = 1)]
 public struct float {
 }
 
 [CCode (cname = "double", cheader_filename = "glib.h", type_id = "G_TYPE_DOUBLE", marshaller_type_name = "DOUBLE")]
+[FloatingType (rank = 2)]
 public struct double {
 }
 
 [CCode (cname = "gunichar", cheader_filename = "glib.h")]
+[IntegerType (rank = 11)]
 public struct unichar {
        [CCode (cname = "g_unichar_isalnum")]
        public bool isalnum ();