diff --git a/oberon.c b/oberon.c
index b56a458a6c1e979a743c9d4139b5df3044f1cdc3..dab60b0bb151dce64579a099f2aa59f5722a2eb6 100644 (file)
--- a/oberon.c
+++ b/oberon.c
@@ -228,8 +228,11 @@ oberon_define_type(oberon_scope_t * scope, char * name, oberon_type_t * type, in
static void
oberon_get_char(oberon_context_t * ctx)
{
static void
oberon_get_char(oberon_context_t * ctx)
{
- ctx -> code_index += 1;
- ctx -> c = ctx -> code[ctx -> code_index];
+ if(ctx -> code[ctx -> code_index])
+ {
+ ctx -> code_index += 1;
+ ctx -> c = ctx -> code[ctx -> code_index];
+ }
}
static void
}
static void
}
}
}
}
+static void
+oberon_read_comment(oberon_context_t * ctx)
+{
+ int nesting = 1;
+ while(nesting >= 1)
+ {
+ if(ctx -> c == '(')
+ {
+ oberon_get_char(ctx);
+ if(ctx -> c == '*')
+ {
+ oberon_get_char(ctx);
+ nesting += 1;
+ }
+ }
+ else if(ctx -> c == '*')
+ {
+ oberon_get_char(ctx);
+ if(ctx -> c == ')')
+ {
+ oberon_get_char(ctx);
+ nesting -= 1;
+ }
+ }
+ else if(ctx -> c == 0)
+ {
+ oberon_error(ctx, "unterminated comment");
+ }
+ else
+ {
+ oberon_get_char(ctx);
+ }
+ }
+}
+
+static void oberon_read_token(oberon_context_t * ctx);
+
static void
oberon_read_symbol(oberon_context_t * ctx)
{
static void
oberon_read_symbol(oberon_context_t * ctx)
{
case '(':
ctx -> token = LPAREN;
oberon_get_char(ctx);
case '(':
ctx -> token = LPAREN;
oberon_get_char(ctx);
+ if(ctx -> c == '*')
+ {
+ oberon_get_char(ctx);
+ oberon_read_comment(ctx);
+ oberon_read_token(ctx);
+ }
break;
case ')':
ctx -> token = RPAREN;
break;
case ')':
ctx -> token = RPAREN;
case '*':
ctx -> token = STAR;
oberon_get_char(ctx);
case '*':
ctx -> token = STAR;
oberon_get_char(ctx);
+ if(ctx -> c == ')')
+ {
+ oberon_get_char(ctx);
+ oberon_error(ctx, "unstarted comment");
+ }
break;
case '/':
ctx -> token = SLASH;
break;
case '/':
ctx -> token = SLASH;
oberon_get_char(ctx);
break;
default:
oberon_get_char(ctx);
break;
default:
- oberon_error(ctx, "invalid char");
+ oberon_error(ctx, "invalid char %c", ctx -> c);
break;
}
}
break;
}
}
@@ -614,7 +665,13 @@ oberon_autocast_to(oberon_context_t * ctx, oberon_expr_t * expr, oberon_type_t *
{
if(pref -> class != expr -> result -> class)
{
{
if(pref -> class != expr -> result -> class)
{
- oberon_error(ctx, "incompatible types");
+ if(pref -> class != OBERON_TYPE_PROCEDURE)
+ {
+ if(expr -> result -> class != OBERON_TYPE_POINTER)
+ {
+ oberon_error(ctx, "incompatible types");
+ }
+ }
}
if(pref -> class == OBERON_TYPE_INTEGER)
}
if(pref -> class == OBERON_TYPE_INTEGER)
{
if(param -> class == OBERON_CLASS_VAR_PARAM)
{
{
if(param -> class == OBERON_CLASS_VAR_PARAM)
{
- if(arg -> is_item)
+ if(arg -> read_only)
{
{
- switch(arg -> item.mode)
- {
- case MODE_VAR:
- case MODE_INDEX:
- case MODE_FIELD:
- // Допустимо разыменование?
- //case MODE_DEREF:
- break;
- default:
- oberon_error(ctx, "var-parameter accept only variables");
- break;
- }
+ oberon_error(ctx, "assign to read-only var");
}
}
+
+ //if(arg -> is_item)
+ //{
+ // switch(arg -> item.mode)
+ // {
+ // case MODE_VAR:
+ // case MODE_INDEX:
+ // case MODE_FIELD:
+ // // Допустимо разыменование?
+ // //case MODE_DEREF:
+ // break;
+ // default:
+ // oberon_error(ctx, "var-parameter accept only variables");
+ // break;
+ // }
+ //}
}
oberon_autocast_to(ctx, arg, param -> type);
arg = arg -> next;
}
oberon_autocast_to(ctx, arg, param -> type);
arg = arg -> next;
@@ -2513,6 +2575,71 @@ oberon_make_abs_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_
return expr;
}
return expr;
}
+static void
+oberon_make_new_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_args)
+{
+ if(num_args < 1)
+ {
+ oberon_error(ctx, "too few arguments");
+ }
+
+ if(num_args > 1)
+ {
+ oberon_error(ctx, "too mach arguments");
+ }
+
+ oberon_expr_t * dst;
+ dst = list_args;
+
+ oberon_type_t * type;
+ type = dst -> result;
+
+ if(type -> class != OBERON_TYPE_POINTER)
+ {
+ oberon_error(ctx, "not a pointer");
+ }
+
+ type = type -> base;
+
+ oberon_expr_t * src;
+ src = oberon_new_item(MODE_NEW, dst -> result, 0);
+ src -> item.num_args = 0;
+ src -> item.args = NULL;
+
+ if(type -> class == OBERON_TYPE_ARRAY)
+ {
+ // Пригодится при работе с открытыми массивами
+ /*
+ int dim = 1;
+ oberon_expr_t * sizes = NULL;
+ oberon_expr_t * last_size = NULL;
+ sizes = last_size = oberon_new_item(MODE_INTEGER, ctx -> int_type, 1);
+ sizes -> item.integer = type -> size;
+ oberon_type_t * base = type -> base;
+ while(base -> class == OBERON_TYPE_ARRAY)
+ {
+ oberon_expr_t * size;
+ size = last_size = oberon_new_item(MODE_INTEGER, ctx -> int_type, 1);
+ size -> item.integer = base -> size;
+
+ last_size -> next = size;
+ last_size = size;
+ base = base -> base;
+ dim += 1;
+ }
+ */
+
+ src -> item.num_args = 0;
+ src -> item.args = NULL;
+ }
+ else if(type -> class != OBERON_TYPE_RECORD)
+ {
+ oberon_error(ctx, "oberon_make_new_call: wat");
+ }
+
+ oberon_assign(ctx, src, dst);
+}
+
oberon_context_t *
oberon_create_context(ModuleImportCallback import_module)
{
oberon_context_t *
oberon_create_context(ModuleImportCallback import_module)
{
register_default_types(ctx);
oberon_new_intrinsic(ctx, "ABS", oberon_make_abs_call, NULL);
register_default_types(ctx);
oberon_new_intrinsic(ctx, "ABS", oberon_make_abs_call, NULL);
+ oberon_new_intrinsic(ctx, "NEW", NULL, oberon_make_new_call);
return ctx;
}
return ctx;
}