X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=oberon.c;h=0aa8d45bf1304f6a95fe211480359d30afa7c9ef;hb=90ad7d921e60c24b11bc08cd173c0e1c80f9b06d;hp=e411c6c2fdaa455bf15fddcd54c7b94a37f3c8c3;hpb=b752043cfbb49243ca3727dbfc9be5b614a8c9c2;p=dsw-obn.git diff --git a/oberon.c b/oberon.c index e411c6c..0aa8d45 100644 --- a/oberon.c +++ b/oberon.c @@ -3,7 +3,9 @@ #include #include #include + #include "oberon.h" +#include "generator.h" enum { EOF_ = 0, @@ -16,26 +18,34 @@ enum { COLON, BEGIN, ASSIGN, - INTEGER -}; - -enum { - MODE_VAR, - MODE_INTEGER, + INTEGER, + TRUE, + FALSE, + LPAREN, + RPAREN, + EQUAL, + NEQ, + LESS, + LEQ, + GREAT, + GEQ, + PLUS, + MINUS, + OR, + STAR, + SLASH, + DIV, + MOD, + AND, + NOT, + PROCEDURE }; -typedef struct -{ - int mode; - int integer; - oberon_var_t * var; -} oberon_item_t; - // ======================================================================= // UTILS // ======================================================================= -static void +void oberon_error(oberon_context_t * ctx, const char * fmt, ...) { va_list ptr; @@ -50,85 +60,141 @@ oberon_error(oberon_context_t * ctx, const char * fmt, ...) exit(1); } -static int -oberon_item_to_type_class(oberon_context_t * ctx, oberon_item_t * item) +// ======================================================================= +// TABLE +// ======================================================================= + +static oberon_scope_t * +oberon_open_scope(oberon_context_t * ctx) { - int class; + oberon_scope_t * scope = malloc(sizeof *scope); + memset(scope, 0, sizeof *scope); - if(item -> mode == MODE_INTEGER) - { - class = OBERON_TYPE_INTEGER; - } - else if(item -> mode == MODE_VAR) - { - class = item -> var -> type -> class; - } - else - { - oberon_error(ctx, "oberon_item_to_type_class: wat"); - } + oberon_object_t * list = malloc(sizeof *list); + memset(list, 0, sizeof *list); - return class; + scope -> ctx = ctx; + scope -> list = list; + scope -> up = ctx -> decl; + + ctx -> decl = scope; + return scope; } -// ======================================================================= -// TABLE -// ======================================================================= +static void +oberon_close_scope(oberon_scope_t * scope) +{ + oberon_context_t * ctx = scope -> ctx; + ctx -> decl = scope -> up; +} -static oberon_type_t * -oberon_find_type(oberon_context_t * ctx, char * name) +static oberon_object_t * +oberon_define_object(oberon_scope_t * scope, char * name, int class) { - oberon_type_t * x = ctx -> types; + oberon_object_t * x = scope -> list; while(x -> next && strcmp(x -> next -> name, name) != 0) { x = x -> next; } - return x -> next; + if(x -> next) + { + oberon_error(scope -> ctx, "already defined"); + } + + oberon_object_t * newvar = malloc(sizeof *newvar); + memset(newvar, 0, sizeof *newvar); + newvar -> name = name; + newvar -> class = class; + + x -> next = newvar; + + return newvar; } -static oberon_var_t * -oberon_find_var(oberon_context_t * ctx, char * name) +static oberon_object_t * +oberon_find_object_in_list(oberon_object_t * list, char * name) { - oberon_var_t * x = ctx -> mod -> vars; + oberon_object_t * x = list; while(x -> next && strcmp(x -> next -> name, name) != 0) { x = x -> next; } - return x -> next; } -static void -oberon_define_var(oberon_context_t * ctx, char * name, oberon_type_t * type) +static oberon_object_t * +oberon_find_object(oberon_scope_t * scope, char * name) { - oberon_var_t * x = ctx -> mod -> vars; - while(x -> next && strcmp(x -> next -> name, name) != 0) + oberon_object_t * result = NULL; + + oberon_scope_t * s = scope; + while(result == NULL && s != NULL) { - x = x -> next; + result = oberon_find_object_in_list(s -> list, name); + s = s -> up; } - if(x -> next) + if(result == NULL) { - oberon_error(ctx, "already defined"); + oberon_error(scope -> ctx, "undefined ident %s", name); } - oberon_var_t * newvar = malloc(sizeof *newvar); - memset(newvar, 0, sizeof *newvar); - newvar -> name = name; - newvar -> type = type; + return result; +} - x -> next = newvar; +static void +oberon_define_type(oberon_scope_t * scope, char * name, oberon_type_t * type) +{ + oberon_object_t * id; + id = oberon_define_object(scope, name, OBERON_CLASS_TYPE); + id -> type = type; + oberon_generator_init_type(scope -> ctx, type); } -// ======================================================================= -// GENERATOR -// ======================================================================= +static oberon_type_t * +oberon_find_type(oberon_scope_t * scope, char * name) +{ + oberon_object_t * x = oberon_find_object(scope, name); + if(x -> class != OBERON_CLASS_TYPE) + { + oberon_error(scope -> ctx, "%s not a type", name); + } + + return x -> type; +} static void -oberon_generate_assign(oberon_context_t * ctx, void * src, void * dst, int size) +oberon_define_var(oberon_scope_t * scope, char * name, oberon_type_t * type) +{ + oberon_object_t * var; + var = oberon_define_object(scope, name, OBERON_CLASS_VAR); + var -> type = type; + oberon_generator_init_var(scope -> ctx, var); +} + +/* +static oberon_object_t * +oberon_find_var(oberon_scope_t * scope, char * name) +{ + oberon_object_t * x = oberon_find_object(scope, name); + + if(x -> class != OBERON_CLASS_VAR) + { + oberon_error(scope -> ctx, "%s not a var", name); + } + + return x; +} +*/ + +static oberon_object_t * +oberon_define_proc(oberon_scope_t * scope, char * name) { - printf("G: %p := %p (%i);\n", dst, src, size); + oberon_object_t * proc; + proc = oberon_define_object(scope, name, OBERON_CLASS_PROC); + oberon_generator_init_proc(scope -> ctx, proc); + return proc; } // ======================================================================= @@ -164,9 +230,9 @@ oberon_read_ident(oberon_context_t * ctx) c = ctx -> code[i]; } - char * ident = malloc(len + 2); + char * ident = malloc(len + 1); memcpy(ident, &ctx->code[ctx->code_index], len); - ident[len + 1] = 0; + ident[len] = 0; ctx -> code_index = i; ctx -> c = ctx -> code[i]; @@ -189,6 +255,30 @@ 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; + } + else if(strcmp(ident, "DIV") == 0) + { + ctx -> token = DIV; + } + else if(strcmp(ident, "MOD") == 0) + { + ctx -> token = MOD; + } + else if(strcmp(ident, "PROCEDURE") == 0) + { + ctx -> token = PROCEDURE; + } } static void @@ -225,6 +315,96 @@ oberon_skip_space(oberon_context_t * ctx) } } +static void +oberon_read_symbol(oberon_context_t * ctx) +{ + int c = ctx -> c; + switch(c) + { + case 0: + ctx -> token = EOF_; + break; + case ';': + ctx -> token = SEMICOLON; + oberon_get_char(ctx); + break; + case ':': + ctx -> token = COLON; + oberon_get_char(ctx); + if(ctx -> c == '=') + { + ctx -> token = ASSIGN; + oberon_get_char(ctx); + } + break; + case '.': + ctx -> token = DOT; + oberon_get_char(ctx); + break; + case '(': + ctx -> token = LPAREN; + oberon_get_char(ctx); + break; + case ')': + ctx -> token = RPAREN; + oberon_get_char(ctx); + break; + case '=': + ctx -> token = EQUAL; + oberon_get_char(ctx); + break; + case '#': + ctx -> token = NEQ; + oberon_get_char(ctx); + break; + case '<': + ctx -> token = LESS; + oberon_get_char(ctx); + if(ctx -> c == '=') + { + ctx -> token = LEQ; + oberon_get_char(ctx); + } + break; + case '>': + ctx -> token = GREAT; + oberon_get_char(ctx); + if(ctx -> c == '=') + { + ctx -> token = GEQ; + oberon_get_char(ctx); + } + break; + case '+': + ctx -> token = PLUS; + oberon_get_char(ctx); + break; + case '-': + ctx -> token = MINUS; + oberon_get_char(ctx); + break; + case '*': + ctx -> token = STAR; + oberon_get_char(ctx); + break; + case '/': + ctx -> token = SLASH; + oberon_get_char(ctx); + break; + case '&': + ctx -> token = AND; + oberon_get_char(ctx); + break; + case '~': + ctx -> token = NOT; + oberon_get_char(ctx); + break; + default: + oberon_error(ctx, "invalid char"); + break; + } +} + static void oberon_read_token(oberon_context_t * ctx) { @@ -241,30 +421,370 @@ oberon_read_token(oberon_context_t * ctx) } else { - switch(c) + oberon_read_symbol(ctx); + } +} + +// ======================================================================= +// EXPRESSION +// ======================================================================= + +static void oberon_expect_token(oberon_context_t * ctx, int token); +static oberon_expr_t * oberon_expr(oberon_context_t * ctx); +static void oberon_assert_token(oberon_context_t * ctx, int token); +static char * oberon_assert_ident(oberon_context_t * ctx); + +static oberon_expr_t * +oberon_new_operator(int op, oberon_type_t * result, oberon_expr_t * left, oberon_expr_t * right) +{ + oberon_oper_t * operator; + operator = malloc(sizeof *operator); + memset(operator, 0, sizeof *operator); + + operator -> is_item = 0; + operator -> result = result; + operator -> op = op; + operator -> left = left; + operator -> right = right; + + return (oberon_expr_t *) operator; +} + +static oberon_expr_t * +oberon_new_item(int mode, oberon_type_t * result) +{ + oberon_item_t * item; + item = malloc(sizeof *item); + memset(item, 0, sizeof *item); + + item -> is_item = 1; + item -> result = result; + item -> mode = mode; + + return (oberon_expr_t *)item; +} + +static oberon_expr_t * +oberon_make_unary_op(oberon_context_t * ctx, int token, oberon_expr_t * a) +{ + oberon_expr_t * expr; + oberon_type_t * result; + + result = a -> result; + + if(token == MINUS) + { + if(result -> class != OBERON_TYPE_INTEGER) + { + oberon_error(ctx, "incompatible operator type"); + } + + expr = oberon_new_operator(OP_UNARY_MINUS, result, a, NULL); + } + else if(token == NOT) + { + if(result -> class != OBERON_TYPE_BOOLEAN) + { + oberon_error(ctx, "incompatible operator type"); + } + + expr = oberon_new_operator(OP_LOGIC_NOT, result, a, NULL); + } + else + { + oberon_error(ctx, "oberon_make_unary_op: wat"); + } + + return expr; +} + +static oberon_expr_t * +oberon_factor(oberon_context_t * ctx) +{ + char * name; + oberon_object_t * var; + oberon_expr_t * expr; + + switch(ctx -> token) + { + case IDENT: + name = oberon_assert_ident(ctx); + var = oberon_find_object(ctx -> decl, name); + if(var -> class == OBERON_CLASS_VAR) + { + expr = oberon_new_item(MODE_VAR, var -> type); + } + else if(var -> class == OBERON_CLASS_PROC) + { + expr = oberon_new_item(MODE_CALL, var -> type); + } + else + { + oberon_error(ctx, "invalid desinator"); + } + expr -> item.var = var; + break; + case INTEGER: + expr = oberon_new_item(MODE_INTEGER, ctx -> int_type); + expr -> item.integer = ctx -> integer; + oberon_assert_token(ctx, INTEGER); + break; + case TRUE: + expr = oberon_new_item(MODE_BOOLEAN, ctx -> bool_type); + expr -> item.boolean = 1; + oberon_assert_token(ctx, TRUE); + break; + case FALSE: + expr = oberon_new_item(MODE_BOOLEAN, ctx -> bool_type); + expr -> item.boolean = 0; + oberon_assert_token(ctx, FALSE); + break; + case LPAREN: + oberon_assert_token(ctx, LPAREN); + expr = oberon_expr(ctx); + oberon_assert_token(ctx, RPAREN); + break; + case NOT: + oberon_assert_token(ctx, NOT); + expr = oberon_factor(ctx); + expr = oberon_make_unary_op(ctx, NOT, expr); + break; + default: + oberon_error(ctx, "invalid expression"); + } + + return expr; +} + +/* + * oberon_autocast_binary_op автоматически переобразовывеат тип по след. правилам: + * 1. Классы обоих типов должны быть одинаковы + * 2. В качестве результата должен быть выбран больший тип. + * 3. Если размер результат не должен быть меньше чем базовый int + */ + +static void +oberon_autocast_binary_op(oberon_context_t * ctx, oberon_type_t * a, oberon_type_t * b, oberon_type_t ** result) +{ + if((a -> class) != (b -> class)) + { + oberon_error(ctx, "incompatible types"); + } + + if((a -> size) > (b -> size)) + { + *result = a; + } + else + { + *result = b; + } + + if(((*result) -> class) == OBERON_TYPE_INTEGER) + { + if(((*result) -> size) < (ctx -> int_type -> size)) + { + *result = ctx -> int_type; + } + } + + /* TODO: cast types */ +} + +#define ITMAKESBOOLEAN(x) \ + (((x) >= EQUAL && (x) <= GEQ) || ((x) == OR) || ((x) == AND)) + +#define ITUSEONLYINTEGER(x) \ + ((x) >= LESS && (x) <= GEQ) + +#define ITUSEONLYBOOLEAN(x) \ + (((x) == OR) || ((x) == AND)) + +static oberon_expr_t * +oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_expr_t * b) +{ + oberon_expr_t * expr; + oberon_type_t * result; + + oberon_autocast_binary_op(ctx, a -> result, b -> result, &result); + + if(ITMAKESBOOLEAN(token)) + { + if(ITUSEONLYINTEGER(token)) + { + if(a -> result -> class != OBERON_TYPE_INTEGER + && b -> result -> class != OBERON_TYPE_INTEGER) + { + oberon_error(ctx, "used only with integer types"); + } + } + else if(ITUSEONLYBOOLEAN(token)) + { + if(a -> result -> class != OBERON_TYPE_BOOLEAN + && b -> result -> class != OBERON_TYPE_BOOLEAN) + { + oberon_error(ctx, "used only with boolean type"); + } + } + + if(token == EQUAL) + { + expr = oberon_new_operator(OP_EQ, result, a, b); + } + else if(token == NEQ) + { + expr = oberon_new_operator(OP_NEQ, result, a, b); + } + else if(token == LESS) + { + expr = oberon_new_operator(OP_LSS, result, a, b); + } + else if(token == LEQ) + { + expr = oberon_new_operator(OP_LEQ, result, a, b); + } + else if(token == GREAT) + { + expr = oberon_new_operator(OP_GRT, result, a, b); + } + else if(token == GEQ) + { + expr = oberon_new_operator(OP_GEQ, result, a, b); + } + else if(token == OR) + { + expr = oberon_new_operator(OP_LOGIC_OR, result, a, b); + } + else if(token == AND) + { + expr = oberon_new_operator(OP_LOGIC_AND, result, a, b); + } + else + { + oberon_error(ctx, "oberon_make_bin_op: bool wat"); + } + } + else + { + if(token == PLUS) { - case 0: ctx -> token = EOF_; break; - case ';': ctx -> token = SEMICOLON; oberon_get_char(ctx); break; - case ':': - /****************************************************/ - ctx -> token = COLON; oberon_get_char(ctx); - if(ctx -> c == '=') - { - ctx -> token = ASSIGN; - oberon_get_char(ctx); - } - break; - /****************************************************/ - case '.': ctx -> token = DOT; oberon_get_char(ctx); break; - default: oberon_error(ctx, "invalid char"); + expr = oberon_new_operator(OP_ADD, result, a, b); + } + else if(token == MINUS) + { + expr = oberon_new_operator(OP_SUB, result, a, b); + } + else if(token == STAR) + { + expr = oberon_new_operator(OP_MUL, result, a, b); + } + else if(token == SLASH) + { + expr = oberon_new_operator(OP_DIV, result, a, b); + } + else if(token == DIV) + { + expr = oberon_new_operator(OP_DIV, result, a, b); + } + else if(token == MOD) + { + expr = oberon_new_operator(OP_MOD, result, a, b); + } + else + { + oberon_error(ctx, "oberon_make_bin_op: bin wat"); } } + + return expr; +} + +#define ISMULOP(x) \ + ((x) >= STAR && (x) <= AND) + +static oberon_expr_t * +oberon_term_expr(oberon_context_t * ctx) +{ + oberon_expr_t * expr; + + expr = oberon_factor(ctx); + while(ISMULOP(ctx -> token)) + { + int token = ctx -> token; + oberon_read_token(ctx); + + oberon_expr_t * inter = oberon_factor(ctx); + expr = oberon_make_bin_op(ctx, token, expr, inter); + } + + return expr; +} + +#define ISADDOP(x) \ + ((x) >= PLUS && (x) <= OR) + +static oberon_expr_t * +oberon_simple_expr(oberon_context_t * ctx) +{ + oberon_expr_t * expr; + + int minus = 0; + if(ctx -> token == PLUS) + { + minus = 0; + oberon_assert_token(ctx, PLUS); + } + else if(ctx -> token == MINUS) + { + minus = 1; + oberon_assert_token(ctx, MINUS); + } + + expr = oberon_term_expr(ctx); + while(ISADDOP(ctx -> token)) + { + int token = ctx -> token; + oberon_read_token(ctx); + + oberon_expr_t * inter = oberon_term_expr(ctx); + expr = oberon_make_bin_op(ctx, token, expr, inter); + } + + if(minus) + { + expr = oberon_make_unary_op(ctx, MINUS, expr); + } + + return expr; +} + +#define ISRELATION(x) \ + ((x) >= EQUAL && (x) <= GEQ) + +static oberon_expr_t * +oberon_expr(oberon_context_t * ctx) +{ + oberon_expr_t * expr; + + expr = oberon_simple_expr(ctx); + while(ISRELATION(ctx -> token)) + { + int token = ctx -> token; + oberon_read_token(ctx); + + oberon_expr_t * inter = oberon_simple_expr(ctx); + expr = oberon_make_bin_op(ctx, token, expr, inter); + } + + return expr; } // ======================================================================= // PARSER // ======================================================================= +static void oberon_statement_seq(oberon_context_t * ctx); + static void oberon_expect_token(oberon_context_t * ctx, int token) { @@ -284,9 +804,8 @@ oberon_assert_token(oberon_context_t * ctx, int token) static char * oberon_assert_ident(oberon_context_t * ctx) { - char * ident; oberon_expect_token(ctx, IDENT); - ident = ctx -> string; + char * ident = ctx -> string; oberon_read_token(ctx); return ident; } @@ -295,13 +814,7 @@ static oberon_type_t * oberon_type(oberon_context_t * ctx) { char * name = oberon_assert_ident(ctx); - oberon_type_t * type = oberon_find_type(ctx, name); - - if(type == NULL) - { - oberon_error(ctx, "undefined type"); - } - + oberon_type_t * type = oberon_find_type(ctx -> decl, name); return type; } @@ -311,7 +824,53 @@ oberon_var_decl(oberon_context_t * ctx) char * name = oberon_assert_ident(ctx); oberon_assert_token(ctx, COLON); oberon_type_t * type = oberon_type(ctx); - oberon_define_var(ctx, name, type); + oberon_define_var(ctx -> decl, name, type); +} + +static void +oberon_make_procedure_begin(oberon_context_t * ctx, char * name) +{ + oberon_object_t * proc; + proc = oberon_define_proc(ctx -> decl, name); + + oberon_open_scope(ctx); + + oberon_generate_begin_proc(ctx, proc); +} + +static void +oberon_make_procedure_end(oberon_context_t * ctx) +{ + oberon_generate_end_proc(ctx); + + oberon_close_scope(ctx -> decl); +} + +static void +oberon_proc_decl(oberon_context_t * ctx) +{ + oberon_assert_token(ctx, PROCEDURE); + + char * name; + name = oberon_assert_ident(ctx); + + oberon_assert_token(ctx, SEMICOLON); + + oberon_make_procedure_begin(ctx, name); + if(ctx -> token == BEGIN) + { + oberon_assert_token(ctx, BEGIN); + oberon_statement_seq(ctx); + } + oberon_make_procedure_end(ctx); + + oberon_assert_token(ctx, END); + char * name2 = oberon_assert_ident(ctx); + + if(strcmp(name2, name) != 0) + { + oberon_error(ctx, "procedure name not matched"); + } } static void @@ -326,71 +885,75 @@ oberon_decl_seq(oberon_context_t * ctx) oberon_assert_token(ctx, SEMICOLON); } } + + if(ctx -> token == PROCEDURE) + { + oberon_proc_decl(ctx); + oberon_assert_token(ctx, SEMICOLON); + } } -static oberon_item_t * -oberon_expr(oberon_context_t * ctx) +static void +oberon_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst) { - oberon_item_t * item = malloc(sizeof *item); - memset(item, 0, sizeof *item); + if(src -> result -> class != dst -> result -> class) + { + oberon_error(ctx, "incompatible assignment types"); + } - if(ctx -> token == IDENT) + if(dst -> result -> class == OBERON_TYPE_INTEGER) { - char * name = oberon_assert_ident(ctx); - oberon_var_t * var = oberon_find_var(ctx, name); - if(var == NULL) + if((dst -> result -> size) < (src -> result -> size)) { - oberon_error(ctx, "undefined variable"); + oberon_error(ctx, "incompatible assignment type size"); } - item -> mode = MODE_VAR; - item -> var = var; - } - else if(ctx -> token == INTEGER) - { - item -> mode = MODE_INTEGER; - item -> integer = ctx -> integer; - oberon_assert_token(ctx, INTEGER); - } - else - { - oberon_error(ctx, "invalid expression"); } - return item; + oberon_generate_assign(ctx, src, dst); } static void -oberon_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst) +oberon_make_call(oberon_context_t * ctx, oberon_expr_t * desig) { - if(dst -> mode == MODE_INTEGER) + if(desig -> is_item == 0) { - oberon_error(ctx, "invalid assignment"); + oberon_error(ctx, "expected item"); } - int src_class = oberon_item_to_type_class(ctx, src); - int dst_class = oberon_item_to_type_class(ctx, dst); + if(desig -> item.mode != MODE_CALL) + { + oberon_error(ctx, "expected mode CALL"); + } - if(src_class != dst_class) + if(desig -> item.var -> class != OBERON_CLASS_PROC) { - oberon_error(ctx, "types not matched"); + oberon_error(ctx, "only procedures can be called"); } - // TODO: code generation - oberon_generate_assign(ctx, 0, 0, 4); + // TODO check arguments + + oberon_generate_call_proc(ctx, desig); } static void oberon_statement(oberon_context_t * ctx) { - oberon_item_t * item1; - oberon_item_t * item2; + oberon_expr_t * item1; + oberon_expr_t * item2; if(ctx -> token == IDENT) { item1 = oberon_expr(ctx); - oberon_assert_token(ctx, ASSIGN); - item2 = oberon_expr(ctx); - oberon_assign(ctx, item2, item1); + if(ctx -> token == ASSIGN) + { + oberon_assert_token(ctx, ASSIGN); + item2 = oberon_expr(ctx); + oberon_assign(ctx, item2, item1); + } + else + { + oberon_make_call(ctx, item1); + } } } @@ -406,7 +969,7 @@ oberon_statement_seq(oberon_context_t * ctx) } static void -oberon_parse_it(oberon_context_t * ctx) +oberon_parse_module(oberon_context_t * ctx) { char *name1, *name2; oberon_read_token(ctx); @@ -421,7 +984,9 @@ oberon_parse_it(oberon_context_t * ctx) if(ctx -> token == BEGIN) { oberon_assert_token(ctx, BEGIN); + oberon_generate_begin_module(ctx); oberon_statement_seq(ctx); + oberon_generate_end_module(ctx); } oberon_assert_token(ctx, END); @@ -438,52 +1003,83 @@ oberon_parse_it(oberon_context_t * ctx) // LIBRARY // ======================================================================= +static oberon_type_t * +oberon_new_type_ptr(int class) +{ + oberon_type_t * x = malloc(sizeof *x); + memset(x, 0, sizeof *x); + x -> class = class; + return x; +} + +static oberon_type_t * +oberon_new_type_integer(int size) +{ + oberon_type_t * x; + x = oberon_new_type_ptr(OBERON_TYPE_INTEGER); + x -> size = size; + return x; +} + +static oberon_type_t * +oberon_new_type_boolean(int size) +{ + oberon_type_t * x; + x = oberon_new_type_ptr(OBERON_TYPE_BOOLEAN); + x -> size = size; + return x; +} + +static void +register_default_types(oberon_context_t * ctx) +{ + ctx -> int_type = oberon_new_type_integer(sizeof(int)); + ctx -> bool_type = oberon_new_type_boolean(sizeof(int)); + + oberon_define_type(ctx -> world_scope, "INTEGER", ctx -> int_type); + oberon_define_type(ctx -> world_scope, "BOOLEAN", ctx -> bool_type); +} + oberon_context_t * oberon_create_context() { oberon_context_t * ctx = malloc(sizeof *ctx); memset(ctx, 0, sizeof *ctx); - oberon_type_t * types = malloc(sizeof *types); - memset(types, 0, sizeof *types); + oberon_scope_t * world_scope; + world_scope = oberon_open_scope(ctx); + ctx -> world_scope = world_scope; + + oberon_generator_init_context(ctx); + + register_default_types(ctx); - ctx -> types = types; return ctx; } +void +oberon_destroy_context(oberon_context_t * ctx) +{ + oberon_generator_destroy_context(ctx); + free(ctx); +} + oberon_module_t * oberon_compile_module(oberon_context_t * ctx, const char * code) { oberon_module_t * mod = malloc(sizeof *mod); memset(mod, 0, sizeof *mod); - oberon_var_t * vars = malloc(sizeof *vars); - memset(vars, 0, sizeof *vars); ctx -> mod = mod; - ctx -> mod -> vars = vars; - - oberon_init_scaner(ctx, code); - oberon_parse_it(ctx); - return mod; -} -void -oberon_register_global_type(oberon_context_t * ctx, oberon_type_t * type) -{ - oberon_type_t * x = ctx -> types; - while(x -> next && strcmp(x -> next -> name, type -> name) != 0) - { - x = x -> next; - } + oberon_scope_t * module_scope; + module_scope = oberon_open_scope(ctx); + mod -> decl = module_scope; - if(x -> next) - { - oberon_error(ctx, "already defined"); - } + oberon_init_scaner(ctx, code); + oberon_parse_module(ctx); - // TODO: copy type name (not a pointer) - oberon_type_t * newtype = malloc(sizeof *newtype); - memcpy(newtype, type, sizeof *newtype); - newtype -> next = NULL; + oberon_generate_code(ctx); - x -> next = newtype; + ctx -> mod = NULL; + return mod; }