X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=oberon.c;h=dab60b0bb151dce64579a099f2aa59f5722a2eb6;hb=12ae486a18746b042fcc4ebbefc5449d4d3464af;hp=5b4c4ea84efada1e388a0c775f4d363e16df49d8;hpb=3818049ca3679e8fcc432345d41a2d930f7874e4;p=dsw-obn.git diff --git a/oberon.c b/oberon.c index 5b4c4ea..dab60b0 100644 --- a/oberon.c +++ b/oberon.c @@ -155,42 +155,13 @@ oberon_define_object(oberon_scope_t * scope, char * name, int class, int export, newvar -> read_only = read_only; newvar -> local = scope -> local; newvar -> parent = scope -> parent; + newvar -> module = scope -> ctx -> mod; x -> next = newvar; return newvar; } -/* -static void -oberon_define_field(oberon_context_t * ctx, oberon_type_t * rec, char * name, oberon_type_t * type) -{ - // TODO check base fields - - oberon_object_t * x = rec -> decl; - while(x -> next && strcmp(x -> next -> name, name) != 0) - { - x = x -> next; - } - - if(x -> next) - { - oberon_error(ctx, "multiple definition"); - } - - oberon_object_t * field = malloc(sizeof *field); - memset(field, 0, sizeof *field); - field -> name = name; - field -> class = OBERON_CLASS_FIELD; - field -> type = type; - field -> local = 1; - field -> parent = NULL; - - rec -> num_decl += 1; - x -> next = field; -} -*/ - static oberon_object_t * oberon_find_object_in_list(oberon_object_t * list, char * name) { @@ -257,8 +228,11 @@ oberon_define_type(oberon_scope_t * scope, char * name, oberon_type_t * type, in static void oberon_get_char(oberon_context_t * ctx) { - ctx -> code_index += 1; - ctx -> c = ctx -> code[ctx -> code_index]; + if(ctx -> code[ctx -> code_index]) + { + ctx -> code_index += 1; + ctx -> c = ctx -> code[ctx -> code_index]; + } } static void @@ -408,6 +382,43 @@ oberon_skip_space(oberon_context_t * ctx) } } +static void +oberon_read_comment(oberon_context_t * ctx) +{ + int nesting = 1; + while(nesting >= 1) + { + if(ctx -> c == '(') + { + oberon_get_char(ctx); + if(ctx -> c == '*') + { + oberon_get_char(ctx); + nesting += 1; + } + } + else if(ctx -> c == '*') + { + oberon_get_char(ctx); + if(ctx -> c == ')') + { + oberon_get_char(ctx); + nesting -= 1; + } + } + else if(ctx -> c == 0) + { + oberon_error(ctx, "unterminated comment"); + } + else + { + oberon_get_char(ctx); + } + } +} + +static void oberon_read_token(oberon_context_t * ctx); + static void oberon_read_symbol(oberon_context_t * ctx) { @@ -437,6 +448,12 @@ oberon_read_symbol(oberon_context_t * ctx) case '(': ctx -> token = LPAREN; oberon_get_char(ctx); + if(ctx -> c == '*') + { + oberon_get_char(ctx); + oberon_read_comment(ctx); + oberon_read_token(ctx); + } break; case ')': ctx -> token = RPAREN; @@ -479,6 +496,11 @@ oberon_read_symbol(oberon_context_t * ctx) case '*': ctx -> token = STAR; oberon_get_char(ctx); + if(ctx -> c == ')') + { + oberon_get_char(ctx); + oberon_error(ctx, "unstarted comment"); + } break; case '/': ctx -> token = SLASH; @@ -509,7 +531,7 @@ oberon_read_symbol(oberon_context_t * ctx) oberon_get_char(ctx); break; default: - oberon_error(ctx, "invalid char"); + oberon_error(ctx, "invalid char %c", ctx -> c); break; } } @@ -554,6 +576,7 @@ oberon_new_operator(int op, oberon_type_t * result, oberon_expr_t * left, oberon operator -> is_item = 0; operator -> result = result; + operator -> read_only = 1; operator -> op = op; operator -> left = left; operator -> right = right; @@ -562,7 +585,7 @@ oberon_new_operator(int op, oberon_type_t * result, oberon_expr_t * left, oberon } static oberon_expr_t * -oberon_new_item(int mode, oberon_type_t * result) +oberon_new_item(int mode, oberon_type_t * result, int read_only) { oberon_item_t * item; item = malloc(sizeof *item); @@ -570,6 +593,7 @@ oberon_new_item(int mode, oberon_type_t * result) item -> is_item = 1; item -> result = result; + item -> read_only = read_only; item -> mode = mode; return (oberon_expr_t *)item; @@ -641,7 +665,13 @@ oberon_autocast_to(oberon_context_t * ctx, oberon_expr_t * expr, oberon_type_t * { if(pref -> class != expr -> result -> class) { - oberon_error(ctx, "incompatible types"); + if(pref -> class != OBERON_TYPE_PROCEDURE) + { + if(expr -> result -> class != OBERON_TYPE_POINTER) + { + oberon_error(ctx, "incompatible types"); + } + } } if(pref -> class == OBERON_TYPE_INTEGER) @@ -712,21 +742,26 @@ oberon_autocast_call(oberon_context_t * ctx, oberon_expr_t * desig) { if(param -> class == OBERON_CLASS_VAR_PARAM) { - if(arg -> is_item) + if(arg -> read_only) { - switch(arg -> item.mode) - { - case MODE_VAR: - case MODE_INDEX: - case MODE_FIELD: - // Допустимо разыменование? - //case MODE_DEREF: - break; - default: - oberon_error(ctx, "var-parameter accept only variables"); - break; - } + oberon_error(ctx, "assign to read-only var"); } + + //if(arg -> is_item) + //{ + // switch(arg -> item.mode) + // { + // case MODE_VAR: + // case MODE_INDEX: + // case MODE_FIELD: + // // Допустимо разыменование? + // //case MODE_DEREF: + // break; + // default: + // oberon_error(ctx, "var-parameter accept only variables"); + // break; + // } + //} } oberon_autocast_to(ctx, arg, param -> type); arg = arg -> next; @@ -776,7 +811,7 @@ oberon_make_call_func(oberon_context_t * ctx, oberon_object_t * proc, int num_ar oberon_error(ctx, "attempt to call procedure in expression"); } - call = oberon_new_item(MODE_CALL, proc -> type -> base); + call = oberon_new_item(MODE_CALL, proc -> type -> base, 1); call -> item.var = proc; call -> item.num_args = num_args; call -> item.args = list_args; @@ -827,7 +862,7 @@ oberon_make_call_proc(oberon_context_t * ctx, oberon_object_t * proc, int num_ar } oberon_expr_t * call; - call = oberon_new_item(MODE_CALL, proc -> type -> base); + call = oberon_new_item(MODE_CALL, proc -> type -> base, 1); call -> item.var = proc; call -> item.num_args = num_args; call -> item.args = list_args; @@ -857,7 +892,7 @@ oberno_make_dereferencing(oberon_context_t * ctx, oberon_expr_t * expr) assert(expr -> is_item); oberon_expr_t * selector; - selector = oberon_new_item(MODE_DEREF, expr -> result -> base); + selector = oberon_new_item(MODE_DEREF, expr -> result -> base, expr -> read_only); selector -> item.parent = (oberon_item_t *) expr; return selector; @@ -901,7 +936,7 @@ oberon_make_array_selector(oberon_context_t * ctx, oberon_expr_t * desig, oberon } oberon_expr_t * selector; - selector = oberon_new_item(MODE_INDEX, base); + selector = oberon_new_item(MODE_INDEX, base, desig -> read_only); selector -> item.parent = (oberon_item_t *) desig; selector -> item.num_args = 1; selector -> item.args = index; @@ -929,8 +964,25 @@ oberon_make_record_selector(oberon_context_t * ctx, oberon_expr_t * expr, char * oberon_object_t * field; field = oberon_find_field(ctx, rec, name); + if(field -> export == 0) + { + if(field -> module != ctx -> mod) + { + oberon_error(ctx, "field not exported"); + } + } + + int read_only = 0; + if(field -> read_only) + { + if(field -> module != ctx -> mod) + { + read_only = 1; + } + } + oberon_expr_t * selector; - selector = oberon_new_item(MODE_FIELD, field -> type); + selector = oberon_new_item(MODE_FIELD, field -> type, read_only); selector -> item.var = field; selector -> item.parent = (oberon_item_t *) expr; @@ -984,6 +1036,15 @@ oberon_designator(oberon_context_t * ctx) var = oberon_qualident(ctx, NULL, 1); + int read_only = 0; + if(var -> read_only) + { + if(var -> module != ctx -> mod) + { + read_only = 1; + } + } + switch(var -> class) { case OBERON_CLASS_CONST: @@ -993,8 +1054,10 @@ oberon_designator(oberon_context_t * ctx) case OBERON_CLASS_VAR: case OBERON_CLASS_VAR_PARAM: case OBERON_CLASS_PARAM: + expr = oberon_new_item(MODE_VAR, var -> type, read_only); + break; case OBERON_CLASS_PROC: - expr = oberon_new_item(MODE_VAR, var -> type); + expr = oberon_new_item(MODE_VAR, var -> type, 1); break; default: oberon_error(ctx, "invalid designator"); @@ -1098,17 +1161,17 @@ oberon_factor(oberon_context_t * ctx) expr = oberon_opt_func_parens(ctx, expr); break; case INTEGER: - expr = oberon_new_item(MODE_INTEGER, ctx -> int_type); + expr = oberon_new_item(MODE_INTEGER, ctx -> int_type, 1); expr -> item.integer = ctx -> integer; oberon_assert_token(ctx, INTEGER); break; case TRUE: - expr = oberon_new_item(MODE_BOOLEAN, ctx -> bool_type); + expr = oberon_new_item(MODE_BOOLEAN, ctx -> bool_type, 1); expr -> item.boolean = 1; oberon_assert_token(ctx, TRUE); break; case FALSE: - expr = oberon_new_item(MODE_BOOLEAN, ctx -> bool_type); + expr = oberon_new_item(MODE_BOOLEAN, ctx -> bool_type, 1); expr -> item.boolean = 0; oberon_assert_token(ctx, FALSE); break; @@ -1124,7 +1187,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); + expr = oberon_new_item(MODE_NIL, ctx -> void_ptr_type, 1); break; default: oberon_error(ctx, "invalid expression"); @@ -2294,6 +2357,11 @@ oberon_decl_seq(oberon_context_t * ctx) static void oberon_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst) { + if(dst -> read_only) + { + oberon_error(ctx, "read-only destination"); + } + oberon_autocast_to(ctx, src, dst -> result); oberon_generate_assign(ctx, src, dst); } @@ -2420,17 +2488,11 @@ oberon_parse_module(oberon_context_t * ctx) oberon_assert_token(ctx, SEMICOLON); ctx -> mod -> name = name1; - oberon_object_t * this_module; - this_module = oberon_define_object(ctx -> decl, name1, OBERON_CLASS_MODULE, 0, 0); - this_module -> module = ctx -> mod; - if(ctx -> token == IMPORT) { oberon_import_list(ctx); } - ctx -> decl -> parent = this_module; - oberon_decl_seq(ctx); oberon_generate_begin_module(ctx); @@ -2513,6 +2575,71 @@ oberon_make_abs_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_ return expr; } +static void +oberon_make_new_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_args) +{ + if(num_args < 1) + { + oberon_error(ctx, "too few arguments"); + } + + if(num_args > 1) + { + oberon_error(ctx, "too mach arguments"); + } + + oberon_expr_t * dst; + dst = list_args; + + oberon_type_t * type; + type = dst -> result; + + if(type -> class != OBERON_TYPE_POINTER) + { + oberon_error(ctx, "not a pointer"); + } + + type = type -> base; + + oberon_expr_t * src; + src = oberon_new_item(MODE_NEW, dst -> result, 0); + src -> item.num_args = 0; + src -> item.args = NULL; + + if(type -> class == OBERON_TYPE_ARRAY) + { + // Пригодится при работе с открытыми массивами + /* + int dim = 1; + oberon_expr_t * sizes = NULL; + oberon_expr_t * last_size = NULL; + sizes = last_size = oberon_new_item(MODE_INTEGER, ctx -> int_type, 1); + sizes -> item.integer = type -> size; + oberon_type_t * base = type -> base; + while(base -> class == OBERON_TYPE_ARRAY) + { + oberon_expr_t * size; + size = last_size = oberon_new_item(MODE_INTEGER, ctx -> int_type, 1); + size -> item.integer = base -> size; + + last_size -> next = size; + last_size = size; + base = base -> base; + dim += 1; + } + */ + + src -> item.num_args = 0; + src -> item.args = NULL; + } + else if(type -> class != OBERON_TYPE_RECORD) + { + oberon_error(ctx, "oberon_make_new_call: wat"); + } + + oberon_assign(ctx, src, dst); +} + oberon_context_t * oberon_create_context(ModuleImportCallback import_module) { @@ -2528,6 +2655,7 @@ oberon_create_context(ModuleImportCallback import_module) register_default_types(ctx); oberon_new_intrinsic(ctx, "ABS", oberon_make_abs_call, NULL); + oberon_new_intrinsic(ctx, "NEW", NULL, oberon_make_new_call); return ctx; }