mirror of
https://github.com/peklaiho/madlisp.git
synced 2024-11-22 21:35:03 +00:00
161 lines
4.1 KiB
PHP
Executable File
161 lines
4.1 KiB
PHP
Executable File
#!/usr/bin/env php
|
|
<?php
|
|
|
|
$autoload = null;
|
|
foreach ([__DIR__ . '/../../autoload.php', __DIR__ . '/../vendor/autoload.php', __DIR__ . '/vendor/autoload.php'] as $file) {
|
|
if (file_exists($file)) {
|
|
$autoload = $file;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($autoload) {
|
|
require($autoload);
|
|
} else {
|
|
print('Unable to find Composer autoloader.' . PHP_EOL);
|
|
exit(1);
|
|
}
|
|
|
|
function ml_help()
|
|
{
|
|
print("Usage:" . PHP_EOL);
|
|
print("-d :: Enable debug mode" . PHP_EOL);
|
|
print("-e <code> :: Evaluate code" . PHP_EOL);
|
|
print("-h :: Show this help" . PHP_EOL);
|
|
print("-q :: Skip the init file" . PHP_EOL);
|
|
print("-r :: Run the interactive REPL" . PHP_EOL);
|
|
print("<file> :: Evaluate file" . PHP_EOL);
|
|
print(" :: Read from stdin" . PHP_EOL);
|
|
exit(0);
|
|
}
|
|
|
|
function ml_repl($lisp)
|
|
{
|
|
// Read history
|
|
$historyFile = $_SERVER['HOME'] . DIRECTORY_SEPARATOR . '.madlisp_history';
|
|
if (is_readable($historyFile)) {
|
|
readline_read_history($historyFile);
|
|
}
|
|
|
|
while (true) {
|
|
$input = readline('> ');
|
|
|
|
try {
|
|
$lisp->rep($input, true);
|
|
} catch (MadLisp\MadLispUserException $ex) {
|
|
print('error: ');
|
|
$lisp->print($ex->getValue(), true);
|
|
} catch (MadLisp\MadLispException $ex) {
|
|
print('error: ' . $ex->getMessage());
|
|
} catch (TypeError $ex) {
|
|
// 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());
|
|
}
|
|
|
|
print(PHP_EOL);
|
|
|
|
if ($input) {
|
|
readline_add_history($input);
|
|
readline_write_history($historyFile);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Parse command line arguments
|
|
$debugMode = false;
|
|
$evalCode = null;
|
|
$loadInit = true;
|
|
$runRepl = false;
|
|
$filename = null;
|
|
$lastArg = null;
|
|
|
|
// Arguments after -- are passed to the script
|
|
$dividerFound = false;
|
|
$passedArgs = [];
|
|
|
|
for ($i = 1; $i < $argc; $i++) {
|
|
$a = $argv[$i];
|
|
|
|
if ($dividerFound) {
|
|
$passedArgs[] = $a;
|
|
} elseif ($a == '--') {
|
|
$dividerFound = true;
|
|
} elseif ($a == '-d') {
|
|
$debugMode = true;
|
|
} elseif ($a == '-e') {
|
|
|
|
} elseif ($a == '-h' || $a == '--help') {
|
|
ml_help(); // exit
|
|
} elseif ($a == '-q') {
|
|
$loadInit = false;
|
|
} elseif ($a == '-r') {
|
|
$runRepl = true;
|
|
} else {
|
|
if ($lastArg == '-e') {
|
|
$evalCode = $a;
|
|
} else {
|
|
$filename = $a;
|
|
}
|
|
}
|
|
|
|
$lastArg = $a;
|
|
}
|
|
|
|
// Create the Lisp interpreter
|
|
$factory = new MadLisp\LispFactory();
|
|
$lisp = $factory->make();
|
|
|
|
// Pass command line arguments
|
|
$lisp->setEnvValue('argc', count($passedArgs));
|
|
$lisp->setEnvValue('argv', new MadLisp\Vector($passedArgs));
|
|
|
|
// Load the user's init file if present
|
|
if ($loadInit) {
|
|
$initfile = $_SERVER['HOME'] . DIRECTORY_SEPARATOR . '.madlisp_init';
|
|
if (is_readable($initfile)) {
|
|
$lisp->readEval("(load \"$initfile\")");
|
|
}
|
|
}
|
|
|
|
// Enable debug mode if requested
|
|
if ($debugMode) {
|
|
$lisp->setDebug(true);
|
|
}
|
|
|
|
// Eval code passed via -e
|
|
if ($evalCode) {
|
|
$lisp->rep($evalCode, false);
|
|
}
|
|
|
|
// Eval file
|
|
if ($filename) {
|
|
if (is_readable($filename)) {
|
|
$lisp->rep("(load \"$filename\")", false);
|
|
} else {
|
|
print("Unable to read file: $filename" . PHP_EOL);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
// Run REPL
|
|
if ($runRepl) {
|
|
ml_repl($lisp);
|
|
}
|
|
|
|
// Finally, if we had no other actions, read input from stdin
|
|
if (!$evalCode && !$filename) {
|
|
$input = file_get_contents('php://stdin');
|
|
$lisp->rep($input, false);
|
|
}
|