1 /* valasemanticanalyzer.vala
3 * Copyright (C) 2006-2009 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 var sym
= current_symbol
;
62 while (sym is Block
) {
63 sym
= sym
.parent_symbol
;
69 public PropertyAccessor? current_property_accessor
{
71 var sym
= current_symbol
;
72 while (sym is Block
) {
73 sym
= sym
.parent_symbol
;
75 return sym as PropertyAccessor
;
79 public DataType? current_return_type
{
81 var m
= current_method
;
86 var acc
= current_property_accessor
;
89 return acc
.value_type
;
99 public Block insert_block
;
101 public DataType void_type
= new
VoidType ();
102 public DataType bool_type
;
103 public DataType string_type
;
104 public DataType uchar_type
;
105 public DataType short_type
;
106 public DataType ushort_type
;
107 public DataType int_type
;
108 public DataType uint_type
;
109 public DataType long_type
;
110 public DataType ulong_type
;
111 public DataType size_t_type
;
112 public DataType ssize_t_type
;
113 public DataType int8_type
;
114 public DataType unichar_type
;
115 public DataType double_type
;
116 public DataType type_type
;
117 public Class object_type
;
118 public StructValueType gvalue_type
;
119 public DataType glist_type
;
120 public DataType gslist_type
;
121 public DataType garray_type
;
122 public DataType gvaluearray_type
;
123 public Class gerror_type
;
125 public int next_lambda_id
= 0;
127 // keep replaced alive to make sure they remain valid
128 // for the whole execution of CodeNode.accept
129 public List
<CodeNode
> replaced_nodes
= new ArrayList
<CodeNode
> ();
131 public SemanticAnalyzer () {
135 * Analyze and check code in the specified context.
137 * @param context a code context
139 public void analyze (CodeContext context
) {
140 this
.context
= context
;
142 root_symbol
= context
.root
;
144 bool_type
= new
BooleanType ((Struct
) root_symbol
.scope
.lookup ("bool"));
145 string_type
= new
ObjectType ((Class
) root_symbol
.scope
.lookup ("string"));
147 uchar_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("uchar"));
148 short_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("short"));
149 ushort_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("ushort"));
150 int_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("int"));
151 uint_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("uint"));
152 long_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("long"));
153 ulong_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("ulong"));
154 int8_type
= new
IntegerType ((Struct
) root_symbol
.scope
.lookup ("int8"));
155 double_type
= new
FloatingType ((Struct
) root_symbol
.scope
.lookup ("double"));
157 var unichar_struct
= (Struct
) root_symbol
.scope
.lookup ("unichar");
158 if (unichar_struct
!= null) {
159 unichar_type
= new
IntegerType (unichar_struct
);
161 var size_t_struct
= (Struct
) root_symbol
.scope
.lookup ("size_t");
162 if (size_t_struct
!= null) {
163 size_t_type
= new
IntegerType (size_t_struct
);
165 var ssize_t_struct
= (Struct
) root_symbol
.scope
.lookup ("ssize_t");
166 if (ssize_t_struct
!= null) {
167 ssize_t_type
= new
IntegerType (ssize_t_struct
);
170 if (context
.profile
== Profile
.GOBJECT
) {
171 var glib_ns
= root_symbol
.scope
.lookup ("GLib");
173 object_type
= (Class
) glib_ns
.scope
.lookup ("Object");
174 type_type
= new
IntegerType ((Struct
) glib_ns
.scope
.lookup ("Type"));
175 gvalue_type
= new
StructValueType ((Struct
) glib_ns
.scope
.lookup ("Value"));
177 glist_type
= new
ObjectType ((Class
) glib_ns
.scope
.lookup ("List"));
178 gslist_type
= new
ObjectType ((Class
) glib_ns
.scope
.lookup ("SList"));
179 garray_type
= new
ObjectType ((Class
) glib_ns
.scope
.lookup ("Array"));
180 gvaluearray_type
= new
ObjectType ((Class
) glib_ns
.scope
.lookup ("ValueArray"));
182 gerror_type
= (Class
) glib_ns
.scope
.lookup ("Error");
185 current_symbol
= root_symbol
;
186 context
.root
.check (this
);
187 context
.accept (this
);
190 public override void visit_source_file (SourceFile file
) {
191 current_source_file
= file
;
196 // check whether type is at least as accessible as the specified symbol
197 public bool is_type_accessible (Symbol sym
, DataType type
) {
198 foreach (Symbol type_symbol
in type
.get_symbols ()) {
199 Scope method_scope
= sym
.get_top_accessible_scope ();
200 Scope type_scope
= type_symbol
.get_top_accessible_scope ();
201 if ((method_scope
== null && type_scope
!= null)
202 || (method_scope
!= null && !method_scope
.is_subscope_of (type_scope
))) {
210 public DataType?
get_value_type_for_symbol (Symbol sym
, bool lvalue
) {
213 var type
= f
.field_type
.copy ();
215 type
.value_owned
= false;
218 } else if (sym is Constant
) {
219 var c
= (Constant
) sym
;
220 return c
.type_reference
;
221 } else if (sym is Property
) {
222 var prop
= (Property
) sym
;
224 if (prop
.set_accessor
!= null && prop
.set_accessor
.value_type
!= null) {
225 return prop
.set_accessor
.value_type
.copy ();
228 if (prop
.get_accessor
!= null && prop
.get_accessor
.value_type
!= null) {
229 return prop
.get_accessor
.value_type
.copy ();
232 } else if (sym is FormalParameter
) {
233 var p
= (FormalParameter
) sym
;
234 var type
= p
.parameter_type
.copy ();
236 type
.value_owned
= false;
239 } else if (sym is LocalVariable
) {
240 var local
= (LocalVariable
) sym
;
241 var type
= local
.variable_type
.copy ();
242 if (!lvalue
&& !local
.floating
) {
243 type
.value_owned
= false;
246 } else if (sym is EnumValue
) {
247 return new
EnumValueType ((Enum
) sym
.parent_symbol
);
248 } else if (sym is Method
) {
249 return new
MethodType ((Method
) sym
);
250 } else if (sym is Signal
) {
251 return new
SignalType ((Signal
) sym
);
256 public static Symbol?
symbol_lookup_inherited (Symbol sym
, string name
) {
257 var result
= sym
.scope
.lookup (name
);
258 if (result
!= null) {
263 var cl
= (Class
) sym
;
264 // first check interfaces without prerequisites
265 // (prerequisites can be assumed to be met already)
266 foreach (DataType base_type
in cl
.get_base_types ()) {
267 if (base_type
.data_type is Interface
) {
268 result
= base_type
.data_type
.scope
.lookup (name
);
269 if (result
!= null) {
274 // then check base class recursively
275 if (cl
.base_class
!= null) {
276 return symbol_lookup_inherited (cl
.base_class
, name
);
278 } else if (sym is Struct
) {
279 var st
= (Struct
) sym
;
280 if (st
.base_type
!= null) {
281 result
= symbol_lookup_inherited (st
.base_type
.data_type
, name
);
282 if (result
!= null) {
286 } else if (sym is Interface
) {
287 var iface
= (Interface
) sym
;
288 // first check interface prerequisites recursively
289 foreach (DataType prerequisite
in iface
.get_prerequisites ()) {
290 if (prerequisite
.data_type is Interface
) {
291 result
= symbol_lookup_inherited (prerequisite
.data_type
, name
);
292 if (result
!= null) {
297 // then check class prerequisite recursively
298 foreach (DataType prerequisite
in iface
.get_prerequisites ()) {
299 if (prerequisite
.data_type is Class
) {
300 result
= symbol_lookup_inherited (prerequisite
.data_type
, name
);
301 if (result
!= null) {
311 public static DataType
get_data_type_for_symbol (TypeSymbol sym
) {
312 DataType type
= null;
314 if (sym is ObjectTypeSymbol
) {
315 type
= new
ObjectType ((ObjectTypeSymbol
) sym
);
316 } else if (sym is Struct
) {
317 var st
= (Struct
) sym
;
318 if (st
.is_boolean_type ()) {
319 type
= new
BooleanType (st
);
320 } else if (st
.is_integer_type ()) {
321 type
= new
IntegerType (st
);
322 } else if (st
.is_floating_type ()) {
323 type
= new
FloatingType (st
);
325 type
= new
StructValueType (st
);
327 } else if (sym is Enum
) {
328 type
= new
EnumValueType ((Enum
) sym
);
329 } else if (sym is ErrorDomain
) {
330 type
= new
ErrorType ((ErrorDomain
) sym
, null);
331 } else if (sym is ErrorCode
) {
332 type
= new
ErrorType ((ErrorDomain
) sym
.parent_symbol
, (ErrorCode
) sym
);
334 Report
.error (null, "internal error: `%s' is not a supported type".printf (sym
.get_full_name ()));
335 return new
InvalidType ();
341 public bool check_arguments (Expression expr
, DataType mtype
, List
<FormalParameter
> params
, List
<Expression
> args
) {
342 Expression prev_arg
= null;
343 Iterator
<Expression
> arg_it
= args
.iterator ();
345 bool diag
= (mtype is MethodType
&& ((MethodType
) mtype
).method_symbol
.get_attribute ("Diagnostics") != null);
347 bool ellipsis
= false;
349 foreach (FormalParameter param
in params
) {
350 if (!param
.check (this
)) {
354 if (param
.ellipsis
) {
359 if (param
.params_array
) {
360 while (arg_it
.next ()) {
361 var arg
= arg_it
.get ();
362 if (!check_argument (arg
, i
, param
.direction
)) {
373 if (arg_it
== null || !arg_it
.next ()) {
374 if (param
.default_expression
== null) {
376 Report
.error (expr
.source_reference
, "Too few arguments, method `%s' does not take %d arguments".printf (mtype
.to_string (), args
.size
));
379 var invocation_expr
= expr as MethodCall
;
380 var object_creation_expr
= expr as ObjectCreationExpression
;
381 if (invocation_expr
!= null) {
382 invocation_expr
.add_argument (param
.default_expression
);
383 } else if (object_creation_expr
!= null) {
384 object_creation_expr
.add_argument (param
.default_expression
);
386 assert_not_reached ();
391 var arg
= arg_it
.get ();
392 if (!check_argument (arg
, i
, param
.direction
)) {
404 while (arg_it
!= null && arg_it
.next ()) {
405 var arg
= arg_it
.get ();
407 // ignore inner error
410 } else if (arg
.value_type is SignalType
) {
412 Report
.error (arg
.source_reference
, "Cannot pass signals as arguments");
414 } else if (arg
.value_type
== null) {
415 // disallow untyped arguments except for type inference of callbacks
416 if (!(arg
.symbol_reference is Method
)) {
418 Report
.error (expr
.source_reference
, "Invalid type for argument %d".printf (i
+ 1));
421 } else if (arg
.target_type
!= null && !arg
.value_type
.compatible (arg
.target_type
)) {
422 // target_type known for printf arguments
424 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 ()));
430 } else if (!ellipsis
&& arg_it
!= null && arg_it
.next ()) {
432 Report
.error (expr
.source_reference
, "Too many arguments, method `%s' does not take %d arguments".printf (mtype
.to_string (), args
.size
));
436 if (diag
&& prev_arg
!= null) {
437 var format_arg
= prev_arg as StringLiteral
;
438 if (format_arg
!= null) {
439 format_arg
.value
= "\"%s:%d: %s".printf (Path
.get_basename (expr
.source_reference
.file
.filename
), expr
.source_reference
.first_line
, format_arg
.value
.offset (1));
446 bool check_argument (Expression arg
, int i
, ParameterDirection direction
) {
448 // ignore inner error
450 } else if (arg is NamedArgument
) {
451 Report
.error (arg
.source_reference
, "Named arguments are not supported yet");
453 } else if (arg
.value_type
== null) {
454 // disallow untyped arguments except for type inference of callbacks
455 if (!(arg
.target_type is DelegateType
) || !(arg
.symbol_reference is Method
)) {
456 Report
.error (arg
.source_reference
, "Invalid type for argument %d".printf (i
+ 1));
459 } else if (arg
.target_type
!= null
460 && (direction
== ParameterDirection
.IN
|| direction
== ParameterDirection
.REF
)
461 && !arg
.value_type
.compatible (arg
.target_type
)) {
462 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 ()));
464 } else if (arg
.target_type
!= null
465 && (direction
== ParameterDirection
.REF
|| direction
== ParameterDirection
.OUT
)
466 && !arg
.target_type
.compatible (arg
.value_type
)
467 && !(arg is NullLiteral
)) {
468 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 ()));
471 // 0 => null, 1 => in, 2 => ref, 3 => out
473 if (arg
.value_type is NullType
) {
475 } else if (arg is UnaryExpression
) {
476 var unary
= (UnaryExpression
) arg
;
477 if (unary
.operator
== UnaryOperator
.REF
) {
479 } else if (unary
.operator
== UnaryOperator
.OUT
) {
485 if (direction
== ParameterDirection
.REF
) {
486 Report
.error (arg
.source_reference
, "Argument %d: Cannot pass null to reference parameter".printf (i
+ 1));
488 } else if (direction
!= ParameterDirection
.OUT
&& !arg
.target_type
.nullable
) {
489 Report
.warning (arg
.source_reference
, "Argument %d: Cannot pass null to non-null parameter type".printf (i
+ 1));
491 } else if (arg_type
== 1) {
492 if (direction
!= ParameterDirection
.IN
) {
493 Report
.error (arg
.source_reference
, "Argument %d: Cannot pass value to reference or output parameter".printf (i
+ 1));
496 } else if (arg_type
== 2) {
497 if (direction
!= ParameterDirection
.REF
) {
498 Report
.error (arg
.source_reference
, "Argument %d: Cannot pass ref argument to non-reference parameter".printf (i
+ 1));
502 // weak variables can only be used with weak ref parameters
503 if (arg
.target_type
.is_disposable ()) {
504 if (!(arg
.value_type is PointerType
) && !arg
.value_type
.value_owned
) {
505 /* variable doesn't own the value */
506 Report
.error (arg
.source_reference
, "Invalid assignment from owned expression to unowned variable");
510 } else if (arg_type
== 3) {
511 if (direction
!= ParameterDirection
.OUT
) {
512 Report
.error (arg
.source_reference
, "Argument %d: Cannot pass out argument to non-output parameter".printf (i
+ 1));
516 // weak variables can only be used with weak out parameters
517 if (arg
.target_type
.is_disposable ()) {
518 if (!(arg
.value_type is PointerType
) && !arg
.value_type
.value_owned
) {
519 /* variable doesn't own the value */
520 Report
.error (arg
.source_reference
, "Invalid assignment from owned expression to unowned variable");
529 private static DataType?
get_instance_base_type (DataType instance_type
, DataType base_type
, CodeNode node_reference
) {
530 // construct a new type reference for the base type with correctly linked type arguments
531 ReferenceType instance_base_type
;
532 if (base_type
.data_type is Class
) {
533 instance_base_type
= new
ObjectType ((Class
) base_type
.data_type
);
535 instance_base_type
= new
ObjectType ((Interface
) base_type
.data_type
);
537 foreach (DataType type_arg
in base_type
.get_type_arguments ()) {
538 // resolve type argument specified in base type (possibly recursively for nested generic types)
539 type_arg
= type_arg
.get_actual_type (instance_type
, null, node_reference
);
540 instance_base_type
.add_type_argument (type_arg
);
542 return instance_base_type
;
545 static DataType?
get_instance_base_type_for_member (DataType derived_instance_type
, TypeSymbol type_symbol
, CodeNode node_reference
) {
546 DataType instance_type
= derived_instance_type
;
548 while (instance_type is PointerType
) {
549 var instance_pointer_type
= (PointerType
) instance_type
;
550 instance_type
= instance_pointer_type
.base_type
;
553 if (instance_type
.data_type
== type_symbol
) {
554 return instance_type
;
557 DataType instance_base_type
= null;
559 // use same algorithm as symbol_lookup_inherited
560 if (instance_type
.data_type is Class
) {
561 var cl
= (Class
) instance_type
.data_type
;
562 // first check interfaces without prerequisites
563 // (prerequisites can be assumed to be met already)
564 foreach (DataType base_type
in cl
.get_base_types ()) {
565 if (base_type
.data_type is Interface
) {
566 instance_base_type
= get_instance_base_type_for_member (get_instance_base_type (instance_type
, base_type
, node_reference
), type_symbol
, node_reference
);
567 if (instance_base_type
!= null) {
568 return instance_base_type
;
572 // then check base class recursively
573 if (instance_base_type
== null) {
574 foreach (DataType base_type
in cl
.get_base_types ()) {
575 if (base_type
.data_type is Class
) {
576 instance_base_type
= get_instance_base_type_for_member (get_instance_base_type (instance_type
, base_type
, node_reference
), type_symbol
, node_reference
);
577 if (instance_base_type
!= null) {
578 return instance_base_type
;
583 } else if (instance_type
.data_type is Struct
) {
584 var st
= (Struct
) instance_type
.data_type
;
585 if (st
.base_type
!= null) {
586 instance_base_type
= get_instance_base_type_for_member (get_instance_base_type (instance_type
, st
.base_type
, node_reference
), type_symbol
, node_reference
);
587 if (instance_base_type
!= null) {
588 return instance_base_type
;
591 } else if (instance_type
.data_type is Interface
) {
592 var iface
= (Interface
) instance_type
.data_type
;
593 // first check interface prerequisites recursively
594 foreach (DataType prerequisite
in iface
.get_prerequisites ()) {
595 if (prerequisite
.data_type is Interface
) {
596 instance_base_type
= get_instance_base_type_for_member (get_instance_base_type (instance_type
, prerequisite
, node_reference
), type_symbol
, node_reference
);
597 if (instance_base_type
!= null) {
598 return instance_base_type
;
602 if (instance_base_type
== null) {
603 // then check class prerequisite recursively
604 foreach (DataType prerequisite
in iface
.get_prerequisites ()) {
605 if (prerequisite
.data_type is Class
) {
606 instance_base_type
= get_instance_base_type_for_member (get_instance_base_type (instance_type
, prerequisite
, node_reference
), type_symbol
, node_reference
);
607 if (instance_base_type
!= null) {
608 return instance_base_type
;
618 public static DataType?
get_actual_type (DataType? derived_instance_type
, MemberAccess? method_access
, GenericType generic_type
, CodeNode node_reference
) {
619 DataType actual_type
= null;
620 if (generic_type
.type_parameter
.parent_symbol is TypeSymbol
) {
621 if (derived_instance_type
!= null) {
622 // trace type arguments back to the datatype where the method has been declared
623 var instance_type
= get_instance_base_type_for_member (derived_instance_type
, (TypeSymbol
) generic_type
.type_parameter
.parent_symbol
, node_reference
);
625 assert (instance_type
!= null);
627 int param_index
= instance_type
.data_type
.get_type_parameter_index (generic_type
.type_parameter
.name
);
628 if (param_index
== -1) {
629 Report
.error (node_reference
.source_reference
, "internal error: unknown type parameter %s".printf (generic_type
.type_parameter
.name
));
630 node_reference
.error
= true;
634 if (param_index
< instance_type
.get_type_arguments ().size
) {
635 actual_type
= (DataType
) instance_type
.get_type_arguments ().get (param_index
);
640 var m
= (Method
) generic_type
.type_parameter
.parent_symbol
;
642 if (method_access
== null) {
646 int param_index
= m
.get_type_parameter_index (generic_type
.type_parameter
.name
);
647 if (param_index
== -1) {
648 Report
.error (node_reference
.source_reference
, "internal error: unknown type parameter %s".printf (generic_type
.type_parameter
.name
));
649 node_reference
.error
= true;
653 if (param_index
< method_access
.get_type_arguments ().size
) {
654 actual_type
= (DataType
) method_access
.get_type_arguments ().get (param_index
);
658 if (actual_type
== null) {
659 // no actual type available
662 actual_type
= actual_type
.copy ();
663 actual_type
.value_owned
= actual_type
.value_owned
&& generic_type
.value_owned
;
667 public bool is_in_instance_method () {
668 var sym
= current_symbol
;
669 while (sym
!= null) {
670 if (sym is CreationMethod
) {
672 } else if (sym is Method
) {
673 var m
= (Method
) sym
;
674 return m
.binding
== MemberBinding
.INSTANCE
;
675 } else if (sym is Constructor
) {
676 var c
= (Constructor
) sym
;
677 return c
.binding
== MemberBinding
.INSTANCE
;
678 } else if (sym is Destructor
) {
680 } else if (sym is Property
) {
681 var p
= (Property
) sym
;
682 return p
.binding
== MemberBinding
.INSTANCE
;
684 sym
= sym
.parent_symbol
;
690 public void visit_member_initializer (MemberInitializer init
, DataType type
) {
691 init
.symbol_reference
= symbol_lookup_inherited (type
.data_type
, init
.name
);
692 if (!(init
.symbol_reference is Field
|| init
.symbol_reference is Property
)) {
694 Report
.error (init
.source_reference
, "Invalid member `%s' in `%s'".printf (init
.name
, type
.data_type
.get_full_name ()));
697 if (init
.symbol_reference
.access
!= SymbolAccessibility
.PUBLIC
) {
699 Report
.error (init
.source_reference
, "Access to private member `%s' denied".printf (init
.symbol_reference
.get_full_name ()));
702 DataType member_type
= null;
703 if (init
.symbol_reference is Field
) {
704 var f
= (Field
) init
.symbol_reference
;
705 member_type
= f
.field_type
;
706 } else if (init
.symbol_reference is Property
) {
707 var prop
= (Property
) init
.symbol_reference
;
708 member_type
= prop
.property_type
;
709 if (prop
.set_accessor
== null || !prop
.set_accessor
.writable
) {
711 Report
.error (init
.source_reference
, "Property `%s' is read-only".printf (prop
.get_full_name ()));
716 init
.initializer
.target_type
= member_type
;
720 if (init
.initializer
.value_type
== null || !init
.initializer
.value_type
.compatible (init
.initializer
.target_type
)) {
722 Report
.error (init
.source_reference
, "Invalid type for member `%s'".printf (init
.name
));
727 Struct?
get_arithmetic_struct (DataType type
) {
728 var result
= type
.data_type as Struct
;
729 if (result
== null && type is EnumValueType
) {
730 return (Struct
) int_type
.data_type
;
735 public DataType?
get_arithmetic_result_type (DataType left_type
, DataType right_type
) {
736 var left
= get_arithmetic_struct (left_type
);
737 var right
= get_arithmetic_struct (right_type
);
739 if (left
== null || right
== null) {
740 // at least one operand not struct
744 if ((!left
.is_floating_type () && !left
.is_integer_type ()) ||
745 (!right
.is_floating_type () && !right
.is_integer_type ())) {
746 // at least one operand not numeric
750 if (left
.is_floating_type () == right
.is_floating_type ()) {
751 // both operands integer or floating type
752 if (left
.get_rank () >= right
.get_rank ()) {
758 // one integer and one floating type operand
759 if (left
.is_floating_type ()) {
767 public Method?
find_current_method () {
768 var sym
= current_symbol
;
769 while (sym
!= null) {
773 sym
= sym
.parent_symbol
;
778 public Method?
find_parent_method (Symbol sym
) {
779 while (sym is Block
) {
780 sym
= sym
.parent_symbol
;
782 return sym as Method
;
785 public bool is_in_constructor () {
786 var sym
= current_symbol
;
787 while (sym
!= null) {
788 if (sym is Constructor
) {
791 sym
= sym
.parent_symbol
;