summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/mruby/compile.h48
-rw-r--r--src/parse.y183
-rw-r--r--test/driver.c16
-rw-r--r--tools/mirb/mirb.c42
-rw-r--r--tools/mrbc/mrbc.c4
-rw-r--r--tools/mruby/mruby.c17
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) {