blob: 9ef6e51c5386e661da1934e06451193a72aa03ed [file] [log] [blame]
library petitparser.example.lispshell;
import 'dart:io';
import 'dart:async';
import 'dart:convert';
import 'package:petitparser/petitparser.dart';
import 'package:petitparser/lisp.dart';
/// Read, evaluate, print loop.
void evalInteractive(Parser parser, Environment env, Stream<String> input,
IOSink output, IOSink error) {
output.write('>> ');
input.listen((String line) {
try {
output.writeln('=> ${evalString(parser, env, line)}');
} on ParserError catch (exception) {
error.writeln('Parser error: ' + exception.toString());
} on Error catch (exception) {
error.writeln(exception.toString());
}
output.write('>> ');
});
}
/// Entry point for the command line interpreter.
void main(List<String> arguments) {
// default options
var standardLibrary = true;
var interactiveMode = false;
var files = new List();
// parse arguments
for (var option in arguments) {
if (option.startsWith('-') && files.isEmpty) {
if (option == '-n') {
standardLibrary = false;
} else if (option == '-i') {
interactiveMode = true;
} else if (option == '-?') {
print('${Platform.executable} lisp.dart -n -i [files]');
print(' -i enforces the interactive mode');
print(' -n does not load the standard library');
exit(0);
} else {
print('Unknown option: $option');
exit(1);
}
} else {
var file = new File(option);
if (file.existsSync()) {
files.add(file);
} else {
print('File not found: $option');
exit(2);
}
}
}
// evaluation context
var environment = Natives.import(new Environment());
// add additional primitives
environment.define(new Name('exit'), (env, args) => exit(args == null ? 0 : args.head));
environment.define(new Name('sleep'), (env, args) => sleep(new Duration(milliseconds: args.head)));
// process standard library
if (standardLibrary) {
environment = Standard.import(environment.create());
}
// create empty context
environment = environment.create();
// process files given as argument
files.forEach((file) {
evalString(lispParser, environment, file.readAsStringSync());
});
// process console input
if (interactiveMode || files.isEmpty) {
var input = stdin
.transform(SYSTEM_ENCODING.decoder)
.transform(new LineSplitter());
evalInteractive(lispParser, environment, input, stdout, stderr);
}
}