Class: Proc
- Defined in:
- lib/internal/proc/as_code.rb,
lib/internal/proc/signature.rb,
lib/internal/proc/as_expression.rb
Direct Known Subclasses
Defined Under Namespace
Class Method Summary collapse
-
.load(str) ⇒ UnboundProc
Load a Proc from a String.
Instance Method Summary collapse
-
#push(anotherProc) ⇒ self
Append the body of anotherProc onto proc.
-
#dump(limit) ⇒ String
Dump a Proc to a String.
-
#argument_info ⇒ Object
Return a hash mapping each argument name to a description of that argument.
-
#arguments ⇒ Object
Return an Arguments object representing the arguments in the order in which they appear in the argument list.
-
#as_code(indent = 0) ⇒ Object
Return a string representation of a proc’s definition/body, similarly to Method#as_code.
-
#as_expression ⇒ Object
Return a single-line string representation of a proc’s definition/body, similarly to Method#as_expression.
-
#body ⇒ Node
Returns the Proc’s body Node.
-
#has_rest_arg ⇒ Object
Return true if the proc has a rest arg.
-
#push(anotherProc) ⇒ self
Append the body of anotherProc onto proc.
-
#signature ⇒ Object
Return a String representing the method’s signature.
-
#unbind ⇒ UnboundProc
Create an UnboundProc from a Proc.
-
#var ⇒ Node
Returns the Proc’s argument Node.
Class Method Details
.load(str) ⇒ UnboundProc
Load a Proc from a String. When it is loaded, it will be an UnboundProc, until it is bound to a Binding with UnboundProc#bind.
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'ext/internal/proc/proc.c', line 200
static VALUE proc_load(VALUE klass, VALUE str)
{
#ifdef RUBY_VM
VALUE iseq = marshal_load(str);
return create_proc(rb_cUnboundProc, Qnil, iseq_check(iseq));
#else
VALUE arr = marshal_load(str);
NODE * body, * var;
if( rb_safe_level() >= 4
|| (rb_safe_level() >= 1 && OBJ_TAINTED(str)))
{
/* no playing with knives in the sandbox */
rb_raise(rb_eSecurityError, "Insecure: can't load proc");
}
Check_Type(arr, T_ARRAY);
body = unwrap_node(RARRAY_PTR(arr)[0]);
var = unwrap_node(RARRAY_PTR(arr)[1]);
return create_proc(rb_cUnboundProc, Qnil, body, var);
#endif
}
|
Instance Method Details
#push(anotherProc) ⇒ self
Append the body of anotherProc onto proc.
251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'ext/internal/proc/proc.c', line 251
static VALUE proc_push(VALUE self, VALUE other)
{
#ifdef RUBY_VM
rb_raise(rb_eRuntimeError, "Proc#push not implemented yet for YARV");
#else
struct BLOCK * b1;
struct BLOCK * b2;
Data_Get_Struct(self, struct BLOCK, b1);
Data_Get_Struct(other, struct BLOCK, b2);
b1->body = NEW_NODE(NODE_BLOCK, b1->body, 0, b2->body);
return self;
#endif
}
|
#dump(limit) ⇒ String
Dump a Proc to a String.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'ext/internal/proc/proc.c', line 125
static VALUE proc_dump(VALUE self, VALUE limit)
{
if(rb_safe_level() >= 4)
{
/* no access to potentially sensitive data from the sandbox */
rb_raise(rb_eSecurityError, "Insecure: can't dump proc");
}
{
#ifdef RUBY_VM
rb_proc_t * p;
VALUE iseq, str;
rb_iseq_t * iseqdat;
GetProcPtr(self, p);
iseq = p->block.iseq->self;
iseqdat = iseq_check(iseq);
iseqdat->type = ISEQ_TYPE_TOP; /* TODO: is this right? */
str = marshal_dump(iseq, limit);
return str;
#else
struct BLOCK * b;
VALUE body, var, arr;
Data_Get_Struct(self, struct BLOCK, b);
body = wrap_node(b->body);
var = wrap_node(b->var);
arr = rb_assoc_new(body, var);
return marshal_dump(arr, limit);
#endif
}
}
|
#argument_info ⇒ Object
Return a hash mapping each argument name to a description of that argument.
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/internal/proc/signature.rb', line 133 def argument_info args = self.arguments() info = {} args.each do |name| info[name] = name.to_s end # Rest arg if args.rest_arg then rest_name = args[args.rest_arg] if rest_name then info[rest_name] = "*#{rest_name}" end end return info end |
#arguments ⇒ Object
Return an Arguments object representing the arguments in the order in which they appear in the argument list.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/internal/proc/signature.rb', line 66 def arguments has_rest_arg = self.has_rest_arg if self.respond_to?(:var) then # pre-YARV case self.var when Node::DASGN_CURR return Arguments.new([ self.var.vid ], false, has_rest_arg ? 0 : nil) when Node::MASGN if self.var.head then a = self.var.head.to_a args = a.map { |n| n.vid } else args = [] end if self.var.args then args.push(self.var.args.vid) end return Arguments.new(args, true, has_rest_arg ? args.size - 1: nil) when nil return Arguments.new(nil, false, has_rest_arg ? 0 : nil) when Fixnum return Arguments.new([], false, has_rest_arg ? 0 : nil) else raise "Unexpected node type: #{self.var.class}" end elsif # YARV iseq = self.body local_vars = iseq.local_table has_rest_arg = iseq.arg_rest != -1 has_block_arg = iseq.arg_block != -1 num_args = \ iseq.argc + \ iseq.arg_opt_table.size + \ (has_rest_arg ? 1 : 0) + \ (has_block_arg ? 1 : 0) names = local_vars[0...num_args] # TODO: masgn return Arguments.new(names, true, has_rest_arg ? -1 : nil) else return Arguments.new(nil, false, nil) end end |
#as_code(indent = 0) ⇒ Object
Return a string representation of a proc’s definition/body, similarly to Method#as_code.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/internal/proc/as_code.rb', line 8 def as_code(indent=0) sig = self.signature body_expression = self.body ? self.body.as_code(indent+1) : nil s = "#{' '*indent}proc do" if not sig.args.unspecified then s += " #{sig}" end s += "\n" if body_expression then s += "#{body_expression}\n" end s += "#{' '*indent}end" return s end |
#as_expression ⇒ Object
Return a single-line string representation of a proc’s definition/body, similarly to Method#as_expression.
8 9 10 11 12 13 14 |
# File 'lib/internal/proc/as_expression.rb', line 8 def as_expression sig = self.signature body_expression = self.body ? self.body.as_expression : nil s = sig.args.unspecified ? "" : sig.to_s + ' ' b = body_expression ? body_expression + ' ' : '' return "proc { #{s}#{b}}" end |
#body ⇒ Node
Returns the Proc’s body Node.
On YARV, this will return the instruction sequence for the proc’s block.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'ext/internal/proc/proc.c', line 44
static VALUE proc_body(VALUE self)
{
#ifdef RUBY_VM
rb_proc_t * p;
GetProcPtr(self, p);
return p->block.iseq->self;
#else
struct BLOCK * b;
if(rb_safe_level() >= 4)
{
/* no access to potentially sensitive data from the sandbox */
rb_raise(rb_eSecurityError, "Insecure: can't get proc body");
}
Data_Get_Struct(self, struct BLOCK, b);
return wrap_node(b->body);
#endif
}
|
#has_rest_arg ⇒ Object
Return true if the proc has a rest arg
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/internal/proc/signature.rb', line 112 def has_rest_arg if self.respond_to?(:var) then # pre-YARV has_rest_arg = false if self.var then if self.var.class == Node::MASGN then if self.var.args then has_rest_arg = true end end end else # YARV rest = self.body.arg_rest has_rest_arg = (rest >= 0 ? rest - 1 : nil) end return has_rest_arg end |
#push(anotherProc) ⇒ self
Append the body of anotherProc onto proc.
251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'ext/internal/proc/proc.c', line 251
static VALUE proc_push(VALUE self, VALUE other)
{
#ifdef RUBY_VM
rb_raise(rb_eRuntimeError, "Proc#push not implemented yet for YARV");
#else
struct BLOCK * b1;
struct BLOCK * b2;
Data_Get_Struct(self, struct BLOCK, b1);
Data_Get_Struct(other, struct BLOCK, b2);
b1->body = NEW_NODE(NODE_BLOCK, b1->body, 0, b2->body);
return self;
#endif
}
|
#signature ⇒ Object
Return a String representing the method’s signature.
178 179 180 181 182 |
# File 'lib/internal/proc/signature.rb', line 178 def signature return Signature.new( arguments(), argument_info) end |
#unbind ⇒ UnboundProc
Create an UnboundProc from a Proc.
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'ext/internal/proc/proc.c', line 229
static VALUE proc_unbind(VALUE self)
{
#ifdef RUBY_VM
rb_proc_t * p;
GetProcPtr(self, p);
return create_proc(rb_cUnboundProc, Qnil, p->block.iseq);
#else
struct BLOCK * b;
Data_Get_Struct(self, struct BLOCK, b);
/* no need for a security check to unbind a proc -- though without the
* ability to bind, this doesn't seem very useful.
*/
return create_proc(rb_cUnboundProc, Qnil, b->body, b->var);
#endif
}
|
#var ⇒ Node
Returns the Proc’s argument Node.
This method is undefined on YARV.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'ext/internal/proc/proc.c', line 71
static VALUE proc_var(VALUE self)
{
struct BLOCK * b;
if(rb_safe_level() >= 4)
{
/* no access to potentially sensitive data from the sandbox */
rb_raise(rb_eSecurityError, "Insecure: can't get proc var");
}
Data_Get_Struct(self, struct BLOCK, b);
if(b->var == (NODE*)1)
{
/* no parameter || */
return INT2NUM(1);
}
else if(b->var == (NODE*)2)
{
/* also no params, but I'm not sure how this one gets generated */
return INT2NUM(2);
}
else
{
return wrap_node(b->var);
}
}
|