dnmfarrell / Perl-Lox

Perl Interpreter for the Lox programming language
MIT License
2 stars 0 forks source link

Perl ⇆ Lox #1

Open tobyink opened 3 years ago

tobyink commented 3 years ago

It would be cool if you could do something like:

my $lox = Lox::Box->new;
$lox->eval(<<'DEFINITIONS');
  fun myAdd ( a, b ) {
    return a + b;
  }
DEFINITIONS
my $sum = Lox::Box->eval( 'myAdd(40, 2)' );
say $sum;   # says 42

my $same = Lox::Box->call( 'myAdd' => ( 40, 2 ) );
say $same;  # says 42
tobyink commented 3 years ago

Additionally, it would be good if from Lox, you could call Perl:

var pl = Perl();
print pl.eval("getlogin()");

Should be able to switch this ability off though, so Lox could be used as a safe sandbox.

dnmfarrell commented 3 years ago

Thanks for the cool suggestions!

For the string eval case, I've been thinking it would be nice to have state persist in the repl too, so maybe both can be done with the same change.

tobyink commented 3 years ago

From what I can tell, keeping the same Lox::Interpreter around and just sending more parsed statements to it each time should do the trick.

For what it's worth, I really like the idea of using Lox as sandboxed scripting language within Perl applications. So for example, say you wrote a webmail system in Perl, you might allow webmail users to define filters for their account like:

  if ( message.subject == "Foo" ) {
    message.forward( "foo@example.com" );
  }

That is, you could use it to give people a good scripting environment without access to things they shouldn't be dealing with (like the filesystem) and with a simple syntax.

dnmfarrell commented 3 years ago

Oh, that's a neat idea. I was toying with the idea of adding an import function which would make real coding easier. Are there other builtins that would help that use case ?

FYI the interpreter is terribly slow at the benchmarks I've tried. I haven't profiled the code to see where the bottlenecks are yet.

tobyink commented 3 years ago

For the use case I was thinking of, the useful thing would be to be able to define classes, functions, and instances in Perl and expose them to Lox. Something like:

$lox->define_function( myAdd => sub {
  my ($x, $y) = @_;
  return $x + $y;
} );
$lox->eval( 'print myAdd( 40, 2 );' );  # ==> 42

package Foo::Bar {
  use Moo;
  has 'x' => ( is => 'rwp' );
}
$lox->define_class( Bar => 'Foo::Bar' );
$lox->eval( <<'LOX' );  # ==> 666
var mybar = Bar();
mybar._set_x(666);
print mybar.x();
LOX

my $bar = Foo::Bar->new( x => 999 );
$lox->define_instance( perlbar => $bar );
$lox->eval( 'perlbar._set_x(1000)' );
say $bar->x;  # ==> 1000

This is because in my scenario, the majority of the application, like the Message object for representing an email, would be written in Perl. The objects would just be scriptable by the end user in Lox.

As for benchmarks, If you actually want it to run at a decent speed, the trick is to not interpret it but to compile it.

I am tempted to have a go at writing a cross-compiler to take $stmts and compile it into Java, Perl 5, and/or Raku. Might even be able to compile it into C, though C's object support is non-existent and needs a lot of workarounds. Been a long time since I did much work on compilers, etc, so could be a fun project.