summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 86c0ca1)
raw | patch | inline | side by side (parent: 86c0ca1)
author | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Wed, 2 Aug 2017 18:29:29 +0000 (21:29 +0300) | ||
committer | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Wed, 2 Aug 2017 18:29:29 +0000 (21:29 +0300) |
index 88de2e2292119fbe5c8a4b090caee7c1051bc526..44046a1506ab27c99e6b78e7178309c684f5e7dd 100644 (file)
return 2;
}
}
+ else if(type -> class == OBERON_TYPE_VOID)
+ {
+ return 0;
+ }
return 1;
}
index f111fd16eff755440676a4b6a6e433713cc43b4b..b17711bd5627d68a54b5dd06c4a475023a1a204a 100644 (file)
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)
{
}
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);
}
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)
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)
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:
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)
struct gen_class * class;
int rec_id;
};
+
+struct gen_label_t
+{
+ int id;
+};
diff --git a/src/generator.h b/src/generator.h
index e988ba0c3f1c1e1bb5f8a8dd3a8dfb69d761a3f6..23901dd41c83e027409eace3445ae5d11d276d09 100644 (file)
--- a/src/generator.h
+++ b/src/generator.h
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);
+
/*
* Функции генерации операторов
*/
diff --git a/src/oberon-internals.h b/src/oberon-internals.h
index 0b453494942f4ddc431035a8d99e4c511538d0bc..f0a6bed23e96fa8ec6b70d9cafc3a133713485ba 100644 (file)
--- a/src/oberon-internals.h
+++ b/src/oberon-internals.h
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;
diff --git a/src/oberon.c b/src/oberon.c
index f2310db26de0ab2b1bffb82efee2a4b346bf7052..5816c2b3fb0a96f2076f0e6ff82fbeb2b87058d2 100644 (file)
--- a/src/oberon.c
+++ b/src/oberon.c
IMPORT,
REAL,
CHAR,
- STRING
+ STRING,
+ IF,
+ THEN,
+ ELSE
};
// =======================================================================
{
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");
}
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)
{
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);
diff --git a/src/test.c b/src/test.c
index cacf00d30d71189e19360a4b2467ba052f037858..a144f3616074e1f8891dbc30af0007420bad0ef9 100644 (file)
--- a/src/test.c
+++ b/src/test.c
#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."
;