]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Move expression checking to code nodes
authorJürg Billeter <j@bitron.ch>
Mon, 10 Nov 2008 18:56:28 +0000 (18:56 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Mon, 10 Nov 2008 18:56:28 +0000 (18:56 +0000)
2008-11-10  Jürg Billeter  <j@bitron.ch>

* vala/valaaddressofexpression.vala:
* vala/valabaseaccess.vala:
* vala/valabooleanliteral.vala:
* vala/valacastexpression.vala:
* vala/valacharacterliteral.vala:
* vala/valaconditionalexpression.vala:
* vala/valaintegerliteral.vala:
* vala/valalambdaexpression.vala:
* vala/valanullliteral.vala:
* vala/valaobjectcreationexpression.vala:
* vala/valaparenthesizedexpression.vala:
* vala/valapointerindirection.vala:
* vala/valapostfixexpression.vala:
* vala/valarealliteral.vala:
* vala/valareferencetransferexpression.vala:
* vala/valasemanticanalyzer.vala:
* vala/valasizeofexpression.vala:
* vala/valastringliteral.vala:
* vala/valatypecheck.vala:
* vala/valatypeofexpression.vala:
* vala/valaunaryexpression.vala:

Move expression checking to code nodes

svn path=/trunk/; revision=2009

22 files changed:
ChangeLog
vala/valaaddressofexpression.vala
vala/valabaseaccess.vala
vala/valabooleanliteral.vala
vala/valacastexpression.vala
vala/valacharacterliteral.vala
vala/valaconditionalexpression.vala
vala/valaintegerliteral.vala
vala/valalambdaexpression.vala
vala/valanullliteral.vala
vala/valaobjectcreationexpression.vala
vala/valaparenthesizedexpression.vala
vala/valapointerindirection.vala
vala/valapostfixexpression.vala
vala/valarealliteral.vala
vala/valareferencetransferexpression.vala
vala/valasemanticanalyzer.vala
vala/valasizeofexpression.vala
vala/valastringliteral.vala
vala/valatypecheck.vala
vala/valatypeofexpression.vala
vala/valaunaryexpression.vala

index 0d7530e0e75e5bc476313525126fbbeb688353fa..b5b677a6460d4b3da57520589de9102b7a9eeab8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2008-11-10  Jürg Billeter  <j@bitron.ch>
+
+       * vala/valaaddressofexpression.vala:
+       * vala/valabaseaccess.vala:
+       * vala/valabooleanliteral.vala:
+       * vala/valacastexpression.vala:
+       * vala/valacharacterliteral.vala:
+       * vala/valaconditionalexpression.vala:
+       * vala/valaintegerliteral.vala:
+       * vala/valalambdaexpression.vala:
+       * vala/valanullliteral.vala:
+       * vala/valaobjectcreationexpression.vala:
+       * vala/valaparenthesizedexpression.vala:
+       * vala/valapointerindirection.vala:
+       * vala/valapostfixexpression.vala:
+       * vala/valarealliteral.vala:
+       * vala/valareferencetransferexpression.vala:
+       * vala/valasemanticanalyzer.vala:
+       * vala/valasizeofexpression.vala:
+       * vala/valastringliteral.vala:
+       * vala/valatypecheck.vala:
+       * vala/valatypeofexpression.vala:
+       * vala/valaunaryexpression.vala:
+
+       Move expression checking to code nodes
+
 2008-11-10  Jürg Billeter  <j@bitron.ch>
 
        * gobject/valadbusservermodule.vala:
index 1d1f714bcbafcb415fbf6968f6956816cf57e706..38781bb89329eef2008c2e0d8eaa2ab363f6c6a3 100644 (file)
@@ -1,6 +1,6 @@
 /* valaaddressofexpression.vala
  *
- * Copyright (C) 2007  Jürg Billeter
+ * Copyright (C) 2007-2008  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -69,4 +69,31 @@ public class Vala.AddressofExpression : Expression {
        public override bool is_pure () {
                return inner.is_pure ();
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               if (inner.error) {
+                       return false;
+               }
+               if (!(inner.value_type is ValueType
+                     || inner.value_type is ObjectType
+                     || inner.value_type is PointerType)) {
+                       error = true;
+                       Report.error (source_reference, "Address-of operator not supported for this expression");
+                       return false;
+               }
+
+               if (inner.value_type.is_reference_type_or_type_parameter ()) {
+                       value_type = new PointerType (new PointerType (inner.value_type));
+               } else {
+                       value_type = new PointerType (inner.value_type);
+               }
+
+               return !error;
+       }
 }
index 7c650b8edefda5e53f64025081dad1edeb4e25f9..1de0c7a7849928383edc627f8717d9e6644bdfda 100644 (file)
@@ -1,6 +1,6 @@
 /* valabaseaccess.vala
  *
- * Copyright (C) 2006-2007  Jürg Billeter
+ * Copyright (C) 2006-2008  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -20,7 +20,7 @@
  *     Jürg Billeter <j@bitron.ch>
  */
 
-using GLib;
+using Gee;
 
 /**
  * Represents an access to base class members in the source code.
@@ -49,4 +49,43 @@ public class Vala.BaseAccess : Expression {
        public override bool is_pure () {
                return true;
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               if (!analyzer.is_in_instance_method ()) {
+                       error = true;
+                       Report.error (source_reference, "Base access invalid outside of instance methods");
+                       return false;
+               }
+
+               if (analyzer.current_class == null) {
+                       if (analyzer.current_struct == null) {
+                               error = true;
+                               Report.error (source_reference, "Base access invalid outside of class and struct");
+                               return false;
+                       } else if (analyzer.current_struct.get_base_types ().size != 1) {
+                               error = true;
+                               Report.error (source_reference, "Base access invalid without base type %d".printf (analyzer.current_struct.get_base_types ().size));
+                               return false;
+                       }
+                       Iterator<DataType> base_type_it = analyzer.current_struct.get_base_types ().iterator ();
+                       base_type_it.next ();
+                       value_type = base_type_it.get ();
+               } else if (analyzer.current_class.base_class == null) {
+                       error = true;
+                       Report.error (source_reference, "Base access invalid without base class");
+                       return false;
+               } else {
+                       value_type = new ObjectType (analyzer.current_class.base_class);
+               }
+
+               symbol_reference = value_type.data_type;
+
+               return !error;
+       }
 }
index 24eb3fd9d9cab7e79e113c766a334bb6e0a4af7d..db05f0afde8789406ffbbe768b0deedc04a908db 100644 (file)
@@ -60,4 +60,16 @@ public class Vala.BooleanLiteral : Literal {
        public override bool is_pure () {
                return true;
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               value_type = analyzer.bool_type;
+
+               return !error;
+       }
 }
index 830ab68949d0b9f849e143aca7f93afa2bc6466e..5703815f6cb196f1e136ee69c13b73deb99dc614 100644 (file)
@@ -1,6 +1,6 @@
 /* valacastexpression.vala
  *
- * Copyright (C) 2006-2007  Jürg Billeter
+ * Copyright (C) 2006-2008  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -97,4 +97,28 @@ public class Vala.CastExpression : Expression {
                        type_reference = new_type;
                }
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               if (inner.error) {
+                       error = true;
+                       return false;
+               }
+
+               // FIXME: check whether cast is allowed
+
+               analyzer.current_source_file.add_type_dependency (type_reference, SourceFileDependencyType.SOURCE);
+
+               value_type = type_reference;
+               value_type.value_owned = inner.value_type.value_owned;
+
+               inner.target_type = inner.value_type.copy ();
+
+               return !error;
+       }
 }
index 422be4d4a85d0fb50bb9a7be7e09e9b1904573d2..019439fe7c99ab71dd67f96d9848702db2c8c171 100644 (file)
@@ -77,4 +77,16 @@ public class Vala.CharacterLiteral : Literal {
        public override bool is_pure () {
                return true;
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               value_type = new ValueType ((TypeSymbol) analyzer.root_symbol.scope.lookup ("char"));
+
+               return !error;
+       }
 }
index 59357259bb8dd25238ce5041935ab0dae733ca42..e0d6651810395d36995d41917c1e5b9d95097a15 100644 (file)
@@ -1,6 +1,6 @@
 /* valaconditionalexpression.vala
  *
- * Copyright (C) 2006  Jürg Billeter
+ * Copyright (C) 2006-2008  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -69,4 +69,35 @@ public class Vala.ConditionalExpression : Expression {
        public override bool is_pure () {
                return condition.is_pure () && true_expression.is_pure () && false_expression.is_pure ();
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               if (condition.error || false_expression.error || true_expression.error) {
+                       return false;
+               }
+
+               if (!condition.value_type.compatible (analyzer.bool_type)) {
+                       error = true;
+                       Report.error (condition.source_reference, "Condition must be boolean");
+                       return false;
+               }
+
+               /* FIXME: support memory management */
+               if (false_expression.value_type.compatible (true_expression.value_type)) {
+                       value_type = true_expression.value_type.copy ();
+               } else if (true_expression.value_type.compatible (false_expression.value_type)) {
+                       value_type = false_expression.value_type.copy ();
+               } else {
+                       error = true;
+                       Report.error (condition.source_reference, "Incompatible expressions");
+                       return false;
+               }
+
+               return !error;
+       }
 }
