From b752043cfbb49243ca3727dbfc9be5b614a8c9c2 Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Mon, 24 Jul 2017 22:01:38 +0300 Subject: [PATCH] =?utf8?q?=D0=9D=D0=B0=D1=87=D0=B0=D0=BB=D0=BE=20=D0=BF?= =?utf8?q?=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0,=20=D0=B3=D0=B4=D0=B5-?= =?utf8?q?=D1=82=D0=BE=20=D0=BF=D0=B5=D1=80=D0=B2=D0=B0=D1=8F=20=D0=BD?= =?utf8?q?=D0=B5=D0=B4=D0=B5=D0=BB=D1=8F=20=D0=B8=D1=8E=D0=BB=D1=8F.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + make.sh | 5 + oberon.c | 489 +++++++++++++++++++++++++++++++++++++++++++ oberon.h | 54 +++++ test.c | 28 +++ test_gcc_jit/make.sh | 5 + test_gcc_jit/s1 | Bin 0 -> 10792 bytes test_gcc_jit/s1.c | 22 ++ 8 files changed, 604 insertions(+) create mode 100644 .gitignore create mode 100755 make.sh create mode 100644 oberon.c create mode 100644 oberon.h create mode 100644 test.c create mode 100755 test_gcc_jit/make.sh create mode 100755 test_gcc_jit/s1 create mode 100644 test_gcc_jit/s1.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f47cb20 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.out diff --git a/make.sh b/make.sh new file mode 100755 index 0000000..fe43cd6 --- /dev/null +++ b/make.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -e + +cc -g -Wall -Werror -std=c11 *.c diff --git a/oberon.c b/oberon.c new file mode 100644 index 0000000..e411c6c --- /dev/null +++ b/oberon.c @@ -0,0 +1,489 @@ +#include +#include +#include +#include +#include +#include "oberon.h" + +enum { + EOF_ = 0, + IDENT, + MODULE, + SEMICOLON, + END, + DOT, + VAR, + COLON, + BEGIN, + ASSIGN, + INTEGER +}; + +enum { + MODE_VAR, + MODE_INTEGER, +}; + +typedef struct +{ + int mode; + int integer; + oberon_var_t * var; +} oberon_item_t; + +// ======================================================================= +// UTILS +// ======================================================================= + +static void +oberon_error(oberon_context_t * ctx, const char * fmt, ...) +{ + va_list ptr; + va_start(ptr, fmt); + fprintf(stderr, "error: "); + vfprintf(stderr, fmt, ptr); + fprintf(stderr, "\n"); + fprintf(stderr, " code_index = %i\n", ctx -> code_index); + fprintf(stderr, " c = %c\n", ctx -> c); + fprintf(stderr, " token = %i\n", ctx -> token); + va_end(ptr); + 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 +// ======================================================================= + +static oberon_type_t * +oberon_find_type(oberon_context_t * ctx, char * name) +{ + oberon_type_t * x = ctx -> types; + while(x -> next && strcmp(x -> next -> name, name) != 0) + { + x = x -> next; + } + + return x -> next; +} + +static oberon_var_t * +oberon_find_var(oberon_context_t * ctx, char * name) +{ + oberon_var_t * x = ctx -> mod -> vars; + while(x -> next && strcmp(x -> next -> name, name) != 0) + { + x = x -> next; + } + + return x -> next; +} + +static void +oberon_define_var(oberon_context_t * ctx, char * name, oberon_type_t * type) +{ + oberon_var_t * x = ctx -> mod -> vars; + while(x -> next && strcmp(x -> next -> name, name) != 0) + { + x = x -> next; + } + + if(x -> next) + { + oberon_error(ctx, "already defined"); + } + + oberon_var_t * newvar = malloc(sizeof *newvar); + memset(newvar, 0, sizeof *newvar); + newvar -> name = name; + newvar -> type = type; + + 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 +// ======================================================================= + +static void +oberon_get_char(oberon_context_t * ctx) +{ + ctx -> code_index += 1; + ctx -> c = ctx -> code[ctx -> code_index]; +} + +static void +oberon_init_scaner(oberon_context_t * ctx, const char * code) +{ + ctx -> code = code; + ctx -> code_index = 0; + ctx -> c = ctx -> code[ctx -> code_index]; +} + +static void +oberon_read_ident(oberon_context_t * ctx) +{ + int len = 0; + int i = ctx -> code_index; + + int c = ctx -> code[i]; + while(isalnum(c)) + { + i += 1; + len += 1; + c = ctx -> code[i]; + } + + char * ident = malloc(len + 2); + memcpy(ident, &ctx->code[ctx->code_index], len); + ident[len + 1] = 0; + + ctx -> code_index = i; + ctx -> c = ctx -> code[i]; + ctx -> string = ident; + ctx -> token = IDENT; + + if(strcmp(ident, "MODULE") == 0) + { + ctx -> token = MODULE; + } + else if(strcmp(ident, "END") == 0) + { + ctx -> token = END; + } + else if(strcmp(ident, "VAR") == 0) + { + ctx -> token = VAR; + } + else if(strcmp(ident, "BEGIN") == 0) + { + ctx -> token = BEGIN; + } +} + +static void +oberon_read_integer(oberon_context_t * ctx) +{ + int len = 0; + int i = ctx -> code_index; + + int c = ctx -> code[i]; + while(isdigit(c)) + { + i += 1; + len += 1; + c = ctx -> code[i]; + } + + char * ident = malloc(len + 2); + memcpy(ident, &ctx->code[ctx->code_index], len); + ident[len + 1] = 0; + + ctx -> code_index = i; + ctx -> c = ctx -> code[i]; + ctx -> string = ident; + ctx -> integer = atoi(ident); + ctx -> token = INTEGER; +} + +static void +oberon_skip_space(oberon_context_t * ctx) +{ + while(isspace(ctx -> c)) + { + oberon_get_char(ctx); + } +} + +static void +oberon_read_token(oberon_context_t * ctx) +{ + oberon_skip_space(ctx); + + int c = ctx -> c; + if(isalpha(c)) + { + oberon_read_ident(ctx); + } + else if(isdigit(c)) + { + oberon_read_integer(ctx); + } + else + { + 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; + default: oberon_error(ctx, "invalid char"); + } + } +} + +// ======================================================================= +// PARSER +// ======================================================================= + +static void +oberon_expect_token(oberon_context_t * ctx, int token) +{ + if(ctx -> token != token) + { + oberon_error(ctx, "unexpected token %i (%i)", ctx -> token, token); + } +} + +static void +oberon_assert_token(oberon_context_t * ctx, int token) +{ + oberon_expect_token(ctx, token); + oberon_read_token(ctx); +} + +static char * +oberon_assert_ident(oberon_context_t * ctx) +{ + char * ident; + oberon_expect_token(ctx, IDENT); + ident = ctx -> string; + oberon_read_token(ctx); + return ident; +} + +static oberon_type_t * +oberon_type(oberon_context_t * ctx) +{ + char * name = oberon_assert_ident(ctx); + oberon_type_t * type = oberon_find_type(ctx, name); + + if(type == NULL) + { + oberon_error(ctx, "undefined type"); + } + + return type; +} + +static void +oberon_var_decl(oberon_context_t * ctx) +{ + char * name = oberon_assert_ident(ctx); + oberon_assert_token(ctx, COLON); + oberon_type_t * type = oberon_type(ctx); + oberon_define_var(ctx, name, type); +} + +static void +oberon_decl_seq(oberon_context_t * ctx) +{ + if(ctx -> token == VAR) + { + oberon_assert_token(ctx, VAR); + while(ctx -> token == IDENT) + { + oberon_var_decl(ctx); + 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) + { + item -> mode = MODE_INTEGER; + item -> integer = ctx -> integer; + oberon_assert_token(ctx, INTEGER); + } + else + { + oberon_error(ctx, "invalid expression"); + } + + return item; +} + +static void +oberon_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst) +{ + if(dst -> mode == MODE_INTEGER) + { + oberon_error(ctx, "invalid assignment"); + } + + 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) + { + oberon_error(ctx, "types not matched"); + } + + // TODO: code generation + oberon_generate_assign(ctx, 0, 0, 4); +} + +static void +oberon_statement(oberon_context_t * ctx) +{ + oberon_item_t * item1; + oberon_item_t * item2; + + if(ctx -> token == IDENT) + { + item1 = oberon_expr(ctx); + oberon_assert_token(ctx, ASSIGN); + item2 = oberon_expr(ctx); + oberon_assign(ctx, item2, item1); + } +} + +static void +oberon_statement_seq(oberon_context_t * ctx) +{ + oberon_statement(ctx); + while(ctx -> token == SEMICOLON) + { + oberon_assert_token(ctx, SEMICOLON); + oberon_statement(ctx); + } +} + +static void +oberon_parse_it(oberon_context_t * ctx) +{ + char *name1, *name2; + oberon_read_token(ctx); + + oberon_assert_token(ctx, MODULE); + name1 = oberon_assert_ident(ctx); + oberon_assert_token(ctx, SEMICOLON); + ctx -> mod -> name = name1; + + oberon_decl_seq(ctx); + + if(ctx -> token == BEGIN) + { + oberon_assert_token(ctx, BEGIN); + oberon_statement_seq(ctx); + } + + oberon_assert_token(ctx, END); + name2 = oberon_assert_ident(ctx); + oberon_assert_token(ctx, DOT); + + if(strcmp(name1, name2) != 0) + { + oberon_error(ctx, "module name not matched"); + } +} + +// ======================================================================= +// LIBRARY +// ======================================================================= + +oberon_context_t * +oberon_create_context() +{ + oberon_context_t * ctx = malloc(sizeof *ctx); + memset(ctx, 0, sizeof *ctx); + + oberon_type_t * types = malloc(sizeof *types); + memset(types, 0, sizeof *types); + + ctx -> types = types; + return ctx; +} + +oberon_module_t * +oberon_compile_module(oberon_context_t * ctx, const char * code) +{ + oberon_module_t * mod = malloc(sizeof *mod); + memset(mod, 0, sizeof *mod); + oberon_var_t * vars = malloc(sizeof *vars); + memset(vars, 0, sizeof *vars); + ctx -> mod = mod; + ctx -> mod -> vars = vars; + + oberon_init_scaner(ctx, code); + oberon_parse_it(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; + + x -> next = newtype; +} diff --git a/oberon.h b/oberon.h new file mode 100644 index 0000000..7fee329 --- /dev/null +++ b/oberon.h @@ -0,0 +1,54 @@ +#ifndef EMBEDED_OBERON_SCRIPT_H +#define EMBEDED_OBERON_SCRIPT_H + +enum { + OBERON_TYPE_INTEGER, + OBERON_TYPE_BOOLEAN, +}; + +typedef struct oberon_var_s oberon_var_t; +typedef struct oberon_type_s oberon_type_t; +typedef struct oberon_module_s oberon_module_t; +typedef struct oberon_context_s oberon_context_t; + +struct oberon_type_s +{ + char * name; + int class; + int size; + oberon_type_t * next; +}; + +struct oberon_var_s +{ + char * name; + oberon_type_t * type; + oberon_var_t * next; +}; + +struct oberon_module_s +{ + char * name; + oberon_var_t * vars; +}; + +struct oberon_context_s +{ + const char * code; + int code_index; + + char c; + int token; + char * string; + int integer; + + oberon_module_t * mod; + + oberon_type_t * types; +}; + +oberon_context_t * oberon_create_context(); +void oberon_register_global_type(oberon_context_t * ctx, oberon_type_t * type); +oberon_module_t * oberon_compile_module(oberon_context_t * ctx, const char * code); + +#endif // EMBEDED_OBERON_SCRIPT_H diff --git a/test.c b/test.c new file mode 100644 index 0000000..2247eac --- /dev/null +++ b/test.c @@ -0,0 +1,28 @@ +#include "oberon.h" +#include + +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" + " i := 10;" + "END Test." +; + +static oberon_context_t * ctx; +static oberon_module_t * mod; + +int +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); + return 0; +} diff --git a/test_gcc_jit/make.sh b/test_gcc_jit/make.sh new file mode 100755 index 0000000..03ddd5b --- /dev/null +++ b/test_gcc_jit/make.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -e + +gcc -g -Wall -Werror -std=c11 -lgccjit s1.c -o s1 diff --git a/test_gcc_jit/s1 b/test_gcc_jit/s1 new file mode 100755 index 0000000000000000000000000000000000000000..143c368728b240a28050c4037cf43e46b59c26f4 GIT binary patch literal 10792 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 P+};X1R>Lj>mni-d4RO-u literal 0 HcmV?d00001 diff --git a/test_gcc_jit/s1.c b/test_gcc_jit/s1.c new file mode 100644 index 0000000..f83910e --- /dev/null +++ b/test_gcc_jit/s1.c @@ -0,0 +1,22 @@ +#include + +gcc_jit_context * ctxt; + +int +main(int argc, char **argv) +{ + ctxt = gcc_jit_context_acquire(); + + cc_jit_type * void_type = gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_VOID); + + gcc_jit_function * func = gcc_jit_context_new_function( + ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "BEGIN", 0, NULL, 0 + ); + + gcc_jit_block * block = gcc_jit_function_new_block (func, NULL); + + + + gcc_jit_context_release(ctxt); + return 0; +} -- 2.29.2