DEADSOFTWARE

Добавлена конструкция IF-THEN-ELSE-END
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Wed, 2 Aug 2017 18:29:29 +0000 (21:29 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Wed, 2 Aug 2017 18:29:29 +0000 (21:29 +0300)
src/backends/jvm/generator-jvm-basic.c
src/backends/jvm/generator-jvm.c
src/backends/jvm/generator-jvm.h
src/generator.h
src/oberon-internals.h
src/oberon.c
src/test.c

index 88de2e2292119fbe5c8a4b090caee7c1051bc526..44046a1506ab27c99e6b78e7178309c684f5e7dd 100644 (file)
@@ -365,6 +365,10 @@ jvm_cell_size_for_type(oberon_type_t * type)
                        return 2;
                }
        }
+       else if(type -> class == OBERON_TYPE_VOID)
+       {
+               return 0;
+       }
 
        return 1;
 }
index f111fd16eff755440676a4b6a6e433713cc43b4b..b17711bd5627d68a54b5dd06c4a475023a1a204a 100644 (file)
@@ -1247,6 +1247,70 @@ oberon_generate_end_proc(oberon_context_t * ctx)
        jvm_generate_function_end(p);
 }
 
+gen_label_t *
+oberon_generator_reserve_label(oberon_context_t * ctx)
+{
+       gen_module_t * m;
+       gen_proc_t * p;
+       gen_label_t * l;
+
+       m = ctx -> mod -> gen_mod;
+       p = m -> class -> p;
+
+       l = GC_MALLOC(sizeof *l);
+       memset(l, 0, sizeof *l);
+
+       l -> id = jvm_new_label_id(p);
+       return l;
+}
+
+void
+oberon_generate_label(oberon_context_t * ctx, gen_label_t * l)
+{
+       gen_module_t * m;
+       gen_proc_t * p;
+
+       m = ctx -> mod -> gen_mod;
+       p = m -> class -> p;
+
+       jvm_generate_label(p, l -> id);
+}
+
+void
+oberon_generate_goto(oberon_context_t * ctx, gen_label_t * l)
+{
+       gen_module_t * m;
+       gen_proc_t * p;
+
+       m = ctx -> mod -> gen_mod;
+       p = m -> class -> p;
+
+       jvm_generate(p, 0, 0, "goto L%i", l -> id);
+}
+
+void
+oberon_generate_branch(oberon_context_t * ctx, oberon_expr_t * cond, bool gotoif, gen_label_t * l)
+{
+       gen_module_t * m;
+       gen_proc_t * p;
+
+       m = ctx -> mod -> gen_mod;
+       p = m -> class -> p;
+
+       push_expr(p, cond);
+
+       if(gotoif == false)
+       {
+               /* переход если false */
+               jvm_generate(p, 1, 0, "ifeq L%i", l -> id);
+       }
+       else
+       {
+               /* переход если true */
+               jvm_generate(p, 1, 0, "ifne L%i", l -> id);
+       }
+}
+
 static void
 jvm_generate_call_proc(gen_proc_t * p, oberon_item_t * desig)
 {
@@ -1458,7 +1522,7 @@ jvm_generate_abs(gen_proc_t * p, char prefix)
 }
 
 static void
-jvm_generate_compare_op(gen_proc_t * p, char prefix, int op)
+jvm_generate_compare_op(gen_proc_t * p, oberon_type_t * t, char prefix, int op)
 {
        int label_true = jvm_new_label_id(p);
        int label_done = jvm_new_label_id(p);
@@ -1503,7 +1567,7 @@ jvm_generate_compare_op(gen_proc_t * p, char prefix, int op)
 }
 
 static void
