DEADSOFTWARE

Добавлены выражения
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Mon, 24 Jul 2017 19:05:22 +0000 (22:05 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Mon, 24 Jul 2017 19:05:22 +0000 (22:05 +0300)
gdb_run.sh [new file with mode: 0755]
generator.c
generator.h
oberon.c
oberon.h
test.c

diff --git a/gdb_run.sh b/gdb_run.sh
new file mode 100755 (executable)
index 0000000..b6e0bbd
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+set -e
+
+export PATH="/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1:${PATH}"
+export LIBRARY_PATH="/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1:${LIBRARY_PATH}"
+
+exec gdb ./a.out
index c633e542131722832c5d586e732e18d7f04d85f2..21506b0626fe5db7cfbd117a444d2295de3448a2 100644 (file)
@@ -113,11 +113,64 @@ oberon_generator_init_var(oberon_context_t * ctx, oberon_var_t * var)
 //   GENERATOR
 // ======================================================================= 
 
-static gcc_jit_rvalue *
-oberon_generate_rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item)
+void
+oberon_generate_begin_module(oberon_context_t * ctx)
+{
+       printcontext(ctx, "oberon_generate_begin_module");
+
+       gen_context_t * gen_context = ctx -> gen_context;
+       gcc_jit_context * gcc_context = gen_context -> gcc_context;
+
+       gcc_jit_type * void_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_VOID);
+       gcc_jit_function * func = gcc_jit_context_new_function(
+               gcc_context, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "BEGIN", 0, NULL, 0
+       );
+       gcc_jit_block * gcc_block = gcc_jit_function_new_block(func, NULL);
+
+       gen_context -> gcc_block = gcc_block;
+}
+
+void
+oberon_generate_end_module(oberon_context_t * ctx)
+{
+       printcontext(ctx, "oberon_generate_end_module");
+
+       gen_context_t * gen_context = ctx -> gen_context;
+       gcc_jit_block * gcc_block = gen_context -> gcc_block;
+
+       gcc_jit_block_end_with_void_return(gcc_block, NULL);
+
+       gen_context -> gcc_block = NULL;
+}
+
+static gcc_jit_lvalue *
+lvalue_from_expr(oberon_context_t *ctx, oberon_expr_t * expr)
 {
-       printcontext(ctx, "oberon_generate_rvalue_from_item");
+       gcc_jit_lvalue * left;
+       oberon_item_t * item;
+
+       if(expr -> is_item)
+       {
+               item = (oberon_item_t *) expr;
+               if(item -> mode != MODE_VAR)
+               {
+                       oberon_error(ctx, "invalid lvalue expression");
+               }
+               left = item -> var -> gen_var;
+       }
+       else
+       {
+               oberon_error(ctx, "invalid lvalue expression");
+       }
+
+       return left;
+}
 
+static gcc_jit_rvalue * rvalue_from_expr(oberon_context_t * ctx, oberon_expr_t * expr);
+
+static gcc_jit_rvalue *
+rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item)
+{
        gen_context_t * gen_context = ctx -> gen_context;
        gcc_jit_context * gcc_context = gen_context -> gcc_context;
 
@@ -126,13 +179,11 @@ oberon_generate_rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item)
        {
                gcc_jit_lvalue * gen_var = item -> var -> gen_var;
                right = gcc_jit_lvalue_as_rvalue(gen_var);
-               printf("PUSH (var) %s\n", item -> var -> name);
        }
        else if(item -> mode == MODE_INTEGER)
        {
                gcc_jit_type * int_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_INT);
                right = gcc_jit_context_new_rvalue_from_int(gcc_context, int_type, item -> integer);
-               printf("PUSH (int) %i\n", item -> integer);
        }
        else if(item -> mode == MODE_BOOLEAN)
        {
@@ -145,7 +196,6 @@ oberon_generate_rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item)
                {
                        right = gcc_jit_context_zero(gcc_context, bool_type);                   
                }
-               printf("PUSH (bool) %i\n", item -> boolean);
        }
        else
        {
@@ -155,59 +205,100 @@ oberon_generate_rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item)
        return right;
 }
 
