X-Git-Url: http://deadsoftware.ru/gitweb?p=dsw-obn.git;a=blobdiff_plain;f=src%2Foberon.c;h=5abb2090477536027219f41e2e0b9e78b69d9ab5;hp=29c40cb974b5a822bb89c18cfe567a2d464aa966;hb=0c29ba1953327a9b476a825d8b9b9d185d544972;hpb=ab13caca4af9fb7617a6dfeaaec3b250c5bda0ac diff --git a/src/oberon.c b/src/oberon.c index 29c40cb..5abb209 100644 --- a/src/oberon.c +++ b/src/oberon.c @@ -10,8 +10,6 @@ #include -#include "../include/oberon.h" - #include "oberon-internals.h" #include "oberon-type-compat.h" #include "oberon-common.h" @@ -362,15 +360,20 @@ oberon_get_char(oberon_context_t * ctx) if(ctx -> code[ctx -> code_index]) { ctx -> code_index += 1; + ctx -> xloc.col += 1; ctx -> c = ctx -> code[ctx -> code_index]; } } static void -oberon_init_scaner(oberon_context_t * ctx, const char * code) +oberon_init_scaner(oberon_context_t * ctx, oberon_scanner_t * s) { - ctx -> code = code; + ctx -> code = s -> code; ctx -> code_index = 0; + ctx -> xloc.source = s -> source; + ctx -> xloc.line = 1; + ctx -> xloc.col = 1; + ctx -> loc = ctx -> xloc; ctx -> c = ctx -> code[ctx -> code_index]; } @@ -689,12 +692,40 @@ oberon_read_number(oberon_context_t * ctx) ctx -> real = real; } +static void +oberon_get_lined_char(oberon_context_t * ctx) +{ + do + { + if(ctx -> c == 0xD) + { + oberon_get_char(ctx); + if(ctx -> c == 0xA) + { + oberon_get_char(ctx); + } + ctx -> xloc.line += 1; + ctx -> xloc.col = 1; + } + else if(ctx -> c == 0xA) + { + oberon_get_char(ctx); + ctx -> xloc.line += 1; + ctx -> xloc.col = 1; + } + else + { + oberon_get_char(ctx); + } + } while(ctx -> c == 0xD || ctx -> c == 0xA); +} + static void oberon_skip_space(oberon_context_t * ctx) { while(isspace(ctx -> c)) { - oberon_get_char(ctx); + oberon_get_lined_char(ctx); } } @@ -706,19 +737,19 @@ oberon_read_comment(oberon_context_t * ctx) { if(ctx -> c == '(') { - oberon_get_char(ctx); + oberon_get_lined_char(ctx); if(ctx -> c == '*') { - oberon_get_char(ctx); + oberon_get_lined_char(ctx); nesting += 1; } } else if(ctx -> c == '*') { - oberon_get_char(ctx); + oberon_get_lined_char(ctx); if(ctx -> c == ')') { - oberon_get_char(ctx); + oberon_get_lined_char(ctx); nesting -= 1; } } @@ -728,7 +759,7 @@ oberon_read_comment(oberon_context_t * ctx) } else { - oberon_get_char(ctx); + oberon_get_lined_char(ctx); } } } @@ -910,6 +941,8 @@ oberon_read_token(oberon_context_t * ctx) { oberon_skip_space(ctx); + ctx -> loc = ctx -> xloc; + int c = ctx -> c; if(isalpha(c) || c == '_') { @@ -1055,6 +1088,12 @@ oberon_cast_expr(oberon_context_t * ctx, oberon_expr_t * expr, oberon_type_t * p cast = oberon_new_item(MODE_CHAR, ctx -> char_type, true); cast -> item.integer = expr -> item.string[0]; } + else if(oberon_is_record_type(pref) || oberon_is_pointer_to_record(pref)) + { + assert(expr -> is_item); + cast = oberon_new_item(MODE_AS, pref, expr -> read_only); + cast -> item.parent = (oberon_item_t *) expr; + } else if(!oberon_is_some_types(expr -> result, pref)) { cast = oberon_new_operator(OP_CAST, pref, expr, NULL); @@ -1259,6 +1298,7 @@ oberon_make_call_proc(oberon_context_t * ctx, oberon_item_t * item, int num_args || ((x) == CHAR) \ || ((x) == STRING) \ || ((x) == NIL) \ + || ((x) == LBRACE) \ || ((x) == LPAREN) \ || ((x) == NOT)) @@ -1925,7 +1965,26 @@ oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_ break; } } - else if(oberon_is_number_type(result)) + else if(oberon_is_real_type(result)) + { + switch(token) + { + case PLUS: + expr = oberon_new_operator(OP_ADD, result, a, b); + break; + case MINUS: + expr = oberon_new_operator(OP_SUB, result, a, b); + break; + case STAR: + expr = oberon_new_operator(OP_MUL, result, a, b); + break; + default: + printf("token %i line %i\n", token, ctx -> loc.line); + assert(0); + break; + } + } + else if(oberon_is_integer_type(result)) { switch(token) { @@ -1938,7 +1997,14 @@ oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_ case STAR: expr = oberon_new_operator(OP_MUL, result, a, b); break; + case DIV: + expr = oberon_new_operator(OP_DIV, result, a, b); + break; + case MOD: + expr = oberon_new_operator(OP_MOD, result, a, b); + break; default: + printf("token %i line %i\n", token, ctx -> loc.line); assert(0); break; } @@ -2352,8 +2418,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_NOTYPE - && proc -> has_return == 0) + if(proc -> type -> base -> class == OBERON_TYPE_NOTYPE) { oberon_make_return(ctx, NULL); } @@ -2566,9 +2631,8 @@ oberon_field_list(oberon_context_t * ctx, oberon_type_t * rec, oberon_scope_t * static void oberon_type_record_body(oberon_context_t * ctx, oberon_type_t * rec) { - oberon_scope_t * modscope = ctx -> mod -> decl; oberon_scope_t * oldscope = ctx -> decl; - ctx -> decl = modscope; + ctx -> decl = oldscope; if(ctx -> token == LPAREN) { @@ -2609,11 +2673,11 @@ oberon_type_record_body(oberon_context_t * ctx, oberon_type_t * rec) this_scope -> parent = NULL; this_scope -> parent_type = rec; - oberon_field_list(ctx, rec, modscope); + oberon_field_list(ctx, rec, oldscope); while(ctx -> token == SEMICOLON) { oberon_assert_token(ctx, SEMICOLON); - oberon_field_list(ctx, rec, modscope); + oberon_field_list(ctx, rec, oldscope); } rec -> scope = this_scope; @@ -2758,7 +2822,14 @@ oberon_prevent_recursive_pointer(oberon_context_t * ctx, oberon_type_t * type) if(type -> recursive) { - oberon_error(ctx, "recursive pointer declaration"); + if(type -> class == OBERON_TYPE_POINTER) + { + oberon_error(ctx, "recursive pointer declaration"); + } + else + { + oberon_error(ctx, "recursive array declaration (pointer)"); + } } if(type -> class == OBERON_TYPE_POINTER @@ -2911,20 +2982,12 @@ static void oberon_initialize_type(oberon_context_t * ctx, oberon_type_t * type) static void oberon_initialize_record_fields(oberon_context_t * ctx, oberon_type_t * type) { - if(type -> class != OBERON_TYPE_RECORD) - { - return; - } + assert(type -> class == OBERON_TYPE_RECORD); int num_fields = type -> num_decl; oberon_object_t * field = type -> decl; for(int i = 0; i < num_fields; i++) { - if(field -> type -> class == OBERON_TYPE_POINTER) - { - oberon_initialize_type(ctx, field -> type); - } - oberon_initialize_object(ctx, field); field = field -> next; } @@ -2947,39 +3010,50 @@ oberon_initialize_type(oberon_context_t * ctx, oberon_type_t * type) type -> initialized = 1; - if(type -> class == OBERON_TYPE_POINTER) + if(type -> class == OBERON_TYPE_POINTER || type -> class == OBERON_TYPE_ARRAY) { - oberon_initialize_type(ctx, type -> base); - oberon_generator_init_type(ctx, type); - } - else if(type -> class == OBERON_TYPE_ARRAY) - { - if(type -> size != 0) + if(type -> class == OBERON_TYPE_ARRAY + && type -> size != 0 + && type -> base -> class == OBERON_TYPE_ARRAY + && type -> base -> size == 0) { - if(type -> base -> class == OBERON_TYPE_ARRAY) - { - if(type -> base -> size == 0) - { - oberon_error(ctx, "open array not allowed as array element"); - } - } + oberon_error(ctx, "open array not allowed as array element"); } - oberon_initialize_type(ctx, type -> base); - oberon_generator_init_type(ctx, type); + oberon_type_t * rec = type -> base; + while(rec -> class == OBERON_TYPE_ARRAY || rec -> class == OBERON_TYPE_POINTER) + { + rec = rec -> base; + } + + if(rec -> class == OBERON_TYPE_RECORD + && rec -> initialized == 0) + { + rec -> initialized = 1; + oberon_generator_init_type(ctx, rec); + oberon_initialize_type(ctx, type -> base); + oberon_generator_init_type(ctx, type); + oberon_initialize_record_fields(ctx, rec); + } + else + { + oberon_initialize_type(ctx, type -> base); + oberon_generator_init_type(ctx, type); + } } else if(type -> class == OBERON_TYPE_RECORD) { + printf("Init type: RECORD\n"); oberon_generator_init_type(ctx, type); oberon_initialize_record_fields(ctx, type); } else if(type -> class == OBERON_TYPE_PROCEDURE) { + printf("Init type: PROCEDURE\n"); int num_fields = type -> num_decl; oberon_object_t * field = type -> decl; for(int i = 0; i < num_fields; i++) { - //oberon_initialize_object(ctx, field); oberon_initialize_type(ctx, field -> type); field = field -> next; } @@ -3067,33 +3141,34 @@ oberon_prevent_undeclarated_procedures(oberon_context_t * ctx) static void oberon_decl_seq(oberon_context_t * ctx) { - if(ctx -> token == CONST) + while(ctx -> token >= CONST && ctx -> token <= VAR) { - oberon_assert_token(ctx, CONST); - while(ctx -> token == IDENT) + if(ctx -> token == CONST) { - oberon_const_decl(ctx); - oberon_assert_token(ctx, SEMICOLON); + oberon_assert_token(ctx, CONST); + while(ctx -> token == IDENT) + { + oberon_const_decl(ctx); + oberon_assert_token(ctx, SEMICOLON); + } } - } - - if(ctx -> token == TYPE) - { - oberon_assert_token(ctx, TYPE); - while(ctx -> token == IDENT) + else if(ctx -> token == TYPE) { - oberon_type_decl(ctx); - oberon_assert_token(ctx, SEMICOLON); + oberon_assert_token(ctx, TYPE); + while(ctx -> token == IDENT) + { + oberon_type_decl(ctx); + oberon_assert_token(ctx, SEMICOLON); + } } - } - - if(ctx -> token == VAR) - { - oberon_assert_token(ctx, VAR); - while(ctx -> token == IDENT) + else if(ctx -> token == VAR) { - oberon_var_decl(ctx); - oberon_assert_token(ctx, SEMICOLON); + oberon_assert_token(ctx, VAR); + while(ctx -> token == IDENT) + { + oberon_var_decl(ctx); + oberon_assert_token(ctx, SEMICOLON); + } } } @@ -3247,44 +3322,38 @@ oberon_case_statement(oberon_context_t * ctx) static void oberon_with_guard_do(oberon_context_t * ctx, gen_label_t * end) { - oberon_expr_t * val; - oberon_expr_t * var; - oberon_expr_t * type; + oberon_object_t * var; + oberon_expr_t * var_expr; + oberon_expr_t * type_expr; oberon_expr_t * cond; - oberon_expr_t * cast; + oberon_type_t * type; oberon_type_t * old_type; - gen_var_t * old_var; gen_label_t * this_end; this_end = oberon_generator_reserve_label(ctx); - var = oberon_qualident_expr(ctx); + var_expr = oberon_qualident_expr(ctx); oberon_assert_token(ctx, COLON); - type = oberon_qualident_expr(ctx); - cond = oberon_make_bin_op(ctx, IS, var, type); + type_expr = oberon_qualident_expr(ctx); + cond = oberon_make_bin_op(ctx, IS, var_expr, type_expr); + + var = var_expr -> item.var; + type = type_expr -> result; + old_type = var -> type; oberon_assert_token(ctx, DO); oberon_generate_branch(ctx, cond, false, this_end); - /* Сохраняем ссылку во временной переменной */ - val = oberon_make_temp_var_item(ctx, type -> result); - //cast = oberno_make_record_cast(ctx, var, type -> result); - cast = oberon_cast_expr(ctx, var, type -> result); - oberon_assign(ctx, cast, val); - /* Подменяем тип у оригинальной переменной */ - old_type = var -> item.var -> type; - var -> item.var -> type = type -> result; - /* Подменяем ссылку на переменную */ - old_var = var -> item.var -> gen_var; - var -> item.var -> gen_var = val -> item.var -> gen_var; + var -> type = type; + oberon_set_typecheck(var, true); oberon_statement_seq(ctx); + + var -> type = old_type; + oberon_set_typecheck(var, false); + oberon_generate_goto(ctx, end); oberon_generate_label(ctx, this_end); - - /* Возвращаем исходное состояние */ - var -> item.var -> gen_var = old_var; - var -> item.var -> type = old_type; } static void @@ -3426,7 +3495,7 @@ oberon_statement(oberon_context_t * ctx) oberon_error(ctx, "condition must be boolean"); } - oberon_generate_branch(ctx, cond, true, begin); + oberon_generate_branch(ctx, cond, false, begin); } else if(ctx -> token == FOR) { @@ -3567,14 +3636,14 @@ oberon_import_module(oberon_context_t * ctx, char * alias, char * name) if(m == NULL) { - const char * code; - code = ctx -> import_module(name); - if(code == NULL) + oberon_scanner_t * s; + s = ctx -> import_module(name); + if(s == NULL) { - oberon_error(ctx, "no such module"); + oberon_error(ctx, "no such module %s", name); } - m = oberon_compile_module(ctx, code); + m = oberon_compile_module(ctx, s); assert(m); } @@ -3818,7 +3887,7 @@ oberon_make_abs_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_ arg = list_args; oberon_check_src(ctx, arg); - if(oberon_is_number_type(arg -> result)) + if(!oberon_is_number_type(arg -> result)) { oberon_error(ctx, "ABS accepts only numbers"); } @@ -3852,7 +3921,7 @@ oberon_make_inc_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_ oberon_error(ctx, "too few arguments"); } - if(num_args > 1) + if(num_args > 2) { oberon_error(ctx, "too mach arguments"); } @@ -3866,8 +3935,23 @@ oberon_make_inc_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_ oberon_error(ctx, "expect integer"); } + oberon_expr_t * step; + if(num_args == 2) + { + step = list_args -> next; + oberon_check_src(ctx, step); + if(!oberon_is_integer_type(step -> result)) + { + oberon_error(ctx, "expect integer"); + } + } + else + { + step = oberon_make_integer(ctx, 1); + } + oberon_expr_t * expr; - expr = oberon_make_bin_op(ctx, PLUS, dst, oberon_make_integer(ctx, 1)); + expr = oberon_make_bin_op(ctx, PLUS, dst, step); oberon_assign(ctx, expr, dst); } @@ -3951,7 +4035,7 @@ oberon_make_dec_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_ oberon_error(ctx, "too few arguments"); } - if(num_args > 1) + if(num_args > 2) { oberon_error(ctx, "too mach arguments"); } @@ -3965,8 +4049,23 @@ oberon_make_dec_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_ oberon_error(ctx, "expect integer"); } + oberon_expr_t * step; + if(num_args == 2) + { + step = list_args -> next; + oberon_check_src(ctx, step); + if(!oberon_is_integer_type(step -> result)) + { + oberon_error(ctx, "expect integer"); + } + } + else + { + step = oberon_make_integer(ctx, 1); + } + oberon_expr_t * expr; - expr = oberon_make_bin_op(ctx, MINUS, dst, oberon_make_integer(ctx, 1)); + expr = oberon_make_bin_op(ctx, MINUS, dst, step); oberon_assign(ctx, expr, dst); } @@ -4434,7 +4533,7 @@ oberon_make_ord_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_ } else { - expr = oberon_cast_expr(ctx, arg, ctx -> int_type); + expr = oberon_cast_expr(ctx, arg, ctx -> shortint_type); } return expr; } @@ -4859,6 +4958,8 @@ oberon_create_context(ModuleImportCallback import_module) /* Types */ oberon_new_intrinsic_type(ctx, "BYTE", ctx -> system_byte_type); oberon_new_intrinsic_type(ctx, "PTR", ctx -> system_ptr_type); + oberon_new_intrinsic_type(ctx, "INT32", ctx -> int_type); + oberon_new_intrinsic_type(ctx, "SET32", ctx -> set_type); /* Functions */ oberon_new_intrinsic(ctx, "CC", oberon_make_cc_call, NULL); @@ -4878,10 +4979,12 @@ oberon_destroy_context(oberon_context_t * ctx) } oberon_module_t * -oberon_compile_module(oberon_context_t * ctx, const char * newcode) +oberon_compile_module(oberon_context_t * ctx, oberon_scanner_t * s) { const char * code = ctx -> code; int code_index = ctx -> code_index; + oberon_location_t loc = ctx -> loc; + oberon_location_t xloc = ctx -> xloc; char c = ctx -> c; int token = ctx -> token; char * string = ctx -> string; @@ -4903,13 +5006,15 @@ oberon_compile_module(oberon_context_t * ctx, const char * newcode) ctx -> mod = module; ctx -> module_list = module; - oberon_init_scaner(ctx, newcode); + oberon_init_scaner(ctx, s); oberon_parse_module(ctx); module -> ready = 1; ctx -> code = code; ctx -> code_index = code_index; + ctx -> loc = loc; + ctx -> xloc = xloc; ctx -> c = c; ctx -> token = token; ctx -> string = string;