summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: c3449e2)
raw | patch | inline | side by side (parent: c3449e2)
author | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Mon, 24 Jul 2017 19:05:22 +0000 (22:05 +0300) | ||
committer | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Mon, 24 Jul 2017 19:05:22 +0000 (22:05 +0300) |
gdb_run.sh | [new file with mode: 0755] | patch | blob |
generator.c | patch | blob | history | |
generator.h | patch | blob | history | |
oberon.c | patch | blob | history | |
oberon.h | patch | blob | history | |
test.c | patch | blob | history |
diff --git a/gdb_run.sh b/gdb_run.sh
--- /dev/null
+++ b/gdb_run.sh
@@ -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
diff --git a/generator.c b/generator.c
index c633e542131722832c5d586e732e18d7f04d85f2..21506b0626fe5db7cfbd117a444d2295de3448a2 100644 (file)
--- a/generator.c
+++ b/generator.c
// 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)
{
{
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);
}
diff --git a/generator.h b/generator.h
index e9dbd53847babb686a9d12555abeb091e4ce993c..78ae8601771442915dcdaa1f8f416b58d016d3c1 100644 (file)
--- a/generator.h
+++ b/generator.h
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);
diff --git a/oberon.c b/oberon.c
index 4dfc604a5f38159b0d1668b8376b0cc4fa8195e7..ec4cab05b3804d3c204407e28dcbb2eff1ccea22 100644 (file)
--- a/oberon.c
+++ b/oberon.c
TRUE,
FALSE,
LPAREN,
- RPAREN
+ RPAREN,
+ EQUAL,
+ NEQ,
+ LESS,
+ LEQ,
+ GREAT,
+ GEQ,
+ PLUS,
+ MINUS,
+ OR,
+ STAR,
+ SLASH,
+ DIV,
+ MOD,
+ AND,
+ NOT
};
// =======================================================================
exit(1);
}
+/*
static int
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)
{
oberon_error(ctx, "oberon_autocast_to: types not matched %i -> %i", from_class, to_class);
}
}
+*/
// =======================================================================
// TABLE
{
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
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;
}
// =======================================================================
-// 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)
{
{
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;
}
// =======================================================================
}
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);
}
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)
{
// 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()
{
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;
}
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;
-}
diff --git a/oberon.h b/oberon.h
index ec742c6bd7af90c18b3850a37fe2163b12407de4..7ed16291b9b4da45a0c1b9bb7db798b1e427f067 100644 (file)
--- a/oberon.h
+++ b/oberon.h
oberon_module_t * mod;
oberon_type_t * types;
+ oberon_type_t * int_type;
+ oberon_type_t * bool_type;
+
void * gen_context;
};
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);
index 7149026862087a8f63577916ffd361e8b89b08ef..0837de4ef28f6ba05ca3dbe8f4c191e95fd0caa5 100644 (file)
--- a/test.c
+++ b/test.c
#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"
" i : INTEGER;"
" b : BOOLEAN;"
"BEGIN"
- " k := 10;"
+ " k := -10 + 1;"
" i := k;"
- " b := TRUE;"
+ " b := ~TRUE OR FALSE;"
"END Test."
;
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;