-void
-oberon_generate_begin_module(oberon_context_t * ctx)
+struct {
+       int type; // 0 - unary, 1 - binary, 2 - comp
+       union {
+               enum gcc_jit_unary_op unary_op;
+               enum gcc_jit_binary_op binary_op;
+               enum gcc_jit_comparison comp_op;
+       };
+} op_table[] = {
+       { 0, .unary_op = GCC_JIT_UNARY_OP_LOGICAL_NEGATE },
+       { 0, .unary_op = GCC_JIT_UNARY_OP_MINUS },
+
+       { 1, .binary_op = GCC_JIT_BINARY_OP_PLUS },
+       { 1, .binary_op = GCC_JIT_BINARY_OP_MINUS },
+       { 1, .binary_op = GCC_JIT_BINARY_OP_DIVIDE },
+       { 1, .binary_op = GCC_JIT_BINARY_OP_MODULO },
+       { 1, .binary_op = GCC_JIT_BINARY_OP_LOGICAL_AND },
+       { 1, .binary_op = GCC_JIT_BINARY_OP_LOGICAL_OR },
+
+       { 2, .comp_op = GCC_JIT_COMPARISON_EQ },
+       { 2, .comp_op = GCC_JIT_COMPARISON_NE },
+       { 2, .comp_op = GCC_JIT_COMPARISON_LT },
+       { 2, .comp_op = GCC_JIT_COMPARISON_LE },
+       { 2, .comp_op = GCC_JIT_COMPARISON_GT },
+       { 2, .comp_op = GCC_JIT_COMPARISON_GE }
+};
+
+static gcc_jit_rvalue *
+rvalue_from_operator(oberon_context_t * ctx, oberon_oper_t * operator)
 {
-       printcontext(ctx, "oberon_generate_begin_module");
+       gcc_jit_rvalue * right;
 
        gen_context_t * gen_context = ctx -> gen_context;
        gcc_jit_context * gcc_context = gen_context -> gcc_context;
+       gcc_jit_type * result_type = operator -> result -> gen_type;
 
-       gcc_jit_type * void_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_VOID);
-       gcc_jit_function * func = gcc_jit_context_new_function(
-               gcc_context, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "BEGIN", 0, NULL, 0
-       );
-       gcc_jit_block * gcc_block = gcc_jit_function_new_block(func, NULL);
+       int expr_type = op_table[operator -> op].type;
+       if(expr_type == 0)
+       {
+               enum gcc_jit_unary_op op = op_table[operator -> op].unary_op;
+               gcc_jit_rvalue * l = rvalue_from_expr(ctx, operator -> left);
+               right = gcc_jit_context_new_unary_op(gcc_context, NULL, op, result_type, l);
+       }
+       else if(expr_type == 1)
+       {
+               enum gcc_jit_unary_op op = op_table[operator -> op].binary_op;
+               gcc_jit_rvalue * l = rvalue_from_expr(ctx, operator -> left);
+               gcc_jit_rvalue * r = rvalue_from_expr(ctx, operator -> right);
+               right = gcc_jit_context_new_binary_op(gcc_context, NULL, op, result_type, l, r);
+       }
+       else if(expr_type == 2)
+       {
+               enum gcc_jit_comparison op = op_table[operator -> op].comp_op;
+               gcc_jit_rvalue * l = rvalue_from_expr(ctx, operator -> left);
+                gcc_jit_rvalue * r = rvalue_from_expr(ctx, operator -> right);
+               right = gcc_jit_context_new_comparison(gcc_context, NULL, op, l, r);
+       }
+       else
+       {
+               oberon_error(ctx, "rvalue_from_operator: wat");
+       }
 
-       gen_context -> gcc_block = gcc_block;
+       return right;
 }
 
-void
-oberon_generate_end_module(oberon_context_t * ctx)
+static gcc_jit_rvalue *
+rvalue_from_expr(oberon_context_t * ctx, oberon_expr_t * expr)
 {
-       printcontext(ctx, "oberon_generate_end_module");
-
-       gen_context_t * gen_context = ctx -> gen_context;
-       gcc_jit_block * gcc_block = gen_context -> gcc_block;
+       gcc_jit_rvalue * right;
 
-       gcc_jit_block_end_with_void_return(gcc_block, NULL);
+       if(expr -> is_item)
+       {
+               oberon_item_t * item = (oberon_item_t *) expr;
+               right = rvalue_from_item(ctx, item);
+       }
+       else
+       {
+               oberon_oper_t * operator = (oberon_oper_t *) expr;
+               right = rvalue_from_operator(ctx, operator);
+       }
 
-       gen_context -> gcc_block = NULL;
+       return right;
 }
 
 void
-oberon_generate_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst)
+oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst)
 {
-       printcontext(ctx, "oberon_generate_assign");
-
-       gen_context_t * gen_context = ctx -> gen_context;
-       gcc_jit_block * gcc_block = gen_context -> gcc_block;
-
        gcc_jit_lvalue * left;
-       gcc_jit_rvalue * right;
-
-       right = oberon_generate_rvalue_from_item(ctx, src);
+       left = lvalue_from_expr(ctx, dst);
 
-       if(dst -> mode == MODE_VAR)
-       {
-               printf("STORE %s\n", dst -> var -> name);
-               left = dst -> var -> gen_var;
-       }
-       else
-       {
-               oberon_error(ctx, "oberon_generate_assign: invalid assignment");
-       }       
+       gcc_jit_rvalue * right;
+       right = rvalue_from_expr(ctx, src);
 
+       gen_context_t * gen_context = ctx -> gen_context;
+       gcc_jit_block * gcc_block = gen_context -> gcc_block;
        gcc_jit_block_add_assignment(gcc_block, NULL, left, right);
 }
 
index e9dbd53847babb686a9d12555abeb091e4ce993c..78ae8601771442915dcdaa1f8f416b58d016d3c1 100644 (file)
@@ -6,6 +6,6 @@ void oberon_generator_init_var(oberon_context_t * ctx, oberon_var_t * var);
 void oberon_generate_begin_module(oberon_context_t * ctx);
 void oberon_generate_end_module(oberon_context_t * ctx);
 
-void oberon_generate_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst);
+void oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst);
 
 void oberon_generate_code(oberon_context_t * ctx);
index 4dfc604a5f38159b0d1668b8376b0cc4fa8195e7..ec4cab05b3804d3c204407e28dcbb2eff1ccea22 100644 (file)
--- a/oberon.c
+++ b/oberon.c
@@ -22,7 +22,22 @@ enum {
        TRUE,
        FALSE,
        LPAREN,
-       RPAREN
+       RPAREN,
+       EQUAL,
+       NEQ,
+       LESS,
+       LEQ,
+       GREAT,
+       GEQ,
+       PLUS,
+       MINUS,
+       OR,
+       STAR,
+       SLASH,
+       DIV,
+       MOD,
+       AND,
+       NOT
 };
 
 // =======================================================================
@@ -44,6 +59,7 @@ 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)
 {
@@ -67,7 +83,9 @@ oberon_item_to_type_class(oberon_context_t * ctx, oberon_item_t * item)
 
        return class;
 }
+*/
 
+/*
 static void
 oberon_autocast_to(oberon_context_t * ctx, oberon_item_t * from, oberon_item_t * to)
 {
@@ -79,6 +97,7 @@ oberon_autocast_to(oberon_context_t * ctx, oberon_item_t * from, oberon_item_t *
                oberon_error(ctx, "oberon_autocast_to: types not matched %i -> %i", from_class, to_class);
        }
 }
+*/
 
 // =======================================================================
 //   TABLE
@@ -197,6 +216,18 @@ oberon_read_ident(oberon_context_t * ctx)
        {
                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;
+       }
 }
 
 static void
@@ -267,6 +298,56 @@ oberon_read_symbol(oberon_context_t * ctx)
                        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;
@@ -294,22 +375,56 @@ oberon_read_token(oberon_context_t * ctx)
 }
 
 // =======================================================================
-//   EXPR
+//   EXPRESSION
 // =======================================================================
 
 static void oberon_expect_token(oberon_context_t * ctx, int token);
-static oberon_item_t * oberon_expr(oberon_context_t * ctx);
+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_item_t *
+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_not(oberon_context_t * ctx, oberon_expr_t * expr)
+{
+       return oberon_new_operator(OP_LOGIC_NOT, expr -> result, expr, NULL);
+}
+
+static oberon_expr_t *
 oberon_factor(oberon_context_t * ctx)
 {
        char * name;
        oberon_var_t * var;
-
-       oberon_item_t * item = malloc(sizeof *item);
-       memset(item, 0, sizeof *item);
+       oberon_expr_t * expr;
 
        switch(ctx -> token)
        {
@@ -320,40 +435,229 @@ oberon_factor(oberon_context_t * ctx)
                        {
                                oberon_error(ctx, "undefined variable %s", name);
                        }
-                       item -> mode = MODE_VAR;
-                       item -> var = var;
+                       expr = oberon_new_item(MODE_VAR, var -> type);
+                       expr -> item.var = var;
                        break;
                case INTEGER:
-                       item -> mode = MODE_INTEGER;
-                       item -> integer = ctx -> integer;
+                       expr = oberon_new_item(MODE_INTEGER, ctx -> int_type);
+                       expr -> item.integer = ctx -> integer;
                        oberon_assert_token(ctx, INTEGER);
                        break;
                case TRUE:
-                       item -> mode = MODE_BOOLEAN;
-                       item -> boolean = 1;
+                       expr = oberon_new_item(MODE_BOOLEAN, ctx -> bool_type);
+                       expr -> item.boolean = 1;
                        oberon_assert_token(ctx, TRUE);
                        break;
                case FALSE:
-                       item -> mode = MODE_BOOLEAN;
-                       item -> boolean = 0;
+                       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);
-                       item = oberon_expr(ctx);
+                       expr = oberon_expr(ctx);
                        oberon_assert_token(ctx, RPAREN);
                        break;
+               case NOT:
+                       oberon_assert_token(ctx, NOT);
+                       expr = oberon_factor(ctx);
+                       expr = oberon_make_not(ctx, expr);
+                       break;
                default:
                        oberon_error(ctx, "invalid expression");
        }
 
-       return item;    
+       return expr;
+}
+
+static oberon_expr_t *
+oberon_make_mul_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_expr_t * b)
+{
+       oberon_expr_t * expr;
+       oberon_type_t * result;
+
+       result = a -> result;
+
+       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 if(token == AND)
+       {
+               expr = oberon_new_operator(OP_LOGIC_AND, result, a, b);
+       }
+       else
+       {
+               oberon_error(ctx, "oberon_make_mul_op: 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_mul_op(ctx, token, expr, inter);
+       }
+
+       return expr;
 }
 
-static oberon_item_t *
+static oberon_expr_t *
+oberon_make_add_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_expr_t * b)
+{
+       oberon_expr_t * expr;
+       oberon_type_t * result;
+
+       result = a -> result;
+
+       if(token == PLUS)
+       {
+               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 == OR)
+       {
+               expr = oberon_new_operator(OP_LOGIC_OR, result, a, b);
+       }
+       else
+       {
+               oberon_error(ctx, "oberon_make_add_op: wat");
+       }
+
+       return expr;
+}
+
+static oberon_expr_t *
+oberon_make_unary_minus(oberon_context_t * ctx, oberon_expr_t * expr)
+{
+       return oberon_new_operator(OP_UNARY_MINUS, expr -> result, expr, NULL);
+}
+
+#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_add_op(ctx, token, expr, inter);
+       }
+
+       if(minus)
+       {
+               expr = oberon_make_unary_minus(ctx, expr);
+       }
+
+       return expr;
+}
+
+static oberon_expr_t *
+oberon_make_relation(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_expr_t * b)
+{
+       oberon_expr_t * expr;
+       oberon_type_t * result;
+
+       result = a -> result;
+
+       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
+       {
+               oberon_error(ctx, "oberon_make_relation: wat");
+       }       
+
+       return expr;
+}
+
+#define ISRELATION(x) \
+       ((x) >= EQUAL && (x) <= GEQ)
+
+static oberon_expr_t *
 oberon_expr(oberon_context_t * ctx)
 {
-       return oberon_factor(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_relation(ctx, token, expr, inter);
+       }
+
+       return expr;
 }
 
 // =======================================================================
@@ -423,14 +727,14 @@ oberon_decl_seq(oberon_context_t * ctx)
 }
 
 static void
-oberon_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst)
+oberon_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst)
 {
-       if(dst -> mode == MODE_INTEGER)
-       {
-               oberon_error(ctx, "invalid assignment");
-       }
-
-       oberon_autocast_to(ctx, src, dst);
+//     if(dst -> mode == MODE_INTEGER)
+//     {
+//             oberon_error(ctx, "invalid assignment");
+//     }
+//
+//     oberon_autocast_to(ctx, src, dst);
 
        oberon_generate_assign(ctx, src, dst);
 }
@@ -438,8 +742,8 @@ oberon_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst)
 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)
        {
@@ -496,6 +800,46 @@ oberon_parse_module(oberon_context_t * ctx)
 //   LIBRARY
 // =======================================================================
 
+static oberon_type_t *
+oberon_register_global_type_ret(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;
+       }
+
+       if(x -> next)
+       {
+               oberon_error(ctx, "already defined");
+       }
+
+       // TODO: copy type name (not a pointer)
+       oberon_type_t * newtype = malloc(sizeof *newtype);
+       memcpy(newtype, type, sizeof *newtype);
+       newtype -> next = NULL;
+       oberon_generator_init_type(ctx, newtype);
+
+       x -> next = newtype;
+       return newtype; 
+}
+
+static void
+register_default_types(oberon_context_t * ctx)
+{
+       static oberon_type_t integer = { "INTEGER", OBERON_TYPE_INTEGER, sizeof(int) };
+       static oberon_type_t boolean = { "BOOLEAN", OBERON_TYPE_BOOLEAN, sizeof(int) };
+
+       ctx -> int_type = oberon_register_global_type_ret(ctx, &integer);
+       ctx -> bool_type = oberon_register_global_type_ret(ctx, &boolean);
+}
+
+void
+oberon_register_global_type(oberon_context_t * ctx, oberon_type_t * type)
+{
+       oberon_register_global_type_ret(ctx, type);
+}
+
 oberon_context_t *
 oberon_create_context()
 {
@@ -504,9 +848,12 @@ oberon_create_context()
 
        oberon_type_t * types = malloc(sizeof *types);
        memset(types, 0, sizeof *types);
+       ctx -> types = types;
 
        oberon_generator_init_context(ctx);
-       ctx -> types = types;
+
+       register_default_types(ctx);    
+
        return ctx;
 }
 
