X-Git-Url: https://deadsoftware.ru/gitweb?p=dsw-obn.git;a=blobdiff_plain;f=src%2Foberon.c;h=5a93489b35ed197ee2ac10b262a95c042583d146;hp=50429645b22a713480253b1fb262128dc1b97af6;hb=a0ff807fe0e69c50469e506836467da32f23f754;hpb=9bcd389a97869b2ab6b1c6fdc35c0f09beab66c5 diff --git a/src/oberon.c b/src/oberon.c index 5042964..5a93489 100644 --- a/src/oberon.c +++ b/src/oberon.c @@ -24,8 +24,6 @@ enum { BEGIN, ASSIGN, INTEGER, - TRUE, - FALSE, LPAREN, RPAREN, EQUAL, @@ -77,7 +75,10 @@ enum { EXIT, LBRACE, RBRACE, - DOTDOT + DOTDOT, + CASE, + BAR, + WITH }; // ======================================================================= @@ -341,14 +342,6 @@ oberon_read_ident(oberon_context_t * ctx) { ctx -> token = BEGIN; } - else if(strcmp(ident, "TRUE") == 0) - { - ctx -> token = TRUE; - } - else if(strcmp(ident, "FALSE") == 0) - { - ctx -> token = FALSE; - } else if(strcmp(ident, "OR") == 0) { ctx -> token = OR; @@ -461,8 +454,19 @@ oberon_read_ident(oberon_context_t * ctx) { ctx -> token = EXIT; } + else if(strcmp(ident, "CASE") == 0) + { + ctx -> token = CASE; + } + else if(strcmp(ident, "WITH") == 0) + { + ctx -> token = WITH; + } } +#define ISHEXDIGIT(x) \ + (((x) >= '0' && (x) <= '9') || ((x) >= 'A' && (x) <= 'F')) + static void oberon_read_number(oberon_context_t * ctx) { @@ -490,10 +494,10 @@ oberon_read_number(oberon_context_t * ctx) end_i = ctx -> code_index; - if(isxdigit(ctx -> c)) + if(ISHEXDIGIT(ctx -> c)) { mode = 1; - while(isxdigit(ctx -> c)) + while(ISHEXDIGIT(ctx -> c)) { oberon_get_char(ctx); } @@ -686,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); @@ -822,6 +824,10 @@ oberon_read_symbol(oberon_context_t * ctx) ctx -> token = RBRACE; oberon_get_char(ctx); break; + case '|': + ctx -> token = BAR; + oberon_get_char(ctx); + break; default: oberon_error(ctx, "invalid char %c", ctx -> c); break; @@ -978,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; } @@ -1091,19 +1094,41 @@ oberon_autocast_to(oberon_context_t * ctx, oberon_expr_t * expr, oberon_type_t * // Допускается: // Если классы типов равны // Если INTEGER переводится в REAL - // Есди 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_ARRAY) + if(pref -> class == OBERON_TYPE_CHAR) + { + if(expr -> is_item && expr -> item.mode == MODE_STRING) + { + if(strlen(expr -> item.string) != 1) + { + error = true; + } + } + else + { + error = true; + } + } + else if(pref -> class == OBERON_TYPE_ARRAY) { if(pref -> base -> class != OBERON_TYPE_CHAR) { @@ -1133,7 +1158,16 @@ oberon_autocast_to(oberon_context_t * ctx, oberon_expr_t * expr, oberon_type_t * oberon_error(ctx, "oberon_autocast_to: incompatible types"); } - if(pref -> class == OBERON_TYPE_INTEGER || pref -> class == OBERON_TYPE_REAL) + if(pref -> class == OBERON_TYPE_CHAR) + { + if(expr -> result -> class == OBERON_TYPE_STRING) + { + int c = expr -> item.string[0]; + expr = oberon_new_item(MODE_CHAR, ctx -> char_type, true); + expr -> item.integer = c; + } + } + else if(pref -> class == OBERON_TYPE_INTEGER || pref -> class == OBERON_TYPE_REAL) { if(expr -> result -> size > pref -> size) { @@ -1152,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"); } } @@ -1208,13 +1243,21 @@ oberon_autocast_call(oberon_context_t * ctx, oberon_item_t * desig) { if(param -> class == OBERON_CLASS_VAR_PARAM) { + if(arg -> result != param -> type) + { + oberon_error(ctx, "incompatible type"); + } if(arg -> read_only) { oberon_error(ctx, "assign to read-only var"); } + casted[i] = arg; + } + else + { + casted[i] = oberon_autocast_to(ctx, arg, param -> type); } - casted[i] = oberon_autocast_to(ctx, arg, param -> type); arg = arg -> next; param = param -> next; } @@ -1253,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"); } @@ -1290,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"); } @@ -1314,14 +1357,11 @@ oberon_make_call_proc(oberon_context_t * ctx, oberon_item_t * item, int num_args || ((x) == STRING) \ || ((x) == NIL) \ || ((x) == LPAREN) \ - || ((x) == NOT) \ - || ((x) == TRUE) \ - || ((x) == FALSE)) + || ((x) == NOT)) 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"); @@ -1490,9 +1530,8 @@ oberon_ident_item(oberon_context_t * ctx, char * name) } static oberon_expr_t * -oberon_designator(oberon_context_t * ctx) +oberon_qualident_expr(oberon_context_t * ctx) { - char * name; oberon_object_t * var; oberon_expr_t * expr; @@ -1528,8 +1567,20 @@ oberon_designator(oberon_context_t * ctx) oberon_error(ctx, "invalid designator"); break; } + expr -> item.var = var; + return expr; +} + +static oberon_expr_t * +oberon_designator(oberon_context_t * ctx) +{ + char * name; + oberon_expr_t * expr; + + expr = oberon_qualident_expr(ctx); + while(expr -> result -> class != OBERON_TYPE_PROCEDURE && ISSELECTOR(ctx -> token)) { switch(ctx -> token) @@ -1709,6 +1760,15 @@ oberon_set(oberon_context_t * ctx) return set; } +static oberon_expr_t * +oberon_make_boolean(oberon_context_t * ctx, bool cond) +{ + oberon_expr_t * expr; + expr = oberon_new_item(MODE_BOOLEAN, ctx -> bool_type, true); + expr -> item.integer = cond; + return expr; +} + static oberon_expr_t * oberon_factor(oberon_context_t * ctx) { @@ -1743,16 +1803,6 @@ oberon_factor(oberon_context_t * ctx) expr -> item.real = ctx -> real; oberon_assert_token(ctx, REAL); break; - case TRUE: - expr = oberon_new_item(MODE_BOOLEAN, ctx -> bool_type, true); - expr -> item.boolean = true; - oberon_assert_token(ctx, TRUE); - break; - case FALSE: - expr = oberon_new_item(MODE_BOOLEAN, ctx -> bool_type, true); - expr -> item.boolean = false; - oberon_assert_token(ctx, FALSE); - break; case LBRACE: expr = oberon_set(ctx); break; @@ -1768,7 +1818,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"); @@ -1814,7 +1864,22 @@ oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_ oberon_type_t * result; bool error = false; - if(token == IS) + if(token == IN) + { + if(a -> result -> class != OBERON_TYPE_INTEGER) + { + oberon_error(ctx, "must be integer"); + } + + if(b -> result -> class != OBERON_TYPE_SET) + { + oberon_error(ctx, "must be set"); + } + + result = ctx -> bool_type; + expr = oberon_new_operator(OP_IN, result, a, b); + } + else if(token == IS) { oberon_type_t * v = a -> result; if(v -> class == OBERON_TYPE_POINTER) @@ -2085,12 +2150,9 @@ oberon_expr(oberon_context_t * ctx) return expr; } -static oberon_item_t * -oberon_const_expr(oberon_context_t * ctx) +static void +oberon_check_const(oberon_context_t * ctx, oberon_expr_t * expr) { - oberon_expr_t * expr; - expr = oberon_expr(ctx); - if(expr -> is_item == 0) { oberon_error(ctx, "const expression are required"); @@ -2111,7 +2173,14 @@ oberon_const_expr(oberon_context_t * ctx) oberon_error(ctx, "const expression are required"); break; } +} +static oberon_item_t * +oberon_const_expr(oberon_context_t * ctx) +{ + oberon_expr_t * expr; + expr = oberon_expr(ctx); + oberon_check_const(ctx, expr); return (oberon_item_t *) expr; } @@ -2204,7 +2273,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); @@ -2235,7 +2304,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; @@ -2290,7 +2359,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) @@ -2333,7 +2402,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) { @@ -2379,7 +2448,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); @@ -2417,16 +2486,23 @@ 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); + //oberon_initialize_decl(ctx); oberon_generator_init_type(ctx, signature); oberon_close_scope(ctx -> decl); oberon_object_t * proc; proc = oberon_find_object(ctx -> decl, name, 0); - if(proc != NULL) + if(proc == NULL) + { + proc = oberon_define_object(ctx -> decl, name, OBERON_CLASS_PROC, export, read_only, false); + proc -> type = signature; + proc -> scope = proc_scope; + oberon_generator_init_proc(ctx, proc); + } + else { if(proc -> class != OBERON_CLASS_PROC) { @@ -2448,16 +2524,15 @@ oberon_proc_decl(oberon_context_t * ctx) oberon_compare_signatures(ctx, proc -> type, signature); } - else + + proc_scope -> parent = proc; + oberon_object_t * param = proc_scope -> list -> next; + while(param) { - proc = oberon_define_object(ctx -> decl, name, OBERON_CLASS_PROC, export, read_only, false); - proc -> type = signature; - proc -> scope = proc_scope; - oberon_generator_init_proc(ctx, proc); + param -> parent = proc; + param = param -> next; } - proc -> scope -> parent = proc; - if(forward == 0) { proc -> linked = 1; @@ -2518,7 +2593,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; @@ -2540,7 +2615,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); @@ -2563,7 +2638,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); @@ -2664,7 +2739,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) @@ -2695,7 +2770,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; @@ -2732,7 +2807,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 @@ -2756,7 +2831,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"); } @@ -2810,6 +2885,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++) @@ -2951,7 +3031,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"); } @@ -3156,6 +3236,167 @@ oberon_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst) oberon_generate_assign(ctx, src, dst); } +static oberon_expr_t * +oberon_case_labels(oberon_context_t * ctx, oberon_expr_t * val) +{ + oberon_expr_t * e1; + oberon_expr_t * e2; + oberon_expr_t * cond; + oberon_expr_t * cond2; + + e1 = (oberon_expr_t *) oberon_const_expr(ctx); + oberon_autocast_to(ctx, e1, val -> result); + + e2 = NULL; + if(ctx -> token == DOTDOT) + { + oberon_assert_token(ctx, DOTDOT); + e2 = (oberon_expr_t *) oberon_const_expr(ctx); + oberon_autocast_to(ctx, e2, val -> result); + } + + if(e2 == NULL) + { + /* val == e1 */ + cond = oberon_make_bin_op(ctx, EQUAL, val, e1); + } + else + { + /* val >= e1 && val <= e2 */ + cond = oberon_make_bin_op(ctx, GEQ, val, e1); + cond2 = oberon_make_bin_op(ctx, LEQ, val, e2); + cond = oberon_make_bin_op(ctx, AND, cond, cond2); + } + + return cond; +} + +static void +oberon_case(oberon_context_t * ctx, oberon_expr_t * val, gen_label_t * end) +{ + oberon_expr_t * cond; + oberon_expr_t * cond2; + gen_label_t * this_end; + + if(ISEXPR(ctx -> token)) + { + this_end = oberon_generator_reserve_label(ctx); + + cond = oberon_case_labels(ctx, val); + while(ctx -> token == COMMA) + { + oberon_assert_token(ctx, COMMA); + /* cond || cond2 */ + cond2 = oberon_case_labels(ctx, val); + cond = oberon_make_bin_op(ctx, OR, cond, cond2); + } + oberon_assert_token(ctx, COLON); + + oberon_generate_branch(ctx, cond, false, this_end); + oberon_statement_seq(ctx); + oberon_generate_goto(ctx, end); + + oberon_generate_label(ctx, this_end); + } +} + +static void +oberon_case_statement(oberon_context_t * ctx) +{ + oberon_expr_t * val; + oberon_expr_t * expr; + gen_label_t * end; + + end = oberon_generator_reserve_label(ctx); + + oberon_assert_token(ctx, CASE); + expr = oberon_expr(ctx); + val = oberon_make_temp_var_item(ctx, expr -> result); + oberon_assign(ctx, expr, val); + oberon_assert_token(ctx, OF); + oberon_case(ctx, val, end); + while(ctx -> token == BAR) + { + oberon_assert_token(ctx, BAR); + oberon_case(ctx, val, end); + } + + if(ctx -> token == ELSE) + { + oberon_assert_token(ctx, ELSE); + oberon_statement_seq(ctx); + } + + oberon_generate_label(ctx, end); + oberon_assert_token(ctx, END); +} + +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_expr_t * cond; + oberon_expr_t * cast; + 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); + oberon_assert_token(ctx, COLON); + type = oberon_qualident_expr(ctx); + cond = oberon_make_bin_op(ctx, IS, 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); + 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; + + oberon_statement_seq(ctx); + 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 +oberon_with_statement(oberon_context_t * ctx) +{ + gen_label_t * end; + end = oberon_generator_reserve_label(ctx); + + oberon_assert_token(ctx, WITH); + oberon_with_guard_do(ctx, end); + while(ctx -> token == BAR) + { + oberon_assert_token(ctx, BAR); + oberon_with_guard_do(ctx, end); + } + + if(ctx -> token == ELSE) + { + oberon_assert_token(ctx, ELSE); + oberon_statement_seq(ctx); + } + + oberon_generate_label(ctx, end); + oberon_assert_token(ctx, END); +} + static void oberon_statement(oberon_context_t * ctx) { @@ -3362,6 +3603,14 @@ oberon_statement(oberon_context_t * ctx) } oberon_generate_goto(ctx, ctx -> decl -> exit_label); } + else if(ctx -> token == CASE) + { + oberon_case_statement(ctx); + } + else if(ctx -> token == WITH) + { + oberon_with_statement(ctx); + } else if(ctx -> token == RETURN) { oberon_assert_token(ctx, RETURN); @@ -3483,7 +3732,7 @@ oberon_parse_module(oberon_context_t * ctx) oberon_assert_token(ctx, END); name2 = oberon_assert_ident(ctx); - oberon_assert_token(ctx, DOT); + oberon_expect_token(ctx, DOT); if(strcmp(name1, name2) != 0) { @@ -3500,12 +3749,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); @@ -3513,17 +3761,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); @@ -3531,9 +3782,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); } @@ -3783,6 +4031,15 @@ oberon_make_new_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_ oberon_assign(ctx, src, dst); } +static void +oberon_new_const(oberon_context_t * ctx, char * name, oberon_expr_t * expr) +{ + oberon_object_t * constant; + constant = oberon_define_object(ctx -> decl, name, OBERON_CLASS_CONST, true, false, false); + oberon_check_const(ctx, expr); + constant -> value = (oberon_item_t *) expr; +} + oberon_context_t * oberon_create_context(ModuleImportCallback import_module) { @@ -3798,6 +4055,10 @@ oberon_create_context(ModuleImportCallback import_module) register_default_types(ctx); + /* Constants */ + oberon_new_const(ctx, "TRUE", oberon_make_boolean(ctx, true)); + oberon_new_const(ctx, "FALSE", oberon_make_boolean(ctx, false)); + /* Functions */ oberon_new_intrinsic(ctx, "ABS", oberon_make_abs_call, NULL); oberon_new_intrinsic(ctx, "MIN", oberon_make_min_call, NULL);