vala r1983 - in trunk: . vala
- From: juergbi svn gnome org
- To: svn-commits-list gnome org
- Subject: vala r1983 - in trunk: . vala
- Date: Wed, 5 Nov 2008 21:12:56 +0000 (UTC)
Author: juergbi
Date: Wed Nov 5 21:12:56 2008
New Revision: 1983
URL: http://svn.gnome.org/viewvc/vala?rev=1983&view=rev
Log:
2008-11-05 JÃrg Billeter <j bitron ch>
* vala/valaassignment.vala:
* vala/valasemanticanalyzer.vala:
Move assignment checking to Assignment.check
Modified:
trunk/ChangeLog
trunk/vala/valaassignment.vala
trunk/vala/valasemanticanalyzer.vala
Modified: trunk/vala/valaassignment.vala
==============================================================================
--- trunk/vala/valaassignment.vala (original)
+++ trunk/vala/valaassignment.vala Wed Nov 5 21:12:56 2008
@@ -1,6 +1,6 @@
/* valaassignment.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,6 +97,289 @@
public override bool is_pure () {
return false;
}
+
+ public override bool check (SemanticAnalyzer analyzer) {
+ if (checked) {
+ return !error;
+ }
+
+ checked = true;
+
+ left.lvalue = true;
+
+ left.accept (analyzer);
+
+ if (left.error) {
+ // skip on error in inner expression
+ error = true;
+ return false;
+ }
+
+ if (left is MemberAccess) {
+ var ma = (MemberAccess) left;
+
+ if (!(ma.symbol_reference is Signal || ma.symbol_reference is DynamicProperty) && ma.value_type == null) {
+ error = true;
+ Report.error (source_reference, "unsupported lvalue in assignment");
+ return false;
+ }
+ if (ma.prototype_access) {
+ error = true;
+ Report.error (source_reference, "Access to instance member `%s' denied".printf (ma.symbol_reference.get_full_name ()));
+ return false;
+ }
+
+ if (ma.error || ma.symbol_reference == null) {
+ error = true;
+ /* if no symbol found, skip this check */
+ return false;
+ }
+
+ if (ma.symbol_reference is DynamicSignal) {
+ // target_type not available for dynamic signals
+ } else if (ma.symbol_reference is Signal) {
+ var sig = (Signal) ma.symbol_reference;
+ right.target_type = new DelegateType (sig.get_delegate (ma.inner.value_type));
+ } else {
+ right.target_type = ma.value_type;
+ }
+ } else if (left is ElementAccess) {
+ var ea = (ElementAccess) left;
+
+ if (ea.container is MemberAccess && ea.container.symbol_reference is Signal) {
+ var ma = (MemberAccess) ea.container;
+ var sig = (Signal) ea.container.symbol_reference;
+ right.target_type = new DelegateType (sig.get_delegate (ma.inner.value_type));
+ } else {
+ right.target_type = left.value_type;
+ }
+ } else if (left is PointerIndirection) {
+ right.target_type = left.value_type;
+ } else {
+ error = true;
+ Report.error (source_reference, "unsupported lvalue in assignment");
+ return false;
+ }
+
+ right.accept (analyzer);
+
+ if (right.error) {
+ // skip on error in inner expression
+ error = true;
+ return false;
+ }
+
+ if (operator != AssignmentOperator.SIMPLE && left is MemberAccess) {
+ // transform into simple assignment
+ // FIXME: only do this if the backend doesn't support
+ // the assignment natively
+
+ var ma = (MemberAccess) left;
+
+ if (!(ma.symbol_reference is Signal)) {
+ var old_value = new MemberAccess (ma.inner, ma.member_name);
+
+ var bin = new BinaryExpression (BinaryOperator.PLUS, old_value, new ParenthesizedExpression (right, right.source_reference));
+ bin.target_type = right.target_type;
+ right.target_type = right.target_type.copy ();
+ right.target_type.value_owned = false;
+
+ if (operator == AssignmentOperator.BITWISE_OR) {
+ bin.operator = BinaryOperator.BITWISE_OR;
+ } else if (operator == AssignmentOperator.BITWISE_AND) {
+ bin.operator = BinaryOperator.BITWISE_AND;
+ } else if (operator == AssignmentOperator.BITWISE_XOR) {
+ bin.operator = BinaryOperator.BITWISE_XOR;
+ } else if (operator == AssignmentOperator.ADD) {
+ bin.operator = BinaryOperator.PLUS;
+ } else if (operator == AssignmentOperator.SUB) {
+ bin.operator = BinaryOperator.MINUS;
+ } else if (operator == AssignmentOperator.MUL) {
+ bin.operator = BinaryOperator.MUL;
+ } else if (operator == AssignmentOperator.DIV) {
+ bin.operator = BinaryOperator.DIV;
+ } else if (operator == AssignmentOperator.PERCENT) {
+ bin.operator = BinaryOperator.MOD;
+ } else if (operator == AssignmentOperator.SHIFT_LEFT) {
+ bin.operator = BinaryOperator.SHIFT_LEFT;
+ } else if (operator == AssignmentOperator.SHIFT_RIGHT) {
+ bin.operator = BinaryOperator.SHIFT_RIGHT;
+ }
+
+ right = bin;
+ right.accept (analyzer);
+
+ operator = AssignmentOperator.SIMPLE;
+ }
+ }
+
+ if (left.symbol_reference is Signal) {
+ var sig = (Signal) left.symbol_reference;
+
+ var m = right.symbol_reference as Method;
+
+ if (m == null) {
+ error = true;
+ Report.error (right.source_reference, "unsupported expression for signal handler");
+ return false;
+ }
+
+ var dynamic_sig = sig as DynamicSignal;
+ if (dynamic_sig != null) {
+ bool first = true;
+ foreach (FormalParameter param in dynamic_sig.handler.value_type.get_parameters ()) {
+ if (first) {
+ // skip sender parameter
+ first = false;
+ } else {
+ dynamic_sig.add_parameter (param.copy ());
+ }
+ }
+ right.target_type = new DelegateType (sig.get_delegate (new ObjectType ((ObjectTypeSymbol) sig.parent_symbol)));
+ } else if (!right.value_type.compatible (right.target_type)) {
+ var delegate_type = (DelegateType) right.target_type;
+
+ error = true;
+ Report.error (right.source_reference, "method `%s' is incompatible with signal `%s', expected `%s'".printf (right.value_type.to_string (), right.target_type.to_string (), delegate_type.delegate_symbol.get_prototype_string (m.name)));
+ return false;
+ }
+ } else if (left is MemberAccess) {
+ var ma = (MemberAccess) left;
+
+ if (ma.symbol_reference is Property) {
+ var prop = (Property) ma.symbol_reference;
+
+ var dynamic_prop = prop as DynamicProperty;
+ if (dynamic_prop != null) {
+ dynamic_prop.property_type = right.value_type.copy ();
+ left.value_type = dynamic_prop.property_type.copy ();
+ }
+
+ if (prop.set_accessor == null
+ || (!prop.set_accessor.writable && !(analyzer.find_current_method () is CreationMethod || analyzer.is_in_constructor ()))) {
+ ma.error = true;
+ Report.error (ma.source_reference, "Property `%s' is read-only".printf (prop.get_full_name ()));
+ return false;
+ }
+ } else if (ma.symbol_reference is LocalVariable && right.value_type == null) {
+ var local = (LocalVariable) ma.symbol_reference;
+
+ if (right.symbol_reference is Method &&
+ local.variable_type is DelegateType) {
+ var m = (Method) right.symbol_reference;
+ var dt = (DelegateType) local.variable_type;
+ var cb = dt.delegate_symbol;
+
+ /* check whether method matches callback type */
+ if (!cb.matches_method (m)) {
+ error = true;
+ Report.error (source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
+ return false;
+ }
+
+ right.value_type = local.variable_type;
+ } else {
+ error = true;
+ Report.error (source_reference, "Assignment: Invalid callback assignment attempt");
+ return false;
+ }
+ } else if (ma.symbol_reference is Field && right.value_type == null) {
+ var f = (Field) ma.symbol_reference;
+
+ if (right.symbol_reference is Method &&
+ f.field_type is DelegateType) {
+ var m = (Method) right.symbol_reference;
+ var dt = (DelegateType) f.field_type;
+ var cb = dt.delegate_symbol;
+
+ /* check whether method matches callback type */
+ if (!cb.matches_method (m)) {
+ f.error = true;
+ Report.error (source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
+ return false;
+ }
+
+ right.value_type = f.field_type;
+ } else {
+ error = true;
+ Report.error (source_reference, "Assignment: Invalid callback assignment attempt");
+ return false;
+ }
+ } else if (left.value_type != null && right.value_type != null) {
+ /* if there was an error on either side,
+ * i.e. {left|right}.value_type == null, skip type check */
+
+ if (!right.value_type.compatible (left.value_type)) {
+ error = true;
+ Report.error (source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (right.value_type.to_string (), left.value_type.to_string ()));
+ return false;
+ }
+
+ if (right.value_type.is_disposable ()) {
+ /* rhs transfers ownership of the expression */
+ if (!(left.value_type is PointerType) && !left.value_type.value_owned) {
+ /* lhs doesn't own the value */
+ error = true;
+ Report.error (source_reference, "Invalid assignment from owned expression to unowned variable");
+ }
+ } else if (left.value_type.value_owned) {
+ /* lhs wants to own the value
+ * rhs doesn't transfer the ownership
+ * code generator needs to add reference
+ * increment calls */
+ }
+ }
+ } else if (left is ElementAccess) {
+ var ea = (ElementAccess) left;
+
+ if (!right.value_type.compatible (left.value_type)) {
+ error = true;
+ Report.error (source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (right.value_type.to_string (), left.value_type.to_string ()));
+ return false;
+ }
+
+ if (right.value_type.is_disposable ()) {
+ /* rhs transfers ownership of the expression */
+
+ DataType element_type;
+
+ if (ea.container.value_type is ArrayType) {
+ var array_type = (ArrayType) ea.container.value_type;
+ element_type = array_type.element_type;
+ } else {
+ var args = ea.container.value_type.get_type_arguments ();
+ assert (args.size == 1);
+ element_type = args.get (0);
+ }
+
+ if (!(element_type is PointerType) && !element_type.value_owned) {
+ /* lhs doesn't own the value */
+ error = true;
+ Report.error (source_reference, "Invalid assignment from owned expression to unowned variable");
+ return false;
+ }
+ } else if (left.value_type.value_owned) {
+ /* lhs wants to own the value
+ * rhs doesn't transfer the ownership
+ * code generator needs to add reference
+ * increment calls */
+ }
+ } else {
+ return false;
+ }
+
+ if (left.value_type != null) {
+ value_type = left.value_type.copy ();
+ value_type.value_owned = false;
+ } else {
+ value_type = null;
+ }
+
+ add_error_types (left.get_error_types ());
+ add_error_types (right.get_error_types ());
+
+ return !error;
+ }
}
public enum Vala.AssignmentOperator {
Modified: trunk/vala/valasemanticanalyzer.vala
==============================================================================
--- trunk/vala/valasemanticanalyzer.vala (original)
+++ trunk/vala/valasemanticanalyzer.vala Wed Nov 5 21:12:56 2008
@@ -3314,7 +3314,7 @@
return result;
}
- private Method? find_current_method () {
+ public Method? find_current_method () {
var sym = current_symbol;
while (sym != null) {
if (sym is Method) {
@@ -3325,7 +3325,7 @@
return null;
}
- private bool is_in_constructor () {
+ public bool is_in_constructor () {
var sym = current_symbol;
while (sym != null) {
if (sym is Constructor) {
@@ -3405,277 +3405,6 @@
}
public override void visit_assignment (Assignment a) {
- a.left.lvalue = true;
-
- a.left.accept (this);
-
- if (a.left.error) {
- // skip on error in inner expression
- a.error = true;
- return;
- }
-
- if (a.left is MemberAccess) {
- var ma = (MemberAccess) a.left;
-
- if (!(ma.symbol_reference is Signal || ma.symbol_reference is DynamicProperty) && ma.value_type == null) {
- a.error = true;
- Report.error (a.source_reference, "unsupported lvalue in assignment");
- return;
- }
- if (ma.prototype_access) {
- a.error = true;
- Report.error (a.source_reference, "Access to instance member `%s' denied".printf (ma.symbol_reference.get_full_name ()));
- return;
- }
-
- if (ma.error || ma.symbol_reference == null) {
- a.error = true;
- /* if no symbol found, skip this check */
- return;
- }
-
- if (ma.symbol_reference is DynamicSignal) {
- // target_type not available for dynamic signals
- } else if (ma.symbol_reference is Signal) {
- var sig = (Signal) ma.symbol_reference;
- a.right.target_type = new DelegateType (sig.get_delegate (ma.inner.value_type));
- } else {
- a.right.target_type = ma.value_type;
- }
- } else if (a.left is ElementAccess) {
- var ea = (ElementAccess) a.left;
-
- if (ea.container is MemberAccess && ea.container.symbol_reference is Signal) {
- var ma = (MemberAccess) ea.container;
- var sig = (Signal) ea.container.symbol_reference;
- a.right.target_type = new DelegateType (sig.get_delegate (ma.inner.value_type));
- } else {
- a.right.target_type = a.left.value_type;
- }
- } else if (a.left is PointerIndirection) {
- a.right.target_type = a.left.value_type;
- } else {
- a.error = true;
- Report.error (a.source_reference, "unsupported lvalue in assignment");
- return;
- }
-
- a.right.accept (this);
-
- if (a.right.error) {
- // skip on error in inner expression
- a.error = true;
- return;
- }
-
- if (a.operator != AssignmentOperator.SIMPLE && a.left is MemberAccess) {
- // transform into simple assignment
- // FIXME: only do this if the backend doesn't support
- // the assignment natively
-
- var ma = (MemberAccess) a.left;
-
- if (!(ma.symbol_reference is Signal)) {
- var old_value = new MemberAccess (ma.inner, ma.member_name);
-
- var bin = new BinaryExpression (BinaryOperator.PLUS, old_value, new ParenthesizedExpression (a.right, a.right.source_reference));
- bin.target_type = a.right.target_type;
- a.right.target_type = a.right.target_type.copy ();
- a.right.target_type.value_owned = false;
-
- if (a.operator == AssignmentOperator.BITWISE_OR) {
- bin.operator = BinaryOperator.BITWISE_OR;
- } else if (a.operator == AssignmentOperator.BITWISE_AND) {
- bin.operator = BinaryOperator.BITWISE_AND;
- } else if (a.operator == AssignmentOperator.BITWISE_XOR) {
- bin.operator = BinaryOperator.BITWISE_XOR;
- } else if (a.operator == AssignmentOperator.ADD) {
- bin.operator = BinaryOperator.PLUS;
- } else if (a.operator == AssignmentOperator.SUB) {
- bin.operator = BinaryOperator.MINUS;
- } else if (a.operator == AssignmentOperator.MUL) {
- bin.operator = BinaryOperator.MUL;
- } else if (a.operator == AssignmentOperator.DIV) {
- bin.operator = BinaryOperator.DIV;
- } else if (a.operator == AssignmentOperator.PERCENT) {
- bin.operator = BinaryOperator.MOD;
- } else if (a.operator == AssignmentOperator.SHIFT_LEFT) {
- bin.operator = BinaryOperator.SHIFT_LEFT;
- } else if (a.operator == AssignmentOperator.SHIFT_RIGHT) {
- bin.operator = BinaryOperator.SHIFT_RIGHT;
- }
-
- a.right = bin;
- a.right.accept (this);
-
- a.operator = AssignmentOperator.SIMPLE;
- }
- }
-
- if (a.left.symbol_reference is Signal) {
- var sig = (Signal) a.left.symbol_reference;
-
- var m = a.right.symbol_reference as Method;
-
- if (m == null) {
- a.error = true;
- Report.error (a.right.source_reference, "unsupported expression for signal handler");
- return;
- }
-
- var dynamic_sig = sig as DynamicSignal;
- if (dynamic_sig != null) {
- bool first = true;
- foreach (FormalParameter param in dynamic_sig.handler.value_type.get_parameters ()) {
- if (first) {
- // skip sender parameter
- first = false;
- } else {
- dynamic_sig.add_parameter (param.copy ());
- }
- }
- a.right.target_type = new DelegateType (sig.get_delegate (new ObjectType ((ObjectTypeSymbol) sig.parent_symbol)));
- } else if (!a.right.value_type.compatible (a.right.target_type)) {
- var delegate_type = (DelegateType) a.right.target_type;
-
- a.error = true;
- Report.error (a.right.source_reference, "method `%s' is incompatible with signal `%s', expected `%s'".printf (a.right.value_type.to_string (), a.right.target_type.to_string (), delegate_type.delegate_symbol.get_prototype_string (m.name)));
- return;
- }
- } else if (a.left is MemberAccess) {
- var ma = (MemberAccess) a.left;
-
- if (ma.symbol_reference is Property) {
- var prop = (Property) ma.symbol_reference;
-
- var dynamic_prop = prop as DynamicProperty;
- if (dynamic_prop != null) {
- dynamic_prop.property_type = a.right.value_type.copy ();
- a.left.value_type = dynamic_prop.property_type.copy ();
- }
-
- if (prop.set_accessor == null
- || (!prop.set_accessor.writable && !(find_current_method () is CreationMethod || is_in_constructor ()))) {
- ma.error = true;
- Report.error (ma.source_reference, "Property `%s' is read-only".printf (prop.get_full_name ()));
- return;
- }
- } else if (ma.symbol_reference is LocalVariable && a.right.value_type == null) {
- var local = (LocalVariable) ma.symbol_reference;
-
- if (a.right.symbol_reference is Method &&
- local.variable_type is DelegateType) {
- var m = (Method) a.right.symbol_reference;
- var dt = (DelegateType) local.variable_type;
- var cb = dt.delegate_symbol;
-
- /* check whether method matches callback type */
- if (!cb.matches_method (m)) {
- a.error = true;
- Report.error (a.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
- return;
- }
-
- a.right.value_type = local.variable_type;
- } else {
- a.error = true;
- Report.error (a.source_reference, "Assignment: Invalid callback assignment attempt");
- return;
- }
- } else if (ma.symbol_reference is Field && a.right.value_type == null) {
- var f = (Field) ma.symbol_reference;
-
- if (a.right.symbol_reference is Method &&
- f.field_type is DelegateType) {
- var m = (Method) a.right.symbol_reference;
- var dt = (DelegateType) f.field_type;
- var cb = dt.delegate_symbol;
-
- /* check whether method matches callback type */
- if (!cb.matches_method (m)) {
- f.error = true;
- Report.error (a.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
- return;
- }
-
- a.right.value_type = f.field_type;
- } else {
- a.error = true;
- Report.error (a.source_reference, "Assignment: Invalid callback assignment attempt");
- return;
- }
- } else if (a.left.value_type != null && a.right.value_type != null) {
- /* if there was an error on either side,
- * i.e. a.{left|right}.value_type == null, skip type check */
-
- if (!a.right.value_type.compatible (a.left.value_type)) {
- a.error = true;
- Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.value_type.to_string (), a.left.value_type.to_string ()));
- return;
- }
-
- if (a.right.value_type.is_disposable ()) {
- /* rhs transfers ownership of the expression */
- if (!(a.left.value_type is PointerType) && !a.left.value_type.value_owned) {
- /* lhs doesn't own the value */
- a.error = true;
- Report.error (a.source_reference, "Invalid assignment from owned expression to unowned variable");
- }
- } else if (a.left.value_type.value_owned) {
- /* lhs wants to own the value
- * rhs doesn't transfer the ownership
- * code generator needs to add reference
- * increment calls */
- }
- }
- } else if (a.left is ElementAccess) {
- var ea = (ElementAccess) a.left;
-
- if (!a.right.value_type.compatible (a.left.value_type)) {
- a.error = true;
- Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.value_type.to_string (), a.left.value_type.to_string ()));
- return;
- }
-
- if (a.right.value_type.is_disposable ()) {
- /* rhs transfers ownership of the expression */
-
- DataType element_type;
-
- if (ea.container.value_type is ArrayType) {
- var array_type = (ArrayType) ea.container.value_type;
- element_type = array_type.element_type;
- } else {
- var args = ea.container.value_type.get_type_arguments ();
- assert (args.size == 1);
- element_type = args.get (0);
- }
-
- if (!(element_type is PointerType) && !element_type.value_owned) {
- /* lhs doesn't own the value */
- a.error = true;
- Report.error (a.source_reference, "Invalid assignment from owned expression to unowned variable");
- return;
- }
- } else if (a.left.value_type.value_owned) {
- /* lhs wants to own the value
- * rhs doesn't transfer the ownership
- * code generator needs to add reference
- * increment calls */
- }
- } else {
- return;
- }
-
- if (a.left.value_type != null) {
- a.value_type = a.left.value_type.copy ();
- a.value_type.value_owned = false;
- } else {
- a.value_type = null;
- }
-
- a.add_error_types (a.left.get_error_types ());
- a.add_error_types (a.right.get_error_types ());
+ a.check (this);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]