NAME

oh

SYNOPSIS

Command Line Interface:

Evaluate code:
oh e "(print :oh)"
Evaluate code and launch a REPL:
oh e "(setq oh 3)" i
Load files:
oh file.oh file2.oh
Load files and launch a REPL:
oh file1 i file2 i
Load files named i and e:
oh f i f e
Launch a REPL:
oh

Module Interface:

use Oh qw/interpret_string evaluate_element/;

my $result = interpret_string '(+ 1 2 3)';

my $same_result = evaluate_element ['+', 1, 2, 3];

INSTALLATION

cpan Oh

DESCRIPTION

The current iteration is a prototype which has to evolve.

All core concepts and implementation of this interpreter are subject to change, since this is the initial version of the interpreter.

The interpreter tries to perform lisp evaluation rules:

(function-name arg1 arg2 (function2-name arg1 arg2))

It draws inspiration from common lisp and scheme, but it's not tied to any implementation or design.

It has macros which just make the interpreter evaluate the macro and then evaluate what the macro returns.

(defmacro some-macro (some &rest args) `(some-function ,some ,@args))

It has both scheme like lambda arguments and common lisp style lambda arguments.

the operator 'macro' uses scheme like arguments instead.

(macro some-macro (some . args) `(some-function ,some ,@args))

To define functions there are also both styles:

The scheme style:

(define (fun-name x . y) (list x y))

(fun-name 1 2 3) => (1 (2 3))

The common lisp style:

(defun fun-name (x &rest y) (list x y))

(fun-name 1 2 3) => (1 (2 3))

Lambda uses cl style lambda arguments. Although lambda is just a macro using an operator to create a lambda without argument binding.

(macro lambda (args . code) `(anon (lisp-args ,args) ,@code))

We can make it use scheme style arguments by just replacing 'lisp-args' for 'scheme-args'

(macro lambda (args . code) `(anon (scheme-args ,args) ,@code))

Now lambda would use the scheme style:

((lambda x x) 1 2 3) => (1 2 3)

scheme-args and lisp-args are just operators that perform the binding on the current function environment they are evaluated in.

The interpreter when evaluates a lambda (like the ones created by the operator 'anon'), will set a symbol named 'args' in the environment of this lambda with the arguments it was given.

The operators scheme-args and lisp-args just expect a list of bindings and take the values from the args symbol to perform those bindings.

This means that other ways of argument binding can be created with just an operator, function or macro.

It also means that scheme-args and lisp-args can evolve separatedly and that we are free to choose any way to do the same thing.

Both scheme-args and lisp-args might change or disappear like any other feature of the language, since the interpreter does not have a stable release and will ask for a major rewrite soon.

The current state of the interpreter is lacking a lot of features and concepts to make it a useful language yet.

For example there is not even a way to return from a function. There is only implicit return for the last evaluated expression.

It has some interoperation with perl:

(module::perl_sub_name arg1 arg2 arg3)

This is equivalent to:

module::perl_sub_name(@_);

in perl.

To call a perl method there is 'method':

(method obj 'method_name arg1 arg2 arg3)

It is equivalent to:

my $object = some_object;

my $method = 'method_name';

$module->$method(@_);

The first argument can also be a symbol:

(method 'IO::Socket 'new 'localhost:8080)

It is equivalent to:

my $module = 'IO::Socket';

my $method = 'new';

$module->$method("localhost:8080");

There is a way to create a perl object class, since classes are just a package and packages autovivify:

(perl-defun module perl_sub_name (arg1 arg2 arg3) (do-something arg1 arg2 arg3))

That creates a perl subroutine in the package 'module' with the name 'perl_sub_name'

The created perl subroutine is:

*{$module . '::' . $name} = sub { evaluate_lambda $lambda, @_ };

Which is a perl closure retaining a lambda created by perl-sub.

perl-defun and perl-fun are just a macro:

(macro perl-fun (module name args . code) `(perl-sub ,module ,name (scheme-args ,args) ,@code)) (macro perl-defun (module name args . code) `(perl-sub ,module ,name (lisp-args ,args) ,@code))

To add inheritance use 'parent':

(parent my_module parent1 parent2 parent3)

it's actually:

push @my_module::ISA, qw/parent1 parent2 parent3/;

A better abstraction for objects and classes has to be designed.

The language does not currenly have much more than those concepts.

It is a simple core and the rest are just operators, functions and macros.

LICENSE

CC0 1.0 Universal (CC0 1.0) Public Domain Dedication

To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide.

This software is distributed without any warranty.

https://creativecommons.org/publicdomain/zero/1.0/