X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Foberon.c;h=ece881fc44366290a324ac54b55def84b1c9804b;hb=49ad3c76fc9656759aab23d9034ebc33f8d8bd9d;hp=f1fe4518a135c6e9369e877ac2c08d13575fb12a;hpb=844ae6c007ac4606ad4ac3938876b67c014bb5eb;p=dsw-obn.git diff --git a/src/oberon.c b/src/oberon.c index f1fe451..ece881f 100644 --- a/src/oberon.c +++ b/src/oberon.c @@ -690,8 +690,6 @@ static void oberon_read_string(oberon_context_t * ctx) ctx -> token = STRING; ctx -> string = string; - - printf("oberon_read_string: string ((%s))\n", string); } static void oberon_read_token(oberon_context_t * ctx); @@ -986,11 +984,8 @@ oberno_make_record_cast(oberon_context_t * ctx, oberon_expr_t * expr, oberon_typ oberon_type_t * from = expr -> result; oberon_type_t * to = rec; - printf("oberno_make_record_cast: from class %i to class %i\n", from -> class, to -> class); - if(from -> class == OBERON_TYPE_POINTER && to -> class == OBERON_TYPE_POINTER) { - printf("oberno_make_record_cast: pointers\n"); from = from -> base; to = to -> base; } @@ -1099,18 +1094,25 @@ oberon_autocast_to(oberon_context_t * ctx, oberon_expr_t * expr, oberon_type_t * // Допускается: // Если классы типов равны // Если INTEGER переводится в REAL - // Есди STRING переводится в CHAR - // Есди STRING переводится в ARRAY OF CHAR + // Если STRING переводится в CHAR + // Если STRING переводится в ARRAY OF CHAR + // Если NIL переводится в POINTER + // Если NIL переводится в PROCEDURE oberon_check_src(ctx, expr); bool error = false; if(pref -> class != expr -> result -> class) { - printf("expr class %i\n", expr -> result -> class); - printf("pref class %i\n", pref -> class); - - if(expr -> result -> class == OBERON_TYPE_STRING) + if(expr -> result -> class == OBERON_TYPE_NIL) + { + if(pref -> class != OBERON_TYPE_POINTER + && pref -> class != OBERON_TYPE_PROCEDURE) + { + error = true; + } + } + else if(expr -> result -> class == OBERON_TYPE_STRING) { if(pref -> class == OBERON_TYPE_CHAR) { @@ -1184,17 +1186,18 @@ oberon_autocast_to(oberon_context_t * ctx, oberon_expr_t * expr, oberon_type_t * else if(pref -> class == OBERON_TYPE_POINTER) { assert(pref -> base); - if(expr -> result -> base -> class == OBERON_TYPE_RECORD) + if(expr -> result -> class == OBERON_TYPE_NIL) + { + // do nothing + } + else if(expr -> result -> base -> class == OBERON_TYPE_RECORD) { oberon_check_record_compatibility(ctx, expr -> result, pref); expr = oberno_make_record_cast(ctx, expr, pref); } else if(expr -> result -> base != pref -> base) { - if(expr -> result -> base -> class != OBERON_TYPE_VOID) - { - oberon_error(ctx, "incompatible pointer types"); - } + oberon_error(ctx, "incompatible pointer types"); } } @@ -1293,7 +1296,7 @@ oberon_make_call_func(oberon_context_t * ctx, oberon_item_t * item, int num_args } else { - if(signature -> base -> class == OBERON_TYPE_VOID) + if(signature -> base -> class == OBERON_TYPE_NOTYPE) { oberon_error(ctx, "attempt to call procedure in expression"); } @@ -1330,7 +1333,7 @@ oberon_make_call_proc(oberon_context_t * ctx, oberon_item_t * item, int num_args } else { - if(signature -> base -> class != OBERON_TYPE_VOID) + if(signature -> base -> class != OBERON_TYPE_NOTYPE) { oberon_error(ctx, "attempt to call function as non-typed procedure"); } @@ -1359,7 +1362,6 @@ oberon_make_call_proc(oberon_context_t * ctx, oberon_item_t * item, int num_args static oberon_expr_t * oberno_make_dereferencing(oberon_context_t * ctx, oberon_expr_t * expr) { - printf("oberno_make_dereferencing\n"); if(expr -> result -> class != OBERON_TYPE_POINTER) { oberon_error(ctx, "not a pointer"); @@ -1451,7 +1453,7 @@ oberon_make_record_selector(oberon_context_t * ctx, oberon_expr_t * expr, char * } } - int read_only = 0; + int read_only = expr -> read_only; if(field -> read_only) { if(field -> module != ctx -> mod) @@ -1571,11 +1573,46 @@ oberon_qualident_expr(oberon_context_t * ctx) return expr; } +static oberon_expr_t * +oberon_make_type_guard(oberon_context_t * ctx, oberon_expr_t * expr, oberon_object_t * objtype) +{ + oberon_type_t * type; + + if(objtype -> class != OBERON_CLASS_TYPE) + { + oberon_error(ctx, "must be type"); + } + type = objtype -> type; + + /* Охрана типа применима, если */ + /* 1. v - параметр-переменная типа запись, или v - указатель, и если */ + /* 2. T - расширение статического типа v */ + + if(expr -> is_item + && expr -> item.mode == MODE_VAR + && expr -> item.var -> class == OBERON_CLASS_VAR_PARAM) + { + // accept + } + else if(expr -> result -> class == OBERON_TYPE_POINTER) + { + // accept + } + else + { + oberon_error(ctx, "guard type used only with var-param or pointers"); + } + + oberon_check_record_compatibility(ctx, type, expr -> result); + return oberno_make_record_cast(ctx, expr, objtype -> type); +} + static oberon_expr_t * oberon_designator(oberon_context_t * ctx) { char * name; oberon_expr_t * expr; + oberon_object_t * objtype; expr = oberon_qualident_expr(ctx); @@ -1607,13 +1644,9 @@ oberon_designator(oberon_context_t * ctx) break; case LPAREN: oberon_assert_token(ctx, LPAREN); - oberon_object_t * objtype = oberon_qualident(ctx, NULL, 1); - if(objtype -> class != OBERON_CLASS_TYPE) - { - oberon_error(ctx, "must be type"); - } + objtype = oberon_qualident(ctx, NULL, true); oberon_assert_token(ctx, RPAREN); - expr = oberno_make_record_cast(ctx, expr, objtype -> type); + expr = oberon_make_type_guard(ctx, expr, objtype); break; default: oberon_error(ctx, "oberon_designator: wat"); @@ -1816,7 +1849,7 @@ oberon_factor(oberon_context_t * ctx) break; case NIL: oberon_assert_token(ctx, NIL); - expr = oberon_new_item(MODE_NIL, ctx -> void_ptr_type, true); + expr = oberon_new_item(MODE_NIL, ctx -> nil_type, true); break; default: oberon_error(ctx, "invalid expression"); @@ -2271,7 +2304,7 @@ oberon_var_decl(oberon_context_t * ctx) int num; oberon_object_t * list; oberon_type_t * type; - type = oberon_new_type_ptr(OBERON_TYPE_VOID); + type = oberon_new_type_ptr(OBERON_TYPE_NOTYPE); oberon_ident_list(ctx, OBERON_CLASS_VAR, false, &num, &list); oberon_assert_token(ctx, COLON); @@ -2302,7 +2335,7 @@ oberon_fp_section(oberon_context_t * ctx, int * num_decl) oberon_assert_token(ctx, COLON); oberon_type_t * type; - type = oberon_new_type_ptr(OBERON_TYPE_VOID); + type = oberon_new_type_ptr(OBERON_TYPE_NOTYPE); oberon_type(ctx, &type); oberon_object_t * param = list; @@ -2357,7 +2390,7 @@ oberon_opt_formal_pars(oberon_context_t * ctx, oberon_type_t ** type) signature = *type; signature -> class = OBERON_TYPE_PROCEDURE; signature -> num_decl = 0; - signature -> base = ctx -> void_type; + signature -> base = ctx -> notype_type; signature -> decl = NULL; if(ctx -> token == LPAREN) @@ -2400,7 +2433,7 @@ oberon_make_return(oberon_context_t * ctx, oberon_expr_t * expr) oberon_object_t * proc = ctx -> decl -> parent; oberon_type_t * result_type = proc -> type -> base; - if(result_type -> class == OBERON_TYPE_VOID) + if(result_type -> class == OBERON_TYPE_NOTYPE) { if(expr != NULL) { @@ -2446,7 +2479,7 @@ oberon_proc_decl_body(oberon_context_t * ctx, oberon_object_t * proc) oberon_error(ctx, "procedure name not matched"); } - if(proc -> type -> base -> class == OBERON_TYPE_VOID + if(proc -> type -> base -> class == OBERON_TYPE_NOTYPE && proc -> has_return == 0) { oberon_make_return(ctx, NULL); @@ -2484,7 +2517,7 @@ oberon_proc_decl(oberon_context_t * ctx) ctx -> decl -> local = 1; oberon_type_t * signature; - signature = oberon_new_type_ptr(OBERON_TYPE_VOID); + signature = oberon_new_type_ptr(OBERON_TYPE_NOTYPE); oberon_opt_formal_pars(ctx, &signature); //oberon_initialize_decl(ctx); @@ -2591,7 +2624,7 @@ oberon_qualident_type(oberon_context_t * ctx, oberon_type_t ** type) else { to = oberon_define_object(ctx -> decl, name, OBERON_CLASS_TYPE, false, false, false); - to -> type = oberon_new_type_ptr(OBERON_TYPE_VOID); + to -> type = oberon_new_type_ptr(OBERON_TYPE_NOTYPE); } *type = to -> type; @@ -2613,7 +2646,7 @@ oberon_make_multiarray(oberon_context_t * ctx, oberon_expr_t * sizes, oberon_typ } oberon_type_t * dim; - dim = oberon_new_type_ptr(OBERON_TYPE_VOID); + dim = oberon_new_type_ptr(OBERON_TYPE_NOTYPE); oberon_make_multiarray(ctx, sizes -> next, base, &dim); @@ -2636,7 +2669,7 @@ oberon_field_list(oberon_context_t * ctx, oberon_type_t * rec, oberon_scope_t * int num; oberon_object_t * list; oberon_type_t * type; - type = oberon_new_type_ptr(OBERON_TYPE_VOID); + type = oberon_new_type_ptr(OBERON_TYPE_NOTYPE); oberon_ident_list(ctx, OBERON_CLASS_FIELD, true, &num, &list); oberon_assert_token(ctx, COLON); @@ -2737,7 +2770,7 @@ oberon_type(oberon_context_t * ctx, oberon_type_t ** type) oberon_assert_token(ctx, OF); oberon_type_t * base; - base = oberon_new_type_ptr(OBERON_TYPE_VOID); + base = oberon_new_type_ptr(OBERON_TYPE_NOTYPE); oberon_type(ctx, &base); if(num_sizes == 0) @@ -2768,7 +2801,7 @@ oberon_type(oberon_context_t * ctx, oberon_type_t ** type) oberon_assert_token(ctx, TO); oberon_type_t * base; - base = oberon_new_type_ptr(OBERON_TYPE_VOID); + base = oberon_new_type_ptr(OBERON_TYPE_NOTYPE); oberon_type(ctx, &base); oberon_type_t * ptr; @@ -2805,7 +2838,7 @@ oberon_type_decl(oberon_context_t * ctx) if(newtype == NULL) { newtype = oberon_define_object(ctx -> decl, name, OBERON_CLASS_TYPE, export, read_only, false); - newtype -> type = oberon_new_type_ptr(OBERON_TYPE_VOID); + newtype -> type = oberon_new_type_ptr(OBERON_TYPE_NOTYPE); assert(newtype -> type); } else @@ -2829,7 +2862,7 @@ oberon_type_decl(oberon_context_t * ctx) type = newtype -> type; oberon_type(ctx, &type); - if(type -> class == OBERON_TYPE_VOID) + if(type -> class == OBERON_TYPE_NOTYPE) { oberon_error(ctx, "recursive alias declaration"); } @@ -2883,6 +2916,11 @@ oberon_prevent_recursive_record(oberon_context_t * ctx, oberon_type_t * type) type -> recursive = 1; + if(type -> base) + { + oberon_prevent_recursive_record(ctx, type -> base); + } + int num_fields = type -> num_decl; oberon_object_t * field = type -> decl; for(int i = 0; i < num_fields; i++) @@ -3024,7 +3062,7 @@ oberon_initialize_record_fields(oberon_context_t * ctx, oberon_type_t * type) static void oberon_initialize_type(oberon_context_t * ctx, oberon_type_t * type) { - if(type -> class == OBERON_TYPE_VOID) + if(type -> class == OBERON_TYPE_NOTYPE) { oberon_error(ctx, "undeclarated type"); } @@ -3742,12 +3780,11 @@ oberon_parse_module(oberon_context_t * ctx) static void register_default_types(oberon_context_t * ctx) { - ctx -> void_type = oberon_new_type_ptr(OBERON_TYPE_VOID); - oberon_generator_init_type(ctx, ctx -> void_type); + ctx -> notype_type = oberon_new_type_ptr(OBERON_TYPE_NOTYPE); + oberon_generator_init_type(ctx, ctx -> notype_type); - ctx -> void_ptr_type = oberon_new_type_ptr(OBERON_TYPE_POINTER); - ctx -> void_ptr_type -> base = ctx -> void_type; - oberon_generator_init_type(ctx, ctx -> void_ptr_type); + ctx -> nil_type = oberon_new_type_ptr(OBERON_TYPE_NIL); + oberon_generator_init_type(ctx, ctx -> nil_type); ctx -> string_type = oberon_new_type_string(1); oberon_generator_init_type(ctx, ctx -> string_type); @@ -3755,17 +3792,20 @@ register_default_types(oberon_context_t * ctx) ctx -> bool_type = oberon_new_type_boolean(); oberon_define_type(ctx -> world_scope, "BOOLEAN", ctx -> bool_type, 1); + ctx -> char_type = oberon_new_type_char(1); + oberon_define_type(ctx -> world_scope, "CHAR", ctx -> char_type, 1); + ctx -> byte_type = oberon_new_type_integer(1); - oberon_define_type(ctx -> world_scope, "BYTE", ctx -> byte_type, 1); + oberon_define_type(ctx -> world_scope, "SHORTINT", ctx -> byte_type, 1); ctx -> shortint_type = oberon_new_type_integer(2); - oberon_define_type(ctx -> world_scope, "SHORTINT", ctx -> shortint_type, 1); + oberon_define_type(ctx -> world_scope, "INTEGER", ctx -> shortint_type, 1); ctx -> int_type = oberon_new_type_integer(4); - oberon_define_type(ctx -> world_scope, "INTEGER", ctx -> int_type, 1); + oberon_define_type(ctx -> world_scope, "LONGINT", ctx -> int_type, 1); ctx -> longint_type = oberon_new_type_integer(8); - oberon_define_type(ctx -> world_scope, "LONGINT", ctx -> longint_type, 1); + oberon_define_type(ctx -> world_scope, "HUGEINT", ctx -> longint_type, 1); ctx -> real_type = oberon_new_type_real(4); oberon_define_type(ctx -> world_scope, "REAL", ctx -> real_type, 1); @@ -3773,9 +3813,6 @@ register_default_types(oberon_context_t * ctx) ctx -> longreal_type = oberon_new_type_real(8); oberon_define_type(ctx -> world_scope, "LONGREAL", ctx -> longreal_type, 1); - ctx -> char_type = oberon_new_type_char(1); - oberon_define_type(ctx -> world_scope, "CHAR", ctx -> char_type, 1); - ctx -> set_type = oberon_new_type_set(4); oberon_define_type(ctx -> world_scope, "SET", ctx -> set_type, 1); }