return 2;
}
}
+ else if(type -> class == OBERON_TYPE_VOID)
+ {
+ return 0;
+ }
return 1;
}
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);
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:
struct gen_class * class;
int rec_id;
};
+
+struct gen_label_t
+{
+ int id;
+};
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);
+
/*
* Функции генерации операторов
*/
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;
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
|| 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);
#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."
;