diff --git a/oberon.c b/oberon.c
index e411c6c2fdaa455bf15fddcd54c7b94a37f3c8c3..440364361e45956f86091d3022fd50b3099f1026 100644 (file)
--- a/oberon.c
+++ b/oberon.c
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
+
#include "oberon.h"
#include "oberon.h"
+#include "generator.h"
enum {
EOF_ = 0,
enum {
EOF_ = 0,
COLON,
BEGIN,
ASSIGN,
COLON,
BEGIN,
ASSIGN,
- INTEGER
+ INTEGER,
+ TRUE,
+ FALSE,
+ LPAREN,
+ RPAREN,
+ EQUAL,
+ NEQ,
+ LESS,
+ LEQ,
+ GREAT,
+ GEQ,
+ PLUS,
+ MINUS,
+ OR,
+ STAR,
+ SLASH,
+ DIV,
+ MOD,
+ AND,
+ NOT,
+ PROCEDURE
};
};
-enum {
- MODE_VAR,
- MODE_INTEGER,
-};
-
-typedef struct
-{
- int mode;
- int integer;
- oberon_var_t * var;
-} oberon_item_t;
-
// =======================================================================
// UTILS
// =======================================================================
// =======================================================================
// UTILS
// =======================================================================
-static void
+void
oberon_error(oberon_context_t * ctx, const char * fmt, ...)
{
va_list ptr;
oberon_error(oberon_context_t * ctx, const char * fmt, ...)
{
va_list ptr;
exit(1);
}
exit(1);
}
-static int
-oberon_item_to_type_class(oberon_context_t * ctx, oberon_item_t * item)
-{
- int class;
-
- if(item -> mode == MODE_INTEGER)
- {
- class = OBERON_TYPE_INTEGER;
- }
- else if(item -> mode == MODE_VAR)
- {
- class = item -> var -> type -> class;
- }
- else
- {
- oberon_error(ctx, "oberon_item_to_type_class: wat");
- }
-
- return class;
-}
-
// =======================================================================
// TABLE
// =======================================================================
// =======================================================================
// TABLE
// =======================================================================
memset(newvar, 0, sizeof *newvar);
newvar -> name = name;
newvar -> type = type;
memset(newvar, 0, sizeof *newvar);
newvar -> name = name;
newvar -> type = type;
+ oberon_generator_init_var(ctx, newvar);
x -> next = newvar;
}
x -> next = newvar;
}
-// =======================================================================
-// GENERATOR
-// =======================================================================
-
-static void
-oberon_generate_assign(oberon_context_t * ctx, void * src, void * dst, int size)
-{
- printf("G: %p := %p (%i);\n", dst, src, size);
-}
-
// =======================================================================
// SCANER
// =======================================================================
// =======================================================================
// SCANER
// =======================================================================
c = ctx -> code[i];
}
c = ctx -> code[i];
}
- char * ident = malloc(len + 2);
+ char * ident = malloc(len + 1);
memcpy(ident, &ctx->code[ctx->code_index], len);
memcpy(ident, &ctx->code[ctx->code_index], len);
- ident[len + 1] = 0;
+ ident[len] = 0;
ctx -> code_index = i;
ctx -> c = ctx -> code[i];
ctx -> code_index = i;
ctx -> c = ctx -> code[i];
{
ctx -> token = BEGIN;
}
{
ctx -> token = BEGIN;
}
+ else if(strcmp(ident, "TRUE") == 0)
+ {
+ ctx -> token = TRUE;
+ }
+ else if(strcmp(ident, "FALSE") == 0)
+ {
+ 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;
+ }
+ else if(strcmp(ident, "PROCEDURE") == 0)
+ {
+ ctx -> token = PROCEDURE;
+ }
}
static void
}
static void
}
}
}
}
+static void
+oberon_read_symbol(oberon_context_t * ctx)
+{
+ int c = ctx -> c;
+ switch(c)
+ {
+ case 0:
+ ctx -> token = EOF_;
+ break;
+ case ';':
+ ctx -> token = SEMICOLON;
+ oberon_get_char(ctx);
+ break;
+ case ':':
+ ctx -> token = COLON;
+ oberon_get_char(ctx);
+ if(ctx -> c == '=')
+ {
+ ctx -> token = ASSIGN;
+ oberon_get_char(ctx);
+ }
+ break;
+ case '.':
+ ctx -> token = DOT;
+ oberon_get_char(ctx);
+ break;
+ case '(':
+ ctx -> token = LPAREN;
+ oberon_get_char(ctx);
+ break;
+ case ')':
+ 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;
+ }
+}
+
static void
oberon_read_token(oberon_context_t * ctx)
{
static void
oberon_read_token(oberon_context_t * ctx)
{
}
else
{
}
else
{
- switch(c)
+ oberon_read_symbol(ctx);
+ }
+}
+
+// =======================================================================
+// EXPRESSION
+// =======================================================================
+
+static void oberon_expect_token(oberon_context_t * ctx, int token);
+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_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_unary_op(oberon_context_t * ctx, int token, oberon_expr_t * a)
+{
+ oberon_expr_t * expr;
+ oberon_type_t * result;
+
+ result = a -> result;
+
+ if(token == MINUS)
+ {
+ if(result -> class != OBERON_TYPE_INTEGER)
+ {
+ oberon_error(ctx, "incompatible operator type");
+ }
+
+ expr = oberon_new_operator(OP_UNARY_MINUS, result, a, NULL);
+ }
+ else if(token == NOT)
+ {
+ if(result -> class != OBERON_TYPE_BOOLEAN)
+ {
+ oberon_error(ctx, "incompatible operator type");
+ }
+
+ expr = oberon_new_operator(OP_LOGIC_NOT, result, a, NULL);
+ }
+ else
+ {
+ oberon_error(ctx, "oberon_make_unary_op: wat");
+ }
+
+ return expr;
+}
+
+static oberon_expr_t *
+oberon_factor(oberon_context_t * ctx)
+{
+ char * name;
+ oberon_var_t * var;
+ oberon_expr_t * expr;
+
+ switch(ctx -> token)
+ {
+ case IDENT:
+ name = oberon_assert_ident(ctx);
+ var = oberon_find_var(ctx, name);
+ if(var == NULL)
+ {
+ oberon_error(ctx, "undefined variable %s", name);
+ }
+ expr = oberon_new_item(MODE_VAR, var -> type);
+ expr -> item.var = var;
+ break;
+ case INTEGER:
+ expr = oberon_new_item(MODE_INTEGER, ctx -> int_type);
+ expr -> item.integer = ctx -> integer;
+ oberon_assert_token(ctx, INTEGER);
+ break;
+ case TRUE:
+ expr = oberon_new_item(MODE_BOOLEAN, ctx -> bool_type);
+ expr -> item.boolean = 1;
+ oberon_assert_token(ctx, TRUE);
+ break;
+ case FALSE:
+ 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);
+ expr = oberon_expr(ctx);
+ oberon_assert_token(ctx, RPAREN);
+ break;
+ case NOT:
+ oberon_assert_token(ctx, NOT);
+ expr = oberon_factor(ctx);
+ expr = oberon_make_unary_op(ctx, NOT, expr);
+ break;
+ default:
+ oberon_error(ctx, "invalid expression");
+ }
+
+ return expr;
+}
+
+/*
+ * oberon_autocast_binary_op автоматически переобразовывеат тип по след. правилам:
+ * 1. Классы обоих типов должны быть одинаковы
+ * 2. В качестве результата должен быть выбран больший тип.
+ * 3. Если размер результат не должен быть меньше чем базовый int
+ */
+
+static void
+oberon_autocast_binary_op(oberon_context_t * ctx, oberon_type_t * a, oberon_type_t * b, oberon_type_t ** result)
+{
+ if((a -> class) != (b -> class))
+ {
+ oberon_error(ctx, "incompatible types");
+ }
+
+ if((a -> size) > (b -> size))
+ {
+ *result = a;
+ }
+ else
+ {
+ *result = b;
+ }
+
+ if(((*result) -> class) == OBERON_TYPE_INTEGER)
+ {
+ if(((*result) -> size) < (ctx -> int_type -> size))
+ {
+ *result = ctx -> int_type;
+ }
+ }
+
+ /* TODO: cast types */
+}
+
+#define ITMAKESBOOLEAN(x) \
+ (((x) >= EQUAL && (x) <= GEQ) || ((x) == OR) || ((x) == AND))
+
+#define ITUSEONLYINTEGER(x) \
+ ((x) >= LESS && (x) <= GEQ)
+
+#define ITUSEONLYBOOLEAN(x) \
+ (((x) == OR) || ((x) == AND))
+
+static oberon_expr_t *
+oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_expr_t * b)
+{
+ oberon_expr_t * expr;
+ oberon_type_t * result;
+
+ oberon_autocast_binary_op(ctx, a -> result, b -> result, &result);
+
+ if(ITMAKESBOOLEAN(token))
+ {
+ if(ITUSEONLYINTEGER(token))
+ {
+ if(a -> result -> class != OBERON_TYPE_INTEGER
+ && b -> result -> class != OBERON_TYPE_INTEGER)
+ {
+ oberon_error(ctx, "used only with integer types");
+ }
+ }
+ else if(ITUSEONLYBOOLEAN(token))
+ {
+ if(a -> result -> class != OBERON_TYPE_BOOLEAN
+ && b -> result -> class != OBERON_TYPE_BOOLEAN)
+ {
+ oberon_error(ctx, "used only with boolean type");
+ }
+ }
+
+ 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 if(token == OR)
+ {
+ expr = oberon_new_operator(OP_LOGIC_OR, result, a, b);
+ }
+ else if(token == AND)
+ {
+ expr = oberon_new_operator(OP_LOGIC_AND, result, a, b);
+ }
+ else
+ {
+ oberon_error(ctx, "oberon_make_bin_op: bool wat");
+ }
+ }
+ else
+ {
+ 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 == 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)
{
{
- case 0: ctx -> token = EOF_; break;
- case ';': ctx -> token = SEMICOLON; oberon_get_char(ctx); break;
- case ':':
- /****************************************************/
- ctx -> token = COLON; oberon_get_char(ctx);
- if(ctx -> c == '=')
- {
- ctx -> token = ASSIGN;
- oberon_get_char(ctx);
- }
- break;
- /****************************************************/
- case '.': ctx -> token = DOT; oberon_get_char(ctx); break;
- default: oberon_error(ctx, "invalid char");
+ expr = oberon_new_operator(OP_MOD, result, a, b);
}
}
+ else
+ {
+ oberon_error(ctx, "oberon_make_bin_op: bin 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_bin_op(ctx, token, expr, inter);
+ }
+
+ return expr;
+}
+
+#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_bin_op(ctx, token, expr, inter);
+ }
+
+ if(minus)
+ {
+ expr = oberon_make_unary_op(ctx, MINUS, expr);
+ }
+
+ return expr;
+}
+
+#define ISRELATION(x) \
+ ((x) >= EQUAL && (x) <= GEQ)
+
+static oberon_expr_t *
+oberon_expr(oberon_context_t * 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_bin_op(ctx, token, expr, inter);
+ }
+
+ return expr;
}
// =======================================================================
// PARSER
// =======================================================================
}
// =======================================================================
// PARSER
// =======================================================================
+static void oberon_statement_seq(oberon_context_t * ctx);
+
static void
oberon_expect_token(oberon_context_t * ctx, int token)
{
static void
oberon_expect_token(oberon_context_t * ctx, int token)
{
static char *
oberon_assert_ident(oberon_context_t * ctx)
{
static char *
oberon_assert_ident(oberon_context_t * ctx)
{
- char * ident;
oberon_expect_token(ctx, IDENT);
oberon_expect_token(ctx, IDENT);
- ident = ctx -> string;
+ char * ident = ctx -> string;
oberon_read_token(ctx);
return ident;
}
oberon_read_token(ctx);
return ident;
}
oberon_define_var(ctx, name, type);
}
oberon_define_var(ctx, name, type);
}
+static void
+oberon_make_procedure_begin(oberon_context_t * ctx, char * name)
+{
+
+}
+
+static void
+oberon_make_procedure_end(oberon_context_t * ctx)
+{
+
+}
+
+static void
+oberon_proc_decl(oberon_context_t * ctx)
+{
+ oberon_assert_token(ctx, PROCEDURE);
+
+ char * name;
+ name = oberon_assert_ident(ctx);
+
+ oberon_assert_token(ctx, SEMICOLON);
+
+ oberon_make_procedure_begin(ctx, name);
+ if(ctx -> token == BEGIN)
+ {
+ oberon_assert_token(ctx, BEGIN);
+ oberon_statement_seq(ctx);
+ }
+ oberon_make_procedure_end(ctx);
+
+ oberon_assert_token(ctx, END);
+ char * name2 = oberon_assert_ident(ctx);
+
+ if(strcmp(name2, name) != 0)
+ {
+ oberon_error(ctx, "procedure name not matched");
+ }
+}
+
static void
oberon_decl_seq(oberon_context_t * ctx)
{
static void
oberon_decl_seq(oberon_context_t * ctx)
{
oberon_assert_token(ctx, SEMICOLON);
}
}
oberon_assert_token(ctx, SEMICOLON);
}
}
-}
-
-static oberon_item_t *
-oberon_expr(oberon_context_t * ctx)
-{
- oberon_item_t * item = malloc(sizeof *item);
- memset(item, 0, sizeof *item);
- if(ctx -> token == IDENT)
- {
- char * name = oberon_assert_ident(ctx);
- oberon_var_t * var = oberon_find_var(ctx, name);
- if(var == NULL)
- {
- oberon_error(ctx, "undefined variable");
- }
- item -> mode = MODE_VAR;
- item -> var = var;
- }
- else if(ctx -> token == INTEGER)
+ if(ctx -> token == PROCEDURE)
{
{
- item -> mode = MODE_INTEGER;
- item -> integer = ctx -> integer;
- oberon_assert_token(ctx, INTEGER);
- }
- else
- {
- oberon_error(ctx, "invalid expression");
+ oberon_proc_decl(ctx);
+ oberon_assert_token(ctx, SEMICOLON);
}
}
-
- return item;
}
static void
}
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)
+ if(src -> result -> class != dst -> result -> class)
{
{
- oberon_error(ctx, "invalid assignment");
+ oberon_error(ctx, "incompatible assignment types");
}
}
- int src_class = oberon_item_to_type_class(ctx, src);
- int dst_class = oberon_item_to_type_class(ctx, dst);
-
- if(src_class != dst_class)
+ if(dst -> result -> class == OBERON_TYPE_INTEGER)
{
{
- oberon_error(ctx, "types not matched");
+ if((dst -> result -> size) < (src -> result -> size))
+ {
+ oberon_error(ctx, "incompatible assignment type size");
+ }
}
}
- // TODO: code generation
- oberon_generate_assign(ctx, 0, 0, 4);
+ oberon_generate_assign(ctx, src, dst);
}
static void
oberon_statement(oberon_context_t * ctx)
{
}
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)
{
if(ctx -> token == IDENT)
{
}
static void
}
static void
-oberon_parse_it(oberon_context_t * ctx)
+oberon_parse_module(oberon_context_t * ctx)
{
char *name1, *name2;
oberon_read_token(ctx);
{
char *name1, *name2;
oberon_read_token(ctx);
if(ctx -> token == BEGIN)
{
oberon_assert_token(ctx, BEGIN);
if(ctx -> token == BEGIN)
{
oberon_assert_token(ctx, BEGIN);
+ oberon_generate_begin_module(ctx);
oberon_statement_seq(ctx);
oberon_statement_seq(ctx);
+ oberon_generate_end_module(ctx);
}
oberon_assert_token(ctx, END);
}
oberon_assert_token(ctx, END);
// LIBRARY
// =======================================================================
// 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_context_t *
oberon_create_context()
{
oberon_type_t * types = malloc(sizeof *types);
memset(types, 0, sizeof *types);
oberon_type_t * types = malloc(sizeof *types);
memset(types, 0, sizeof *types);
-
ctx -> types = types;
ctx -> types = types;
+
+ oberon_generator_init_context(ctx);
+
+ register_default_types(ctx);
+
return ctx;
}
return ctx;
}
+void
+oberon_destroy_context(oberon_context_t * ctx)
+{
+ oberon_generator_destroy_context(ctx);
+ free(ctx);
+}
+
oberon_module_t *
oberon_compile_module(oberon_context_t * ctx, const char * code)
{
oberon_module_t *
oberon_compile_module(oberon_context_t * ctx, const char * code)
{
ctx -> mod -> vars = vars;
oberon_init_scaner(ctx, code);
ctx -> mod -> vars = vars;
oberon_init_scaner(ctx, code);
- oberon_parse_it(ctx);
+ oberon_parse_module(ctx);
+
+ oberon_generate_code(ctx);
return mod;
}
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;
-
- x -> next = newtype;
-}