1. Thoughts on eval()

I've been thinking a bit about this, and I think I see a way, although
there are a few implementation details that will have to be worked out.

I think that I'd add a new keyword, "eval", which would be a function 
taking a sequence, which is just plain text source code.  I can probably
'inject' this into the scanner/parser stream, and then put it into its
own special SubProgram to be executed.  It would probably be like having 
a separate TopLevel SubProgram, where you could do whatever, including 
defining new routines (which could be called from subsequent calls to
eval).

The function would return 1 if no [compile-time] errors happened, or 0 
if errors did happen (like perl)--run-time errors would be handled 
normally.

Obviously, use of eval() would break the preprocessor.

Matt Lewis

new topic     » topic index » view message » categorize

2. Re: Thoughts on eval()

Hey, Matt.

Have you read my previous idea? http://www.listfilter.com/EUforum/m8646.html

I think if you have func(args, text) or proc(args, text) be functions that
return a routine_id().  The functions themselves, as you say, insert their text
into the normal Code[] space after being scanned and parsed.  Then you just call
your eval'ed function with call_func(id, {}) or whatever.

I think it would require a bit of re-wiring.  My original proposal was to
overload function and procedure like integer, atom, object, and sequence are. 
Looking further into keylist.e, though, I think it would be much easier to just
add func() and proc().  It would still be consistent with call_func() and
call_proc().

example:
integer a, b, c, rid
sequence args, text

args = "integer x, integer y"
text = "return x + y"

rid = func(args, text)

a = 2
b = 2

c = call_func(rid, {a, b}) -- c is now 4


Problem would be what happens when rid no longer refers to the function?  How is
it destroyed or is it just left lost in the Code[] space?

I notice that the interpreter does a quick scan of the symbol table to try and
match a literal.  I don't know if this is normal for interpreters or compilers
but I think that it is pretty cool.  One optimization should be that func() or
proc() would return the same routine_id for a function that was already defined.

Maybe the IL code could be stored in the variable space and added and removed
from the Code[] space as needed?

Also, I realize that this would not work with RDS official backend.  Shrouded,
bound, or translated programs would need to include the proper files from the
interpreter.  Hmm.  It could probably still work with RDS backend but you would
have to include the interpreter code just for the eval-type functions.

Okay, I'm done rambling.  I just like this idea and I think that it fits pretty
good with the rest of the language.

=====================================
Too many freaks, not enough circuses.

j.

new topic     » goto parent     » topic index » view message » categorize

3. Re: Thoughts on eval()

I guess to be more robust, func() or proc() would return -1 to show an error in
parsing instead of crashing the program.  It is likely that programs would form
these anonymous functions with sprintf().


=====================================
Too many freaks, not enough circuses.

j.

new topic     » goto parent     » topic index » view message » categorize

4. Re: Thoughts on eval()

Jason Gade wrote:
> 
> Hey, Matt.
> 
> Have you read my previous idea? <a
> href="http://www.listfilter.com/EUforum/m8646.html">http://www.listfilter.com/EUforum/m8646.html</a>
> 
> I think if you have func(args, text) or proc(args, text) be functions that
> return a
> routine_id().  The functions themselves, as you say, insert their text into
> the normal
> Code[] space after being scanned and parsed.  Then you just call your eval'ed
> function
> with call_func(id, {}) or whatever.
> 
> I think it would require a bit of re-wiring.  My original proposal was to
> overload
> function and procedure like integer, atom, object, and sequence are.  Looking
> further
> into keylist.e, though, I think it would be much easier to just add func() and
> proc().
>  It would still be consistent with call_func() and call_proc().

No, I think it's easier to simply treat what's passed to eval() as more code
for euphoria to parse and execute.

