From: DeaDDooMER Date: Mon, 24 Jul 2017 19:01:38 +0000 (+0300) Subject: Начало проекта, где-то первая неделя июля. X-Git-Url: http://deadsoftware.ru/gitweb?p=dsw-obn.git;a=commitdiff_plain;h=b752043cfbb49243ca3727dbfc9be5b614a8c9c2 Начало проекта, где-то первая неделя июля. --- b752043cfbb49243ca3727dbfc9be5b614a8c9c2 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 0000000..143c368 Binary files /dev/null and b/test_gcc_jit/s1 differ 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; +}