DEADSOFTWARE

964f0a0e4797875c123aae905c700bab23f17a9f
[dsw-obn.git] / src / oberon-type-compat.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <ctype.h>
5 #include <string.h>
6 #include <assert.h>
7 #include <stdbool.h>
8 #include <math.h>
10 #include "oberon-internals.h"
11 #include "oberon-type-compat.h"
12 #include "oberon-common.h"
14 bool
15 oberon_is_array_type(oberon_type_t * t)
16 {
17 return t -> class == OBERON_TYPE_ARRAY;
18 }
20 bool
21 oberon_is_open_array(oberon_type_t * t)
22 {
23 /* Открытые массивы всегда размером 0 */
25 return oberon_is_array_type(t) && (t -> size == 0);
26 }
28 bool
29 oberon_is_real_type(oberon_type_t * t)
30 {
31 return t -> class == OBERON_TYPE_REAL;
32 }
34 bool
35 oberon_is_integer_type(oberon_type_t * t)
36 {
37 return t -> class == OBERON_TYPE_INTEGER;
38 }
40 bool
41 oberon_is_system_byte_type(oberon_type_t * t)
42 {
43 return t -> class == OBERON_TYPE_SYSTEM_BYTE;
44 }
46 bool
47 oberon_is_system_ptr_type(oberon_type_t * t)
48 {
49 return t -> class == OBERON_TYPE_SYSTEM_PTR;
50 }
52 bool
53 oberon_is_byte_type(oberon_type_t * t)
54 {
55 return oberon_is_integer_type(t) && t -> size == 1;
56 }
58 bool
59 oberon_is_number_type(oberon_type_t * t)
60 {
61 return oberon_is_integer_type(t)
62 || oberon_is_real_type(t);
63 }
65 bool
66 oberon_is_char_type(oberon_type_t * t)
67 {
68 return t -> class == OBERON_TYPE_CHAR;
69 }
71 bool
72 oberon_is_set_type(oberon_type_t * t)
73 {
74 return t -> class == OBERON_TYPE_SET;
75 }
77 bool
78 oberon_is_string_type(oberon_type_t * t)
79 {
80 return t -> class == OBERON_TYPE_STRING;
81 }
83 bool
84 oberon_is_procedure_type(oberon_type_t * t)
85 {
86 return t -> class == OBERON_TYPE_PROCEDURE;
87 }
89 bool
90 oberon_is_record_type(oberon_type_t * t)
91 {
92 return t -> class == OBERON_TYPE_RECORD;
93 }
95 bool
96 oberon_is_pointer_type(oberon_type_t * t)
97 {
98 return t -> class == OBERON_TYPE_POINTER;
99 }
101 bool
102 oberon_is_pointer_to_record(oberon_type_t * t)
104 return oberon_is_pointer_type(t) && oberon_is_record_type(t -> base);
107 bool
108 oberon_is_boolean_type(oberon_type_t * t)
110 return t -> class == OBERON_TYPE_BOOLEAN;
113 bool
114 oberon_is_array_of_char_type(oberon_type_t * t)
116 return oberon_is_array_type(t) && oberon_is_char_type(t -> base);
119 bool
120 oberon_is_array_of_system_byte_type(oberon_type_t * t)
122 return oberon_is_array_type(t) && oberon_is_system_byte_type(t -> base);
125 bool
126 oberon_is_nil_type(oberon_type_t * t)
128 return t -> class == OBERON_TYPE_NIL;
131 bool
132 oberon_is_type_expr(oberon_expr_t * e)
134 return (e -> is_item) && (e -> item.mode == MODE_TYPE);
139 bool
140 oberon_is_some_types(oberon_type_t * a, oberon_type_t * b)
142 /* Две переменные a и b с типами Ta и Tb имеют одинаковый тип, если */
143 /* 1. Ta и Tb оба обозначены одним и тем же идентификатором типа, или */
144 /* 2. Ta объявлен равным Tb в объявлении типа вида Ta = Tb, или */
145 /* 3. a и b появляются в одном и том же списке идентификаторов переменных, полей записи */
146 /* или объявлении формальных параметров и не являются открытыми массивами. */
148 return (a == b) && !oberon_is_open_array(a) && !oberon_is_open_array(b);
151 bool
152 oberon_is_some_procedure_signatures(oberon_type_t * a, oberon_type_t * b)
154 /* Два списка формальных параметров совпадают если */
155 /* 1. они имеют одинаковое количество параметров, и */
156 /* 2. они имеют или одинаковый тип результата функции или не имеют никакого, и */
157 /* 3. параметры в соответствующих позициях имеют равные типы, и */
158 /* 4. параметры в соответствующих позициях - оба или параметры-значения */
159 /* или параметры-переменные. */
161 if(a -> num_decl != b -> num_decl)
163 return false;
166 if(!oberon_is_some_types(a -> base, b -> base))
168 return false;
171 int num = a -> num_decl;
172 oberon_object_t * va = a -> decl;
173 oberon_object_t * vb = b -> decl;
174 for(int i = 0; i < num; i++)
176 if(!oberon_is_equal_types(va -> type, vb -> type))
178 return false;
181 if(va -> class != vb -> class)
183 return false;
186 va = va -> next;
187 vb = vb -> next;
190 return true;
193 bool
194 oberon_is_equal_types(oberon_type_t * a, oberon_type_t * b)
196 /* Два типа Ta, и Tb равны, если */
197 /* 1. Ta и Tb - одинаковые типы, или */
198 /* 2. Ta и Tb - типы открытый массив с равными типами элементов, или */
199 /* 3. Ta и Tb - процедурные типы, чьи списки формальных параметров совпадают. */
201 return oberon_is_some_types(a, b)
202 || (oberon_is_open_array(a) && oberon_is_open_array(b) && oberon_is_some_types(a -> base, b -> base))
203 || (oberon_is_procedure_type(a) && oberon_is_procedure_type(b) && oberon_is_some_procedure_signatures(a, b));
206 bool
207 oberon_incluses_type(oberon_type_t * a, oberon_type_t * b)
209 /* a поглощает b */
210 /* LONGREAL >= REAL >= LONGINT >= INTEGER >= SHORTINT */
212 /*
213 printf("oberon_incluses_type: a %i %i\n", a -> class, a -> size);
214 printf("oberon_incluses_type: b %i %i\n", b -> class, b -> size);
215 */
217 if(a -> class == OBERON_TYPE_REAL)
219 if(b -> class == OBERON_TYPE_INTEGER)
221 return true;
223 else if(b -> class == OBERON_TYPE_REAL)
225 return (a -> size >= b -> size);
228 else if(a -> class == OBERON_TYPE_INTEGER)
230 if(b -> class == OBERON_TYPE_INTEGER)
232 return (a -> size >= b -> size);
236 return false;
239 bool
240 oberon_extension_of(oberon_type_t * ext, oberon_type_t * rec)
242 /* Тип Tb есть расширение типа Ta (Ta есть базовый тип Tb) если */
243 /* 1. Ta и Tb - одинаковые типы, или */
244 /* 2. Tb - непосредственное расширение типа, являющегося расширением Ta */
245 /* Если Pa = POINTER TO Ta и Pb = POINTER TO Tb, то Pb есть расширение Pa */
246 /* (Pa есть базовый тип Pb), если Tb есть расширение Ta. */
248 if(ext -> class == OBERON_TYPE_POINTER && rec -> class == OBERON_TYPE_POINTER)
250 ext = ext -> base;
251 rec = rec -> base;
254 if(ext -> class != OBERON_TYPE_RECORD || rec -> class != OBERON_TYPE_RECORD)
256 return false;
259 if(oberon_is_some_types(ext, rec))
261 return true;
264 while(rec -> base)
266 if(oberon_is_some_types(ext, rec -> base))
268 return true;
269 }
270 rec = rec -> base;
273 return false;
276 bool
277 oberon_is_const_string(oberon_expr_t * e)
279 return e -> result -> class == OBERON_TYPE_STRING && e -> is_item && e -> item.mode == MODE_STRING;
282 bool
283 oberon_is_string_of_one(oberon_expr_t * e)
285 return oberon_is_const_string(e) && strlen(e -> item.string) == 1;
288 bool
289 oberon_is_assignment_compatible_expressions(oberon_expr_t * e, oberon_type_t * Tv)
291 /* Выражение e типа Te совместимо по присваиванию с переменной v типа Tv, */
292 /* если выполнено одно из следующих условий: */
293 /* 1. Te и Tv - одинаковые типы; */
294 /* 2. Te и Tv - числовые типы и Tv поглощает Te; */
295 /* 3. Te и Tv - типы запись, Te есть расширение Tv, а v имеет динамический тип Tv; */
296 /* 4. Te и Tv - типы указатель и Te - расширение Tv; */
297 /* 5. Tv - тип указатель или процедурный тип, а e - NIL; */
298 /* 6. Tv - ARRAY n OF CHAR, e - строковая константа из m символов и m < n; */
299 /* 7. Tv - процедурный тип, а e - имя процедуры, чьи формальные параметры */
300 /* совпадают с параметрами Tv. */
301 /* Доп: Tv - символ, е - строковая константа из одного символа */
303 /* SYSTEM: Переменным типа BYTE можно присваивать значения переменных типа CHAR или SHORTINT. */
304 /* SYSTEM: Переменным типа PTR могут быть присвоены значения переменных-указателей любого типа. */
306 oberon_type_t * Te = e -> result;
308 return oberon_is_some_types(Te, Tv)
309 || (oberon_is_number_type(Te) && oberon_is_number_type(Tv) && oberon_incluses_type(Tv, Te))
310 || (oberon_is_record_type(Te) && oberon_is_record_type(Tv) && oberon_extension_of(Tv, Te))
311 || (oberon_is_pointer_type(Te) && oberon_is_pointer_type(Tv) && oberon_extension_of(Tv, Te))
312 || ((oberon_is_pointer_type(Tv) || oberon_is_procedure_type(Tv)) && oberon_is_nil_type(Te))
313 || (oberon_is_array_of_char_type(Tv) && !oberon_is_open_array(Tv) && oberon_is_const_string(e) && (strlen(e -> item.string) < Tv -> size))
314 || (oberon_is_procedure_type(Tv) && e -> is_item && e -> item.var -> class == OBERON_CLASS_PROC && oberon_is_some_procedure_signatures(Tv, e -> result))
315 || (oberon_is_char_type(Tv) && oberon_is_string_of_one(e))
316 || (oberon_is_system_byte_type(Tv) && (oberon_is_char_type(Te) || oberon_is_byte_type(Te)))
317 || (oberon_is_system_ptr_type(Tv) && oberon_is_pointer_type(Te));
320 static bool
321 oberon_is_compatible_arrays_types(oberon_type_t * Tf, oberon_type_t * Ta)
323 /* Фактический параметр a типа Ta является совместимым массивом для формального параметра f типа Tf если */
324 /* 1. Tf и Ta - одинаковые типы или */
325 /* 2. Tf - открытый массив, Ta - любой массив, а типы их элементов - совместимые массивы или */
326 /* 3. f - параметр-значение типа ARRAY OF CHAR, а фактический параметр a - строка. */
328 return oberon_is_some_types(Tf, Ta)
329 || (oberon_is_open_array(Tf) && oberon_is_array_type(Ta) && oberon_is_compatible_arrays_types(Tf -> base, Ta -> base));
332 bool
333 oberon_is_compatible_arrays(oberon_object_t * f, oberon_expr_t * a)
335 oberon_type_t * Tf = f -> type;
336 oberon_type_t * Ta = a -> result;
338 return oberon_is_compatible_arrays_types(Tf, Ta)
339 || (oberon_is_array_of_char_type(Tf) && oberon_is_const_string(a));
342 void
343 oberon_check_compatible_arrays(oberon_context_t * ctx, oberon_object_t * f, oberon_expr_t * a)
345 if(!oberon_is_compatible_arrays(f, a))
347 oberon_error(ctx, "incompatible types");
351 bool
352 oberon_is_compatible_bin_expr(int token, oberon_expr_t * a, oberon_expr_t * b)
354 if(token == EQUAL || token == NEQ || token == LESS || token == LEQ || token == GREAT || token == GEQ)
356 if((oberon_is_char_type(a -> result) || oberon_is_string_of_one(a))
357 && (oberon_is_char_type(b -> result) || oberon_is_string_of_one(b)))
359 return true;
361 else
363 return oberon_is_compatible_bin_expr_types(token, a -> result, b -> result);
366 else
368 return oberon_is_compatible_bin_expr_types(token, a -> result, b -> result);
372 bool
373 oberon_is_compatible_bin_expr_types(int token, oberon_type_t * a, oberon_type_t * b)
375 if(token == PLUS || token == MINUS || token == STAR || token == SLASH)
377 if(oberon_is_number_type(a) && oberon_is_number_type(b))
379 return true;
381 else if(oberon_is_set_type(a) && oberon_is_set_type(b))
383 return true;
386 else if(token == DIV || token == MOD)
388 if(oberon_is_integer_type(a) && oberon_is_integer_type(b))
390 return true;
393 else if(token == OR || token == AND)
395 if(oberon_is_boolean_type(a) && oberon_is_boolean_type(b))
397 return true;
400 else if(token == EQUAL || token == NEQ)
402 if(oberon_is_number_type(a) && oberon_is_number_type(b))
404 return true;
406 else if(oberon_is_char_type(a) && oberon_is_char_type(b))
408 return true;
410 else if((oberon_is_array_of_char_type(a) || oberon_is_string_type(a))
411 && (oberon_is_array_of_char_type(b) || oberon_is_string_type(b)))
413 return true;
415 else if(oberon_is_boolean_type(a) && oberon_is_boolean_type(b))
417 return true;
419 else if(oberon_is_set_type(a) && oberon_is_set_type(b))
421 return true;
423 else if((oberon_is_nil_type(a) || oberon_is_pointer_type(a) || oberon_is_procedure_type(a))
424 && (oberon_is_nil_type(b) || oberon_is_pointer_type(b) || oberon_is_procedure_type(b)))
426 return true;
429 else if(token == LESS || token == LEQ || token == GREAT || token == GEQ)
431 if(oberon_is_number_type(a) && oberon_is_number_type(b))
433 return true;
435 else if(oberon_is_char_type(a) && oberon_is_char_type(b))
437 return true;
439 else if((oberon_is_array_of_char_type(a) || oberon_is_string_type(a))
440 && (oberon_is_array_of_char_type(b) || oberon_is_string_type(b)))
442 return true;
445 else if(token == IN)
447 if(oberon_is_integer_type(a) && oberon_is_set_type(b))
449 return true;
452 else if(token == IS)
454 if(oberon_extension_of(a, b))
456 return true;
460 return false;
463 bool
464 oberon_is_compatible_var_param(oberon_type_t * Tf, oberon_type_t * Ta)
466 /* Пусть Tf - тип формального параметра f (не открытого массива) */
467 /* и Ta - тип соответствующего фактического параметра a. */
468 /* Для параметров-переменных Ta и Tf должны быть одинаковыми типами */
469 /* или Tf должен быть типом запись, а Ta - расширением Tf. */
471 /* SYSTEM: Если формальный параметр-переменная имеет тип ARRAY OF BYTE, */
472 /* то соответствующий фактический параметр может иметь любой тип. */
473 /* SYSTEM: Если формальный параметр-переменная имеет тип PTR, */
474 /* фактический параметр может быть указателем любого типа. */
476 return oberon_is_some_types(Tf, Ta)
477 || (oberon_is_record_type(Tf) && oberon_extension_of(Ta, Tf))
478 || (oberon_is_system_byte_type(Tf) && (oberon_is_char_type(Ta) || oberon_is_byte_type(Ta)))
479 || (oberon_is_array_of_system_byte_type(Tf))
480 || (oberon_is_system_ptr_type(Tf));
483 void
484 oberon_check_compatible_var_param(oberon_context_t * ctx, oberon_type_t * Tf, oberon_type_t * Ta)
486 if(!oberon_is_compatible_var_param(Tf, Ta))
488 oberon_error(ctx, "incompatible types");
492 void
493 oberon_check_type_expr(oberon_context_t * ctx, oberon_expr_t * e)
495 if(!oberon_is_type_expr(e))
497 oberon_error(ctx, "expected type");
501 void
502 oberon_check_compatible_bin_expr(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_expr_t * b)
504 if(!oberon_is_compatible_bin_expr(token, a, b))
506 oberon_error(ctx, "incompatibe expression types");
510 void
511 oberon_check_assignment_compatible(oberon_context_t * ctx, oberon_expr_t * e, oberon_type_t * Tv)
513 if(!oberon_is_assignment_compatible_expressions(e, Tv))
515 oberon_error(ctx, "incompatible types");
519 void
520 oberon_check_extension_of(oberon_context_t * ctx, oberon_type_t * ext, oberon_type_t * rec)
522 if(!oberon_extension_of(ext, rec))
524 oberon_error(ctx, "not extension");
528 oberon_type_t *
529 oberon_get_longer_type(oberon_context_t * ctx, oberon_type_t * a, oberon_type_t * b)
531 if(oberon_incluses_type(a, b))
533 return a;
535 else
537 return b;
541 oberon_type_t *
542 oberon_get_longer_real_type(oberon_context_t * ctx, oberon_type_t * a, oberon_type_t * b)
544 oberon_type_t * result = oberon_get_longer_type(ctx, a, b);
545 if(oberon_is_integer_type(result))
547 return ctx -> real_type;
549 else
551 return result;