2020-05-26 08:43:59 +00:00
|
|
|
<?php
|
2020-06-17 10:24:15 +00:00
|
|
|
require(__DIR__ . '/vendor/autoload.php');
|
2020-05-27 09:27:47 +00:00
|
|
|
|
2020-06-10 13:40:15 +00:00
|
|
|
if (php_sapi_name() != 'cli') {
|
|
|
|
exit('Currently only cli usage is supported.');
|
2020-06-06 13:12:45 +00:00
|
|
|
}
|
|
|
|
|
2020-06-17 10:24:15 +00:00
|
|
|
function ml_repl($lisp)
|
2020-06-10 13:40:15 +00:00
|
|
|
{
|
|
|
|
// Read history
|
2020-10-24 07:27:02 +00:00
|
|
|
$historyFile = $_SERVER['HOME'] . DIRECTORY_SEPARATOR . '.madlisp_history';
|
2020-06-10 13:40:15 +00:00
|
|
|
if (is_readable($historyFile)) {
|
|
|
|
readline_read_history($historyFile);
|
|
|
|
}
|
2020-05-26 08:43:59 +00:00
|
|
|
|
2020-06-10 13:40:15 +00:00
|
|
|
while (true) {
|
|
|
|
$input = readline('> ');
|
2020-05-26 08:43:59 +00:00
|
|
|
|
2020-06-10 13:40:15 +00:00
|
|
|
try {
|
2020-06-17 10:24:15 +00:00
|
|
|
$lisp->rep($input, true);
|
2020-06-10 13:40:15 +00:00
|
|
|
} catch (MadLisp\MadLispException $ex) {
|
|
|
|
print('error: ' . $ex->getMessage());
|
|
|
|
} catch (TypeError $ex) {
|
2020-12-09 00:44:47 +00:00
|
|
|
// Clean up the error message a little
|
|
|
|
if (preg_match('/must be an instance of ([^,]+), (.+) given/', $ex->getMessage(), $matches)) {
|
|
|
|
$message = 'expected ' . $matches[1] . ', ' . $matches[2] . ' given';
|
|
|
|
} elseif (preg_match('/must be of the type ([^,]+), (.+) given/', $ex->getMessage(), $matches)) {
|
|
|
|
$message = 'expected ' . $matches[1] . ', ' . $matches[2] . ' given';
|
|
|
|
} else {
|
|
|
|
$message = $ex->getMessage();
|
|
|
|
}
|
|
|
|
|
|
|
|
print('error: invalid argument type: ' . $message);
|
|
|
|
} catch (Throwable $ex) {
|
|
|
|
// Catch all other exceptions
|
|
|
|
print('error: ' . $ex->getMessage());
|
2020-06-06 13:12:45 +00:00
|
|
|
}
|
2020-06-10 13:40:15 +00:00
|
|
|
|
|
|
|
print(PHP_EOL);
|
2020-06-19 12:20:31 +00:00
|
|
|
|
|
|
|
if ($input) {
|
|
|
|
readline_add_history($input);
|
|
|
|
readline_write_history($historyFile);
|
|
|
|
}
|
2020-05-26 08:43:59 +00:00
|
|
|
}
|
2020-06-10 13:40:15 +00:00
|
|
|
}
|
|
|
|
|
2020-06-17 11:04:43 +00:00
|
|
|
// Create the Lisp interpreter
|
|
|
|
$factory = new MadLisp\LispFactory();
|
|
|
|
$lisp = $factory->make();
|
2020-06-10 13:40:15 +00:00
|
|
|
|
2020-10-24 07:27:02 +00:00
|
|
|
// Load the user's init file if present
|
|
|
|
$initfile = $_SERVER['HOME'] . DIRECTORY_SEPARATOR . '.madlisp_init';
|
|
|
|
if (is_readable($initfile)) {
|
|
|
|
$lisp->readEval("(load \"$initfile\")");
|
|
|
|
}
|
|
|
|
|
2020-06-17 11:04:43 +00:00
|
|
|
if ($argc < 2) {
|
|
|
|
// Read input from stdin
|
|
|
|
$input = file_get_contents('php://stdin');
|
|
|
|
$lisp->rep($input, false);
|
|
|
|
} elseif ($argv[1] == '-r') {
|
|
|
|
// Run the repl
|
|
|
|
ml_repl($lisp);
|
|
|
|
} elseif ($argv[1] == '-e') {
|
|
|
|
// Evaluate next argument
|
|
|
|
$lisp->rep($argv[2] ?? '', false);
|
|
|
|
} elseif ($argv[1] == '-h') {
|
|
|
|
// Show help
|
|
|
|
print("Usage:" . PHP_EOL);
|
|
|
|
print("-e <code> :: Evaluate code" . PHP_EOL);
|
|
|
|
print("-h :: Show this help" . PHP_EOL);
|
|
|
|
print("-r :: Run the interactive Repl" . PHP_EOL);
|
|
|
|
print("<filename> :: Evaluate file" . PHP_EOL);
|
|
|
|
print("<no arguments> :: Read from stdin" . PHP_EOL);
|
|
|
|
} else {
|
|
|
|
// Read file
|
|
|
|
$file = $argv[1];
|
|
|
|
if (is_readable($file)) {
|
|
|
|
$input = "(load \"$file\")";
|
2020-06-17 10:24:15 +00:00
|
|
|
$lisp->rep($input, false);
|
2020-06-10 13:40:15 +00:00
|
|
|
} else {
|
2020-06-17 11:04:43 +00:00
|
|
|
print("Unable to read file: $file\n");
|
|
|
|
exit(1); // exit with error code
|
2020-06-10 13:40:15 +00:00
|
|
|
}
|
2020-05-26 08:43:59 +00:00
|
|
|
}
|