1. Suggested enhancement

I had previously made a suggestion for something equivalent to
  BASIC's "CHAIN" statement; several people gave some quite
  useful suggestions as to how roughly equivalent functionality
  could be implemented.  I have been using them, with acceptable
  results (though I still think a CHAIN would be marginally
  better).

  Today, however, inspiration walked up behind me and whacked me
  upside the head with a two-by-four, which leads to an Idea
  that I think, if implemented, would be quite a nifty (dare I
  say "elegant") enhancement to Euphoria:

  Allow a procedure/function call "execute" (or something along
  those lines) which takes a sequence of characters forming
  valid Euphoria statements, and returns whatever executing
  those statements results in - or nothing at all, if there's no
  return value in the statements.  This would allow:

  1. A CHAIN facility - read a Euphoria program text into the
           variable foo, then "execute(foo)".

  2. A macro facility for any Euphoria program - let the user
           define macros using Euphoria, and any interface that
           the program author feels is best for the purpose,
           then "execute(macrovariable)".

  3. A procedural parameter capability - you could write highly
           generic routines without needing to redefine
           procedures or functions for (for example)
           comparisons. "function sort(fooseq, compareproc) ...
           if execute(compareproc) = -1 then ..."

  4. A dynamic code facility - since "includes" are idempotent,
           and cannot be done except at the absolute top level
           of the program, there's no simple way of defining
           what gets done "on the fly" such that you can have
           the Euphoria-knowledgeable user instruct you as to
           how to handle unforseen situations, and be able to
           implement those solutions immediately (i.e., without
           shutting down and restarting the program).
           "while 1 do ... userproc = ... execute(userproc) ..."

  Comments?  Questions?  Discussion?

 =========================================================================
Jeff Zeitlin                                      jeff.zeitlin at execnet.com
---
 ~ OLXWin 1.00b ~ I have seen the future and it is now the past.

new topic     » topic index » view message » categorize

2. Re: Suggested enhancement

JEFF ZEITLIN wrote:
>   Allow a procedure/function call "execute" (or something along
>   those lines) which takes a sequence of characters forming
>   valid Euphoria statements, and returns whatever executing
>   those statements results in - or nothing at all, if there's no
>   return value in the statements.

I have used a program language/environment called "MUMPS" which provided
this functionality. It allows your code to write code, a really
interesting feature, eh? I just thought I'd let everybody know that this
can be/has been done before.

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

3. Re: Suggested enhancement

On Thu, 16 Jan 1997, John DeHope wrote:

> I have used a program language/environment called "MUMPS" which provided
> this functionality. It allows your code to write code, a really
> interesting feature, eh? I just thought I'd let everybody know that this
> can be/has been done before.
>
That's be great!  I can just let my games write new games and I can take a
vacation!  When's that new version coming out? =)


Michael Packard
Lord Generic Productions
lgp at exo.com http://exo.com/~lgp
A Crash Course in Game Design and Production
http://exo.com/~lgp/euphoria

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

4. Re: Suggested enhancement

On Thu, 16 Jan 1997, John DeHope wrote:

> JEFF ZEITLIN wrote:
> >   Allow a procedure/function call "execute" (or something along
> >   those lines) which takes a sequence of characters forming
> >   valid Euphoria statements, and returns whatever executing
> >   those statements results in - or nothing at all, if there's no
> >   return value in the statements.
>
> I have used a program language/environment called "MUMPS" which provided
> this functionality. It allows your code to write code, a really
> interesting feature, eh? I just thought I'd let everybody know that this
> can be/has been done before.

It was also done in the BBC Microcomputer's BASIC. The command EVAL() let
you enter a string comprising any mathematical function available on the
computer, (including established variables) and returned the result.

e.g.
A = 17: B = 42: C = EVAL("SQR(B - A)")

and C would be set to 5.

It looks like I'm gonna be around for a while..., :)

Carl

--
Carl R White    | e-mail...:                     crwhite at comp.brad.ac.uk
                | finger...:              crwhite at dcsun1.comp.brad.ac.uk
                | web......: http://www.student.comp.brad.ac.uk/~crwhite

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

5. Re: Suggested enhancement

> It was also done in the BBC Microcomputer's BASIC. The command EVAL() let
> you enter a string comprising any mathematical function available on the
> computer, (including established variables) and returned the result.
>
> e.g.
> A = 17: B = 42: C = EVAL("SQR(B - A)")
>
> and C would be set to 5.

<nothing-to-do-with-euphoria>

LISP does that too, lest anyone forget, as well as some variants of LPC, the
programming language that powers some kinds of MUDs and the Roxen httpd.
The Amylaar version specifically has a structure called a "closure" that
can be written up by the routine on the fly. And, in the totally obscure
category, an old COMPUTE!'s Gazette utility called "Smart VAL" lets the VAL()
function on Commodore 64 BASIC 2.0 act identically to the example above.

</nothing-to-do-with-euphoria>

