diff options
| -rw-r--r-- | include/mruby/compile.h | 48 | ||||
| -rw-r--r-- | src/parse.y | 183 | ||||
| -rw-r--r-- | test/driver.c | 16 | ||||
| -rw-r--r-- | tools/mirb/mirb.c | 42 | ||||
| -rw-r--r-- | tools/mrbc/mrbc.c | 4 | ||||
| -rw-r--r-- | tools/mruby/mruby.c | 17 |
6 files changed, 199 insertions, 111 deletions
diff --git a/include/mruby/compile.h b/include/mruby/compile.h index b41eed57e..42820896e 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -14,13 +14,27 @@ extern "C" { #include "mruby.h" #include <stdio.h> #include <setjmp.h> +#include <stdio.h> + +/* load context */ +typedef struct mrbc_context { + mrb_sym *syms; + int slen; + char *filename; + int lineno; + int capture_errors:1; +} mrbc_context; + +mrbc_context* mrbc_context_new(mrb_state *mrb); +void mrbc_context_free(mrb_state *mrb, mrbc_context *cxt); +const char *mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s); +/* AST node structure */ typedef struct mrb_ast_node { struct mrb_ast_node *car, *cdr; } mrb_ast_node; -#include <stdio.h> - +/* lexer states */ enum mrb_lex_state_enum { EXPR_BEG, /* ignore newline, +/- is a sign. */ EXPR_END, /* newline significant, +/- is an operator. */ @@ -36,21 +50,23 @@ enum mrb_lex_state_enum { EXPR_MAX_STATE }; +/* saved error message */ struct mrb_parser_message { int lineno; int column; char* message; }; +/* parser structure */ struct mrb_parser_state { mrb_state *mrb; struct mrb_pool *pool; mrb_ast_node *cells; const char *s, *send; FILE *f; + char *filename; int lineno; int column; - const char *filename; enum mrb_lex_state_enum lstate; int sterm; @@ -59,6 +75,8 @@ struct mrb_parser_state { unsigned int cmdarg_stack; int paren_nest; int lpar_beg; + int in_def, in_single, cmd_start; + mrb_ast_node *locals; mrb_ast_node *pb; char buf[1024]; @@ -66,9 +84,6 @@ struct mrb_parser_state { mrb_ast_node *heredoc; - int in_def, in_single, cmd_start; - mrb_ast_node *locals; - void *ylval; int nerr; @@ -82,21 +97,24 @@ struct mrb_parser_state { jmp_buf jmp; }; -/* parser structure */ struct mrb_parser_state* mrb_parser_new(mrb_state*); +void mrb_parser_free(struct mrb_parser_state*); const char *mrb_parser_filename(struct mrb_parser_state*, const char*); -int mrb_parser_lineno(struct mrb_parser_state*, int); -void mrb_parser_parse(struct mrb_parser_state*); +void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*); /* utility functions */ -struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*); -struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*); -struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,size_t); +struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*); +struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*); +struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,int,mrbc_context*); int mrb_generate_code(mrb_state*, mrb_ast_node*); -int mrb_compile_file(mrb_state*,FILE*); -int mrb_compile_string(mrb_state*,char*); -int mrb_compile_nstring(mrb_state*,char*,size_t); +/* program load functions */ +mrb_value mrb_load_file(mrb_state*,FILE*); +mrb_value mrb_load_string(mrb_state *mrb, const char *path); +mrb_value mrb_load_nstring(mrb_state *mrb, const char *path, int len); +mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt); +mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *path, mrbc_context *cxt); +mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *path, int len, mrbc_context *cxt); #if defined(__cplusplus) } /* extern "C" { */ diff --git a/src/parse.y b/src/parse.y index af8b93cfa..2b69ac726 100644 --- a/src/parse.y +++ b/src/parse.y @@ -20,6 +20,7 @@ #include "mruby.h" #include "mruby/compile.h" +#include "mruby/proc.h" #include "node.h" #include "st.h" @@ -686,7 +687,7 @@ new_float(parser_state *p, const char *s) // (:str . (s . len)) static node* -new_str(parser_state *p, const char *s, size_t len) +new_str(parser_state *p, const char *s, int len) { return cons((node*)NODE_STR, cons((node*)strndup(s, len), (node*)len)); } @@ -2961,7 +2962,7 @@ static void yyerror(parser_state *p, const char *s) { char* c; - size_t n; + int n; if (! p->capture_errors) { if (p->filename) { @@ -2995,7 +2996,7 @@ static void yywarn(parser_state *p, const char *s) { char* c; - size_t n; + int n; if (! p->capture_errors) { if (p->filename) { @@ -4668,8 +4669,45 @@ yylex(void *lval, parser_state *p) return t; } +static void +parser_init_cxt(parser_state *p, mrbc_context *cxt) +{ + if (!cxt) return; + if (cxt->lineno) p->lineno = cxt->lineno; + if (cxt->filename) p->filename = cxt->filename; + if (cxt->syms) { + int len = cxt->slen; + + p->locals = cons(0,0); + while (len--) { + local_add_f(p, cxt->syms[len]); + } + } + p->capture_errors = cxt->capture_errors; +} + +static void +parser_update_cxt(parser_state *p, mrbc_context *cxt) +{ + node *n, *n0; + int i = 0; + + if (!cxt) return; + if ((int)p->tree->car != NODE_SCOPE) return; + n0 = n = p->tree->cdr->car; + while (n) { + i++; + n = n->cdr; + } + cxt->syms = mrb_realloc(p->mrb, cxt->syms, i*sizeof(mrb_sym)); + cxt->slen = i; + for (i=0, n=n0; n; i++,n=n->cdr) { + cxt->syms[i] = (mrb_sym)n->car; + } +} + void -mrb_parser_parse(parser_state *p) +mrb_parser_parse(parser_state *p, mrbc_context *c) { node *tree; @@ -4685,6 +4723,7 @@ mrb_parser_parse(parser_state *p) p->nerr = p->nwarn = 0; p->sterm = 0; + parser_init_cxt(p, c); yyparse(p); tree = p->tree; if (!tree) { @@ -4696,9 +4735,7 @@ mrb_parser_parse(parser_state *p) } } else { - if ((intptr_t)tree->car == NODE_SCOPE) { - p->locals = cons(tree->cdr->car, 0); - } + parser_update_cxt(p, c); if (p->begin_tree) { tree = new_begin(p, p->begin_tree); append(tree, p->tree); @@ -4729,7 +4766,6 @@ mrb_parser_new(mrb_state *mrb) p->in_def = p->in_single = FALSE; p->capture_errors = 0; - p->lineno = 1; p->column = 0; #if defined(PARSER_TEST) || defined(PARSER_DEBUG) @@ -4739,28 +4775,46 @@ mrb_parser_new(mrb_state *mrb) return p; } -const char* -mrb_parser_filename(parser_state *p, const char *s) +void +mrb_parser_free(parser_state *p) { + mrb_pool_close(p->pool); +} + +mrbc_context* +mrbc_context_new(mrb_state *mrb) { - if (s) { - p->filename = strdup(s); - } - return p->filename; + mrbc_context *c; + + c = mrb_malloc(mrb, sizeof(mrbc_context)); + memset(c, 0, sizeof(mrbc_context)); + return c; } -int -mrb_parser_lineno(struct mrb_parser_state *p, int n) +void +mrbc_context_free(mrb_state *mrb, mrbc_context *cxt) +{ + mrb_free(mrb, cxt->syms); + mrb_free(mrb, cxt->filename); + mrb_free(mrb, cxt); +} + +const char* +mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s) { - if (n <= 0) { - return p->lineno; + if (s) { + int len = strlen(s); + char *p = mrb_malloc(mrb, len); + + memcpy(p, s, len); + if (c->filename) mrb_free(mrb, c->filename); + c->filename = p; + c->lineno = 1; } - p->column = 0; - p->lineno = n; - return n; + return c->filename; } parser_state* -mrb_parse_file(mrb_state *mrb, FILE *f) +mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c) { parser_state *p; @@ -4769,12 +4823,12 @@ mrb_parse_file(mrb_state *mrb, FILE *f) p->s = p->send = NULL; p->f = f; - mrb_parser_parse(p); + mrb_parser_parse(p, c); return p; } parser_state* -mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len) +mrb_parse_nstring(mrb_state *mrb, const char *s, int len, mrbc_context *c) { parser_state *p; @@ -4783,56 +4837,81 @@ mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len) p->s = s; p->send = s + len; - mrb_parser_parse(p); + mrb_parser_parse(p, c); return p; } parser_state* -mrb_parse_string(mrb_state *mrb, const char *s) +mrb_parse_string(mrb_state *mrb, const char *s, mrbc_context *c) { - return mrb_parse_nstring(mrb, s, strlen(s)); + return mrb_parse_nstring(mrb, s, strlen(s), c); } -void parser_dump(mrb_state *mrb, node *tree, int offset); - -int -mrb_compile_file(mrb_state * mrb, FILE *f) +static mrb_value +load_exec(mrb_state *mrb, parser_state *p) { - parser_state *p; int n; - p = mrb_parse_file(mrb, f); - if (!p) return -1; - if (!p->tree) return -1; - if (p->nerr) return -1; + if (!p) { + mrb_parser_free(p); + return mrb_nil_value(); + } + if (p->capture_errors && (!p->tree || p->nerr)) { + char buf[256]; + + n = snprintf(buf, sizeof(buf), "line %d: %s\n", + p->error_buffer[0].lineno, p->error_buffer[0].message); + mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n)); + mrb_parser_free(p); + return mrb_nil_value(); + } n = mrb_generate_code(mrb, p->tree); - mrb_pool_close(p->pool); + mrb_parser_free(p); + if (n < 0) { + mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SCRIPT_ERROR, "codegen error", 13)); + return mrb_nil_value(); + } + return mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb)); +} - return n; +mrb_value +mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c) +{ + return load_exec(mrb, mrb_parse_file(mrb, f, c)); } -int -mrb_compile_nstring(mrb_state *mrb, char *s, size_t len) +mrb_value +mrb_load_file(mrb_state *mrb, FILE *f) { - parser_state *p; - int n; + return mrb_load_file_cxt(mrb, f, NULL); +} - p = mrb_parse_nstring(mrb, s, len); - if (!p) return -1; - if (!p->tree) return -1; - if (p->nerr) return -1; - n = mrb_generate_code(mrb, p->tree); - mrb_pool_close(p->pool); +mrb_value +mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *c) +{ + return load_exec(mrb, mrb_parse_nstring(mrb, s, len, c)); +} - return n; +mrb_value +mrb_load_nstring(mrb_state *mrb, const char *s, int len) +{ + return mrb_load_nstring_cxt(mrb, s, len, NULL); } -int -mrb_compile_string(mrb_state *mrb, char *s) +mrb_value +mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *c) +{ + return load_exec(mrb, mrb_parse_nstring(mrb, s, strlen(s), c)); +} + +mrb_value +mrb_load_string(mrb_state *mrb, const char *s) { - return mrb_compile_nstring(mrb, s, strlen(s)); + return mrb_load_string_cxt(mrb, s, NULL); } +void parser_dump(mrb_state *mrb, node *tree, int offset); + static void dump_prefix(int offset) { diff --git a/test/driver.c b/test/driver.c index 6b42d025b..4fe58432d 100644 --- a/test/driver.c +++ b/test/driver.c @@ -26,10 +26,8 @@ void print_hint(void) int main(void) { - struct mrb_parser_state *parser; mrb_state *mrb; mrb_value return_value; - int byte_code; const char *prog = "report()"; print_hint(); @@ -42,16 +40,8 @@ main(void) } mrb_init_mrbtest(mrb); - parser = mrb_parse_nstring(mrb, prog, strlen(prog)); - - /* generate bytecode */ - byte_code = mrb_generate_code(mrb, parser->tree); - - /* evaluate the bytecode */ - return_value = mrb_run(mrb, - /* pass a proc for evaulation */ - mrb_proc_new(mrb, mrb->irep[byte_code]), - mrb_top_self(mrb)); + /* evaluate the test */ + return_value = mrb_load_string(mrb, prog); /* did an exception occur? */ if (mrb->exc) { mrb_p(mrb, return_value); @@ -62,5 +52,5 @@ main(void) } mrb_close(mrb); - return 0; + return EXIT_SUCCESS; } diff --git a/tools/mirb/mirb.c b/tools/mirb/mirb.c index 35558acfb..8b36cb5a6 100644 --- a/tools/mirb/mirb.c +++ b/tools/mirb/mirb.c @@ -132,23 +132,24 @@ main(void) { char last_char, ruby_code[1024], last_code_line[1024]; int char_index; + mrbc_context *cxt; struct mrb_parser_state *parser; - mrb_state *mrb_interpreter; - mrb_value mrb_return_value; - int byte_code; + mrb_state *mrb; + mrb_value result; + int n; int code_block_open = FALSE; print_hint(); /* new interpreter instance */ - mrb_interpreter = mrb_open(); - if (mrb_interpreter == NULL) { - fprintf(stderr, "Invalid mrb_interpreter, exiting mirb"); + mrb = mrb_open(); + if (mrb == NULL) { + fprintf(stderr, "Invalid mrb interpreter, exiting mirb"); return EXIT_FAILURE; } - /* new parser instance */ - parser = mrb_parser_new(mrb_interpreter); + cxt = mrbc_context_new(mrb); + cxt->capture_errors = 1; memset(ruby_code, 0, sizeof(*ruby_code)); memset(last_code_line, 0, sizeof(*last_code_line)); @@ -192,11 +193,11 @@ main(void) } /* parse code */ + parser = mrb_parser_new(mrb); parser->s = ruby_code; parser->send = ruby_code + strlen(ruby_code); - parser->capture_errors = 1; parser->lineno = 1; - mrb_parser_parse(parser); + mrb_parser_parse(parser, cxt); code_block_open = is_code_block_open(parser); if (code_block_open) { @@ -209,31 +210,32 @@ main(void) } else { /* generate bytecode */ - byte_code = mrb_generate_code(mrb_interpreter, parser->tree); + n = mrb_generate_code(mrb, parser->tree); /* evaluate the bytecode */ - mrb_return_value = mrb_run(mrb_interpreter, + result = mrb_run(mrb, /* pass a proc for evaulation */ - mrb_proc_new(mrb_interpreter, mrb_interpreter->irep[byte_code]), - mrb_top_self(mrb_interpreter)); + mrb_proc_new(mrb, mrb->irep[n]), + mrb_top_self(mrb)); /* did an exception occur? */ - if (mrb_interpreter->exc) { - mrb_p(mrb_interpreter, mrb_obj_value(mrb_interpreter->exc)); - mrb_interpreter->exc = 0; + if (mrb->exc) { + mrb_p(mrb, mrb_obj_value(mrb->exc)); + mrb->exc = 0; } else { /* no */ printf(" => "); - mrb_p(mrb_interpreter, mrb_return_value); + mrb_p(mrb, result); } } - memset(ruby_code, 0, sizeof(*ruby_code)); memset(ruby_code, 0, sizeof(*last_code_line)); } + mrb_parser_free(parser); } } - mrb_close(mrb_interpreter); + mrbc_context_free(mrb, cxt); + mrb_close(mrb); return 0; } diff --git a/tools/mrbc/mrbc.c b/tools/mrbc/mrbc.c index 99fea76d8..55e2fcf32 100644 --- a/tools/mrbc/mrbc.c +++ b/tools/mrbc/mrbc.c @@ -172,7 +172,7 @@ main(int argc, char **argv) return n; } - p = mrb_parse_file(mrb, args.rfp); + p = mrb_parse_file(mrb, args.rfp, NULL); if (!p || !p->tree || p->nerr) { cleanup(&args); mrb_close(mrb); @@ -183,7 +183,7 @@ main(int argc, char **argv) parser_dump(mrb, p->tree, 0); n = mrb_generate_code(mrb, p->tree); - mrb_pool_close(p->pool); + mrb_parser_free(p); if (args.verbose) codedump_all(mrb, n); diff --git a/tools/mruby/mruby.c b/tools/mruby/mruby.c index 5cf3d8a37..3628e79c9 100644 --- a/tools/mruby/mruby.c +++ b/tools/mruby/mruby.c @@ -165,17 +165,16 @@ main(int argc, char **argv) n = mrb_load_irep(mrb, args.rfp); } else { + mrbc_context *c = mrbc_context_new(mrb); if (args.cmdline) { - p = mrb_parse_string(mrb, (char*)args.cmdline); - } + mrbc_filename(mrb, c, "-e"); + p = mrb_parse_string(mrb, (char*)args.cmdline, c); + } else { - p = mrb_parser_new(mrb); - if (p) { - mrb_parser_filename(p, argv[1]); - p->f = args.rfp; - mrb_parser_parse(p); - } + mrbc_filename(mrb, c, argv[1]); + p = mrb_parse_file(mrb, args.rfp, c); } + mrbc_context_free(mrb, c); if (!p || !p->tree || p->nerr) { cleanup(mrb, &args); return -1; @@ -185,7 +184,7 @@ main(int argc, char **argv) parser_dump(mrb, p->tree, 0); n = mrb_generate_code(mrb, p->tree); - mrb_pool_close(p->pool); + mrb_parser_free(p); } if (n >= 0) { |