index 2a952b455d519a8811c43a35460d44f36f9b3813..73a2910de10c659bb63e44a65806ecb4ce7dd82c 100644 (file)
@@ -106,4 +106,16 @@ public class Vala.IntegerLiteral : Literal {
        public override bool is_pure () {
                return true;
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               value_type = new IntegerType ((TypeSymbol) analyzer.root_symbol.scope.lookup (get_type_name ()), value, get_type_name ());
+
+               return !error;
+       }
 }
index 9af274766770391df61d00c79729c14b59e1bdab..3cd074cfa7be6ac2fb3004fb97f5e590d5e5a2f9 100644 (file)
@@ -1,6 +1,6 @@
 /* valalambdaexpression.vala
  *
- * Copyright (C) 2006-2007  Jürg Billeter
+ * Copyright (C) 2006-2008  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -111,4 +111,88 @@ public class Vala.LambdaExpression : Expression {
        public override bool is_pure () {
                return false;
        }
+
+       string get_lambda_name (SemanticAnalyzer analyzer) {
+               var result = "__lambda%d".printf (analyzer.next_lambda_id);
+
+               analyzer.next_lambda_id++;
+
+               return result;
+       }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               if (!(target_type is DelegateType)) {
+                       error = true;
+                       Report.error (source_reference, "lambda expression not allowed in this context");
+                       return false;
+               }
+
+               bool in_instance_method = false;
+               var current_method = analyzer.find_current_method ();
+               if (current_method != null) {
+                       in_instance_method = (current_method.binding == MemberBinding.INSTANCE);
+               } else {
+                       in_instance_method = analyzer.is_in_constructor ();
+               }
+
+               var cb = (Delegate) ((DelegateType) target_type).delegate_symbol;
+               method = new Method (get_lambda_name (analyzer), cb.return_type);
+               if (!cb.has_target || !in_instance_method) {
+                       method.binding = MemberBinding.STATIC;
+               }
+               method.owner = analyzer.current_symbol.scope;
+
+               var lambda_params = get_parameters ();
+               Iterator<string> lambda_param_it = lambda_params.iterator ();
+               foreach (FormalParameter cb_param in cb.get_parameters ()) {
+                       if (!lambda_param_it.next ()) {
+                               /* lambda expressions are allowed to have less parameters */
+                               break;
+                       }
+
+                       string lambda_param = lambda_param_it.get ();
+
+                       var param = new FormalParameter (lambda_param, cb_param.parameter_type);
+
+                       method.add_parameter (param);
+               }
+
+               if (lambda_param_it.next ()) {
+                       /* lambda expressions may not expect more parameters */
+                       error = true;
+                       Report.error (source_reference, "lambda expression: too many parameters");
+                       return false;
+               }
+
+               if (expression_body != null) {
+                       var block = new Block (source_reference);
+                       block.scope.parent_scope = method.scope;
+
+                       if (method.return_type.data_type != null) {
+                               block.add_statement (new ReturnStatement (expression_body, source_reference));
+                       } else {
+                               block.add_statement (new ExpressionStatement (expression_body, source_reference));
+                       }
+
+                       method.body = block;
+               } else {
+                       method.body = statement_body;
+               }
+               method.body.owner = method.scope;
+
+               /* lambda expressions should be usable like MemberAccess of a method */
+               symbol_reference = method;
+
+               accept_children (analyzer);
+
+               value_type = new MethodType (method);
+
+               return !error;
+       }
 }