> 
> example:
> }}}
<eucode>
> 
> integer a, b, c, rid
> sequence args, text
> 
> args = "integer x, integer y"
> text = "return x + y"
> 
> rid = func(args, text)
> 
> a = 2
> b = 2
> 
> c = call_func(rid, {a, b}) -- c is now 4
> 
> </eucode>
{{{

> 
> Problem would be what happens when rid no longer refers to the function?  How
> is it
> destroyed or is it just left lost in the Code[] space?

I'm not planning on removing anything from the symbol table.

> I notice that the interpreter does a quick scan of the symbol table to try and
> match
> a literal.  I don't know if this is normal for interpreters or compilers but I
> think
> that it is pretty cool.  One optimization should be that func() or proc()
> would return
> the same routine_id for a function that was already defined.

I don't know what you mean here.
 
> Maybe the IL code could be stored in the variable space and added and removed
> from
> the Code[] space as needed?

If you examine how the interpreter does things, there's really no difference
between 'Code' space and variable space.  SubPrograms (including one for
TopLevel) contain a code section.  The CurrentSub is constantly changed,
so that the interpreter executes code from different places all the time.
 
> Also, I realize that this would not work with RDS official backend.  Shrouded,
> bound,
> or translated programs would need to include the proper files from the
> interpreter.
>  Hmm.  It could probably still work with RDS backend but you would have to
>  include
> the interpreter code just for the eval-type functions.

Actually, I don't think it would work quite that simply, because there 
would be no way to touch any symbols in your program through eval(),
other than a giant, manual if-elsif that updated your variables, which
would need to be changed for each program.  

Matt Lewis

new topic     » goto parent     » topic index » view message » categorize

5. Re: Thoughts on eval()

Matt Lewis wrote:
> No, I think it's easier to simply treat what's passed to eval() as more code
> for euphoria to parse and execute.

That's exaclty what I'm saying.  Only what gets passed to eval() gets added in
to the rest of the code.

> > I notice that the interpreter does a quick scan of the symbol table to try
> > and match
> > a literal.  I don't know if this is normal for interpreters or compilers but
> > I think
> > that it is pretty cool.  One optimization should be that func() or proc()
> > would return
> > the same routine_id for a function that was already defined.
> 
> I don't know what you mean here.

It was a bit of a tangent -- nevermind.


>  
> > Maybe the IL code could be stored in the variable space and added and
> > removed from
> > the Code[] space as needed?
> 
> If you examine how the interpreter does things, there's really no difference
> between 'Code' space and variable space.  SubPrograms (including one for
> TopLevel) contain a code section.  The CurrentSub is constantly changed,
> so that the interpreter executes code from different places all the time.

Okay.  I didn't quite get that far.  From what I could see is that all the
parsed IL code went into the Code[] sequence.  Names of functions in SymTab[][]
had a field that pointed to the proper place in the Code[] sequence.  I still
don't have a full understanding of it, though.

>  
> > Also, I realize that this would not work with RDS official backend. 
> > Shrouded, bound,
> > or translated programs would need to include the proper files from the
> > interpreter.
> >  Hmm.  It could probably still work with RDS backend but you would have to
> >  include
> > the interpreter code just for the eval-type functions.
> 
> Actually, I don't think it would work quite that simply, because there 
> would be no way to touch any symbols in your program through eval(),
> other than a giant, manual if-elsif that updated your variables, which
> would need to be changed for each program.  

Good point.  It could still be used with bound/translated etc. programs but
couldn't share any symbols.  And it would be slower.

> 
> Matt Lewis
> 


=====================================
Too many freaks, not enough circuses.

j.

new topic     » goto parent     » topic index » view message » categorize

6. Re: Thoughts on eval()

Im not sure this will work but could you 'trick' the parser into thinking it
is including a file and parse it that way?

new topic     » goto parent     » topic index » view message » categorize

7. Re: Thoughts on eval()

Jason Gade wrote:
> 
> Matt Lewis wrote:
> > If you examine how the interpreter does things, there's really no difference
> > between 'Code' space and variable space.  SubPrograms (including one for
> > TopLevel) contain a code section.  The CurrentSub is constantly changed,
> > so that the interpreter executes code from different places all the time.
> 
> Okay.  I didn't quite get that far.  From what I could see is that all the
> parsed IL
> code went into the Code[] sequence.  Names of functions in SymTab[][] had a
> field that
> pointed to the proper place in the Code[] sequence.  I still don't have a full
> understanding
> of it, though.

Okay, I see now that code for subprograms is stored in SymTab[x][S_CODE] right?

So what I'm saying is that func() or proc() would add an entry to SymTab with
the proper code and return a routine id that could be used to call it.  I haven't
checked out the routine_id code yet.

I think you are saying that eval() would execute in place as if the statements
were in the top level?

=====================================
Too many freaks, not enough circuses.

j.

new topic     » goto parent     » topic index » view message » categorize

8. Re: Thoughts on eval()

Jason Gade wrote:
> 
> Jason Gade wrote:
> > 
> > Matt Lewis wrote:
> > > If you examine how the interpreter does things, there's really no
> > > difference
> > > between 'Code' space and variable space.  SubPrograms (including one for
> > > TopLevel) contain a code section.  The CurrentSub is constantly changed,
> > > so that the interpreter executes code from different places all the time.
> > 
> > Okay.  I didn't quite get that far.  From what I could see is that all the
> > parsed IL
> > code went into the Code[] sequence.  Names of functions in SymTab[][] had a
> > field that
> > pointed to the proper place in the Code[] sequence.  I still don't have a
> > full understanding
> > of it, though.
> 
> Okay, I see now that code for subprograms is stored in SymTab[x][S_CODE]
> right?
> 
> So what I'm saying is that func() or proc() would add an entry to SymTab with
> the proper
> code and return a routine id that could be used to call it.  I haven't checked
> out
> the routine_id code yet.
> 
> I think you are saying that eval() would execute in place as if the statements
> were
> in the top level?

Basically.  Except that any procedure definitions would add a SubProgram
entry into SymTab which would be callable via another eval statement.
Routine_id might or might not work on these routines--I suspect that they
won't, unless inside another eval statement, or if the original eval was
done at the toplevel, simply because they'll have been defined 'later' 
in the source.

So you could do something like:
ok = eval( "procedure foo()\nputs(1,\"foo!\,\")\nend procedure" )
ok = eval( "foo()" )
ok = eval( "rid = routine_id(\"foo\")" )
call_proc( rid, {})


Matt Lewis

new topic     » goto parent     » topic index » view message » categorize

9. Re: Thoughts on eval()

This is the type of evaluate() I prefer:

It is neccessary that it can be used with official interpreter (full speed one).
So if you wanted to use evaluate() function you would include eval.e file. (Along
with this file would come other PD source files which are required to parse,
execute the evaluate() string.)

If it crashed it would have to return crash line, column and message, same as
normal interpreter.

This evaluate would then be able to execute for example scripting (macro)
language of an application. so that this application can run at full speed with
official interpreter, and runs slow only when using evaluate().

evaluate() would for me also be very useful for debugging purposes. Now I have
to write my own scripting language (very simple one) if I want to execute
something while my program is running. I could just use evaluate().


Example:

include eval.e
Void = evaluate ("include myfile.e\nmyfunc()")

or maybe even better but more complicated:

include eval.e
p = parse ("include myfile.e\nmyfunc()")
Void = execute (p)



Matt Lewis wrote:
> 
> 
> I've been thinking a bit about this, and I think I see a way, although
> there are a few implementation details that will have to be worked out.
> 
> I think that I'd add a new keyword, "eval", which would be a function 
> taking a sequence, which is just plain text source code.  I can probably
> 'inject' this into the scanner/parser stream, and then put it into its
> own special SubProgram to be executed.  It would probably be like having 
> a separate TopLevel SubProgram, where you could do whatever, including 
> defining new routines (which could be called from subsequent calls to
> eval).
> 
> The function would return 1 if no [compile-time] errors happened, or 0 
> if errors did happen (like perl)--run-time errors would be handled 
> normally.
> 
> Obviously, use of eval() would break the preprocessor.
> 
> Matt Lewis
>

new topic     » goto parent     » topic index » view message » categorize

10. Re: Thoughts on eval()

Tone Škoda wrote:
> 
> This is the type of evaluate() I prefer:
> 
> It is neccessary that it can be used with official interpreter (full speed
> one). So
> if you wanted to use evaluate() function you would include eval.e file. (Along
> with
> this file would come other PD source files which are required to parse,
> execute the
> evaluate() string.)
> 
> If it crashed it would have to return crash line, column and message, same as
> normal
> interpreter.
> 
> This evaluate would then be able to execute for example scripting (macro)
> language
> of an application. so that this application can run at full speed with
> official interpreter,
> and runs slow only when using evaluate().
> 
> evaluate() would for me also be very useful for debugging purposes. Now I have
> to write
> my own scripting language (very simple one) if I want to execute something
> while my
> program is running. I could just use evaluate().
> 

This already exists, in the Euphoria clone that David Cuny wrote, and
I modified it to work as an embeddable scripting language.  I use it in 
my Euphoria Database Browser (euscript.e).  You just have to provide
the hooks into your app.

Matt Lewis

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu