From d4a3e6902cdd03726f78558870a0c48a7c39ebcf Mon Sep 17 00:00:00 2001 From: Juerg Billeter Date: Sat, 15 Dec 2007 07:20:51 +0000 Subject: [PATCH] move is_type_compatible method from SemanticAnalyzer to DataType 2007-12-15 Juerg Billeter * vala/valadatatype.vala, vala/valasemanticanalyzer.vala, vapi/glib-2.0.vapi: move is_type_compatible method from SemanticAnalyzer to DataType svn path=/trunk/; revision=771 --- ChangeLog | 6 +++ vala/valadatatype.vala | 77 +++++++++++++++++++++++++++ vala/valasemanticanalyzer.vala | 118 +++++++---------------------------------- vapi/glib-2.0.vapi | 1 + 4 files changed, 103 insertions(+), 99 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1d540ae..14a3cb6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2007-12-15 Jürg Billeter + + * vala/valadatatype.vala, vala/valasemanticanalyzer.vala, + vapi/glib-2.0.vapi: move is_type_compatible method from + SemanticAnalyzer to DataType + 2007-12-14 Jürg Billeter * vala/valadatatype.vala, vala/valasemanticanalyzer.vala, diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala index 648b738..3559c09 100644 --- a/vala/valadatatype.vala +++ b/vala/valadatatype.vala @@ -331,6 +331,83 @@ public class Vala.DataType : CodeNode { } } + public virtual bool compatible (DataType! target_type) { + if (target_type is DelegateType && this is DelegateType) { + return ((DelegateType) target_type).delegate_symbol == ((DelegateType) this).delegate_symbol; + } + + /* only null is compatible to null */ + if (target_type.data_type == null && target_type.type_parameter == null) { + return (data_type == null && target_type.type_parameter == null); + } + + if (data_type == null) { + /* null can be cast to any reference or array type or pointer type */ + if (target_type.type_parameter != null || + target_type.data_type.is_reference_type () || + target_type.is_out || + target_type.data_type is Pointer || + target_type.data_type is Array || + target_type.data_type is Callback || + target_type.data_type.get_attribute ("PointerType") != null) { + return true; + } + + /* null is not compatible with any other type (i.e. value types) */ + return false; + } + + if (target_type.data_type != null && target_type.data_type.get_attribute ("PointerType") != null) { + /* any reference or array type or pointer type can be cast to a generic pointer */ + if (type_parameter != null || + data_type.is_reference_type () || + data_type is Pointer || + data_type is Array || + data_type is Callback || + data_type.get_attribute ("PointerType") != null) { + return true; + } + + return false; + } + + /* temporarily ignore type parameters */ + if (target_type.type_parameter != null) { + return true; + } + + if (data_type is Array != target_type.data_type is Array) { + return false; + } + + if (data_type is Enum && target_type.data_type is Struct && ((Struct) target_type.data_type).is_integer_type ()) { + return true; + } + + if (data_type == target_type.data_type) { + return true; + } + + if (data_type is Struct && target_type.data_type is Struct) { + var expr_struct = (Struct) data_type; + var expect_struct = (Struct) target_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 data_type.is_subtype_of (target_type.data_type); + } + /** * Returns whether instances of this type are invokable. * diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala index db64109..2821e06 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -90,11 +90,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor { pointer_type = (Typesymbol) root_symbol.scope.lookup ("pointer"); int_type = new ValueType ((Typesymbol) root_symbol.scope.lookup ("int")); - uint_type = new ValueType ((Typesymbol) root_symbol.scope.lookup ("uint")); - ulong_type = new ValueType ((Typesymbol) root_symbol.scope.lookup ("ulong")); - unichar_type = new ValueType ((Typesymbol) root_symbol.scope.lookup ("unichar")); // TODO: don't require GLib namespace in semantic analyzer @@ -790,7 +787,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { error = true; continue; } - if (!is_type_compatible (e.static_type, child_type)) { + if (!e.static_type.compatible (child_type)) { error = true; e.error = true; Report.error (e.source_reference, "Expected initializer of type `%s' but got `%s'".printf (child_type.data_type.name, e.static_type.data_type.name)); @@ -822,7 +819,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } - if (stmt.condition.static_type.data_type != bool_type.data_type) { + if (!stmt.condition.static_type.compatible (bool_type)) { stmt.error = true; Report.error (stmt.condition.source_reference, "Condition must be boolean"); return; @@ -855,7 +852,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } - if (stmt.condition.static_type.data_type != bool_type.data_type) { + if (!stmt.condition.static_type.compatible (bool_type)) { stmt.error = true; Report.error (stmt.condition.source_reference, "Condition must be boolean"); return; @@ -869,7 +866,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } - if (stmt.condition.static_type.data_type != bool_type.data_type) { + if (!stmt.condition.static_type.compatible (bool_type)) { stmt.error = true; Report.error (stmt.condition.source_reference, "Condition must be boolean"); return; @@ -959,7 +956,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } if (stmt.return_expression != null && - !is_type_compatible (stmt.return_expression.static_type, current_return_type)) { + !stmt.return_expression.static_type.compatible (current_return_type)) { Report.error (stmt.source_reference, "Return: Cannot convert from `%s' to `%s'".printf (stmt.return_expression.static_type.to_string (), current_return_type.to_string ())); return; } @@ -1415,83 +1412,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor { current_source_file.add_symbol_dependency (expr.symbol_reference, SourceFileDependencyType.SOURCE); } - private bool is_type_compatible (DataType! expression_type, DataType! expected_type) { - if (expected_type is DelegateType && expression_type is DelegateType) { - return ((DelegateType) expected_type).delegate_symbol == ((DelegateType) expression_type).delegate_symbol; - } - - /* only null is compatible to null */ - if (expected_type.data_type == null && expected_type.type_parameter == null) { - return (expression_type.data_type == null && expected_type.type_parameter == null); - } - - if (expression_type.data_type == null) { - /* null can be cast to any reference or array type or pointer type */ - if (expected_type.type_parameter != null || - expected_type.data_type.is_reference_type () || - expected_type.is_out || - expected_type.data_type is Pointer || - expected_type.data_type is Array || - expected_type.data_type is Callback || - expected_type.data_type == pointer_type) { - return true; - } - - /* null is not compatible with any other type (i.e. value types) */ - return false; - } - - if (expected_type.data_type == pointer_type) { - /* any reference or array type or pointer type can be cast to a generic pointer */ - if (expression_type.type_parameter != null || - expression_type.data_type.is_reference_type () || - expression_type.data_type is Pointer || - expression_type.data_type is Array || - expression_type.data_type is Callback || - expression_type.data_type == pointer_type) { - return true; - } - - return false; - } - - /* temporarily ignore type parameters */ - if (expected_type.type_parameter != null) { - return true; - } - - if (expression_type.data_type is Array != expected_type.data_type is Array) { - return false; - } - - if (expression_type.data_type is Enum && expected_type.data_type == int_type.data_type) { - return true; - } - - if (expression_type.data_type == expected_type.data_type) { - 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); - } - public override void visit_invocation_expression (InvocationExpression! expr) { expr.call.accept (this); @@ -1552,7 +1472,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { ret_type = mtype.get_return_type (); params = mtype.get_parameters (); - if (ret_type.data_type == null && ret_type.type_parameter == null) { + if (ret_type is VoidType) { // void return type if (!(expr.parent_node is ExpressionStatement)) { expr.error = true; @@ -1628,7 +1548,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { Report.error (expr.source_reference, "Invalid type for argument %d".printf (i + 1)); return false; } - } else if (!is_type_compatible (arg.static_type, param.type_reference)) { + } else if (!arg.static_type.compatible (param.type_reference)) { expr.error = true; Report.error (expr.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.static_type.to_string (), param.type_reference.to_string ())); return false; @@ -1799,7 +1719,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { index_type = get_actual_type (expr.container.static_type, get_method, get_param.type_reference, expr); } - if (!is_type_compatible (index.static_type, index_type)) { + if (!index.static_type.compatible (index_type)) { expr.error = true; Report.error (expr.source_reference, "index expression: Cannot convert from `%s' to `%s'".printf (index.static_type.to_string (), index_type.to_string ())); return; @@ -1976,7 +1896,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { Iterator arg_it = expr.get_argument_list ().iterator (); arg_it.next (); var ex = arg_it.get (); - if (ex.static_type == null || !is_type_compatible (ex.static_type, string_type)) { + if (ex.static_type == null || !ex.static_type.compatible (string_type)) { expr.error = true; Report.error (expr.source_reference, "Invalid type for argument 1"); } @@ -2009,7 +1929,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } } - if (init.initializer.static_type == null || !is_type_compatible (init.initializer.static_type, member_type)) { + if (init.initializer.static_type == null || !init.initializer.static_type.compatible (member_type)) { expr.error = true; Report.error (init.source_reference, "Invalid type for member `%s'".printf (init.name)); return; @@ -2061,7 +1981,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { expr.static_type = expr.inner.static_type; } else if (expr.operator == UnaryOperator.LOGICAL_NEGATION) { // boolean type - if (expr.inner.static_type.data_type != bool_type.data_type) { + if (!expr.inner.static_type.compatible (bool_type)) { expr.error = true; Report.error (expr.source_reference, "Operator not supported for `%s'".printf (expr.inner.static_type.to_string ())); return; @@ -2319,8 +2239,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor { || expr.operator == BinaryOperator.INEQUALITY) { /* relational operation */ - if (!is_type_compatible (expr.right.static_type, expr.left.static_type) - && !is_type_compatible (expr.left.static_type, expr.right.static_type)) { + if (!expr.right.static_type.compatible (expr.left.static_type) + && !expr.left.static_type.compatible (expr.right.static_type)) { Report.error (expr.source_reference, "Equality operation: `%s' and `%s' are incompatible, comparison would always evaluate to false".printf (expr.right.static_type.to_string (), expr.left.static_type.to_string ())); expr.error = true; return; @@ -2347,7 +2267,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { expr.static_type = expr.left.static_type; } else if (expr.operator == BinaryOperator.AND || expr.operator == BinaryOperator.OR) { - if (expr.left.static_type.data_type != bool_type.data_type || expr.right.static_type.data_type != bool_type.data_type) { + if (!expr.left.static_type.compatible (bool_type) || !expr.right.static_type.compatible (bool_type)) { expr.error = true; Report.error (expr.source_reference, "Operands must be boolean"); } @@ -2465,8 +2385,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor { base_type.transfers_ownership = type.transfers_ownership; } else { if (base_type.data_type != type.data_type) { - if (is_type_compatible (type, base_type)) { - } else if (is_type_compatible (base_type, type)) { + if (type.compatible (base_type)) { + } else if (base_type.compatible (type)) { base_type.data_type = type.data_type; } else { base_type.error = true; @@ -2487,7 +2407,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } public override void visit_conditional_expression (ConditionalExpression! expr) { - if (expr.condition.static_type.data_type != bool_type.data_type) { + if (!expr.condition.static_type.compatible (bool_type)) { expr.error = true; Report.error (expr.condition.source_reference, "Condition must be boolean"); return; @@ -2771,7 +2691,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } } else if (a.left.static_type != null && a.right.static_type != null) { - if (!is_type_compatible (a.right.static_type, a.left.static_type)) { + if (!a.right.static_type.compatible (a.left.static_type)) { /* if there was an error on either side, * i.e. a.{left|right}.static_type == null, skip type check */ a.error = true; @@ -2798,7 +2718,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } else if (a.left is ElementAccess) { var ea = (ElementAccess) a.left; - if (!is_type_compatible (a.right.static_type, a.left.static_type)) { + if (!a.right.static_type.compatible (a.left.static_type)) { /* if there was an error on either side, * i.e. a.{left|right}.static_type == null, skip type check */ a.error = true; diff --git a/vapi/glib-2.0.vapi b/vapi/glib-2.0.vapi index 465cbad..2ffa53f 100644 --- a/vapi/glib-2.0.vapi +++ b/vapi/glib-2.0.vapi @@ -30,6 +30,7 @@ public struct bool { [SimpleType] [CCode (cname = "gpointer", cheader_filename = "glib.h", type_id = "G_TYPE_POINTER", marshaller_type_name = "POINTER", get_value_function = "g_value_get_pointer", set_value_function = "g_value_set_pointer", default_value = "NULL")] +[PointerType] public struct pointer { [CCode (cname ="GPOINTER_TO_INT")] public int to_int (); -- 2.7.4