index 69321a890b799ca07fa9fe4ba7165deeb0067097..daa7145122821dd622a03276dde6f96550a9a6ce 100644 (file)
@@ -49,4 +49,16 @@ public class Vala.NullLiteral : Literal {
        public override bool is_pure () {
                return true;
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               value_type = new NullType (source_reference);
+
+               return !error;
+       }
 }
index 04b5f07d894031967a4daa90b3b9d14cbd299e12..c458c042aece6152343061e221d5ee39ea064832 100644 (file)
@@ -1,6 +1,6 @@
 /* valaobjectcreationexpression.vala
  *
- * Copyright (C) 2006-2007  Jürg Billeter
+ * Copyright (C) 2006-2008  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
index 2c2db7a333a4474bdac3aa46d65dae4d523edde4..c7e2dd5af57bd365c4a1a312ebe67a44f1269719 100644 (file)
@@ -72,4 +72,38 @@ public class Vala.ParenthesizedExpression : Expression {
        public override bool is_pure () {
                return inner.is_pure ();
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               inner.target_type = target_type;
+
+               accept_children (analyzer);
+
+               if (inner.error) {
+                       // ignore inner error
+                       error = true;
+                       return false;
+               }
+
+               if (inner.value_type == null) {
+                       // static type may be null for method references
+                       error = true;
+                       Report.error (inner.source_reference, "Invalid expression type");
+                       return false;
+               }
+
+               value_type = inner.value_type.copy ();
+               // don't call g_object_ref_sink on inner and outer expression
+               value_type.floating_reference = false;
+
+               // don't transform expression twice
+               inner.target_type = inner.value_type.copy ();
+
+               return !error;
+       }
 }
index 5606a3ca23f91d47ff3ee19a0e499dd35be7b4e8..7ea1354dd26fad68002cb8fc37e52345d9692880 100644 (file)
@@ -1,6 +1,6 @@
 /* valapointerindirection.vala
  *
- * Copyright (C) 2007  Jürg Billeter
+ * Copyright (C) 2007-2008  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -69,4 +69,36 @@ public class Vala.PointerIndirection : Expression {
        public override bool is_pure () {
                return inner.is_pure ();
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               if (inner.error) {
+                       return false;
+               }
+               if (inner.value_type == null) {
+                       error = true;
+                       Report.error (source_reference, "internal error: unknown type of inner expression");
+                       return false;
+               }
+               if (inner.value_type is PointerType) {
+                       var pointer_type = (PointerType) inner.value_type;
+                       if (pointer_type.base_type is ReferenceType) {
+                               error = true;
+                               Report.error (source_reference, "Pointer indirection not supported for this expression");
+                               return false;
+                       }
+                       value_type = pointer_type.base_type;
+               } else {
+                       error = true;
+                       Report.error (source_reference, "Pointer indirection not supported for this expression");
+                       return false;
+               }
+
+               return !error;
+       }
 }
index 9c5f13c11041a1d428336e934bea2f13f54aa20e..c1d8eba6fa8d04daec745fcf9a046d3f2bbb8db6 100644 (file)
@@ -1,6 +1,6 @@
 /* valapostfixexpression.vala
  *
- * Copyright (C) 2006-2007  Jürg Billeter
+ * Copyright (C) 2006-2008  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -61,4 +61,16 @@ public class Vala.PostfixExpression : Expression {
        public override bool is_pure () {
                return false;
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               value_type = inner.value_type;
+
+               return !error;
+       }
 }
index 562d8389d6398dea76bf5ca3fb49a19f43e6d622..19d598da888cbf632efd0545ac7f73164910f36a 100644 (file)
@@ -69,4 +69,16 @@ public class Vala.RealLiteral : Literal {
        public override string to_string () {
                return value;
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               value_type = new ValueType ((TypeSymbol) analyzer.root_symbol.scope.lookup (get_type_name ()));
+
+               return !error;
+       }
 }
index 2c6b4e2925bda9d06b152d19a5303596a3851262..71b965ac6f43ad1e7cf574384765855e4e32017c 100644 (file)
@@ -71,4 +71,40 @@ public class Vala.ReferenceTransferExpression : Expression {
        public override bool is_pure () {
                return false;
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               inner.lvalue = true;
+
+               accept_children (analyzer);
+
+               if (inner.error) {
+                       /* if there was an error in the inner expression, skip type check */
+                       error = true;
+                       return false;
+               }
+
+               if (!(inner is MemberAccess || inner is ElementAccess)) {
+                       error = true;
+                       Report.error (source_reference, "Reference transfer not supported for this expression");
+                       return false;
+               }
+
+               if (!inner.value_type.is_disposable ()
+                   && !(inner.value_type is PointerType)) {
+                       error = true;
+                       Report.error (source_reference, "No reference to be transferred");
+                       return false;
+               }
+
+               value_type = inner.value_type.copy ();
+               value_type.value_owned = true;
+
+               return !error;
+       }
 }
