summaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-09-23 07:49:45 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-09-23 07:49:45 +0000
commit7f7834abf738ab26236bea159fce7f37dea03f1f (patch)
tree1e92b71304d4cb6f6a37bee6b74d659ea43a5aad /compile.c
parent0867b94cb9ec890d608beaa4d100a33508867727 (diff)
* include/ruby/node.h, vm_core.h: move definition of
RUBY_VM_METHOD_NODE to node.h. * class.c, common.mk: remove useless inclusion. * compile.h, iseq.h, vm_core.h: rename compile.h to iseq.h. move some definitions from vm_core.h to iseq.h. * compile.c, iseq.c, vm.c: ditto. * eval.c, compile.c: move some functions for parser from eval.c to compile.c. * eval_intern.h, vm_core.h: move va_init_list() macro to vm_core.h. * iseq.c (rb_iseq_new_top, rb_iseq_first_lineno): added. * load.c, ruby.c: use rb_iseq_new_top() instead of rb_iseq_new() with ISEQ_TYPE_TOP constant directly. * proc.c: use rb_iseq_first_lineno() instead of accessing iseq structure. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19472 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c291
1 files changed, 279 insertions, 12 deletions
diff --git a/compile.c b/compile.c
index 41d1a9247f..8e8decbe96 100644
--- a/compile.c
+++ b/compile.c
@@ -14,21 +14,10 @@
#define USE_INSN_STACK_INCREASE 1
#include "vm_core.h"
-#include "compile.h"
+#include "iseq.h"
#include "insns.inc"
#include "insns_info.inc"
-#ifdef HAVE_STDARG_PROTOTYPES
-#include <stdarg.h>
-#define va_init_list(a,b) va_start(a,b)
-#else
-#include <varargs.h>
-#define va_init_list(a,b) va_start(a)
-#endif
-
-VALUE iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt);
-
-/* types */
typedef struct iseq_link_element {
enum {
@@ -82,6 +71,232 @@ struct iseq_compile_data_ensure_node_stack {
struct ensure_range *erange;
};
+/**
+ * debug function(macro) interface depend on CPDEBUG
+ * if it is less than 0, runtime option is in effect.
+ *
+ * debug level:
+ * 0: no debug output
+ * 1: show node type
+ * 2: show node important parameters
+ * ...
+ * 5: show other parameters
+ * 10: show every AST array
+ */
+
+#ifndef CPDEBUG
+#define CPDEBUG 0
+#endif
+
+#if CPDEBUG >= 0
+#define compile_debug CPDEBUG
+#else
+#define compile_debug iseq->compile_data->option->debug_level
+#endif
+
+NORETURN(PRINTF_ARGS(void rb_compile_bug(const char*, int, const char*, ...), 3, 4));
+
+#if CPDEBUG
+
+#define compile_debug_print_indent(level) \
+ ruby_debug_print_indent(level, compile_debug, gl_node_level * 2)
+
+#define debugp(header, value) (void) \
+ (compile_debug_print_indent(1) && \
+ ruby_debug_print_value(1, compile_debug, header, value))
+
+#define debugi(header, id) (void) \
+ (compile_debug_print_indent(1) && \
+ ruby_debug_print_id(1, compile_debug, header, id))
+
+#define debugp_param(header, value) (void) \
+ (compile_debug_print_indent(1) && \
+ ruby_debug_print_value(1, compile_debug, header, value))
+
+#define debugp_verbose(header, value) (void) \
+ (compile_debug_print_indent(2) && \
+ ruby_debug_print_value(2, compile_debug, header, value))
+
+#define debugp_verbose_node(header, value) (void) \
+ (compile_debug_print_indent(10) && \
+ ruby_debug_print_value(10, compile_debug, header, value))
+
+#define debug_node_start(node) ((void) \
+ (compile_debug_print_indent(1) && \
+ (ruby_debug_print_node(1, CPDEBUG, "", (NODE *)node), gl_node_level)), \
+ gl_node_level++)
+
+#define debug_node_end() gl_node_level --;
+
+#else
+
+static inline ID
+r_id(ID id)
+{
+ return id;
+}
+
+static inline VALUE
+r_value(VALUE value)
+{
+ return value;
+}
+
+#define debugi(header, id) r_id(id)
+#define debugp(header, value) r_value(value)
+#define debugp_verbose(header, value) r_value(value)
+#define debugp_verbose_node(header, value) r_value(value)
+#define debugp_param(header, value) r_value(value)
+#define debug_node_start(node) ((void)0)
+#define debug_node_end() ((void)0)
+#endif
+
+#if CPDEBUG > 1 || CPDEBUG < 0
+PRINTF_ARGS(void ruby_debug_printf(const char*, ...), 1, 2);
+#define debugs if (compile_debug_print_indent(1)) ruby_debug_printf
+#define debug_compile(msg, v) ((void)(compile_debug_print_indent(1) && fputs(msg, stderr)), (v))
+#else
+#define debugs if(0)printf
+#define debug_compile(msg, v) (v)
+#endif
+
+
+/* create new label */
+#define NEW_LABEL(l) new_label_body(iseq, l)
+
+#define iseq_filename(iseq) \
+ (((rb_iseq_t*)DATA_PTR(iseq))->filename)
+
+#define NEW_ISEQVAL(node, name, type) \
+ new_child_iseq(iseq, node, name, 0, type)
+
+#define NEW_CHILD_ISEQVAL(node, name, type) \
+ new_child_iseq(iseq, node, name, iseq->self, type)
+
+#define NEW_SPECIAQL_BLOCK_ISEQVAL(iseq, sym) \
+ new_child_iseq(iseq, iseq->node, iseq->name, iseq->parent_iseq, iseq->type, sym)
+
+/* add instructions */
+#define ADD_SEQ(seq1, seq2) \
+ APPEND_LIST(seq1, seq2)
+
+/* add an instruction */
+#define ADD_INSN(seq, line, insn) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, line, BIN(insn), 0))
+
+/* add an instruction with label operand */
+#define ADD_INSNL(seq, line, insn, label) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) \
+ new_insn_body(iseq, line, BIN(insn), 1, (VALUE)label))
+
+/* add an instruction with some operands (1, 2, 3, 5) */
+#define ADD_INSN1(seq, line, insn, op1) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) \
+ new_insn_body(iseq, line, BIN(insn), 1, (VALUE)op1))
+
+#define ADD_INSN2(seq, line, insn, op1, op2) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) \
+ new_insn_body(iseq, line, BIN(insn), 2, (VALUE)op1, (VALUE)op2))
+
+#define ADD_INSN3(seq, line, insn, op1, op2, op3) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) \
+ new_insn_body(iseq, line, BIN(insn), 3, (VALUE)op1, (VALUE)op2, (VALUE)op3))
+
+/* Specific Insn factory */
+#define ADD_SEND(seq, line, id, argc) \
+ ADD_SEND_R(seq, line, id, argc, (VALUE)Qfalse, (VALUE)INT2FIX(0))
+
+#define ADD_CALL_RECEIVER(seq, line) \
+ ADD_INSN(seq, line, putnil)
+
+#define ADD_CALL(seq, line, id, argc) \
+ ADD_SEND_R(seq, line, id, argc, (VALUE)Qfalse, (VALUE)INT2FIX(VM_CALL_FCALL_BIT))
+
+#define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block) \
+ ADD_SEND_R(seq, line, id, argc, block, (VALUE)INT2FIX(VM_CALL_FCALL_BIT))
+
+#define ADD_SEND_R(seq, line, id, argc, block, flag) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) \
+ new_insn_send(iseq, line, \
+ (VALUE)id, (VALUE)argc, (VALUE)block, (VALUE)flag))
+
+#define ADD_TRACE(seq, line, event) \
+ do { \
+ if ((event) == RUBY_EVENT_LINE && iseq->coverage && \
+ RARRAY_PTR(iseq->coverage)[(line) - 1] == Qnil) { \
+ RARRAY_PTR(iseq->coverage)[(line) - 1] = INT2FIX(0); \
+ ADD_INSN1(seq, line, trace, INT2FIX(RUBY_EVENT_COVERAGE)); \
+ } \
+ if (iseq->compile_data->option->trace_instruction) { \
+ ADD_INSN1(seq, line, trace, INT2FIX(event)); \
+ } \
+ }while(0);
+
+/* add label */
+#define ADD_LABEL(seq, label) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) label)
+
+#define ADD_ADJUST(seq, line, label) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) new_adjust_body(iseq, label, line))
+
+#define ADD_ADJUST_RESTORE(seq, label) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) new_adjust_body(iseq, label, -1))
+
+#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) \
+ (rb_ary_push(iseq->compile_data->catch_table_ary, \
+ rb_ary_new3(5, type, \
+ (VALUE)(ls) | 1, (VALUE)(le) | 1, \
+ iseqv, (VALUE)(lc) | 1)))
+
+/* compile node */
+#define COMPILE(anchor, desc, node) \
+ (debug_compile("== " desc "\n", \
+ iseq_compile_each(iseq, anchor, node, 0)))
+
+/* compile node, this node's value will be poped */
+#define COMPILE_POPED(anchor, desc, node) \
+ (debug_compile("== " desc "\n", \
+ iseq_compile_each(iseq, anchor, node, 1)))
+
+/* compile node, which is poped when 'poped' is true */
+#define COMPILE_(anchor, desc, node, poped) \
+ (debug_compile("== " desc "\n", \
+ iseq_compile_each(iseq, anchor, node, poped)))
+
+#define OPERAND_AT(insn, idx) \
+ (((INSN*)(insn))->operands[idx])
+
+#define INSN_OF(insn) \
+ (((INSN*)(insn))->insn_id)
+
+/* error */
+#define COMPILE_ERROR(strs) \
+{ \
+ VALUE tmp = GET_THREAD()->errinfo; \
+ if (compile_debug) rb_compile_bug strs; \
+ GET_THREAD()->errinfo = iseq->compile_data->err_info; \
+ rb_compile_error strs; \
+ iseq->compile_data->err_info = GET_THREAD()->errinfo; \
+ GET_THREAD()->errinfo = tmp; \
+ ret = 0; \
+ break; \
+}
+
+#define ERROR_ARGS ruby_sourcefile, nd_line(node),
+
+
+#define COMPILE_OK 1
+#define COMPILE_NG 0
+
+
+/* leave name uninitialized so that compiler warn if INIT_ANCHOR is
+ * missing */
+#define DECL_ANCHOR(name) \
+ LINK_ANCHOR *name, name##_body__ = {{0,},}
+#define INIT_ANCHOR(name) \
+ (name##_body__.last = &name##_body__.anchor, name = &name##_body__)
+
+
#include "optinsn.inc"
#if OPT_INSTRUCTIONS_UNIFICATION
#include "optunifs.inc"
@@ -5051,3 +5266,55 @@ iseq_build_from_ary(rb_iseq_t *iseq, VALUE locals, VALUE args,
iseq_build_body(iseq, anchor, body, labels_table);
return iseq->self;
}
+
+/* for parser */
+
+int
+rb_dvar_defined(ID id)
+{
+ rb_thread_t *th = GET_THREAD();
+ rb_iseq_t *iseq;
+ if (th->base_block && (iseq = th->base_block->iseq)) {
+ while (iseq->type == ISEQ_TYPE_BLOCK ||
+ iseq->type == ISEQ_TYPE_RESCUE ||
+ iseq->type == ISEQ_TYPE_ENSURE ||
+ iseq->type == ISEQ_TYPE_EVAL) {
+ int i;
+
+ for (i = 0; i < iseq->local_table_size; i++) {
+ if (iseq->local_table[i] == id) {
+ return 1;
+ }
+ }
+ iseq = iseq->parent_iseq;
+ }
+ }
+ return 0;
+}
+
+int
+rb_local_defined(ID id)
+{
+ rb_thread_t *th = GET_THREAD();
+ rb_iseq_t *iseq;
+
+ if (th->base_block && th->base_block->iseq) {
+ int i;
+ iseq = th->base_block->iseq->local_iseq;
+
+ for (i=0; i<iseq->local_table_size; i++) {
+ if (iseq->local_table[i] == id) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+int
+rb_parse_in_eval(void)
+{
+ return GET_THREAD()->parse_in_eval != 0;
+}
+
+