Cameron Kaiser
http://www.sserv.com/
spectre at sserv.com

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

6. Re: Suggested enhancement

JEFF ZEITLIN suggested:

>   Allow a procedure/function call "execute" (or something along
>   those lines) which takes a sequence of characters forming
>   valid Euphoria statements, and returns whatever executing
>   those statements results in - or nothing at all, if there's no
>   return value in the statements.  This would allow:
>
>   1. A CHAIN facility - read a Euphoria program text into the
>            variable foo, then "execute(foo)".

  If the his would add powerful tools, especially for an array of
functions.
  ie.
        function calculate ( number1, number2, operator )
                VirtualMachine = { "add", "subtract", "multiply",
"divide" }
                foo = VirtualMachine[operator] & "(number1, number2)"
                return execute(foo)   --ie execute( "add(number1,
number2)" )
        end function


>
>   2. A macro facility for any Euphoria program - let the user
>            define macros using Euphoria, and any interface that
>            the program author feels is best for the purpose,
>            then "execute(macrovariable)".
>
>   3. A procedural parameter capability - you could write highly
>            generic routines without needing to redefine
>            procedures or functions for (for example)
>            comparisons. "function sort(fooseq, compareproc) ...
>            if execute(compareproc) = -1 then ..."

  I don't understand this one.

>
>   4. A dynamic code facility - since "includes" are idempotent,
>            and cannot be done except at the absolute top level
>            of the program, there's no simple way of defining
>            what gets done "on the fly" such that you can have
>            the Euphoria-knowledgeable user instruct you as to
>            how to handle unforseen situations, and be able to
>            implement those solutions immediately (i.e., without
>            shutting down and restarting the program).
>            "while 1 do ... userproc = ... execute(userproc) ..."

  This is exactly what i want.
  Especially if the imported procedures could be stored in a precompiled
  form, with necessary stubs to slot right in, fast...
    and of course could recieve paramters and return.

  And if they could call imported procedures, then you'd need some
method
  to avoid infinte regression and overflowing the stack, etc.
  I'd favour a system variable that let you set the size of the stack,
and
  whether the overflow would exit the program or be a 'soft error' that
ended
  the function, returning a NULL or somesuch.

  I'd like to know more how the interpreter works, does it create
  bytecode ??  Can that bytecode be loaded on the fly.

  If these are too much, then can i have this...
        The "switch to" statement (a specialized version of Case,
stripped for
speed)

   switch to variable {
        code for variable = 0;    -- seperated by semi-colons
        code for variable = 1;
          ...
        code for variable = n;
        }
        code for else  -- optional, handles variable <> 0 - n
   end switch

   multiple lines of code

  ie.
        function VirtualMachine ( OPCODE var1 )
                switch to OPCODE {
                        Stack = {} ;
                        Stack = Stack & Heap[ var1 ] ;
                        Heap[ var1 ] = Stack[ length(Stack) ] ;
                        Stack = Stack[ 1 ... length(Stack) - 1 ] ;
                          ... etc ..
                        }
                end switch
        end function


-banjo

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

7. Re: Suggested enhancement

David Cuny wrote (I received this via private mail - I think it
probably meant to go to the list)...

A::>Jeff Zeitlin suggested being able to pass a sequence of Euphoria code to
 ::>Euphoria.

A::>Sounds like a good suggestion. The biggest problem I can think of would be
 ::>when an error occured, how would you know *where* it occured?

 Well, the ex.err dump would show that it happened on an EXECUTE
 statement/function, and would dump the variables.  One of the
 dumped variables would be the executed code - so you would at
 least be able to pin it down by that much.  If it wasn't passed
 as a variable, there wouldn't be a lot of code to desk check;
 it's unlikely in the extreme that one would write more than
 about a line of code this way - and I can't think of any real
 reason why someone would want to do so, rather than just
 writing it directly into the program.  Wait, yes I can, but
 there's still not going to be much code.

 In the case where it happens in a large chunk of code in a
 variable, I think it might depend on how it is actually
 implemented; if I were doing this, I would most likely make it
 a "back door" to the parser and interpreter routines - much
 like JPSoftware did when they added the %@EXEC[] function to
 4DOS.  There would be a small performance hit for EXECUTEd
 code, but...  Anyway, I see no reason why the ex.err report
 couldn't at least print the offending statement "in EXECUTE
 parameter" - for example

program.ex:41
attempt to divide by 0 in "? 1/0" in EXECUTE parameter

Global & Local Variables

...etc.