index b3ef264336c3b457402cbe4d99eb16ab2e43010d..522dade9214afb3490c9c583cfc19da838c3a682 100644 (file)
@@ -63,7 +63,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        public Interface collection_type;
        public Interface map_type;
 
-       private int next_lambda_id = 0;
+       public int next_lambda_id = 0;
 
        // keep replaced alive to make sure they remain valid
        // for the whole execution of CodeNode.accept
@@ -300,27 +300,27 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
 
        public override void visit_boolean_literal (BooleanLiteral expr) {
-               expr.value_type = bool_type;
+               expr.check (this);
        }
 
        public override void visit_character_literal (CharacterLiteral expr) {
-               expr.value_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("char"));
+               expr.check (this);
        }
 
        public override void visit_integer_literal (IntegerLiteral expr) {
-               expr.value_type = new IntegerType ((TypeSymbol) root_symbol.scope.lookup (expr.get_type_name ()), expr.value, expr.get_type_name ());
+               expr.check (this);
        }
 
        public override void visit_real_literal (RealLiteral expr) {
-               expr.value_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup (expr.get_type_name ()));
+               expr.check (this);
        }
 
        public override void visit_string_literal (StringLiteral expr) {
-               expr.value_type = string_type.copy ();
+               expr.check (this);
        }
 
        public override void visit_null_literal (NullLiteral expr) {
-               expr.value_type = new NullType (expr.source_reference);
+               expr.check (this);
        }
 
        public DataType? get_value_type_for_symbol (Symbol sym, bool lvalue) {
@@ -421,29 +421,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
 
        public override void visit_parenthesized_expression (ParenthesizedExpression expr) {
-               expr.inner.target_type = expr.target_type;
-
-               expr.accept_children (this);
-
-               if (expr.inner.error) {
-                       // ignore inner error
-                       expr.error = true;
-                       return;
-               }
-
-               if (expr.inner.value_type == null) {
-                       // static type may be null for method references
-                       expr.error = true;
-                       Report.error (expr.inner.source_reference, "Invalid expression type");
-                       return;
-               }
-
-               expr.value_type = expr.inner.value_type.copy ();
-               // don't call g_object_ref_sink on inner and outer expression
-               expr.value_type.floating_reference = false;
-
-               // don't transform expression twice
-               expr.inner.target_type = expr.inner.value_type.copy ();
+               expr.check (this);
        }
        
        public override void visit_member_access (MemberAccess expr) {
@@ -799,38 +777,11 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
 
        public override void visit_base_access (BaseAccess expr) {
-               if (!is_in_instance_method ()) {
-                       expr.error = true;
-                       Report.error (expr.source_reference, "Base access invalid outside of instance methods");
-                       return;
-               }
-
-               if (current_class == null) {
-                       if (current_struct == null) {
-                               expr.error = true;
-                               Report.error (expr.source_reference, "Base access invalid outside of class and struct");
-                               return;
-                       } else if (current_struct.get_base_types ().size != 1) {
-                               expr.error = true;
-                               Report.error (expr.source_reference, "Base access invalid without base type %d".printf (current_struct.get_base_types ().size));
-                               return;
-                       }
-                       Iterator<DataType> base_type_it = current_struct.get_base_types ().iterator ();
-                       base_type_it.next ();
-                       expr.value_type = base_type_it.get ();
-               } else if (current_class.base_class == null) {
-                       expr.error = true;
-                       Report.error (expr.source_reference, "Base access invalid without base class");
-                       return;
-               } else {
-                       expr.value_type = new ObjectType (current_class.base_class);
-               }
-
-               expr.symbol_reference = expr.value_type.data_type;
+               expr.check (this);
        }
 
        public override void visit_postfix_expression (PostfixExpression expr) {
-               expr.value_type = expr.inner.value_type;
+               expr.check (this);
        }
 
        public override void visit_object_creation_expression (ObjectCreationExpression expr) {
@@ -872,213 +823,31 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
 
        public override void visit_sizeof_expression (SizeofExpression expr) {
-               expr.value_type = ulong_type;
+               expr.check (this);
        }
 
        public override void visit_typeof_expression (TypeofExpression expr) {
-               expr.value_type = type_type;
-       }
-
-       private bool is_numeric_type (DataType type) {
-               if (!(type.data_type is Struct)) {
-                       return false;
-               }
-
-               var st = (Struct) type.data_type;
-               return st.is_integer_type () || st.is_floating_type ();
-       }
-
-       private bool is_integer_type (DataType type) {
-               if (!(type.data_type is Struct)) {
-                       return false;
-               }
-
-               var st = (Struct) type.data_type;
-               return st.is_integer_type ();
+               expr.check (this);
        }
 
        public override void visit_unary_expression (UnaryExpression expr) {
-               if (expr.operator == UnaryOperator.REF || expr.operator == UnaryOperator.OUT) {
-                       expr.inner.lvalue = true;
-                       expr.inner.target_type = expr.target_type;
-               }
-
-               expr.accept_children (this);
-
-               if (expr.inner.error) {
-                       /* if there was an error in the inner expression, skip type check */
-                       expr.error = true;
-                       return;
-               }
-
-               if (expr.operator == UnaryOperator.PLUS || expr.operator == UnaryOperator.MINUS) {
-                       // integer or floating point type
-                       if (!is_numeric_type (expr.inner.value_type)) {
-                               expr.error = true;
-                               Report.error (expr.source_reference, "Operator not supported for `%s'".printf (expr.inner.value_type.to_string ()));
-                               return;
-                       }
-
-                       expr.value_type = expr.inner.value_type;
-               } else if (expr.operator == UnaryOperator.LOGICAL_NEGATION) {
-                       // boolean type
-                       if (!expr.inner.value_type.compatible (bool_type)) {
-                               expr.error = true;
-                               Report.error (expr.source_reference, "Operator not supported for `%s'".printf (expr.inner.value_type.to_string ()));
-                               return;
-                       }
-
-                       expr.value_type = expr.inner.value_type;
-               } else if (expr.operator == UnaryOperator.BITWISE_COMPLEMENT) {
-                       // integer type
-                       if (!is_integer_type (expr.inner.value_type)) {
-                               expr.error = true;
-                               Report.error (expr.source_reference, "Operator not supported for `%s'".printf (expr.inner.value_type.to_string ()));
-                               return;
-                       }
-
-                       expr.value_type = expr.inner.value_type;
-               } else if (expr.operator == UnaryOperator.INCREMENT ||
-                          expr.operator == UnaryOperator.DECREMENT) {
-                       // integer type
-                       if (!is_integer_type (expr.inner.value_type)) {
-                               expr.error = true;
-                               Report.error (expr.source_reference, "Operator not supported for `%s'".printf (expr.inner.value_type.to_string ()));
-                               return;
-                       }
-
-                       var ma = find_member_access (expr.inner);
-                       if (ma == null) {
-                               expr.error = true;
-                               Report.error (expr.source_reference, "Prefix operators not supported for this expression");
-                               return;
-                       }
-
-                       var old_value = new MemberAccess (ma.inner, ma.member_name, expr.inner.source_reference);
-                       var bin = new BinaryExpression (expr.operator == UnaryOperator.INCREMENT ? BinaryOperator.PLUS : BinaryOperator.MINUS, old_value, new IntegerLiteral ("1"), expr.source_reference);
-
-                       var assignment = new Assignment (ma, bin, AssignmentOperator.SIMPLE, expr.source_reference);
-                       var parenthexp = new ParenthesizedExpression (assignment, expr.source_reference);
-                       parenthexp.target_type = expr.target_type;
-                       replaced_nodes.add (expr);
-                       expr.parent_node.replace_expression (expr, parenthexp);
-                       parenthexp.accept (this);
-                       return;
-               } else if (expr.operator == UnaryOperator.REF || expr.operator == UnaryOperator.OUT) {
-                       if (expr.inner.symbol_reference is Field || expr.inner.symbol_reference is FormalParameter || expr.inner.symbol_reference is LocalVariable) {
-                               // ref and out can only be used with fields, parameters, and local variables
-                               expr.lvalue = true;
-                               expr.value_type = expr.inner.value_type;
-                       } else {
-                               expr.error = true;
-                               Report.error (expr.source_reference, "ref and out method arguments can only be used with fields, parameters, and local variables");
-                               return;
-                       }
-               } else {
-                       expr.error = true;
-                       Report.error (expr.source_reference, "internal error: unsupported unary operator");
-                       return;
-               }
-       }
-
-       private MemberAccess? find_member_access (Expression expr) {
-               if (expr is ParenthesizedExpression) {
-                       var pe = (ParenthesizedExpression) expr;
-                       return find_member_access (pe.inner);
-               }
-
-               if (expr is MemberAccess) {
-                       return (MemberAccess) expr;
-               }
-
-               return null;
+               expr.check (this);
        }
 
        public override void visit_cast_expression (CastExpression expr) {
-               if (expr.inner.error) {
-                       expr.error = true;
-                       return;
-               }
-
-               // FIXME: check whether cast is allowed
-
-               current_source_file.add_type_dependency (expr.type_reference, SourceFileDependencyType.SOURCE);
-
-               expr.value_type = expr.type_reference;
-               expr.value_type.value_owned = expr.inner.value_type.value_owned;
-
-               expr.inner.target_type = expr.inner.value_type.copy ();
+               expr.check (this);
        }
 
        public override void visit_pointer_indirection (PointerIndirection expr) {
-               if (expr.inner.error) {
-                       return;
-               }
-               if (expr.inner.value_type == null) {
-                       expr.error = true;
-                       Report.error (expr.source_reference, "internal error: unknown type of inner expression");
-                       return;
-               }
-               if (expr.inner.value_type is PointerType) {
-                       var pointer_type = (PointerType) expr.inner.value_type;
-                       if (pointer_type.base_type is ReferenceType) {
-                               expr.error = true;
-                               Report.error (expr.source_reference, "Pointer indirection not supported for this expression");
-                               return;
-                       }
-                       expr.value_type = pointer_type.base_type;
-               } else {
-                       expr.error = true;
-                       Report.error (expr.source_reference, "Pointer indirection not supported for this expression");
-                       return;
-               }
+               expr.check (this);
        }
 
        public override void visit_addressof_expression (AddressofExpression expr) {
-               if (expr.inner.error) {
-                       return;
-               }
-               if (!(expr.inner.value_type is ValueType
-                     || expr.inner.value_type is ObjectType
-                     || expr.inner.value_type is PointerType)) {
-                       expr.error = true;
-                       Report.error (expr.source_reference, "Address-of operator not supported for this expression");
-                       return;
-               }
-
-               if (expr.inner.value_type.is_reference_type_or_type_parameter ()) {
-                       expr.value_type = new PointerType (new PointerType (expr.inner.value_type));
-               } else {
-                       expr.value_type = new PointerType (expr.inner.value_type);
-               }
+               expr.check (this);
        }
 
        public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
-               expr.inner.lvalue = true;
-
-               expr.accept_children (this);
-
-               if (expr.inner.error) {
-                       /* if there was an error in the inner expression, skip type check */
-                       expr.error = true;
-                       return;
-               }
-
-               if (!(expr.inner is MemberAccess || expr.inner is ElementAccess)) {
-                       expr.error = true;
-                       Report.error (expr.source_reference, "Reference transfer not supported for this expression");
-                       return;
-               }
-
-               if (!expr.inner.value_type.is_disposable ()
-                   && !(expr.inner.value_type is PointerType)) {
-                       expr.error = true;
-                       Report.error (expr.source_reference, "No reference to be transferred");
-                       return;
-               }
-
-               expr.value_type = expr.inner.value_type.copy ();
-               expr.value_type.value_owned = true;
+               expr.check (this);
        }
 
        public DataType? get_arithmetic_result_type (DataType left_type, DataType right_type) {
@@ -1118,46 +887,11 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
 
        public override void visit_type_check (TypeCheck expr) {
-               if (expr.type_reference.data_type == null) {
-                       /* if type resolving didn't succeed, skip this check */
-                       expr.error = true;
-                       return;
-               }
-
-               current_source_file.add_type_dependency (expr.type_reference, SourceFileDependencyType.SOURCE);
-
-               expr.value_type = bool_type;
+               expr.check (this);
        }
 
        public override void visit_conditional_expression (ConditionalExpression expr) {
-               if (expr.condition.error || expr.false_expression.error || expr.true_expression.error) {
-                       return;
-               }
-
-               if (!expr.condition.value_type.compatible (bool_type)) {
-                       expr.error = true;
-                       Report.error (expr.condition.source_reference, "Condition must be boolean");
-                       return;
-               }
-
-               /* FIXME: support memory management */
-               if (expr.false_expression.value_type.compatible (expr.true_expression.value_type)) {
-                       expr.value_type = expr.true_expression.value_type.copy ();
-               } else if (expr.true_expression.value_type.compatible (expr.false_expression.value_type)) {
-                       expr.value_type = expr.false_expression.value_type.copy ();
-               } else {
-                       expr.error = true;
-                       Report.error (expr.condition.source_reference, "Incompatible expressions");
-                       return;
-               }
-       }
-
-       private string get_lambda_name () {
-               var result = "__lambda%d".printf (next_lambda_id);
-
-               next_lambda_id++;
-
-               return result;
+               expr.check (this);
        }
 
        public Method? find_current_method () {
@@ -1183,71 +917,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
 
        public override void visit_lambda_expression (LambdaExpression l) {
-               if (!(l.target_type is DelegateType)) {
-                       l.error = true;
-                       Report.error (l.source_reference, "lambda expression not allowed in this context");
-                       return;
-               }
-
-               bool in_instance_method = false;
-               var current_method = find_current_method ();
-               if (current_method != null) {
-                       in_instance_method = (current_method.binding == MemberBinding.INSTANCE);
-               } else {
-                       in_instance_method = is_in_constructor ();
-               }
-
-               var cb = (Delegate) ((DelegateType) l.target_type).delegate_symbol;
-               l.method = new Method (get_lambda_name (), cb.return_type);
-               if (!cb.has_target || !in_instance_method) {
-                       l.method.binding = MemberBinding.STATIC;
-               }
-               l.method.owner = current_symbol.scope;
-
-               var lambda_params = l.get_parameters ();
-               Iterator<string> lambda_param_it = lambda_params.iterator ();
-               foreach (FormalParameter cb_param in cb.get_parameters ()) {
-                       if (!lambda_param_it.next ()) {
-                               /* lambda expressions are allowed to have less parameters */
-                               break;
-                       }
-
-                       string lambda_param = lambda_param_it.get ();
-
-                       var param = new FormalParameter (lambda_param, cb_param.parameter_type);
-
-                       l.method.add_parameter (param);
-               }
-
-               if (lambda_param_it.next ()) {
-                       /* lambda expressions may not expect more parameters */
-                       l.error = true;
-                       Report.error (l.source_reference, "lambda expression: too many parameters");
-                       return;
-               }
-
-               if (l.expression_body != null) {
-                       var block = new Block (l.source_reference);
-                       block.scope.parent_scope = l.method.scope;
-
-                       if (l.method.return_type.data_type != null) {
-                               block.add_statement (new ReturnStatement (l.expression_body, l.source_reference));
-                       } else {
-                               block.add_statement (new ExpressionStatement (l.expression_body, l.source_reference));
-                       }
-
-                       l.method.body = block;
-               } else {
-                       l.method.body = l.statement_body;
-               }
-               l.method.body.owner = l.method.scope;
-
-               /* lambda expressions should be usable like MemberAccess of a method */
-               l.symbol_reference = l.method;
-
-               l.accept_children (this);
-
-               l.value_type = new MethodType (l.method);
+               l.check (this);
        }
 
        public override void visit_assignment (Assignment a) {
index bd858bd5145986ff80ab068dab3c8eafa15d38d0..d558f100c70fc8c1f4577ce606e473e8051d279c 100644 (file)
@@ -1,6 +1,6 @@
 /* valasizeofexpression.vala
  *
- * Copyright (C) 2006-2007  Jürg Billeter
+ * Copyright (C) 2006-2008  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -68,4 +68,16 @@ public class Vala.SizeofExpression : Expression {
                        type_reference = new_type;
                }
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               value_type = analyzer.ulong_type;
+
+               return !error;
+       }
 }
index 2206b744b8c59c6a0c64c0ed615bb7cea10f39bf..d6fc9ac4df61d274aa6c3d25f278cbe23c92e60c 100644 (file)
@@ -76,4 +76,16 @@ public class Vala.StringLiteral : Literal {
        public override string to_string () {
                return value;
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               value_type = analyzer.string_type.copy ();
+
+               return !error;
+       }
 }
index b408d1e52e347d4882a2c25b80bc6474d6cda9d0..4c2436252c6c119e8de218d3454cfd479db6ea04 100644 (file)
@@ -1,6 +1,6 @@
 /* valatypecheck.vala
  *
- * Copyright (C) 2006-2007  Jürg Billeter
+ * Copyright (C) 2006-2008  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -77,4 +77,24 @@ public class Vala.TypeCheck : Expression {
                        type_reference = new_type;
                }
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               if (type_reference.data_type == null) {
+                       /* if type resolving didn't succeed, skip this check */
+                       error = true;
+                       return false;
+               }
+
+               analyzer.current_source_file.add_type_dependency (type_reference, SourceFileDependencyType.SOURCE);
+
+               value_type = analyzer.bool_type;
+
+               return !error;
+       }
 }
index d7111003fb64bd707318f7b2b939b3d0185f44c6..918ae6ccd4bc238e2feb056715168471e14847d2 100644 (file)
@@ -1,6 +1,6 @@
 /* valatypeofexpression.vala
  *
- * Copyright (C) 2006-2007  Jürg Billeter
+ * Copyright (C) 2006-2008  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -68,4 +68,16 @@ public class Vala.TypeofExpression : Expression {
                        type_reference = new_type;
                }
        }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               value_type = analyzer.type_type;
+
+               return !error;
+       }
 }
index 820804bab7473040af97b12b2f6057c65e427188..aea2a15787412eec99196de14b886d2cc4946bba 100644 (file)
@@ -104,6 +104,129 @@ public class Vala.UnaryExpression : Expression {
 
                return inner.is_pure ();
        }
+
+       bool is_numeric_type (DataType type) {
+               if (!(type.data_type is Struct)) {
+                       return false;
+               }
+
+               var st = (Struct) type.data_type;
+               return st.is_integer_type () || st.is_floating_type ();
+       }
+
+       bool is_integer_type (DataType type) {
+               if (!(type.data_type is Struct)) {
+                       return false;
+               }
+
+               var st = (Struct) type.data_type;
+               return st.is_integer_type ();
+       }
+
+       MemberAccess? find_member_access (Expression expr) {
+               if (expr is ParenthesizedExpression) {
+                       var pe = (ParenthesizedExpression) expr;
+                       return find_member_access (pe.inner);
+               }
+
+               if (expr is MemberAccess) {
+                       return (MemberAccess) expr;
+               }
+
+               return null;
+       }
+
+       public override bool check (SemanticAnalyzer analyzer) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               if (operator == UnaryOperator.REF || operator == UnaryOperator.OUT) {
+                       inner.lvalue = true;
+                       inner.target_type = target_type;
+               }
+
+               accept_children (analyzer);
+
+               if (inner.error) {
+                       /* if there was an error in the inner expression, skip type check */
+                       error = true;
+                       return false;
+               }
+
+               if (operator == UnaryOperator.PLUS || operator == UnaryOperator.MINUS) {
+                       // integer or floating point type
+                       if (!is_numeric_type (inner.value_type)) {
+                               error = true;
+                               Report.error (source_reference, "Operator not supported for `%s'".printf (inner.value_type.to_string ()));
+                               return false;
+                       }
+
+                       value_type = inner.value_type;
+               } else if (operator == UnaryOperator.LOGICAL_NEGATION) {
+                       // boolean type
+                       if (!inner.value_type.compatible (analyzer.bool_type)) {
+                               error = true;
+                               Report.error (source_reference, "Operator not supported for `%s'".printf (inner.value_type.to_string ()));
+                               return false;
+                       }
+
+                       value_type = inner.value_type;
+               } else if (operator == UnaryOperator.BITWISE_COMPLEMENT) {
+                       // integer type
+                       if (!is_integer_type (inner.value_type)) {
+                               error = true;
+                               Report.error (source_reference, "Operator not supported for `%s'".printf (inner.value_type.to_string ()));
+                               return false;
+                       }
+
+                       value_type = inner.value_type;
+               } else if (operator == UnaryOperator.INCREMENT ||
+                          operator == UnaryOperator.DECREMENT) {
+                       // integer type
+                       if (!is_integer_type (inner.value_type)) {
+                               error = true;
+                               Report.error (source_reference, "Operator not supported for `%s'".printf (inner.value_type.to_string ()));
+                               return false;
+                       }
+
+                       var ma = find_member_access (inner);
+                       if (ma == null) {
+                               error = true;
+                               Report.error (source_reference, "Prefix operators not supported for this expression");
+                               return false;
+                       }
+
+                       var old_value = new MemberAccess (ma.inner, ma.member_name, inner.source_reference);
+                       var bin = new BinaryExpression (operator == UnaryOperator.INCREMENT ? BinaryOperator.PLUS : BinaryOperator.MINUS, old_value, new IntegerLiteral ("1"), source_reference);
+
+                       var assignment = new Assignment (ma, bin, AssignmentOperator.SIMPLE, source_reference);
+                       var parenthexp = new ParenthesizedExpression (assignment, source_reference);
+                       parenthexp.target_type = target_type;
+                       analyzer.replaced_nodes.add (this);
+                       parent_node.replace_expression (this, parenthexp);
+                       parenthexp.accept (analyzer);
+                       return true;
+               } else if (operator == UnaryOperator.REF || operator == UnaryOperator.OUT) {
+                       if (inner.symbol_reference is Field || inner.symbol_reference is FormalParameter || inner.symbol_reference is LocalVariable) {
+                               // ref and out can only be used with fields, parameters, and local variables
+                               lvalue = true;
+                               value_type = inner.value_type;
+                       } else {
+                               error = true;
+                               Report.error (source_reference, "ref and out method arguments can only be used with fields, parameters, and local variables");
+                               return false;
+                       }
+               } else {
+                       error = true;
+                       Report.error (source_reference, "internal error: unsupported unary operator");
+                       return false;
+               }
+
+               return !error;
+       }
 }
 
 public enum Vala.UnaryOperator {