X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=oberon.c;h=931d948c57bc15c0faf906e0a6f23b52f991a122;hb=c4d4a265b71124ad0e8588601cfc1d66aca84b96;hp=b56a458a6c1e979a743c9d4139b5df3044f1cdc3;hpb=89dfaf94ddbbc501020554232ce026b6584e8045;p=dsw-obn.git diff --git a/oberon.c b/oberon.c index b56a458..931d948 100644 --- a/oberon.c +++ b/oberon.c @@ -228,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 @@ -379,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) { @@ -408,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; @@ -450,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; @@ -480,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; } } @@ -614,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) @@ -685,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; @@ -2513,6 +2575,69 @@ 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; + 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 = oberon_new_item(MODE_NEWARR, dst -> result, 0); + src -> item.num_args = dim; + src -> item.args = sizes; + src -> item.type = base; + } + else + { + oberon_error(ctx, "oberon_make_new_call: wat"); + } + + oberon_assign(ctx, src, dst); +} + oberon_context_t * oberon_create_context(ModuleImportCallback import_module) { @@ -2528,6 +2653,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; }