A::>If Robert doesn't want to put this together, one of the list members would
 ::>certainly be able to write this. Obviously, there would be a performance hit
 ::>taken if it were coded in Euphoria, but it is doable.

 Certainly it is - but you'd have to write both the parser _and_
 the interpreter, and if you wanted access to Euphoria's
 debugging facilities, you'd have to write the debugger and
 trace facilities as well.  We'd be talking _major_ performance
 hit; it might be acceptable if the language you're parsing
 isn't Euphoria and isn't easily translatable into Euphoria -
 but I doubt that many people would find it so.  One of the
 major benefits of Euphoria, IMO, is that it is _fast_ and
 _compact_ - enough so to impress the Borland that wrote the
 original Turbo Pascal.  I don't think that my EXECUTE proposal
 would slow it down into the realm of most language
 interpreters; one would gain the flexibility of a LISP
 interpreter without having to sacrifice the simplicity or a
 significant portion of the speed of Euphoria.

A::>Euphoria itself certainly has an interesting parser, and is lazy when it
 ::>comes to parsing lines. For example, I can have the line:

A::>    puts( {}, 1 }

A::>and Euphoria parses it happily, only paying attention to the number of
 ::>arguments (and whether any arguments require parameters), and not attempting
 ::>any further validation until the line is actually run.

 Interesting - I would have expected that the built-ins, at
 least, would have at least as strong type-checking as the
 user-written routines.  OTOH, that might have made it
 unacceptably difficult to permit overriding of those routines
 with user code.

A::>Also, the 'end' keyword is not part of the language. For example, if you try
 ::>to run the following code:

A::>    end

A::>you don't get an "unmatched end" error, you get an "unknown command". I get
 ::>the feeling that each of the structure have their own parsing routines, that
 ::>scan the input until they find a matching "end" clause.

 Possibly - it's certainly how I would think to do it...

A::>The biggest problem in coding a Euphoria parser in Euphoria is the lack of
 ::>forward declarations.

 I'm not sure I perceive why forward declarations would be
 necessary - would you be willing to elucidate?

 =========================================================================
Jeff Zeitlin                                      jeff.zeitlin at execnet.com
---
 ~ OLXWin 1.00b ~ ..... Help!, The TD has fallen and it can't get up!

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

8. Re: Suggested enhancement

Jeff Zeitlin wrote:

> I'm not sure I perceive why forward declarations would be
> necessary - would you be willing to elucidate?

In most cases you can do the same job as a mutual recursion does if you just
rewrite the algorithm, but this can be difficult and makes the code hard to
read. The reason why this matters so much for parsers is that parser algorithms
are naturally mutually recursive, since their grammar form (EBNF, context-free
grammar or syntax diagram) is by definition mutually recursive. As regards to
efficiency, a good grammar-based parser (by this I mean the grammar is
"factored non-left-recursive") is practically as efficient as a non-mutually
recursive parser. Check any good text on compiler construction for details.

> 3. A procedural parameter capability - you could write highly
>           generic routines without needing to redefine
>           procedures or functions for (for example) [cut]

This is the best proposed enhancement to Euphoria I've heard till now...
Wish I had come with it ;)! I believe it's possible to embed this feature
into the language in one of two different ways, so to keep type-safety:

  1. Allow fully general procedure/function parameters types, for example,
     a function that sorts an arbitrary sequence of objects in some user-defined
     order would have as header

        function sort (sequence nonsorted, function less_eq(object a, object b))

     or something similar. The trouble with this approach is that the
     proc/fun parameters could have their own proc/fun parameters. This makes
     for a difficult interpreter implementation, and considerable execution
     overheads if used extensively. The type-checking issues are also very
     difficult to deal with, unless one restricts the allowed types of the
     proc/fun's arguments. All this is due to the more complex calling mechanism
     and the possibility of having a proc/fun argument reference its static
     context (non local variables known only to itself) when it is called
     inside the routine it was passed to.

  2. Allow restricted procedure/function parameter types, such that their
     argument is just an "object", not another proc/fun. This would put all
     the effort of type-consistency in the programmer's hands, in a way much
     like the type idea of Euphoria, so it fits nicely in that scheme.

I believe 2 would be the best choice for the enhancement. I'm not sure having
dynamic run-time macro facilities would be an advisable idea. Just think
all the parsing, type-checking and precompiling that will happen with all
those macros moving around the program... Cameron Kaiser mentioned the
possibility of using closures, but the implementation of closures is very
expensive both in time and space...

Somebody suggested the idea of having proc/fun types could be useful for
having sequences of proc/funs (sorry, I can't find the exact reference between
the lots of e-mails here). This is very difficult to have in Euphoria, since
you would be able to put type incompatible functions in the same list, and
then sometime later call the functions stored in the list. This obviously
requires a lot of type information to be mantained besides those functions
in the sequence (this is called a "descriptor"). Managing all that type info
would be difficult, and there is also needed information about the static
context of all those functions. This mandatory dynamic type checking would
cause a significant overhead to the execution time, too.

In short, I believe the idea of restricted proc/fun argument types would be
a great thing to have, but it shouldn't be as general as the mentioned
features for efficiency problems would arise.

-----------------------------
Carlos Gonzalia,
Universidad Nacional del Sur
Bahia Blanca, Argentina.
gonzalia at criba.edu.ar
-----------------------------

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

Search



Quick Links

User menu

Not signed in.

Misc Menu