rb_eval_string_protect with correct error line number

P

Phlip

Rubies:

rb_eval_string_protect() calls eval(), so at error time $ERROR_POSITION ($@)
gives me a useless number. I want the line number (and preferably the column
number) of the offending part of the evaluated string.

Raw Ruby does that like this:

stwing = """
puts 'a'
puts undeclaredVariable
puts 'c'
"""

begin
eval(stwing, nil, "yo", 0)
rescue
p $@
end

That outputs ["yo:2"]

How can I get the correct error line number, using the equivalent of
eval()'s last two optional parameters, without converting my string to a
Ruby string and then calling "eval" on it?
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: rb_eval_string_protect with correct error line number"

|How can I get the correct error line number, using the equivalent of
|eval()'s last two optional parameters, without converting my string to a
|Ruby string and then calling "eval" on it?

There's no way with the current implementation. Use double eval for
the purpose.

matz.
 
P

Phlip

Yukihiro said:
|How can I get the correct error line number, using the equivalent of
|eval()'s last two optional parameters, without converting my string to a
|Ruby string and then calling "eval" on it?

There's no way with the current implementation. Use double eval for
the purpose.

I was hoping not to need to ask:

VALUE value = rb_str_new2( source );
rb_gv_set("evalMe", value);

rb_eval_string_protect("eval($evalMe, nil, 'eval', 1)", &state);

Why is that giving me a state == 6 and a rb_p(ruby_errorinfo) of "(eval)"? I
can't find the line number. rb_backtrace() ain't revealing it either.

Writing to a file and calling rb_load_protect() gives a rb_p(ruby_errorinfo)
of "embedded", similarly without a line number.
 
P

Phlip

Phlip said:
VALUE value = rb_str_new2( source );
rb_gv_set("evalMe", value);

rb_eval_string_protect("eval($evalMe, nil, 'eval', 1)", &state);

Why is that giving me a state == 6 and a rb_p(ruby_errorinfo) of "(eval)"? I
can't find the line number. rb_backtrace() ain't revealing it either.

In case nobody finds a better way, this seems to work:

rb_gv_set("$errorLineNumber", Qnil);
....

VALUE value = rb_str_new2( source );
rb_gv_set("$evalMe", value);

rb_eval_string_protect(
"begin\n"
" $errorLineNumber = nil\n"
" eval($evalMe, nil, 'eval', 1)\n"
"rescue\n"
" $errorLineNumber = $@[0].slice(5..100).to_i()\n"
" p $!\n"
" p $@\n"
" raise\n"
"end\n"
, &state);

if (state) return state;
....
VALUE errorLineNumber = rb_gv_get("$errorLineNumber");

if (errorLineNumber != Qnil) // else it's in a library or something
hard
{
int lineNo = NUM2INT(errorLineNumber);
 
P

Phlip

Phlip wrote:

This code embeds Ruby, executes a string found in 'source', and fetches any
error message:
rb_gv_set("$errorLineNumber", Qnil);
...

VALUE value = rb_str_new2( source );
rb_gv_set("$evalMe", value);

rb_eval_string_protect(
"begin\n"
" $errorLineNumber = nil\n"
" eval($evalMe, nil, 'eval', 1)\n"
"rescue\n"
" $errorLineNumber = $@[0].slice(5..100).to_i()\n"
" p $!\n"
" p $@\n"
" raise\n"
"end\n"
, &state);

if (state) return state;
...
VALUE errorLineNumber = rb_gv_get("$errorLineNumber");

if (errorLineNumber != Qnil) // else it's in a library or something
hard
{
int lineNo = NUM2INT(errorLineNumber);

Next problem: 'source' may contain free-form Ruby code, entered by a user.
If the user creates a variable 'foo', executes the code, erases 'foo', and
executes again, 'foo' still exists on the heap.

I want an error message if 'foo' no longer exists, from the user's point of
view. How do I reset Ruby back to the state before the eval() call? I tried
passing eval() a Proc.new{}, and I tried terminal functions like
ruby_prog_init(), ruby_finalize(), and ruby_cleanup(). They seem to destroy
too much.

So, how to clean up a local stack?
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: How to clean out my stack"

|So, how to clean up a local stack?

How about wrapping user code in the non-iterating block?
E.g.

loop {
..user code..
break
}

The local variables defined within a block will disappear, when the
block execution terminated.

matz.
 
P

Phlip

Yukihiro said:
In message "Re: How to clean out my stack"
|So, how to clean up a local stack?

How about wrapping user code in the non-iterating block?
E.g.

loop {
..user code..
break
}

That did it - thanks!

BTW major props for this bitchen language, holmes.

I'm writing a front-end for this:

http://flea.sourceforge.net/

Those shapes come from command sets like this:

b.tube.shorter(0.8).left.link(b)

That tells the 'b' chromosome (axiom, turtle, whatever) to draw a tube, then
get shorter, bend to the left, and recurse into itself. The result (rendered
in POVray) is a spiral.

http://flea.sourceforge.net/link_example.png

Traditionally, you write a file called something.flea, and run a command
line script to render it. I'm writing an editor to put the Flea commands
into a panel on the left, and an OpenGL output on the right. So this
requires me to embed Ruby inside this editor. I could have also written the
editor in Ruby, but I chose C++ because I'm a masochist.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,525
Members
44,997
Latest member
mileyka

Latest Threads

Top