Line data Source code
1 : /* valareferencetransferexpression.vala
2 : *
3 : * Copyright (C) 2007-2010 Jürg Billeter
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Lesser General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2.1 of the License, or (at your option) any later version.
9 :
10 : * This library is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Lesser General Public License for more details.
14 :
15 : * You should have received a copy of the GNU Lesser General Public
16 : * License along with this library; if not, write to the Free Software
17 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 : *
19 : * Author:
20 : * Jürg Billeter <j@bitron.ch>
21 : */
22 :
23 :
24 : /**
25 : * Represents a reference transfer expression.
26 : *
27 : * {{{ (owned) foo }}}
28 : */
29 19771 : public class Vala.ReferenceTransferExpression : Expression {
30 : /**
31 : * The variable whose reference is to be transferred.
32 : */
33 : public Expression inner {
34 337720 : get {
35 337720 : return _inner;
36 : }
37 18243 : private set {
38 18243 : _inner = value;
39 18243 : _inner.parent_node = this;
40 : }
41 : }
42 :
43 18241 : private Expression _inner;
44 :
45 : /**
46 : * Creates a new reference transfer expression.
47 : *
48 : * @param inner variable whose reference is to be transferred
49 : * @return newly created reference transfer expression
50 : */
51 54723 : public ReferenceTransferExpression (Expression inner, SourceReference? source_reference = null) {
52 18241 : this.inner = inner;
53 18241 : this.source_reference = source_reference;
54 : }
55 :
56 50045 : public override void accept (CodeVisitor visitor) {
57 50045 : visitor.visit_reference_transfer_expression (this);
58 :
59 50045 : visitor.visit_expression (this);
60 : }
61 :
62 50045 : public override void accept_children (CodeVisitor visitor) {
63 50045 : inner.accept (visitor);
64 : }
65 :
66 2 : public override void replace_expression (Expression old_node, Expression new_node) {
67 2 : if (inner == old_node) {
68 2 : inner = new_node;
69 : }
70 : }
71 :
72 0 : public override bool is_pure () {
73 0 : return false;
74 : }
75 :
76 0 : public override bool is_accessible (Symbol sym) {
77 0 : return inner.is_accessible (sym);
78 : }
79 :
80 17109 : public override bool check (CodeContext context) {
81 17109 : if (checked) {
82 9 : return !error;
83 : }
84 :
85 17100 : checked = true;
86 :
87 17100 : inner.lvalue = true;
88 :
89 17100 : inner.check (context);
90 :
91 17100 : if (inner.error) {
92 : /* if there was an error in the inner expression, skip type check */
93 0 : error = true;
94 0 : return false;
95 : }
96 :
97 17100 : if (!(inner is MemberAccess || inner is ElementAccess)) {
98 1 : error = true;
99 1 : Report.error (source_reference, "Reference transfer not supported for this expression");
100 1 : return false;
101 : }
102 :
103 17099 : if (inner.value_type is ArrayType && ((ArrayType) inner.value_type).inline_allocated) {
104 1 : error = true;
105 1 : Report.error (source_reference, "Ownership of inline-allocated array cannot be transferred");
106 1 : return false;
107 : }
108 :
109 17098 : var is_owned_delegate = inner.value_type is DelegateType && inner.value_type.value_owned;
110 17098 : if (!inner.value_type.is_disposable ()
111 4249 : && !(inner.value_type is PointerType)
112 3 : && !is_owned_delegate) {
113 1 : error = true;
114 1 : Report.error (source_reference, "No reference to be transferred");
115 1 : return false;
116 : }
117 :
118 17097 : value_type = inner.value_type.copy ();
119 17097 : value_type.value_owned = true;
120 17097 : value_type.check (context);
121 :
122 17097 : return !error;
123 : }
124 :
125 167 : public override void emit (CodeGenerator codegen) {
126 167 : inner.emit (codegen);
127 :
128 167 : codegen.visit_reference_transfer_expression (this);
129 :
130 167 : codegen.visit_expression (this);
131 : }
132 :
133 35016 : public override void get_defined_variables (Collection<Variable> collection) {
134 35016 : inner.get_defined_variables (collection);
135 35016 : unowned LocalVariable? local = inner.symbol_reference as LocalVariable;
136 35016 : unowned Parameter? param = inner.symbol_reference as Parameter;
137 35016 : if (local != null) {
138 14736 : collection.add (local);
139 20280 : } else if (param != null && param.direction == ParameterDirection.OUT) {
140 0 : collection.add (param);
141 : }
142 : }
143 :
144 11672 : public override void get_used_variables (Collection<Variable> collection) {
145 11672 : inner.get_used_variables (collection);
146 11672 : unowned LocalVariable? local = inner.symbol_reference as LocalVariable;
147 11672 : unowned Parameter? param = inner.symbol_reference as Parameter;
148 11672 : if (local != null) {
149 4912 : collection.add (local);
150 6760 : } else if (param != null && param.direction == ParameterDirection.OUT) {
151 0 : collection.add (param);
152 : }
153 : }
154 :
155 0 : public override string to_string () {
156 0 : return "(owned) %s".printf (inner.to_string ());
157 : }
158 : }
|