-jvm_generate_operator(gen_proc_t * p, char prefix, int op)
+jvm_generate_operator(gen_proc_t * p, oberon_type_t * t, char prefix, int op)
 {
        int cell_size = jvm_cell_size_for_postfix(prefix);
        switch(op)
@@ -1553,7 +1617,7 @@ jvm_generate_operator(gen_proc_t * p, char prefix, int op)
                case OP_LEQ:
                case OP_GRT:
                case OP_GEQ:
-                       jvm_generate_compare_op(p, prefix, op);
+                       jvm_generate_compare_op(p, t, prefix, op);
                        break;
                default:
                        gen_error("jvm_generate_operator: unk op %i", op);
@@ -1602,6 +1666,7 @@ jvm_generate_logical_and(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b)
 static void
 push_operator(gen_proc_t * p, oberon_oper_t * oper)
 {
+       oberon_type_t * preq = oper -> left -> result;
        char prefix = jvm_get_prefix(oper -> result);
        int op = oper -> op;
        switch(op)
@@ -1615,7 +1680,7 @@ push_operator(gen_proc_t * p, oberon_oper_t * oper)
                case OP_LOGIC_NOT:
                case OP_ABS:
                        push_expr(p, oper -> left);
-                       jvm_generate_operator(p, prefix, op);
+                       jvm_generate_operator(p, preq, prefix, op);
                        break;
 
                case OP_ADD:
@@ -1635,7 +1700,7 @@ push_operator(gen_proc_t * p, oberon_oper_t * oper)
                case OP_GEQ:
                        push_expr(p, oper -> left);
                        push_expr(p, oper -> right);
-                       jvm_generate_operator(p, prefix, op);
+                       jvm_generate_operator(p, preq, prefix, op);
                        break;
 
                case OP_LOGIC_OR:
index 67abe236f652824352f3311ed9b27b50bbfe1fca..3095a49070d204df2acb0fb2fa7a89ddfc9abc2a 100644 (file)
@@ -66,3 +66,8 @@ struct gen_module_t
        struct gen_class * class;
        int rec_id;
 };
+
+struct gen_label_t
+{
+       int id;
+};
index e988ba0c3f1c1e1bb5f8a8dd3a8dfb69d761a3f6..23901dd41c83e027409eace3445ae5d11d276d09 100644 (file)
@@ -27,6 +27,11 @@ void oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc);
 void oberon_generate_end_proc(oberon_context_t * ctx);
 void oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig);
 
+gen_label_t * oberon_generator_reserve_label(oberon_context_t * ctx);
+void oberon_generate_label(oberon_context_t * ctx, gen_label_t * l);
+void oberon_generate_branch(oberon_context_t * ctx, oberon_expr_t * cond, bool gotoif, gen_label_t * l);
+void oberon_generate_goto(oberon_context_t * ctx, gen_label_t * l);
+
 /*
  * Функции генерации операторов
  */
index 0b453494942f4ddc431035a8d99e4c511538d0bc..f0a6bed23e96fa8ec6b70d9cafc3a133713485ba 100644 (file)
@@ -8,7 +8,7 @@ typedef struct gen_module_t gen_module_t;
 typedef struct gen_proc_t gen_proc_t;
 typedef struct gen_type_t gen_type_t;
 typedef struct gen_var_t gen_var_t;
-typedef struct gen_block_t gen_block_t;
+typedef struct gen_label_t gen_label_t;
 typedef struct gen_context_t gen_context_t;
 
 typedef struct oberon_type_t oberon_type_t;
index f2310db26de0ab2b1bffb82efee2a4b346bf7052..5816c2b3fb0a96f2076f0e6ff82fbeb2b87058d2 100644 (file)
@@ -61,7 +61,10 @@ enum {
        IMPORT,
        REAL,
        CHAR,
-       STRING
+       STRING,
+       IF,
+       THEN,
+       ELSE
 };
 
 // =======================================================================
@@ -380,6 +383,18 @@ oberon_read_ident(oberon_context_t * ctx)
        {
                ctx -> token = IS;
        }
+       else if(strcmp(ident, "IF") == 0)
+       {
+               ctx -> token = IF;
+       }
+       else if(strcmp(ident, "THEN") == 0)
+       {
+               ctx -> token = THEN;
+       }
+       else if(strcmp(ident, "ELSE") == 0)
+       {
+               ctx -> token = ELSE;
+       }
 }
 
 static void
@@ -1641,6 +1656,10 @@ oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_
                                || b -> result -> class == OBERON_TYPE_INTEGER
                                || a -> result -> class == OBERON_TYPE_REAL
                                || b -> result -> class == OBERON_TYPE_REAL)
+                       {
+                               // accept
+                       }
+                       else
                        {
                                oberon_error(ctx, "used only with numeric types");
                        }
@@ -2845,6 +2864,9 @@ oberon_decl_seq(oberon_context_t * ctx)
        oberon_prevent_undeclarated_procedures(ctx);
 }
 
+static void
+oberon_statement_seq(oberon_context_t * ctx);
+
 static void
 oberon_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst)
 {
@@ -2877,6 +2899,36 @@ oberon_statement(oberon_context_t * ctx)
                        oberon_opt_proc_parens(ctx, item1);
                }
        }
