Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Avoiding Greenspun's Rule; scripting within Perl

by rlucas (Scribe)
on Mar 20, 2012 at 18:36 UTC ( [id://960621]=perlquestion: print w/replies, xml ) Need Help??

rlucas has asked for the wisdom of the Perl Monks concerning the following question:

Brethren, I have an application for which I find myself following Greenspun's Tenth Rule.

I need a way for users to provide expressions that will be evaluated at runtime. The primary reason for this is to be able to interpolate strings based upon conditions (a sort of templating application), but another use is to provide conditional routing logic for what questions to ask next (in a survey application).

I've been down this road before; it always starts out like this in the templating part:

# OK, users can write a variable name between {} brackets: while ($text =~ m/{([^\}]*}/g ) { #do some interpolation }
And, like this in the conditional routing part:
# hardcoded operation for routing: my ($if_question, $if_answer, $then_question, $else_question) = get_ha +rdcoded_logic(); if (get_answer($if_question) eq $if_answer) { set_next($then_question); } else { set_next($else_question); }

(Now, don't get me wrong. In general, YAGNI and KISS. And if the above works, and often it does, then OK.)

However, two things tend to happen if things mature and expectations increase. First is, you discover that you need the IF/THEN logic in the variable interpolation. (You might then decide, OK, I need a template engine here, and start using Template or Mason or whatever. Or, you might decide that you should combine your interpolation system with your routing system, to simplify syntax etc.)

Second is, you discover that the IF/THEN logic isn't enough; you need negation, and nesting IFs, and boolean operators, and grouping/precedence.

So, now you find yourself basically creating abstract syntax trees with control structures, grouping, operator definition, reserved words, ... holy crap, you've just fallen prey to Greenspun's Rule (or a corollary). And meanwhile, important business requirements are falling by the wayside as you create your own interpreter within Perl.

If this were a C program, I'd think "OK, I need to embed Lua." But this is Perl, after all: a scripting language itself, the exemplar of the string eval, the ultimate hackable environment. (And, all of the objects / methods / functions that I'd want to call or use are Perl native.)

Fellow monks, what do you suggest when your Perl app requires an embedded scripting language? (E.g., Lua, Safe.pm, ???) Ideally, the solution would be amenable to syntax-checking, and would either be so safe as to be able to accept mostly arbitrary user input to the script, or would be so parseable/structured that it becomes tractable to build an interface or abstraction layer for building expressions.

Replies are listed 'Best First'.
Re: Avoiding Greenspun's Rule; scripting within Perl
by choroba (Cardinal) on Mar 20, 2012 at 18:55 UTC
Re: Avoiding Greenspun's Rule; scripting within Perl
by jandrew (Chaplain) on Mar 21, 2012 at 04:18 UTC

    At the risk of oversimplifying your issue it may be that you can solve your if-then-else parsing with dispatch tables. If this is a new concept then give it a once over. The main link is here. The Author is Mark Jason Dominus++

    If what you were really looking for is very open ended parsing of potentially diverse inputs this may not be the answer, but as Robert Morris implied even codeing in Common Lisp is suceptable to Greenspun's 10th rule.

    As a consequence the solution may be a partial abstraction of input handling (dispatch tables) in combination with putting boundaries on the scope of the input.

Re: Avoiding Greenspun's Rule; scripting within Perl
by Rhandom (Curate) on Mar 21, 2012 at 13:47 UTC
    Many projects I've been writing lately have included the ability to use Javascript via JavaScript::V8. It is cheap and it is blazingly fast and if you are a web shop then you most likely have a team that already speaks Javascript.

    I'd like to use perl as an embeded language inside of perl, but I have yet to see a safe (Safe.pm) locked down environment. Javascript isn't perfect as they could still consume all memory, or write an infinite loop, but there is no danger of it having access to more than I give it.

    my @a=qw(random brilliant braindead); print $a[rand(@a)];

      I've not used JavaScript::V8, but have used JavaScript::SpiderMonkey and JE (the latter of which is a pure Perl javascript implementation!) and find Javascript to be a good choice for this sort of thing.

      I have also taken a look at the various Perl Lua offerings (Inline::Lua, Outline::Lua, etc), but none of them have impressed me much. I can't seem to find a way to, for example, lock down Lua's file IO functions, so it doesn't seem to be useful as a sandbox. (It might be possible with Lua::API, but that module is very low level and I've not had much success with it.)

      perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
Re: Avoiding Greenspun's Rule; scripting within Perl
by Anonymous Monk on Mar 20, 2012 at 22:51 UTC
Re: Avoiding Greenspun's Rule; scripting within Perl
by jdporter (Paladin) on Mar 21, 2012 at 14:33 UTC
    • Greenspun's Tenth Rule* of Programming: "Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp."
    • Zawinski's Law of Software Envelopment: "Every program attempts to expand until it can read mail. Those programs which cannot so expand are replaced by ones which can."
    • jdporter's Conflation: "Every sufficiently complicated program includes a half-baked implementation of half of the POP (or IMAP) spec." For example: Adso.pl

    It occurs to me that GTR* (not to be confused with the GRT) has a modern corollary which involves s/Lisp/XML/. :-P

    I reckon we are the only monastery ever to have a dungeon stuffed with 16,000 zombies.

    * I wonder if it should be abbreviated "G10R". But then people might think that means "gocalizatior". </geekery>

Re: Avoiding Greenspun's Rule; scripting within Perl
by JavaFan (Canon) on Mar 22, 2012 at 12:59 UTC
    Fellow monks, what do you suggest when your Perl app requires an embedded scripting language?
    Well, Perl of course! And it's easy, all you need is an eval. ;-).

    But you don't seem to need a full blown programming language. Neither Perl, nor Lua. I'm a bit at a loss, you toss templating systems aside, because you want a simpler syntax -- and then end up looking for a Perl equivalent of embedding Lua.

    Tell me again, why aren't you opting for a templating language?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://960621]
Approved by Corion
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2024-04-18 22:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found