DEADSOFTWARE

3da62edc2bb5b059b7ee20b90f20c238400de495
[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 "../include/oberon.h"
12 #include "oberon-common.h"
13 #include "oberon-internals.h"
14 #include "oberon-type-compat.h"
16 bool
17 oberon_is_array_type(oberon_type_t * t)
18 {
19 return t -> class == OBERON_TYPE_ARRAY;
20 }
22 bool
23 oberon_is_open_array(oberon_type_t * t)
24 {
25 /* Открытые массивы всегда размером 0 */
27 return oberon_is_array_type(t) && (t -> size == 0);
28 }
30 bool
31 oberon_is_real_type(oberon_type_t * t)
32 {
33 return t -> class == OBERON_TYPE_REAL;
34 }
36 bool
37 oberon_is_integer_type(oberon_type_t * t)
38 {
39 return t -> class == OBERON_TYPE_INTEGER;
40 }
42 bool
43 oberon_is_system_byte_type(oberon_type_t * t)
44 {
45 return t -> class == OBERON_TYPE_SYSTEM_BYTE;
46 }
48 bool
49 oberon_is_system_ptr_type(oberon_type_t * t)
50 {
51 return t -> class == OBERON_TYPE_SYSTEM_PTR;
52 }
54 bool
55 oberon_is_byte_type(oberon_type_t * t)
56 {
57 return oberon_is_integer_type(t) && t -> size == 1;
58 }
60 bool
61 oberon_is_number_type(oberon_type_t * t)
62 {
63 return oberon_is_integer_type(t)
64 || oberon_is_real_type(t);
65 }
67 bool
68 oberon_is_char_type(oberon_type_t * t)
69 {
70 return t -> class == OBERON_TYPE_CHAR;
71 }
73 bool
74 oberon_is_set_type(oberon_type_t * t)
75 {
76 return t -> class == OBERON_TYPE_SET;
77 }
79 bool
80 oberon_is_string_type(oberon_type_t * t)
81 {
82 return t -> class == OBERON_TYPE_STRING;
83 }
85 bool
86 oberon_is_procedure_type(oberon_type_t * t)
87 {
88 return t -> class == OBERON_TYPE_PROCEDURE;
89 }
91 bool
92 oberon_is_record_type(oberon_type_t * t)
93 {
94 return t -> class == OBERON_TYPE_RECORD;
95 }
97 bool
98 oberon_is_pointer_type(oberon_type_t * t)
99 {
100 return t -> class == OBERON_TYPE_POINTER;
103 bool
104 oberon_is_pointer_to_record(oberon_type_t * t)
106 return oberon_is_pointer_type(t) && oberon_is_record_type(t -> base);
109 bool
110 oberon_is_boolean_type(oberon_type_t * t)
112 return t -> class == OBERON_TYPE_BOOLEAN;
115 bool
116 oberon_is_array_of_char_type(oberon_type_t * t)
118 return oberon_is_array_type(t) && oberon_is_char_type(t -> base);
121 bool
122 oberon_is_array_of_system_byte_type(oberon_type_t * t)
124 return oberon_is_array_type(t) && oberon_is_system_byte_type(t -> base);
127 bool
128 oberon_is_nil_type(oberon_type_t * t)
130 return t -> class == OBERON_TYPE_NIL;
133 bool
134 oberon_is_type_expr(oberon_expr_t * e)
136 return (e -> is_item) && (e -> item.mode == MODE_TYPE);
141 bool
142 oberon_is_some_types(oberon_type_t * a, oberon_type_t * b)
144 /* Две переменные a и b с типами Ta и Tb имеют одинаковый тип, если */
145 /* 1. Ta и Tb оба обозначены одним и тем же идентификатором типа, или */
146 /* 2. Ta объявлен равным Tb в объявлении типа вида Ta = Tb, или */
147 /* 3. a и b появляются в одном и том же списке идентификаторов переменных, полей записи */
148 /* или объявлении формальных параметров и не являются открытыми массивами. */
150 return (a == b) && !oberon_is_open_array(a) && !oberon_is_open_array(b);
153 bool
154 oberon_is_some_procedure_signatures(oberon_type_t * a, oberon_type_t * b)
156 /* Два списка формальных параметров совпадают если */
157 /* 1. они имеют одинаковое количество параметров, и */
158 /* 2. они имеют или одинаковый тип результата функции или не имеют никакого, и */
159 /* 3. параметры в соответствующих позициях имеют равные типы, и */
160 /* 4. параметры в соответствующих позициях - оба или параметры-значения */
161 /* или параметры-переменные. */
163 if(a -> num_decl != b -> num_decl)
165 return false;
168 if(!oberon_is_some_types(a -> base, b -> base))
170 return false;
173 int num = a -> num_decl;
174 oberon_object_t * va = a -> decl;
175 oberon_object_t * vb = b -> decl;
176 for(int i = 0; i < num; i++)
178 if(!oberon_is_equal_types(va -> type, vb -> type))
180 return false;
183 if(va -> class != vb -> class)
185 return false;
188 va = va -> next;
189 vb = vb -> next;
192 return true;
195 bool
196 oberon_is_equal_types(oberon_type_t * a, oberon_type_t * b)
198 /* Два типа Ta, и Tb равны, если */
199 /* 1. Ta и Tb - одинаковые типы, или */
200 /* 2. Ta и Tb - типы открытый массив с равными типами элементов, или */
201 /* 3. Ta и Tb - процедурные типы, чьи списки формальных параметров совпадают. */
203 return oberon_is_some_types(a, b)
204 || (oberon_is_open_array(a) && oberon_is_open_array(b) && oberon_is_some_types(a -> base, b -> base))
205 || (oberon_is_procedure_type(a) && oberon_is_procedure_type(b) && oberon_is_some_procedure_signatures(a, b));
208 bool
209 oberon_incluses_type(oberon_type_t * a, oberon_type_t * b)
211 /* a поглощает b */
212 /* LONGREAL >= REAL >= LONGINT >= INTEGER >= SHORTINT */
214 /*
215 printf("oberon_incluses_type: a %i %i\n", a -> class, a -> size);
216 printf("oberon_incluses_type: b %i %i\n", b -> class, b -> size);
217 */
219 if(a -> class == OBERON_TYPE_REAL)
221 if(b -> class == OBERON_TYPE_INTEGER)
223 return true;
225 else if(b -> class == OBERON_TYPE_REAL)
227 return (a -> size >= b -> size);
230 else if(a -> class == OBERON_TYPE_INTEGER)
232 if(b -> class == OBERON_TYPE_INTEGER)
234 return (a -> size >= b -> size);
238 return false;
241 bool
242 oberon_extension_of(oberon_type_t * ext, oberon_type_t * rec)
244 /* Тип Tb есть расширение типа Ta (Ta есть базовый тип Tb) если */
245 /* 1. Ta и Tb - одинаковые типы, или */
246 /* 2. Tb - непосредственное расширение типа, являющегося расширением Ta */
247 /* Если Pa = POINTER TO Ta и Pb = POINTER TO Tb, то Pb есть расширение Pa */
248 /* (Pa есть базовый тип Pb), если Tb есть расширение Ta. */
250 if(ext -> class == OBERON_TYPE_POINTER && rec -> class == OBERON_TYPE_POINTER)
252 ext = ext -> base;
253 rec = rec -> base;
256 if(ext -> class != OBERON_TYPE_RECORD || rec -> class != OBERON_TYPE_RECORD)
258 return false;
261 if(oberon_is_some_types(ext, rec))
263 return true;
266 while(rec -> base)
268 if(oberon_is_some_types(ext, rec -> base))
270 return true;
271 }
272 rec = rec -> base;
275 return false;
278 bool
279 oberon_is_const_string(oberon_expr_t * e)
281 return e -> result -> class == OBERON_TYPE_STRING && e -> is_item && e -> item.mode == MODE_STRING;
284 bool
285 oberon_is_string_of_one(oberon_expr_t * e)
287 return oberon_is_const_string(e) && strlen(e -> item.string) == 1;
290 bool
291 oberon_is_assignment_compatible_expressions(oberon_expr_t * e, oberon_type_t * Tv)
293 /* Выражение e типа Te совместимо по присваиванию с переменной v типа Tv, */
294 /* если выполнено одно из следующих условий: */
295 /* 1. Te и Tv - одинаковые типы; */
296 /* 2. Te и Tv - числовые типы и Tv поглощает Te; */
297 /* 3. Te и Tv - типы запись, Te есть расширение Tv, а v имеет динамический тип Tv; */
298 /* 4. Te и Tv - типы указатель и Te - расширение Tv; */
299 /* 5. Tv - тип указатель или процедурный тип, а e - NIL; */
300 /* 6. Tv - ARRAY n OF CHAR, e - строковая константа из m символов и m < n; */
301 /* 7. Tv - процедурный тип, а e - имя процедуры, чьи формальные параметры */
302 /* совпадают с параметрами Tv. */
303 /* Доп: Tv - символ, е - строковая константа из одного символа */
305 /* SYSTEM: переменным типа BYTE можно присваивать значения переменных типа CHAR или SHORTINT. */
306 /* SYSTEM: Переменным типа PTR могут быть присвоены значения переменных-указателей любого типа. */
308 oberon_type_t * Te = e -> result;
310 return oberon_is_some_types(Te, Tv)
311 || (oberon_is_number_type(Te) && oberon_is_number_type(Tv) && oberon_incluses_type(Tv, Te))
312 || (oberon_is_record_type(Te) && oberon_is_record_type(Tv) && oberon_extension_of(Tv, Te))
313 || (oberon_is_pointer_type(Te) && oberon_is_pointer_type(Tv) && oberon_extension_of(Tv, Te))
314 || ((oberon_is_pointer_type(Tv) || oberon_is_procedure_type(Tv)) && oberon_is_nil_type(Te))
315 || (oberon_is_array_of_char_type(Tv) && !oberon_is_open_array(Tv) && oberon_is_const_string(e) && (strlen(e -> item.string) < Tv -> size))
316 || (oberon_is_procedure_type(Tv) && e -> is_item && e -> item.var -> class == OBERON_CLASS_PROC && oberon_is_some_procedure_signatures(Tv, e -> result))
317 || (oberon_is_char_type(Tv) && oberon_is_string_of_one(e))
318 || (oberon_is_system_byte_type(Tv) && (oberon_is_char_type(Te) || oberon_is_byte_type(Te)))
319 || (oberon_is_system_ptr_type(Tv) && oberon_is_pointer_type(Te));
322 static bool
323 oberon_is_compatible_arrays_types(oberon_type_t * Tf, oberon_type_t * Ta)
325 /* Фактический параметр a типа Ta является совместимым массивом для формального параметра f типа Tf если */
326 /* 1. Tf и Ta - одинаковые типы или */
327 /* 2. Tf - открытый массив, Ta - любой массив, а типы их элементов - совместимые массивы или */
328 /* 3. f - параметр-значение типа ARRAY OF CHAR, а фактический параметр a - строка. */
330 return oberon_is_some_types(Tf, Ta)
331 || (oberon_is_open_array(Tf) && oberon_is_array_type(Ta) && oberon_is_compatible_arrays_types(Tf -> base, Ta -> base));
334 bool
335 oberon_is_compatible_arrays(oberon_object_t * f, oberon_expr_t * a)
337 oberon_type_t * Tf = f -> type;
338 oberon_type_t * Ta = a -> result;
340 return oberon_is_compatible_arrays_types(Tf, Ta)
341 || (oberon_is_array_of_char_type(Tf) && oberon_is_const_string(a));
344 void
345 oberon_check_compatible_arrays(oberon_context_t * ctx, oberon_object_t * f, oberon_expr_t * a)
347 if(!oberon_is_compatible_arrays(f, a))
349 oberon_error(ctx, "incompatible types");
353 bool
354 oberon_is_compatible_bin_expr(int token, oberon_expr_t * a, oberon_expr_t * b)
356 if(token == EQUAL || token == NEQ || token == LESS || token == LEQ || token == GREAT || token == GEQ)
358 if((oberon_is_char_type(a -> result) || oberon_is_string_of_one(a))
359 && (oberon_is_char_type(b -> result) || oberon_is_string_of_one(b)))
361 return true;
363 else
365 return oberon_is_compatible_bin_expr_types(token, a -> result, b -> result);
368 else
370 return oberon_is_compatible_bin_expr_types(token, a -> result, b -> result);
374 bool
375 oberon_is_compatible_bin_expr_types(int token, oberon_type_t * a, oberon_type_t * b)
377 if(token == PLUS || token == MINUS || token == STAR || token == SLASH)
379 if(oberon_is_number_type(a) && oberon_is_number_type(b))
381 return true;
383 else if(oberon_is_set_type(a) && oberon_is_set_type(b))
385 return true;
388 else if(token == DIV || token == MOD)
390 if(oberon_is_integer_type(a) && oberon_is_integer_type(b))
392 return true;
395 else if(token == OR || token == AND)
397 if(oberon_is_boolean_type(a) && oberon_is_boolean_type(b))
399 return true;
402 else if(token == EQUAL || token == NEQ)
404 if(oberon_is_number_type(a) && oberon_is_number_type(b))
406 return true;
408 else if(oberon_is_char_type(a) && oberon_is_char_type(b))
410 return true;
412 else if((oberon_is_array_of_char_type(a) || oberon_is_string_type(a))
413 && (oberon_is_array_of_char_type(b) || oberon_is_string_type(b)))
415 return true;
417 else if(oberon_is_boolean_type(a) && oberon_is_boolean_type(b))
419 return true;
421 else if(oberon_is_set_type(a) && oberon_is_set_type(b))
423 return true;
425 else if((oberon_is_nil_type(a) || oberon_is_pointer_to_record(a) || oberon_is_procedure_type(a))
426 && (oberon_is_nil_type(b) || oberon_is_pointer_to_record(b) || oberon_is_procedure_type(b)))
428 return true;
431 else if(token == LESS || token == LEQ || token == GREAT || token == GEQ)
433 if(oberon_is_number_type(a) && oberon_is_number_type(b))
435 return true;
437 else if(oberon_is_char_type(a) && oberon_is_char_type(b))
439 return true;
441 else if((oberon_is_array_of_char_type(a) || oberon_is_string_type(a))
442 && (oberon_is_array_of_char_type(b) || oberon_is_string_type(b)))
444 return true;
447 else if(token == IN)
449 if(oberon_is_integer_type(a) && oberon_is_set_type(b))
451 return true;
454 else if(token == IS)
456 if(oberon_extension_of(a, b))
458 return true;
462 return false;
465 bool
466 oberon_is_compatible_var_param(oberon_type_t * Tf, oberon_type_t * Ta)
468 /* Пусть Tf - тип формального параметра f (не открытого массива) */
469 /* и Ta - тип соответствующего фактического параметра a. */
470 /* Для параметров-переменных Ta и Tf должны быть одинаковыми типами */
471 /* или Tf должен быть типом запись, а Ta - расширением Tf. */
473 /* SYSTEM: Если формальный параметр-переменная имеет тип ARRAY OF BYTE, */
474 /* то соответствующий фактический параметр может иметь любой тип. */
475 /* SYSTEM: Если формальный параметр-переменная имеет тип PTR, */
476 /* фактический параметр может быть указателем любого типа. */
478 return oberon_is_some_types(Tf, Ta)
479 || (oberon_is_record_type(Tf) && oberon_extension_of(Ta, Tf))
480 || (oberon_is_array_of_system_byte_type(Tf))
481 || (oberon_is_system_ptr_type(Tf));
484 void
485 oberon_check_compatible_var_param(oberon_context_t * ctx, oberon_type_t * Tf, oberon_type_t * Ta)
487 if(!oberon_is_compatible_var_param(Tf, Ta))
489 oberon_error(ctx, "incompatible types");
493 void
494 oberon_check_type_expr(oberon_context_t * ctx, oberon_expr_t * e)
496 if(!oberon_is_type_expr(e))
498 oberon_error(ctx, "expected type");
502 void
503 oberon_check_compatible_bin_expr(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_expr_t * b)
505 if(!oberon_is_compatible_bin_expr(token, a, b))
507 oberon_error(ctx, "incompatibe expression types");
511 void
512 oberon_check_assignment_compatible(oberon_context_t * ctx, oberon_expr_t * e, oberon_type_t * Tv)
514 if(!oberon_is_assignment_compatible_expressions(e, Tv))
516 oberon_error(ctx, "incompatible types");
520 void
521 oberon_check_extension_of(oberon_context_t * ctx, oberon_type_t * ext, oberon_type_t * rec)
523 if(!oberon_extension_of(ext, rec))
525 oberon_error(ctx, "not extension");
529 oberon_type_t *
530 oberon_get_longer_type(oberon_context_t * ctx, oberon_type_t * a, oberon_type_t * b)
532 if(oberon_incluses_type(a, b))
534 return a;
536 else
538 return b;
542 oberon_type_t *
543 oberon_get_longer_real_type(oberon_context_t * ctx, oberon_type_t * a, oberon_type_t * b)
545 oberon_type_t * result = oberon_get_longer_type(ctx, a, b);
546 if(oberon_is_integer_type(result))
548 return ctx -> real_type;
550 else
552 return result;