1. Thoughts on eval()
- Posted by Matt Lewis <matthewwalkerlewis at yahoo.com> Dec 14, 2004
- 538 views
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
2. Re: Thoughts on eval()
- Posted by Jason Gade <jaygade at yahoo.com> Dec 14, 2004
- 516 views
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.
3. Re: Thoughts on eval()
- Posted by Jason Gade <jaygade at yahoo.com> Dec 14, 2004
- 530 views
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.
4. Re: Thoughts on eval()
- Posted by Matt Lewis <matthewwalkerlewis at yahoo.com> Dec 14, 2004
- 555 views
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
5. Re: Thoughts on eval()
- Posted by Jason Gade <jaygade at yahoo.com> Dec 14, 2004
- 510 views
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.
6. Re: Thoughts on eval()
- Posted by "Alex Chamberlain" <alex at ear26.freeserve.co.uk> Dec 14, 2004
- 491 views
Im not sure this will work but could you 'trick' the parser into thinking it is including a file and parse it that way?
7. Re: Thoughts on eval()
- Posted by Jason Gade <jaygade at yahoo.com> Dec 14, 2004
- 496 views
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.
8. Re: Thoughts on eval()
- Posted by Matt Lewis <matthewwalkerlewis at yahoo.com> Dec 14, 2004
- 513 views
- Last edited Dec 15, 2004
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
9. Re: Thoughts on eval()
- Posted by Tone Škoda <tskoda at email.si> Dec 14, 2004
- 514 views
- Last edited Dec 15, 2004
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 >
10. Re: Thoughts on eval()
- Posted by Matt Lewis <matthewwalkerlewis at yahoo.com> Dec 15, 2004
- 522 views
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