+       else if(ctx -> token == IF)
+       {
+               gen_label_t * end;
+               gen_label_t * els;
+               oberon_expr_t * cond;
+
+               els = oberon_generator_reserve_label(ctx);
+               end = oberon_generator_reserve_label(ctx);
+
+               oberon_assert_token(ctx, IF);
+               cond = oberon_expr(ctx);
+               if(cond -> result -> class != OBERON_TYPE_BOOLEAN)
+               {
+                       oberon_error(ctx, "condition must be boolean");
+               }
+               oberon_assert_token(ctx, THEN);
+               oberon_generate_branch(ctx, cond, false, els);
+               oberon_statement_seq(ctx);
+               oberon_generate_goto(ctx, end);
+
+               if(ctx -> token == ELSE)
+               {
+                       oberon_generate_label(ctx, els);
+                       oberon_assert_token(ctx, ELSE);
+                       oberon_statement_seq(ctx);
+               }
+
+               oberon_generate_label(ctx, end);
+               oberon_assert_token(ctx, END);          
+       }
        else if(ctx -> token == RETURN)
        {
                oberon_assert_token(ctx, RETURN);
index cacf00d30d71189e19360a4b2467ba052f037858..a144f3616074e1f8891dbc30af0007420bad0ef9 100644 (file)
@@ -4,52 +4,41 @@
 
 #include "../include/oberon.h"
 
-/*
 static char source_test[] =
        "(* Main module *)"
        "MODULE Test;"
        "IMPORT Out;"
-       "VAR"
-       "  msg : ARRAY 20 OF CHAR;"
-       "BEGIN"
-       "  msg := ''"
-       "END Test."
-;
-*/
-
-static char source_test[] =
-       "(* Main module *)"
-       "MODULE Test;"
-       "IMPORT Out;"
-       "CONST"
-       "  helloworld = 'Hello World!';"
-       "  null = 0X;"
-       "  space = 020X;"
-       "  bang = 021X;"
-       "  h = 048X;"
-       "  e = 045X;"
-       "  l = 04CX;"
-       "  o = 04FX;"
-       "  w = 057X;"
-       "  r = 052X;"
-       "  d = 044X;"
        ""
        "TYPE"
-       "  Ident = ARRAY 20 OF CHAR;"
-       "  PrintString = PROCEDURE (str : ARRAY OF CHAR);"
+       "  R = INTEGER;"
        ""
-       "VAR"
-       "  msg   : Ident;"
-       "  print : PrintString;"
+       "PROCEDURE Factorial(n : R) : R;"
+       "BEGIN"
+       "  IF n <= 1 THEN"
+       "    RETURN 1;"
+       "  ELSE"
+       "    RETURN n * Factorial(n - 1);"
+       "  END;"
+       "  RETURN 0; (* Детектор ретурнов - дерьмо *)"
+       "END Factorial;"
        ""
        "BEGIN"
-       "  msg := helloworld;"
-       "  print := Out.String;"
-       "  Out.Open;"
-       "  print(msg);"
-       "  Out.Ln;"
-       "  print(\"It's works!\");"
-       "  Out.Ln;"
+       "  Out.Open();"
+       "  Out.Int(Factorial(0), 0); Out.Ln;"
+       "  Out.Int(Factorial(1), 0); Out.Ln;"
+       "  Out.Int(Factorial(2), 0); Out.Ln;"
+       "  Out.Int(Factorial(3), 0); Out.Ln;"
+       "  Out.Int(Factorial(4), 0); Out.Ln;"
+       "  Out.Int(Factorial(5), 0); Out.Ln;"
+       "  Out.Int(Factorial(6), 0); Out.Ln;"
+       "  Out.Int(Factorial(7), 0); Out.Ln;"
+       "  Out.Int(Factorial(8), 0); Out.Ln;"
+       "  Out.Int(Factorial(9), 0); Out.Ln;"
+       "  Out.Int(Factorial(10), 0); Out.Ln;"
+       "  Out.Int(Factorial(11), 0); Out.Ln;"
+       "  Out.Int(Factorial(12), 0); Out.Ln;"
+       "  Out.Int(Factorial(13), 0); Out.Ln;"
+       "  Out.Int(Factorial(14), 0); Out.Ln;"
        "END Test."
 ;