]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Move invocation expression checking to InvocationExpression.check
authorJürg Billeter <j@bitron.ch>
Wed, 5 Nov 2008 22:03:37 +0000 (22:03 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Wed, 5 Nov 2008 22:03:37 +0000 (22:03 +0000)
2008-11-05  Jürg Billeter  <j@bitron.ch>

* vala/valainvocationexpression.vala:
* vala/valasemanticanalyzer.vala:

Move invocation expression checking to InvocationExpression.check

svn path=/trunk/; revision=1987

ChangeLog
vala/valainvocationexpression.vala
vala/valasemanticanalyzer.vala

index 7c17eb0fb71a21fb3c95a0bf423399ff32d0f911..3a82a0b4a12bfd45cb0e6da6b068dfc3c0505d81 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2008-11-05  Jürg Billeter  <j@bitron.ch>
+
+       * vala/valainvocationexpression.vala:
+       * vala/valasemanticanalyzer.vala:
+
+       Move invocation expression checking to InvocationExpression.check
+
 2008-11-05  Jürg Billeter  <j@bitron.ch>
 
        * vala/valamemberaccess.vala:
index 91873d5b86b0d8c008e460fef2bfba83645bc5cf..63fdab9c565fc26aa03e800d030a44030ea82d4a 100644 (file)
@@ -120,4 +120,306 @@ public class Vala.InvocationExpression : Expression {
        public override bool is_pure () {
                return false;
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               call.accept (analyzer);
+
+               if (call.error) {
+                       /* if method resolving didn't succeed, skip this check */
+                       error = true;
+                       return false;
+               }
+
+               if (call is MemberAccess) {
+                       var ma = (MemberAccess) call;
+                       if (ma.prototype_access) {
+                               error = true;
+                               Report.error (source_reference, "Access to instance member `%s' denied".printf (call.symbol_reference.get_full_name ()));
+                               return false;
+                       }
+               }
+
+               var mtype = call.value_type;
+
+               if (mtype is ObjectType) {
+                       // constructor chain-up
+                       var cm = analyzer.find_current_method () as CreationMethod;
+                       assert (cm != null);
+                       if (cm.chain_up) {
+                               error = true;
+                               Report.error (source_reference, "Multiple constructor calls in the same constructor are not permitted");
+                               return false;
+                       }
+                       cm.chain_up = true;
+               }
+
+               // check for struct construction
+               if (call is MemberAccess &&
+                   ((call.symbol_reference is CreationMethod
+                     && call.symbol_reference.parent_symbol is Struct)
+                    || call.symbol_reference is Struct)) {
+                       var struct_creation_expression = new ObjectCreationExpression ((MemberAccess) call, source_reference);
+                       struct_creation_expression.struct_creation = true;
+                       foreach (Expression arg in get_argument_list ()) {
+                               struct_creation_expression.add_argument (arg);
+                       }
+                       struct_creation_expression.target_type = target_type;
+                       analyzer.replaced_nodes.add (this);
+                       parent_node.replace_expression (this, struct_creation_expression);
+                       struct_creation_expression.accept (analyzer);
+                       return false;
+               } else if (call is MemberAccess
+                          && call.symbol_reference is CreationMethod) {
+                       // constructor chain-up
+                       var cm = analyzer.find_current_method () as CreationMethod;
+                       assert (cm != null);
+                       if (cm.chain_up) {
+                               error = true;
+                               Report.error (source_reference, "Multiple constructor calls in the same constructor are not permitted");
+                               return false;
+                       }
+                       cm.chain_up = true;
+               }
+
+               Gee.List<FormalParameter> params;
+
+               if (mtype != null && mtype.is_invokable ()) {
+                       params = mtype.get_parameters ();
+               } else {
+                       error = true;
+                       Report.error (source_reference, "invocation not supported in this context");
+                       return false;
+               }
+
+               Expression last_arg = null;
+
+               var args = get_argument_list ();
+               Iterator<Expression> arg_it = args.iterator ();
+               foreach (FormalParameter param in params) {
+                       if (param.ellipsis) {
+                               break;
+                       }
+
+                       if (arg_it.next ()) {
+                               Expression arg = arg_it.get ();
+
+                               /* store expected type for callback parameters */
+                               arg.target_type = param.parameter_type;
+
+                               // resolve generic type parameters
+                               var ma = call as MemberAccess;
+                               if (arg.target_type.type_parameter != null) {
+                                       if (ma != null && ma.inner != null) {
+                                               arg.target_type = analyzer.get_actual_type (ma.inner.value_type, ma.symbol_reference, arg.target_type, arg);
+                                               assert (arg.target_type != null);
+                                       }
+                               }
+
+                               last_arg = arg;
+                       }
+               }
+
+               // printf arguments
+               if (mtype is MethodType && ((MethodType) mtype).method_symbol.printf_format) {
+                       StringLiteral format_literal = null;
+                       if (last_arg != null) {
+                               // use last argument as format string
+                               format_literal = last_arg as StringLiteral;
+                       } else {
+                               // use instance as format string for string.printf (...)
+                               var ma = call as MemberAccess;
+                               if (ma != null) {
+                                       format_literal = ma.inner as StringLiteral;
+                               }
+                       }
+                       if (format_literal != null) {
+                               string format = format_literal.eval ();
+
+                               bool unsupported_format = false;
+
+                               weak string format_it = format;
+                               unichar c = format_it.get_char ();
+                               while (c != '\0') {
+                                       if (c != '%') {
+                                               format_it = format_it.next_char ();
+                                               c = format_it.get_char ();
+                                               continue;
+                                       }
+
+                                       format_it = format_it.next_char ();
+                                       c = format_it.get_char ();
+                                       // flags
+                                       while (c == '#' || c == '0' || c == '-' || c == ' ' || c == '+') {
+                                               format_it = format_it.next_char ();
+                                               c = format_it.get_char ();
+                                       }
+                                       // field width
+                                       while (c >= '0' && c <= '9') {
+                                               format_it = format_it.next_char ();
+                                               c = format_it.get_char ();
+                                       }
+                                       // precision
+                                       if (c == '.') {
+                                               format_it = format_it.next_char ();
+                                               c = format_it.get_char ();
+                                               while (c >= '0' && c <= '9') {
+                                                       format_it = format_it.next_char ();
+                                                       c = format_it.get_char ();
+                                               }
+                                       }
+                                       // length modifier
+                                       int length = 0;
+                                       if (c == 'h') {
+                                               length = -1;
+                                               format_it = format_it.next_char ();
+                                               c = format_it.get_char ();
+                                               if (c == 'h') {
+                                                       length = -2;
+                                                       format_it = format_it.next_char ();
+                                                       c = format_it.get_char ();
+                                               }
+                                       } else if (c == 'l') {
+                                               length = 1;
+                                               format_it = format_it.next_char ();
+                                               c = format_it.get_char ();
+                                       } else if (c == 'z') {
+                                               length = 2;
+                                               format_it = format_it.next_char ();
+                                               c = format_it.get_char ();
+                                       }
+                                       // conversion specifier
+                                       DataType param_type = null;
+                                       if (c == 'd' || c == 'i' || c == 'c') {
+                                               // integer
+                                               if (length == -2) {
+                                                       param_type = analyzer.int8_type;
+                                               } else if (length == -1) {
+                                                       param_type = analyzer.short_type;
+                                               } else if (length == 0) {
+                                                       param_type = analyzer.int_type;
+                                               } else if (length == 1) {
+                                                       param_type = analyzer.long_type;
+                                               } else if (length == 2) {
+                                                       param_type = analyzer.ssize_t_type;
+                                               }
+                                       } else if (c == 'o' || c == 'u' || c == 'x' || c == 'X') {
+                                               // unsigned integer
+                                               if (length == -2) {
+                                                       param_type = analyzer.uchar_type;
+                                               } else if (length == -1) {
+                                                       param_type = analyzer.ushort_type;
+                                               } else if (length == 0) {
+                                                       param_type = analyzer.uint_type;
+                                               } else if (length == 1) {
+                                                       param_type = analyzer.ulong_type;
+                                               } else if (length == 2) {
+                                                       param_type = analyzer.size_t_type;
+                                               }
+                                       } else if (c == 'e' || c == 'E' || c == 'f' || c == 'F'
+                                                  || c == 'g' || c == 'G' || c == 'a' || c == 'A') {
+                                               // double
+                                               param_type = analyzer.double_type;
+                                       } else if (c == 's') {
+                                               // string
+                                               param_type = analyzer.string_type;
+                                       } else if (c == 'p') {
+                                               // pointer
+                                               param_type = new PointerType (new VoidType ());
+                                       } else if (c == '%') {
+                                               // literal %
+                                       } else {
+                                               unsupported_format = true;
+                                               break;
+                                       }
+                                       if (c != '\0') {
+                                               format_it = format_it.next_char ();
+                                               c = format_it.get_char ();
+                                       }
+                                       if (param_type != null) {
+                                               if (arg_it.next ()) {
+                                                       Expression arg = arg_it.get ();
+
+                                                       arg.target_type = param_type;
+                                               } else {
+                                                       Report.error (source_reference, "Too few arguments for specified format");
+                                                       return false;
+                                               }
+                                       }
+                               }
+                               if (!unsupported_format && arg_it.next ()) {
+                                       Report.error (source_reference, "Too many arguments for specified format");
+                                       return false;
+                               }
+                       }
+               }
+
+               foreach (Expression arg in get_argument_list ()) {
+                       arg.accept (analyzer);
+               }
+
+               DataType ret_type;
+
+               ret_type = mtype.get_return_type ();
+               params = mtype.get_parameters ();
+
+               if (ret_type is VoidType) {
+                       // void return type
+                       if (!(parent_node is ExpressionStatement)
+                           && !(parent_node is ForStatement)
+                           && !(parent_node is YieldStatement)) {
+                               // A void method invocation can be in the initializer or
+                               // iterator of a for statement
+                               error = true;
+                               Report.error (source_reference, "invocation of void method not allowed as expression");
+                               return false;
+                       }
+               }
+
+               // resolve generic return values
+               var ma = call as MemberAccess;
+               if (ret_type.type_parameter != null) {
+                       if (ma != null && ma.inner != null) {
+                               ret_type = analyzer.get_actual_type (ma.inner.value_type, ma.symbol_reference, ret_type, this);
+                               if (ret_type == null) {
+                                       return false;
+                               }
+                       }
+               }
+               Gee.List<DataType> resolved_type_args = new ArrayList<DataType> ();
+               foreach (DataType type_arg in ret_type.get_type_arguments ()) {
+                       if (type_arg.type_parameter != null && ma != null && ma.inner != null) {
+                               resolved_type_args.add (analyzer.get_actual_type (ma.inner.value_type, ma.symbol_reference, type_arg, this));
+                       } else {
+                               resolved_type_args.add (type_arg);
+                       }
+               }
+               ret_type = ret_type.copy ();
+               ret_type.remove_all_type_arguments ();
+               foreach (DataType resolved_type_arg in resolved_type_args) {
+                       ret_type.add_type_argument (resolved_type_arg);
+               }
+
+               if (mtype is MethodType) {
+                       var m = ((MethodType) mtype).method_symbol;
+                       foreach (DataType error_type in m.get_error_types ()) {
+                               // ensure we can trace back which expression may throw errors of this type
+                               var call_error_type = error_type.copy ();
+                               call_error_type.source_reference = source_reference;
+
+                               add_error_type (call_error_type);
+                       }
+               }
+
+               value_type = ret_type;
+
+               analyzer.check_arguments (this, mtype, params, get_argument_list ());
+
+               return !error;
+       }
 }
index e63803687f931e989bb2e323c285e7630de29520..2fb5d635858eafe724332ea0d53027524cb1b180 100644 (file)
@@ -41,20 +41,20 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 
        public DataType bool_type;
        public DataType string_type;
-       DataType uchar_type;
-       DataType short_type;
-       DataType ushort_type;
-       DataType int_type;
-       DataType uint_type;
-       DataType long_type;
-       DataType ulong_type;
+       public DataType uchar_type;
+       public DataType short_type;
+       public DataType ushort_type;
+       public DataType int_type;
+       public DataType uint_type;
+       public DataType long_type;
+       public DataType ulong_type;
        public DataType size_t_type;
-       DataType ssize_t_type;
-       DataType int8_type;
-       DataType unichar_type;
-       DataType double_type;
-       DataType type_type;
-       Class object_type;
+       public DataType ssize_t_type;
+       public DataType int8_type;
+       public DataType unichar_type;
+       public DataType double_type;
+       public DataType type_type;
+       public Class object_type;
        public TypeSymbol initially_unowned_type;
        DataType glist_type;
        DataType gslist_type;
@@ -69,7 +69,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 
        // keep replaced alive to make sure they remain valid
        // for the whole execution of CodeNode.accept
-       Gee.List<CodeNode> replaced_nodes = new ArrayList<CodeNode> ();
+       public Gee.List<CodeNode> replaced_nodes = new ArrayList<CodeNode> ();
 
        public SemanticAnalyzer () {
        }
@@ -1550,297 +1550,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
 
        public override void visit_invocation_expression (InvocationExpression expr) {
-               expr.call.accept (this);
-
-               if (expr.call.error) {
-                       /* if method resolving didn't succeed, skip this check */
-                       expr.error = true;
-                       return;
-               }
-
-               if (expr.call is MemberAccess) {
-                       var ma = (MemberAccess) expr.call;
-                       if (ma.prototype_access) {
-                               expr.error = true;
-                               Report.error (expr.source_reference, "Access to instance member `%s' denied".printf (expr.call.symbol_reference.get_full_name ()));
-                               return;
-                       }
-               }
-
-               var mtype = expr.call.value_type;
-
-               if (mtype is ObjectType) {
-                       // constructor chain-up
-                       var cm = find_current_method () as CreationMethod;
-                       assert (cm != null);
-                       if (cm.chain_up) {
-                               expr.error = true;
-                               Report.error (expr.source_reference, "Multiple constructor calls in the same constructor are not permitted");
-                               return;
-                       }
-                       cm.chain_up = true;
-               }
-
-               // check for struct construction
-               if (expr.call is MemberAccess &&
-                   ((expr.call.symbol_reference is CreationMethod
-                     && expr.call.symbol_reference.parent_symbol is Struct)
-                    || expr.call.symbol_reference is Struct)) {
-                       var struct_creation_expression = new ObjectCreationExpression ((MemberAccess) expr.call, expr.source_reference);
-                       struct_creation_expression.struct_creation = true;
-                       foreach (Expression arg in expr.get_argument_list ()) {
-                               struct_creation_expression.add_argument (arg);
-                       }
-                       struct_creation_expression.target_type = expr.target_type;
-                       replaced_nodes.add (expr);
-                       expr.parent_node.replace_expression (expr, struct_creation_expression);
-                       struct_creation_expression.accept (this);
-                       return;
-               } else if (expr.call is MemberAccess
-                          && expr.call.symbol_reference is CreationMethod) {
-                       // constructor chain-up
-                       var cm = find_current_method () as CreationMethod;
-                       assert (cm != null);
-                       if (cm.chain_up) {
-                               expr.error = true;
-                               Report.error (expr.source_reference, "Multiple constructor calls in the same constructor are not permitted");
-                               return;
-                       }
-                       cm.chain_up = true;
-               }
-
-               Gee.List<FormalParameter> params;
-
-               if (mtype != null && mtype.is_invokable ()) {
-                       params = mtype.get_parameters ();
-               } else {
-                       expr.error = true;
-                       Report.error (expr.source_reference, "invocation not supported in this context");
-                       return;
-               }
-
-               Expression last_arg = null;
-
-               var args = expr.get_argument_list ();
-               Iterator<Expression> arg_it = args.iterator ();
-               foreach (FormalParameter param in params) {
-                       if (param.ellipsis) {
-                               break;
-                       }
-
-                       if (arg_it.next ()) {
-                               Expression arg = arg_it.get ();
-
-                               /* store expected type for callback parameters */
-                               arg.target_type = param.parameter_type;
-
-                               // resolve generic type parameters
-                               var ma = expr.call as MemberAccess;
-                               if (arg.target_type.type_parameter != null) {
-                                       if (ma != null && ma.inner != null) {
-                                               arg.target_type = get_actual_type (ma.inner.value_type, ma.symbol_reference, arg.target_type, arg);
-                                               assert (arg.target_type != null);
-                                       }
-                               }
-
-                               last_arg = arg;
-                       }
-               }
-
-               // printf arguments
-               if (mtype is MethodType && ((MethodType) mtype).method_symbol.printf_format) {
-                       StringLiteral format_literal = null;
-                       if (last_arg != null) {
-                               // use last argument as format string
-                               format_literal = last_arg as StringLiteral;
-                       } else {
-                               // use instance as format string for string.printf (...)
-                               var ma = expr.call as MemberAccess;
-                               if (ma != null) {
-                                       format_literal = ma.inner as StringLiteral;
-                               }
-                       }
-                       if (format_literal != null) {
-                               string format = format_literal.eval ();
-
-                               bool unsupported_format = false;
-
-                               weak string format_it = format;
-                               unichar c = format_it.get_char ();
-                               while (c != '\0') {
-                                       if (c != '%') {
-                                               format_it = format_it.next_char ();
-                                               c = format_it.get_char ();
-                                               continue;
-                                       }
-
-                                       format_it = format_it.next_char ();
-                                       c = format_it.get_char ();
-                                       // flags
-                                       while (c == '#' || c == '0' || c == '-' || c == ' ' || c == '+') {
-                                               format_it = format_it.next_char ();
-                                               c = format_it.get_char ();
-                                       }
-                                       // field width
-                                       while (c >= '0' && c <= '9') {
-                                               format_it = format_it.next_char ();
-                                               c = format_it.get_char ();
-                                       }
-                                       // precision
-                                       if (c == '.') {
-                                               format_it = format_it.next_char ();
-                                               c = format_it.get_char ();
-                                               while (c >= '0' && c <= '9') {
-                                                       format_it = format_it.next_char ();
-                                                       c = format_it.get_char ();
-                                               }
-                                       }
-                                       // length modifier
-                                       int length = 0;
-                                       if (c == 'h') {
-                                               length = -1;
-                                               format_it = format_it.next_char ();
-                                               c = format_it.get_char ();
-                                               if (c == 'h') {
-                                                       length = -2;
-                                                       format_it = format_it.next_char ();
-                                                       c = format_it.get_char ();
-                                               }
-                                       } else if (c == 'l') {
-                                               length = 1;
-                                               format_it = format_it.next_char ();
-                                               c = format_it.get_char ();
-                                       } else if (c == 'z') {
-                                               length = 2;
-                                               format_it = format_it.next_char ();
-                                               c = format_it.get_char ();
-                                       }
-                                       // conversion specifier
-                                       DataType param_type = null;
-                                       if (c == 'd' || c == 'i' || c == 'c') {
-                                               // integer
-                                               if (length == -2) {
-                                                       param_type = int8_type;
-                                               } else if (length == -1) {
-                                                       param_type = short_type;
-                                               } else if (length == 0) {
-                                                       param_type = int_type;
-                                               } else if (length == 1) {
-                                                       param_type = long_type;
-                                               } else if (length == 2) {
-                                                       param_type = ssize_t_type;
-                                               }
-                                       } else if (c == 'o' || c == 'u' || c == 'x' || c == 'X') {
-                                               // unsigned integer
-                                               if (length == -2) {
-                                                       param_type = uchar_type;
-                                               } else if (length == -1) {
-                                                       param_type = ushort_type;
-                                               } else if (length == 0) {
-                                                       param_type = uint_type;
-                                               } else if (length == 1) {
-                                                       param_type = ulong_type;
-                                               } else if (length == 2) {
-                                                       param_type = size_t_type;
-                                               }
-                                       } else if (c == 'e' || c == 'E' || c == 'f' || c == 'F'
-                                                  || c == 'g' || c == 'G' || c == 'a' || c == 'A') {
-                                               // double
-                                               param_type = double_type;
-                                       } else if (c == 's') {
-                                               // string
-                                               param_type = string_type;
-                                       } else if (c == 'p') {
-                                               // pointer
-                                               param_type = new PointerType (new VoidType ());
-                                       } else if (c == '%') {
-                                               // literal %
-                                       } else {
-                                               unsupported_format = true;
-                                               break;
-                                       }
-                                       if (c != '\0') {
-                                               format_it = format_it.next_char ();
-                                               c = format_it.get_char ();
-                                       }
-                                       if (param_type != null) {
-                                               if (arg_it.next ()) {
-                                                       Expression arg = arg_it.get ();
-
-                                                       arg.target_type = param_type;
-                                               } else {
-                                                       Report.error (expr.source_reference, "Too few arguments for specified format");
-                                                       return;
-                                               }
-                                       }
-                               }
-                               if (!unsupported_format && arg_it.next ()) {
-                                       Report.error (expr.source_reference, "Too many arguments for specified format");
-                                       return;
-                               }
-                       }
-               }
-
-               foreach (Expression arg in expr.get_argument_list ()) {
-                       arg.accept (this);
-               }
-
-               DataType ret_type;
-
-               ret_type = mtype.get_return_type ();
-               params = mtype.get_parameters ();
-
-               if (ret_type is VoidType) {
-                       // void return type
-                       if (!(expr.parent_node is ExpressionStatement)
-                           && !(expr.parent_node is ForStatement)
-                           && !(expr.parent_node is YieldStatement)) {
-                               // A void method invocation can be in the initializer or
-                               // iterator of a for statement
-                               expr.error = true;
-                               Report.error (expr.source_reference, "invocation of void method not allowed as expression");
-                               return;
-                       }
-               }
-
-               // resolve generic return values
-               var ma = expr.call as MemberAccess;
-               if (ret_type.type_parameter != null) {
-                       if (ma != null && ma.inner != null) {
-                               ret_type = get_actual_type (ma.inner.value_type, ma.symbol_reference, ret_type, expr);
-                               if (ret_type == null) {
-                                       return;
-                               }
-                       }
-               }
-               Gee.List<DataType> resolved_type_args = new ArrayList<DataType> ();
-               foreach (DataType type_arg in ret_type.get_type_arguments ()) {
-                       if (type_arg.type_parameter != null && ma != null && ma.inner != null) {
-                               resolved_type_args.add (get_actual_type (ma.inner.value_type, ma.symbol_reference, type_arg, expr));
-                       } else {
-                               resolved_type_args.add (type_arg);
-                       }
-               }
-               ret_type = ret_type.copy ();
-               ret_type.remove_all_type_arguments ();
-               foreach (DataType resolved_type_arg in resolved_type_args) {
-                       ret_type.add_type_argument (resolved_type_arg);
-               }
-
-               if (mtype is MethodType) {
-                       var m = ((MethodType) mtype).method_symbol;
-                       foreach (DataType error_type in m.get_error_types ()) {
-                               // ensure we can trace back which expression may throw errors of this type
-                               var call_error_type = error_type.copy ();
-                               call_error_type.source_reference = expr.source_reference;
-
-                               expr.add_error_type (call_error_type);
-                       }
-               }
-
-               expr.value_type = ret_type;
-
-               check_arguments (expr, mtype, params, expr.get_argument_list ());
+               expr.check (this);
        }
 
        public bool check_arguments (Expression expr, DataType mtype, Gee.List<FormalParameter> params, Gee.List<Expression> args) {