1 /* valasemanticanalyzer.vala
3 * Copyright (C) 2006-2010 Jürg Billeter
4 * Copyright (C) 2006-2008 Raffaele Sandrini
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
28 * Code visitor analyzing and checking code.
30 public class Vala
.SemanticAnalyzer
: CodeVisitor
{
31 public CodeContext context
{ get; set; }
33 public Symbol root_symbol
;
34 public Symbol current_symbol
{ get; set; }
35 public SourceFile current_source_file
{ get; set; }
37 public TypeSymbol? current_type_symbol
{
39 var sym
= current_symbol
;
41 if (sym is TypeSymbol
) {
42 return (TypeSymbol
) sym
;
44 sym
= sym
.parent_symbol
;
50 public Class? current_class
{
51 get { return current_type_symbol as Class
; }
55 public Struct? current_struct
{
56 get { return current_type_symbol as Struct
; }
59 public Method? current_method
{
61 unowned Symbol sym
= current_symbol
;
62 while (sym is Block
) {
63 sym
= sym
.parent_symbol
;
69 public Method? current_async_method
{
71 unowned Symbol sym
= current_symbol
;
72 while (sym is Block
|| sym is Method
) {
73 var m
= sym as Method
;
74 if (m
!= null && m
.coroutine
) {
78 sym
= sym
.parent_symbol
;
84 public PropertyAccessor? current_property_accessor
{
86 unowned Symbol sym
= current_symbol
;
87 while (sym is Block
) {
88 sym
= sym
.parent_symbol
;
90 return sym as PropertyAccessor
;
94 public Symbol? current_method_or_property_accessor
{
96 unowned Symbol sym
= current_symbol
;
97 while (sym is Block
) {
98 sym
= sym
.parent_symbol
;
102 } else if (sym is PropertyAccessor
) {
110 public DataType? current_return_type
{
112 var m
= current_method
;
114 return m
.return_type
;
117 var acc
= current_property_accessor
;
120 return acc
.value_type
;
126 if (is_in_constructor () || is_in_destructor ()) {
134 public Block insert_block
;
136 public DataType void_type
= new
VoidType ();
137 public DataType bool_type
;
138 public DataType string_type
;
139 public DataType regex_type
;
140 public DataType uchar_type
;
141 public DataType short_type
;
142 public DataType ushort_type
;
143 public DataType int_type
;
144 public DataType uint_type
;
145 public DataType long_type
;
146 public DataType ulong_type
;
147 public DataType size_t_type
;
148 public DataType ssize_t_type
;
149 public DataType int8_type
;
150 public DataType unichar_type
;
151 public DataType double_type
;
152 public DataType type_type
;
153 public Class object_type
;
154 public StructValueType gvalue_type
;
155 public DataType glist_type
;
156 public DataType gslist_type
;
157 public DataType garray_type
;
158 public DataType gvaluearray_type
;
159 public Class gerror_type
;
160 public DataType list_type
;
161 public DataType tuple_type
;
162 public DataType error_type
;
164 public int next_lambda_id
= 0;
166 // keep replaced alive to make sure they remain valid
167 // for the whole execution of CodeNode.accept
168 public List
<CodeNode
> replaced_nodes
= new ArrayList
<CodeNode
> ();
170 public SemanticAnalyzer () {
174 * Analyze and check code in the specified context.
176 * @param context a code context
178 public void analyze (CodeContext context
) {
179 this
.context
= context
;
181 root_symbol
= context
.root
;
183 bool_type
= new
BooleanType ((Struct
) root_symbol
.scope
.lookup ("bool"));
184 string_type
= new
ObjectType ((Class
) root_symbol
.scope
.lookup ("string"));
185 int_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("int"));
186 uint_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("uint"));
187 double_type
= new
FloatingType ((Struct
) root_symbol
.scope
.lookup ("double"));
189 if (context
.profile
!= Profile
.DOVA
) {
190 uchar_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("uchar"));
191 int8_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("int8"));
192 short_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("short"));
193 ushort_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("ushort"));
194 long_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("long"));
195 ulong_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("ulong"));
196 size_t_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("size_t"));
197 ssize_t_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("ssize_t"));
199 long_type
= int_type
;
200 ulong_type
= uint_type
;
201 size_t_type
= uint_type
;
202 ssize_t_type
= int_type
;
205 var unichar_struct
= (Struct
) root_symbol
.scope
.lookup ("unichar");
206 if (unichar_struct
!= null) {
207 unichar_type
= new
IntegerType (unichar_struct
);
210 if (context
.profile
== Profile
.GOBJECT
) {
211 var glib_ns
= root_symbol
.scope
.lookup ("GLib");
213 object_type
= (Class
) glib_ns
.scope
.lookup ("Object");
214 type_type
= new
IntegerType ((Struct
) glib_ns
.scope
.lookup ("Type"));
215 gvalue_type
= new
StructValueType ((Struct
) glib_ns
.scope
.lookup ("Value"));
217 glist_type
= new
ObjectType ((Class
) glib_ns
.scope
.lookup ("List"));
218 gslist_type
= new
ObjectType ((Class
) glib_ns
.scope
.lookup ("SList"));
219 garray_type
= new
ObjectType ((Class
) glib_ns
.scope
.lookup ("Array"));
220 gvaluearray_type
= new
ObjectType ((Class
) glib_ns
.scope
.lookup ("ValueArray"));
222 gerror_type
= (Class
) glib_ns
.scope
.lookup ("Error");
223 regex_type
= new
ObjectType ((Class
) root_symbol
.scope
.lookup ("GLib").scope
.lookup ("Regex"));
224 } else if (context
.profile
== Profile
.DOVA
) {
225 var dova_ns
= root_symbol
.scope
.lookup ("Dova");
227 object_type
= (Class
) dova_ns
.scope
.lookup ("Object");
228 type_type
= new
ObjectType ((Class
) dova_ns
.scope
.lookup ("Type"));
229 list_type
= new
ObjectType ((Class
) dova_ns
.scope
.lookup ("List"));
230 tuple_type
= new
ObjectType ((Class
) dova_ns
.scope
.lookup ("Tuple"));
231 error_type
= new
ObjectType ((Class
) dova_ns
.scope
.lookup ("Error"));
234 current_symbol
= root_symbol
;
235 context
.root
.check (context
);
236 context
.accept (this
);
239 public override void visit_source_file (SourceFile file
) {
240 current_source_file
= file
;
242 file
.check (context
);
245 // check whether type is at least as accessible as the specified symbol
246 public bool is_type_accessible (Symbol sym
, DataType type
) {
247 return type
.is_accessible (sym
);
250 public DataType?
get_value_type_for_symbol (Symbol sym
, bool lvalue
) {
253 var type
= f
.variable_type
.copy ();
255 type
.value_owned
= false;
258 } else if (sym is EnumValue
) {
259 return new
EnumValueType ((Enum
) sym
.parent_symbol
);
260 } else if (sym is Constant
) {
261 var c
= (Constant
) sym
;
262 return c
.type_reference
;
263 } else if (sym is Property
) {
264 var prop
= (Property
) sym
;
266 if (prop
.set_accessor
!= null && prop
.set_accessor
.value_type
!= null) {
267 return prop
.set_accessor
.value_type
.copy ();
270 if (prop
.get_accessor
!= null && prop
.get_accessor
.value_type
!= null) {
271 return prop
.get_accessor
.value_type
.copy ();
274 } else if (sym is Parameter
) {
275 var p
= (Parameter
) sym
;
276 var type
= p
.variable_type
.copy ();
278 type
.value_owned
= false;
281 } else if (sym is LocalVariable
) {
282 var local
= (LocalVariable
) sym
;
283 var type
= local
.variable_type
.copy ();
284 if (!lvalue
&& !local
.floating
) {
285 type
.value_owned
= false;
288 } else if (sym is Method
) {
289 return new
MethodType ((Method
) sym
);
290 } else if (sym is Signal
) {
291 return new
SignalType ((Signal
) sym
);
296 public static Symbol?
symbol_lookup_inherited (Symbol sym
, string name
) {
297 var result
= sym
.scope
.lookup (name
);
298 if (result
!= null) {
303 var cl
= (Class
) sym
;
304 // first check interfaces without prerequisites
305 // (prerequisites can be assumed to be met already)
306 foreach (DataType base_type
in cl
.get_base_types ()) {
307 if (base_type
.data_type is Interface
) {
308 result
= base_type
.data_type
.scope
.lookup (name
);
309 if (result
!= null) {
314 // then check base class recursively
315 if (cl
.base_class
!= null) {
316 return symbol_lookup_inherited (cl
.base_class
, name
);
318 } else if (sym is Struct
) {
319 var st
= (Struct
) sym
;
320 if (st
.base_type
!= null) {
321 result
= symbol_lookup_inherited (st
.base_type
.data_type
, name
);
322 if (result
!= null) {
326 } else if (sym is Interface
) {
327 var iface
= (Interface
) sym
;
328 // first check interface prerequisites recursively
329 foreach (DataType prerequisite
in iface
.get_prerequisites ()) {
330 if (prerequisite
.data_type is Interface
) {
331 result
= symbol_lookup_inherited (prerequisite
.data_type
, name
);
332 if (result
!= null) {
337 // then check class prerequisite recursively
338 foreach (DataType prerequisite
in iface
.get_prerequisites ()) {
339 if (prerequisite
.data_type is Class
) {
340 result
= symbol_lookup_inherited (prerequisite
.data_type
, name
);
341 if (result
!= null) {
351 public static DataType
get_data_type_for_symbol (TypeSymbol sym
) {
352 DataType type
= null;
354 if (sym is ObjectTypeSymbol
) {
355 type
= new
ObjectType ((ObjectTypeSymbol
) sym
);
356 } else if (sym is Struct
) {
357 var st
= (Struct
) sym
;
358 if (st
.is_boolean_type ()) {
359 type
= new
BooleanType (st
);
360 } else if (st
.is_integer_type ()) {
361 type
= new
IntegerType (st
);
362 } else if (st
.is_floating_type ()) {
363 type
= new
FloatingType (st
);
365 type
= new
StructValueType (st
);
367 } else if (sym is Enum
) {
368 type
= new
EnumValueType ((Enum
) sym
);
369 } else if (sym is ErrorDomain
) {
370 type
= new
ErrorType ((ErrorDomain
) sym
, null);
371 } else if (sym is ErrorCode
) {
372 type
= new
ErrorType ((ErrorDomain
) sym
.parent_symbol
, (ErrorCode
) sym
);
374 Report
.error (null, "internal error: `%s' is not a supported type".printf (sym
.get_full_name ()));
375 return new
InvalidType ();
381 public bool check_arguments (Expression expr
, DataType mtype
, List
<Parameter
> params
, List
<Expression
> args
) {
382 Expression prev_arg
= null;
383 Iterator
<Expression
> arg_it
= args
.iterator ();
385 bool diag
= (mtype is MethodType
&& ((MethodType
) mtype
).method_symbol
.get_attribute ("Diagnostics") != null);
387 bool ellipsis
= false;
389 foreach (Parameter param
in params
) {
390 if (!param
.check (context
)) {
394 if (param
.ellipsis
) {
399 if (param
.params_array
) {
400 while (arg_it
.next ()) {
401 var arg
= arg_it
.get ();
402 if (!check_argument (arg
, i
, param
.direction
)) {
413 if (arg_it
== null || !arg_it
.next ()) {
414 if (param
.initializer
== null) {
416 var m
= mtype as MethodType
;
418 Report
.error (expr
.source_reference
, "%d missing arguments for `%s'".printf (m
.get_parameters ().size
- args
.size
, m
.to_prototype_string ()));
420 Report
.error (expr
.source_reference
, "Too few arguments, method `%s' does not take %d arguments".printf (mtype
.to_string (), args
.size
));
424 var invocation_expr
= expr as MethodCall
;
425 var object_creation_expr
= expr as ObjectCreationExpression
;
426 if (invocation_expr
!= null) {
427 invocation_expr
.add_argument (param
.initializer
);
428 } else if (object_creation_expr
!= null) {
429 object_creation_expr
.add_argument (param
.initializer
);
431 assert_not_reached ();
436 var arg
= arg_it
.get ();
437 if (!check_argument (arg
, i
, param
.direction
)) {
449 while (arg_it
!= null && arg_it
.next ()) {
450 var arg
= arg_it
.get ();
452 // ignore inner error
455 } else if (arg
.value_type is SignalType
) {
457 Report
.error (arg
.source_reference
, "Cannot pass signals as arguments");
459 } else if (arg
.value_type
== null) {
460 // disallow untyped arguments except for type inference of callbacks
461 if (!(arg
.symbol_reference is Method
)) {
463 Report
.error (expr
.source_reference
, "Invalid type for argument %d".printf (i
+ 1));
466 } else if (arg
.target_type
!= null && !arg
.value_type
.compatible (arg
.target_type
)) {
467 // target_type known for printf arguments
469 Report
.error (arg
.source_reference
, "Argument %d: Cannot convert from `%s' to `%s'".printf (i
+ 1, arg
.value_type
.to_string (), arg
.target_type
.to_string ()));
475 } else if (!ellipsis
&& arg_it
!= null && arg_it
.next ()) {
477 var m
= mtype as MethodType
;
479 Report
.error (expr
.source_reference
, "%d extra arguments for `%s'".printf (args
.size
- m
.get_parameters ().size
, m
.to_prototype_string ()));
481 Report
.error (expr
.source_reference
, "Too many arguments, method `%s' does not take %d arguments".printf (mtype
.to_string (), args
.size
));
486 if (diag
&& prev_arg
!= null) {
487 var format_arg
= prev_arg as StringLiteral
;
488 if (format_arg
!= null) {
489 format_arg
.value
= "\"%s:%d: %s".printf (Path
.get_basename (expr
.source_reference
.file
.filename
), expr
.source_reference
.first_line
, format_arg
.value
.substring (1));
496 bool check_argument (Expression arg
, int i
, ParameterDirection direction
) {
498 // ignore inner error
500 } else if (arg is NamedArgument
) {
501 Report
.error (arg
.source_reference
, "Named arguments are not supported yet");
503 } else if (arg
.value_type
== null) {
504 // disallow untyped arguments except for type inference of callbacks
505 if (!(arg
.target_type is DelegateType
) || !(arg
.symbol_reference is Method
)) {
506 Report
.error (arg
.source_reference
, "Invalid type for argument %d".printf (i
+ 1));
509 } else if (arg
.target_type
!= null
510 && (direction
== ParameterDirection
.IN
|| direction
== ParameterDirection
.REF
)
511 && !arg
.value_type
.compatible (arg
.target_type
)) {
512 Report
.error (arg
.source_reference
, "Argument %d: Cannot convert from `%s' to `%s'".printf (i
+ 1, arg
.value_type
.to_string (), arg
.target_type
.to_string ()));
514 } else if (arg
.target_type
!= null
515 && (direction
== ParameterDirection
.REF
|| direction
== ParameterDirection
.OUT
)
516 && !arg
.target_type
.compatible (arg
.value_type
)
517 && !(arg is NullLiteral
)) {
518 Report
.error (arg
.source_reference
, "Argument %d: Cannot convert from `%s' to `%s'".printf (i
+ 1, arg
.target_type
.to_string (), arg
.value_type
.to_string ()));
521 // 0 => null, 1 => in, 2 => ref, 3 => out
523 if (arg
.value_type is NullType
) {
525 } else if (arg is UnaryExpression
) {
526 var unary
= (UnaryExpression
) arg
;
527 if (unary
.operator
== UnaryOperator
.REF
) {
529 } else if (unary
.operator
== UnaryOperator
.OUT
) {
535 if (direction
== ParameterDirection
.REF
) {
536 Report
.error (arg
.source_reference
, "Argument %d: Cannot pass null to reference parameter".printf (i
+ 1));
538 } else if (direction
!= ParameterDirection
.OUT
&& !arg
.target_type
.nullable
) {
539 Report
.warning (arg
.source_reference
, "Argument %d: Cannot pass null to non-null parameter type".printf (i
+ 1));
541 } else if (arg_type
== 1) {
542 if (direction
!= ParameterDirection
.IN
) {
543 Report
.error (arg
.source_reference
, "Argument %d: Cannot pass value to reference or output parameter".printf (i
+ 1));
546 } else if (arg_type
== 2) {
547 if (direction
!= ParameterDirection
.REF
) {
548 Report
.error (arg
.source_reference
, "Argument %d: Cannot pass ref argument to non-reference parameter".printf (i
+ 1));
552 // weak variables can only be used with weak ref parameters
553 if (arg
.target_type
.is_disposable ()) {
554 if (!(arg
.value_type is PointerType
) && !arg
.value_type
.value_owned
) {
555 /* variable doesn't own the value */
556 Report
.error (arg
.source_reference
, "Argument %d: Cannot pass unowned ref argument to owned reference parameter".printf (i
+ 1));
561 // owned variables can only be used with owned ref parameters
562 if (arg
.value_type
.is_disposable ()) {
563 if (!arg
.target_type
.value_owned
) {
564 /* parameter doesn't own the value */
565 Report
.error (arg
.source_reference
, "Argument %d: Cannot pass owned ref argument to unowned reference parameter".printf (i
+ 1));
569 } else if (arg_type
== 3) {
570 if (direction
!= ParameterDirection
.OUT
) {
571 Report
.error (arg
.source_reference
, "Argument %d: Cannot pass out argument to non-output parameter".printf (i
+ 1));
575 // weak variables can only be used with weak out parameters
576 if (arg
.target_type
.is_disposable ()) {
577 if (!(arg
.value_type is PointerType
) && !arg
.value_type
.value_owned
) {
578 /* variable doesn't own the value */
579 Report
.error (arg
.source_reference
, "Invalid assignment from owned expression to unowned variable");
585 var ma
= arg as MemberAccess
;
586 if (ma
!= null && ma
.prototype_access
) {
587 // allow prototype access if target type is delegate without target
588 var deleg_type
= arg
.target_type as DelegateType
;
589 if (deleg_type
== null || deleg_type
.delegate_symbol
.has_target
) {
590 Report
.error (arg
.source_reference
, "Access to instance member `%s' denied".printf (arg
.symbol_reference
.get_full_name ()));
597 private static DataType?
get_instance_base_type (DataType instance_type
, DataType base_type
, CodeNode node_reference
) {
598 // construct a new type reference for the base type with correctly linked type arguments
599 ReferenceType instance_base_type
;
600 if (base_type
.data_type is Class
) {
601 instance_base_type
= new
ObjectType ((Class
) base_type
.data_type
);
603 instance_base_type
= new
ObjectType ((Interface
) base_type
.data_type
);
605 foreach (DataType type_arg
in base_type
.get_type_arguments ()) {
606 // resolve type argument specified in base type (possibly recursively for nested generic types)
607 type_arg
= type_arg
.get_actual_type (instance_type
, null, node_reference
);
608 instance_base_type
.add_type_argument (type_arg
);
610 return instance_base_type
;
613 static DataType?
get_instance_base_type_for_member (DataType derived_instance_type
, TypeSymbol type_symbol
, CodeNode node_reference
) {
614 DataType instance_type
= derived_instance_type
;
616 while (instance_type is PointerType
) {
617 var instance_pointer_type
= (PointerType
) instance_type
;
618 instance_type
= instance_pointer_type
.base_type
;
621 if (CodeContext
.get ().profile
== Profile
.DOVA
) {
622 while (instance_type is ArrayType
) {
623 var instance_array_type
= (ArrayType
) instance_type
;
624 instance_type
= new
ObjectType ((Class
) CodeContext
.get ().root
.scope
.lookup ("Dova").scope
.lookup ("Array"));
625 instance_type
.add_type_argument (instance_array_type
.element_type
);
629 if (instance_type is DelegateType
&& ((DelegateType
) instance_type
).delegate_symbol
== type_symbol
) {
630 return instance_type
;
631 } else if (instance_type
.data_type
== type_symbol
) {
632 return instance_type
;
635 DataType instance_base_type
= null;
637 // use same algorithm as symbol_lookup_inherited
638 if (instance_type
.data_type is Class
) {
639 var cl
= (Class
) instance_type
.data_type
;
640 // first check interfaces without prerequisites
641 // (prerequisites can be assumed to be met already)
642 foreach (DataType base_type
in cl
.get_base_types ()) {
643 if (base_type
.data_type is Interface
) {
644 instance_base_type
= get_instance_base_type_for_member (get_instance_base_type (instance_type
, base_type
, node_reference
), type_symbol
, node_reference
);
645 if (instance_base_type
!= null) {
646 return instance_base_type
;
650 // then check base class recursively
651 if (instance_base_type
== null) {
652 foreach (DataType base_type
in cl
.get_base_types ()) {
653 if (base_type
.data_type is Class
) {
654 instance_base_type
= get_instance_base_type_for_member (get_instance_base_type (instance_type
, base_type
, node_reference
), type_symbol
, node_reference
);
655 if (instance_base_type
!= null) {
656 return instance_base_type
;
661 } else if (instance_type
.data_type is Struct
) {
662 var st
= (Struct
) instance_type
.data_type
;
663 if (st
.base_type
!= null) {
664 instance_base_type
= get_instance_base_type_for_member (get_instance_base_type (instance_type
, st
.base_type
, node_reference
), type_symbol
, node_reference
);
665 if (instance_base_type
!= null) {
666 return instance_base_type
;
669 } else if (instance_type
.data_type is Interface
) {
670 var iface
= (Interface
) instance_type
.data_type
;
671 // first check interface prerequisites recursively
672 foreach (DataType prerequisite
in iface
.get_prerequisites ()) {
673 if (prerequisite
.data_type is Interface
) {
674 instance_base_type
= get_instance_base_type_for_member (get_instance_base_type (instance_type
, prerequisite
, node_reference
), type_symbol
, node_reference
);
675 if (instance_base_type
!= null) {
676 return instance_base_type
;
680 if (instance_base_type
== null) {
681 // then check class prerequisite recursively
682 foreach (DataType prerequisite
in iface
.get_prerequisites ()) {
683 if (prerequisite
.data_type is Class
) {
684 instance_base_type
= get_instance_base_type_for_member (get_instance_base_type (instance_type
, prerequisite
, node_reference
), type_symbol
, node_reference
);
685 if (instance_base_type
!= null) {
686 return instance_base_type
;
696 public static DataType?
get_actual_type (DataType? derived_instance_type
, MemberAccess? method_access
, GenericType generic_type
, CodeNode node_reference
) {
697 DataType actual_type
= null;
698 if (generic_type
.type_parameter
.parent_symbol is TypeSymbol
) {
699 if (derived_instance_type
!= null) {
700 // trace type arguments back to the datatype where the method has been declared
701 var instance_type
= get_instance_base_type_for_member (derived_instance_type
, (TypeSymbol
) generic_type
.type_parameter
.parent_symbol
, node_reference
);
703 assert (instance_type
!= null);
706 if (instance_type is DelegateType
) {
707 param_index
= ((DelegateType
) instance_type
).delegate_symbol
.get_type_parameter_index (generic_type
.type_parameter
.name
);
709 param_index
= instance_type
.data_type
.get_type_parameter_index (generic_type
.type_parameter
.name
);
711 if (param_index
== -1) {
712 Report
.error (node_reference
.source_reference
, "internal error: unknown type parameter %s".printf (generic_type
.type_parameter
.name
));
713 node_reference
.error
= true;
717 if (param_index
< instance_type
.get_type_arguments ().size
) {
718 actual_type
= (DataType
) instance_type
.get_type_arguments ().get (param_index
);
723 var m
= (Method
) generic_type
.type_parameter
.parent_symbol
;
725 if (method_access
== null) {
729 int param_index
= m
.get_type_parameter_index (generic_type
.type_parameter
.name
);
730 if (param_index
== -1) {
731 Report
.error (node_reference
.source_reference
, "internal error: unknown type parameter %s".printf (generic_type
.type_parameter
.name
));
732 node_reference
.error
= true;
736 if (param_index
< method_access
.get_type_arguments ().size
) {
737 actual_type
= (DataType
) method_access
.get_type_arguments ().get (param_index
);
741 if (actual_type
== null) {
742 // no actual type available
745 actual_type
= actual_type
.copy ();
746 actual_type
.value_owned
= actual_type
.value_owned
&& generic_type
.value_owned
;
750 public bool is_in_instance_method () {
751 var sym
= current_symbol
;
752 while (sym
!= null) {
753 if (sym is CreationMethod
) {
755 } else if (sym is Method
) {
756 var m
= (Method
) sym
;
757 return m
.binding
== MemberBinding
.INSTANCE
;
758 } else if (sym is Constructor
) {
759 var c
= (Constructor
) sym
;
760 return c
.binding
== MemberBinding
.INSTANCE
;
761 } else if (sym is Destructor
) {
763 } else if (sym is Property
) {
764 var p
= (Property
) sym
;
765 return p
.binding
== MemberBinding
.INSTANCE
;
767 sym
= sym
.parent_symbol
;
773 public void visit_member_initializer (MemberInitializer init
, DataType type
) {
774 init
.symbol_reference
= symbol_lookup_inherited (type
.data_type
, init
.name
);
775 if (!(init
.symbol_reference is Field
|| init
.symbol_reference is Property
)) {
777 Report
.error (init
.source_reference
, "Invalid member `%s' in `%s'".printf (init
.name
, type
.data_type
.get_full_name ()));
780 if (init
.symbol_reference
.access
!= SymbolAccessibility
.PUBLIC
) {
782 Report
.error (init
.source_reference
, "Access to private member `%s' denied".printf (init
.symbol_reference
.get_full_name ()));
785 DataType member_type
= null;
786 if (init
.symbol_reference is Field
) {
787 var f
= (Field
) init
.symbol_reference
;
788 member_type
= f
.variable_type
;
789 } else if (init
.symbol_reference is Property
) {
790 var prop
= (Property
) init
.symbol_reference
;
791 member_type
= prop
.property_type
;
792 if (prop
.set_accessor
== null || !prop
.set_accessor
.writable
) {
794 Report
.error (init
.source_reference
, "Property `%s' is read-only".printf (prop
.get_full_name ()));
799 init
.initializer
.formal_target_type
= member_type
;
800 init
.initializer
.target_type
= init
.initializer
.formal_target_type
.get_actual_type (type
, null, init
);;
802 init
.check (context
);
804 if (init
.initializer
.value_type
== null || !init
.initializer
.value_type
.compatible (init
.initializer
.target_type
)) {
806 Report
.error (init
.source_reference
, "Invalid type for member `%s'".printf (init
.name
));
811 Struct?
get_arithmetic_struct (DataType type
) {
812 var result
= type
.data_type as Struct
;
813 if (result
== null && type is EnumValueType
) {
814 return (Struct
) int_type
.data_type
;
819 public DataType?
get_arithmetic_result_type (DataType left_type
, DataType right_type
) {
820 var left
= get_arithmetic_struct (left_type
);
821 var right
= get_arithmetic_struct (right_type
);
823 if (left
== null || right
== null) {
824 // at least one operand not struct
828 if ((!left
.is_floating_type () && !left
.is_integer_type ()) ||
829 (!right
.is_floating_type () && !right
.is_integer_type ())) {
830 // at least one operand not numeric
834 if (left
.is_floating_type () == right
.is_floating_type ()) {
835 // both operands integer or floating type
836 if (left
.get_rank () >= right
.get_rank ()) {
842 // one integer and one floating type operand
843 if (left
.is_floating_type ()) {
851 public Method?
find_current_method () {
852 var sym
= current_symbol
;
853 while (sym
!= null) {
857 sym
= sym
.parent_symbol
;
862 public Method?
find_parent_method (Symbol sym
) {
863 while (sym is Block
) {
864 sym
= sym
.parent_symbol
;
866 return sym as Method
;
869 public Symbol?
find_parent_method_or_property_accessor (Symbol sym
) {
870 while (sym is Block
) {
871 sym
= sym
.parent_symbol
;
875 } else if (sym is PropertyAccessor
) {
882 public bool is_in_constructor () {
883 var sym
= current_symbol
;
884 while (sym
!= null) {
885 if (sym is Constructor
) {
888 sym
= sym
.parent_symbol
;
893 public bool is_in_destructor () {
894 var sym
= current_symbol
;
895 while (sym
!= null) {
896 if (sym is Destructor
) {
899 sym
= sym
.parent_symbol
;