Line data Source code
1 : /* valawithtatement.vala
2 : *
3 : * Copyright (C) 2020 Nick Schrader
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 : * Authors:
20 : * Nick Schrader <nick.schrader@mailbox.org>
21 : */
22 :
23 83 : public class Vala.WithStatement : Block {
24 : /**
25 : * Expression representing the type of body's dominant scope.
26 : */
27 : public Expression expression {
28 410 : get { return _expression; }
29 49 : private set {
30 264 : _expression = value;
31 49 : _expression.parent_node = this;
32 : }
33 : }
34 :
35 : /**
36 : * Specifies the with-variable.
37 : */
38 295 : public LocalVariable? with_variable { get; private set; }
39 :
40 : /**
41 : * The block which dominant scope is type of expression.
42 : */
43 : public Block body {
44 222 : get { return _body; }
45 49 : private set {
46 98 : _body = value;
47 49 : _body.parent_node = this;
48 : }
49 : }
50 :
51 49 : Expression _expression;
52 49 : Block _body;
53 :
54 147 : public WithStatement (LocalVariable? variable, Expression expression, Block body, SourceReference? source_reference = null) {
55 49 : base (source_reference);
56 49 : this.with_variable = variable;
57 49 : this.expression = expression;
58 49 : this.body = body;
59 : }
60 :
61 85 : public override void accept (CodeVisitor visitor) {
62 85 : visitor.visit_with_statement (this);
63 : }
64 :
65 49 : public override void accept_children (CodeVisitor visitor) {
66 49 : if (expression.symbol_reference == with_variable) {
67 36 : expression.accept (visitor);
68 : }
69 :
70 49 : if (with_variable != null) {
71 13 : with_variable.accept (visitor);
72 : }
73 :
74 49 : body.accept (visitor);
75 : }
76 :
77 49 : bool is_object_or_value_type (DataType? type) {
78 49 : if (type == null) {
79 4 : return false;
80 45 : } else if (type is PointerType) {
81 2 : var pointer_type = (PointerType) type;
82 2 : return is_object_or_value_type (pointer_type.base_type) && expression is PointerIndirection;
83 : } else {
84 43 : return type is ObjectType || type is ValueType;
85 : }
86 : }
87 :
88 48 : public override bool check (CodeContext context) {
89 48 : if (checked) {
90 0 : return !error;
91 : }
92 :
93 48 : checked = true;
94 :
95 48 : if (!expression.check (context)) {
96 1 : error = true;
97 1 : return false;
98 : }
99 :
100 47 : if (!is_object_or_value_type (expression.value_type)) {
101 7 : error = true;
102 7 : Report.error (expression.source_reference, "with statement expects an object or basic type");
103 7 : return false;
104 : }
105 :
106 40 : var local_var = expression.symbol_reference as LocalVariable;
107 40 : if (with_variable != null || local_var == null) {
108 25 : if (with_variable != null) {
109 13 : local_var = with_variable;
110 : } else {
111 12 : local_var = new LocalVariable (expression.value_type.copy (), get_temp_name (), expression, source_reference);
112 : }
113 25 : body.insert_statement (0, new DeclarationStatement (local_var, source_reference));
114 : }
115 40 : with_variable = local_var;
116 :
117 40 : var old_symbol = context.analyzer.current_symbol;
118 40 : owner = context.analyzer.current_symbol.scope;
119 40 : context.analyzer.current_symbol = this;
120 :
121 40 : if (!body.check (context)) {
122 2 : error = true;
123 : }
124 :
125 40 : context.analyzer.current_symbol = old_symbol;
126 :
127 40 : return !error;
128 : }
129 :
130 36 : public override void emit (CodeGenerator codegen) {
131 36 : if (expression.symbol_reference == with_variable) {
132 14 : expression.emit (codegen);
133 : }
134 36 : body.emit (codegen);
135 : }
136 :
137 37 : public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
138 37 : if (source_reference == null) {
139 34 : source_reference = this.source_reference;
140 : }
141 37 : expression.get_error_types (collection, source_reference);
142 37 : body.get_error_types (collection, source_reference);
143 : }
144 :
145 0 : public override void get_defined_variables (Collection<Variable> collection) {
146 0 : if (expression.symbol_reference != with_variable) {
147 0 : collection.add (with_variable);
148 : }
149 : }
150 : }
|