summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 12ae486)
raw | patch | inline | side by side (parent: 12ae486)
author | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Mon, 24 Jul 2017 20:05:37 +0000 (23:05 +0300) | ||
committer | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Mon, 24 Jul 2017 20:05:37 +0000 (23:05 +0300) |
generator.c | patch | blob | history | |
notes | patch | blob | history | |
oberon.c | patch | blob | history | |
oberon.h | patch | blob | history | |
test.c | patch | blob | history |
diff --git a/generator.c b/generator.c
index 179320aef7df8ffb4cf1aa4a6ecc3b4df4250f17..d54bbfdb408ad0dc720b6095e7b99f8e878ac4a9 100644 (file)
--- a/generator.c
+++ b/generator.c
}
else if(type -> class == OBERON_TYPE_BOOLEAN)
{
- gcc_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_BOOL);
+ if(type -> size == sizeof(bool))
+ {
+ gcc_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_BOOL);
+ }
+ else
+ {
+ oberon_error(ctx, "generator: unsupported boolean size");
+ }
+ }
+ else if(type -> class == OBERON_TYPE_REAL)
+ {
+ if(type -> size == sizeof(float))
+ {
+ gcc_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_FLOAT);
+ }
+ else if(type -> size == sizeof(double))
+ {
+ gcc_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_DOUBLE);
+ }
+ else if(type -> size == sizeof(long double))
+ {
+ gcc_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_LONG_DOUBLE);
+ }
+ else
+ {
+ oberon_error(ctx, "generator: unsupported real size");
+ }
}
else if(type -> class == OBERON_TYPE_ARRAY)
{
right = gcc_jit_context_new_call_through_ptr(gcc_context, NULL, gcc_alloc, 1, &fnarg);
right = gcc_jit_context_new_cast(gcc_context, NULL, right, result_type);
}
+ else if(item -> mode == MODE_REAL)
+ {
+ gcc_jit_type * int_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_FLOAT);
+ right = gcc_jit_context_new_rvalue_from_int(gcc_context, int_type, item -> real);
+ }
else
{
oberon_error(ctx, "rvalue_from_item: invalid mode %i", item -> mode);
index d8331b14584b22f479cb511a9a1c786bcab1f6e8..ebd198db2fc9f0cb61fe90b31f496dbfa4a13cf9 100644 (file)
--- a/notes
+++ b/notes
-- нету типа real, оператор / должен возвращать дробный результат
- нету открытых массивов
- нет символов и строк
+- нужен автокаст int -> real для DIV. Да и вообще каст типов.
- нету операторов if, while и т.д.
diff --git a/oberon.c b/oberon.c
index dab60b0bb151dce64579a099f2aa59f5722a2eb6..4b20dad3d30de42797478959dc92d2cd1e8929b9 100644 (file)
--- a/oberon.c
+++ b/oberon.c
#include <ctype.h>
#include <string.h>
#include <assert.h>
+#include <stdbool.h>
#include "oberon.h"
#include "generator.h"
TO,
UPARROW,
NIL,
- IMPORT
+ IMPORT,
+ REAL
};
// =======================================================================
return x;
}
+static oberon_type_t *
+oberon_new_type_real(int size)
+{
+ oberon_type_t * x;
+ x = oberon_new_type_ptr(OBERON_TYPE_REAL);
+ x -> size = size;
+ return x;
+}
+
// =======================================================================
// TABLE
// =======================================================================
}
static void
-oberon_read_integer(oberon_context_t * ctx)
-{
- int len = 0;
- int i = ctx -> code_index;
+oberon_read_number(oberon_context_t * ctx)
+{
+ long integer;
+ double real;
+ char * ident;
+ int start_i;
+ int exp_i;
+ int end_i;
+
+ /*
+ * mode = 0 == DEC
+ * mode = 1 == HEX
+ * mode = 2 == REAL
+ * mode = 3 == LONGREAL
+ */
+ int mode = 0;
+ start_i = ctx -> code_index;
+
+ while(isdigit(ctx -> c))
+ {
+ oberon_get_char(ctx);
+ }
- int c = ctx -> code[i];
- while(isdigit(c))
+ end_i = ctx -> code_index;
+
+ if(isxdigit(ctx -> c))
{
- i += 1;
- len += 1;
- c = ctx -> code[i];
+ mode = 1;
+ while(isxdigit(ctx -> c))
+ {
+ oberon_get_char(ctx);
+ }
+
+ end_i = ctx -> code_index;
+
+ if(ctx -> c != 'H')
+ {
+ oberon_error(ctx, "invalid hex number");
+ }
+ oberon_get_char(ctx);
}
+ else if(ctx -> c == '.')
+ {
+ mode = 2;
+ oberon_get_char(ctx);
- char * ident = malloc(len + 2);
- memcpy(ident, &ctx->code[ctx->code_index], len);
- ident[len + 1] = 0;
+ while(isdigit(ctx -> c))
+ {
+ oberon_get_char(ctx);
+ }
+
+ if(ctx -> c == 'E' || ctx -> c == 'D')
+ {
+ exp_i = ctx -> code_index;
+
+ if(ctx -> c == 'D')
+ {
+ mode = 3;
+ }
+
+ oberon_get_char(ctx);
+
+ if(ctx -> c == '+' || ctx -> c == '-')
+ {
+ oberon_get_char(ctx);
+ }
+
+ while(isdigit(ctx -> c))
+ {
+ oberon_get_char(ctx);
+ }
+
+ }
+
+ end_i = ctx -> code_index;
+ }
+
+ int len = end_i - start_i;
+ ident = malloc(len + 1);
+ memcpy(ident, &ctx -> code[start_i], len);
+ ident[len] = 0;
+
+ if(mode == 3)
+ {
+ int i = exp_i - start_i;
+ ident[i] = 'E';
+ }
+
+ switch(mode)
+ {
+ case 0:
+ integer = atol(ident);
+ real = integer;
+ ctx -> token = INTEGER;
+ break;
+ case 1:
+ sscanf(ident, "%lx", &integer);
+ real = integer;
+ ctx -> token = INTEGER;
+ break;
+ case 2:
+ case 3:
+ sscanf(ident, "%lf", &real);
+ ctx -> token = REAL;
+ break;
+ default:
+ oberon_error(ctx, "oberon_read_number: wat");
+ break;
+ }
- ctx -> code_index = i;
- ctx -> c = ctx -> code[i];
ctx -> string = ident;
- ctx -> integer = atoi(ident);
- ctx -> token = INTEGER;
+ ctx -> integer = integer;
+ ctx -> real = real;
}
static void
}
else if(isdigit(c))
{
- oberon_read_integer(ctx);
+ oberon_read_number(ctx);
}
else
{
expr -> item.integer = ctx -> integer;
oberon_assert_token(ctx, INTEGER);
break;
+ case REAL:
+ expr = oberon_new_item(MODE_REAL, ctx -> real_type, 1);
+ expr -> item.real = ctx -> real;
+ oberon_assert_token(ctx, REAL);
+ break;
case TRUE:
expr = oberon_new_item(MODE_BOOLEAN, ctx -> bool_type, 1);
expr -> item.boolean = 1;
@@ -1304,6 +1411,46 @@ oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_
oberon_error(ctx, "oberon_make_bin_op: bool wat");
}
}
+ else if(token == SLASH)
+ {
+ if(a -> result -> class != OBERON_TYPE_REAL)
+ {
+ if(a -> result -> class == OBERON_TYPE_INTEGER)
+ {
+ oberon_error(ctx, "TODO cast int -> real");
+ }
+ else
+ {
+ oberon_error(ctx, "operator / requires numeric type");
+ }
+ }
+
+ if(b -> result -> class != OBERON_TYPE_REAL)
+ {
+ if(b -> result -> class == OBERON_TYPE_INTEGER)
+ {
+ oberon_error(ctx, "TODO cast int -> real");
+ }
+ else
+ {
+ oberon_error(ctx, "operator / requires numeric type");
+ }
+ }
+
+ oberon_autocast_binary_op(ctx, a -> result, b -> result, &result);
+ expr = oberon_new_operator(OP_DIV, result, a, b);
+ }
+ else if(token == DIV)
+ {
+ if(a -> result -> class != OBERON_TYPE_INTEGER
+ || b -> result -> class != OBERON_TYPE_INTEGER)
+ {
+ oberon_error(ctx, "operator DIV requires integer type");
+ }
+
+ oberon_autocast_binary_op(ctx, a -> result, b -> result, &result);
+ expr = oberon_new_operator(OP_DIV, result, a, b);
+ }
else
{
oberon_autocast_binary_op(ctx, a -> result, b -> result, &result);
@@ -1320,14 +1467,6 @@ oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_
{
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);
ctx -> int_type = oberon_new_type_integer(sizeof(int));
oberon_define_type(ctx -> world_scope, "INTEGER", ctx -> int_type, 1);
- ctx -> bool_type = oberon_new_type_boolean(sizeof(int));
+ ctx -> bool_type = oberon_new_type_boolean(sizeof(bool));
oberon_define_type(ctx -> world_scope, "BOOLEAN", ctx -> bool_type, 1);
+
+ ctx -> real_type = oberon_new_type_real(sizeof(float));
+ oberon_define_type(ctx -> world_scope, "REAL", ctx -> real_type, 1);
}
static void
diff --git a/oberon.h b/oberon.h
index 53693a79629e8b772c38497cfc0c00046891cbed..189369b9c0cb324564b82aca21b21000a416e944 100644 (file)
--- a/oberon.h
+++ b/oberon.h
OBERON_TYPE_PROCEDURE,
OBERON_TYPE_ARRAY,
OBERON_TYPE_RECORD,
- OBERON_TYPE_POINTER
+ OBERON_TYPE_POINTER,
+ OBERON_TYPE_REAL
};
/*
char c;
int token;
char * string;
- int integer;
+ long integer;
+ double real;
/*** END SCANER DATA ***/
/*** PARSER DATA ***/
oberon_type_t * int_type;
oberon_type_t * bool_type;
+ oberon_type_t * real_type;
oberon_type_t * void_type;
oberon_type_t * void_ptr_type;
oberon_scope_t * world_scope;
MODE_FIELD,
MODE_DEREF,
MODE_NIL,
- MODE_NEW
+ MODE_NEW,
+ MODE_REAL
};
enum
int read_only;
int mode;
- int integer;
+ long integer;
+ double real;
int boolean;
oberon_object_t * var;
index 1f440779e411b51f514c9409fddf97b033019685..1780bafa8ad900781c4af6e7f6b77868710a5119 100644 (file)
--- a/test.c
+++ b/test.c
"(* Main module *)"
"MODULE Test;"
"IMPORT Out;"
+ "CONST"
+ " real = 0.1E3;"
""
"VAR"
" nx- : INTEGER;"
" ChParam(nx);"
" Out.Int(nx, 0);"
" Out.Ln;"
+ " Out.Real(real / 3.0, 0);"
+ " Out.Ln;"
"END Test."
;
// " String- : PROCEDURE(str : ARRAY OF CHAR)"
// " Int- : PROCEDURE(i, n : LONGINT);"
" Int- : PROCEDURE(i, n : INTEGER);"
-// " Real- : PROCEDURE(x : REAL; n : INTEGER);"
+ " Real- : PROCEDURE(x : REAL; n : INTEGER);"
// " LongReal- : PROCEDURE(x : LONGREAL; n : INTEGER);"
" Ln- : PROCEDURE;"
"END Out."
void ImplOutInt(int i, int n)
{
char number[22];
- snprintf(number, 22, "%i", i);
+ snprintf(number, 22, "%d", i);
+ int len = strlen(number);
+ for(int i = 0; i < n - len; i++)
+ {
+ putchar(' ');
+ }
+ printf("%s", number);
+}
+
+typedef void (*TOutReal)(float, int);
+static TOutReal * OutRealPtr;
+void ImplOutReal(float i, int n)
+{
+ char number[32];
+ snprintf(number, 32, "%F", i);
int len = strlen(number);
for(int i = 0; i < n - len; i++)
{
*OutOpenPtr = ImplOutOpen;
OutIntPtr = oberon_generator_get_var(ctx, "Out_Int");
*OutIntPtr = ImplOutInt;
+ OutRealPtr = oberon_generator_get_var(ctx, "Out_Real");
+ *OutRealPtr = ImplOutReal;
OutLnPtr = oberon_generator_get_var(ctx, "Out_Ln");
*OutLnPtr = ImplOutLn;
}