@@ -534,25 +881,3 @@ oberon_compile_module(oberon_context_t * ctx, const char * code)
        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;
-       }
-
-       if(x -> next)
-       {
-               oberon_error(ctx, "already defined");
-       }
-
-       // TODO: copy type name (not a pointer)
-       oberon_type_t * newtype = malloc(sizeof *newtype);
-       memcpy(newtype, type, sizeof *newtype);
-       newtype -> next = NULL;
-       oberon_generator_init_type(ctx, newtype);
-
-       x -> next = newtype;
-}
index ec742c6bd7af90c18b3850a37fe2163b12407de4..7ed16291b9b4da45a0c1b9bb7db798b1e427f067 100644 (file)
--- a/oberon.h
+++ b/oberon.h
@@ -51,6 +51,9 @@ struct oberon_context_s
        oberon_module_t * mod;
        oberon_type_t * types;
 
+       oberon_type_t * int_type;
+       oberon_type_t * bool_type;
+
        void * gen_context;
 };
 
@@ -60,13 +63,59 @@ enum {
        MODE_BOOLEAN
 };
 
-typedef struct
+enum {
+       OP_LOGIC_NOT,
+       OP_UNARY_MINUS,
+       OP_ADD,
+       OP_SUB,
+       OP_MUL,
+       OP_DIV,
+       OP_MOD,
+       OP_LOGIC_AND,
+       OP_LOGIC_OR,
+       OP_EQ,
+       OP_NEQ,
+       OP_LSS,
+       OP_LEQ,
+       OP_GRT,
+       OP_GEQ
+};
+
+typedef struct oberon_item_s oberon_item_t;
+typedef struct oberon_oper_s oberon_oper_t;
+typedef union oberon_expr_u oberon_expr_t;
+
+struct oberon_item_s
 {
+       int is_item;
+       oberon_type_t * result;
+
        int mode;
        int integer;
        int boolean;
        oberon_var_t * var;
-} oberon_item_t;
+};
+
+struct oberon_oper_s
+{
+       int is_item;
+       oberon_type_t * result;
+
+       int op;
+       oberon_expr_t * left;
+       oberon_expr_t * right;
+};
+
+union oberon_expr_u
+{
+       struct {
+               int is_item;
+               oberon_type_t * result;
+       };
+
+       oberon_item_t item;
+       oberon_oper_t oper;
+};
 
 oberon_context_t * oberon_create_context();
 void oberon_destroy_context(oberon_context_t * ctx);
diff --git a/test.c b/test.c
index 7149026862087a8f63577916ffd361e8b89b08ef..0837de4ef28f6ba05ca3dbe8f4c191e95fd0caa5 100644 (file)
--- a/test.c
+++ b/test.c
@@ -1,9 +1,6 @@
 #include "oberon.h"
 #include <assert.h>
 
-static oberon_type_t integer = { "INTEGER", OBERON_TYPE_INTEGER, sizeof(int) };
-static oberon_type_t boolean = { "BOOLEAN", OBERON_TYPE_BOOLEAN, sizeof(int) };
-
 static const char source[] =
        "MODULE Test;"
        "VAR"
@@ -11,9 +8,9 @@ static const char source[] =
        "       i : INTEGER;"
        "       b : BOOLEAN;"
        "BEGIN"
-       "       k := 10;"
+       "       k := -10 + 1;"
        "       i := k;"
-       "       b := TRUE;"
+       "       b := ~TRUE OR FALSE;"
        "END Test."
 ;
 
@@ -24,8 +21,6 @@ int
 main(int argc, char ** argv)
 {
        ctx = oberon_create_context();
-       oberon_register_global_type(ctx, &integer);
-       oberon_register_global_type(ctx, &boolean);
        mod = oberon_compile_module(ctx, source);
        oberon_destroy_context(ctx);
        return 0;