Add full support for comments in MOROS Lisp (#489)

* Add full support for Lisp comments

* Update changelog

* Update doc
This commit is contained in:
Vincent Ollivier 2023-05-24 23:20:54 +02:00 committed by GitHub
parent 4e46f39433
commit 9c850e108b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 58 additions and 64 deletions

View File

@ -1,6 +1,7 @@
# Changelog
## Unreleased
- Add full support for comments in lisp (#489)
- Add parenthesis matching to editor (#488)
- Upgrade smoltcp from 0.8.2 to 0.9.1 (#484)
- Update rust to nightly-2022-12-21 (#485)

View File

@ -187,3 +187,4 @@ Rewrite parts of the code and add new functions and examples.
### 0.5.0 (unpublished)
- Rename or add aliases to many functions
- Add full support for line and inline comments

View File

@ -1,6 +1,5 @@
use super::{Err, Exp, Env, Function};
use super::{Err, Exp, Env, Function, parse_eval};
use super::env::{env_get, env_set, function_env};
use super::parse::parse;
use super::expand::expand;
use super::string;
@ -130,15 +129,13 @@ fn eval_do_args(args: &[Exp], env: &mut Rc<RefCell<Env>>) -> Result<Exp, Err> {
fn eval_load_args(args: &[Exp], env: &mut Rc<RefCell<Env>>) -> Result<Exp, Err> {
ensure_length_eq!(args, 1);
let path = string(&args[0])?;
let mut code = fs::read_to_string(&path).or(Err(Err::Reason("Could not read file".to_string())))?;
let mut input = fs::read_to_string(&path).or(Err(Err::Reason(format!("File not found '{}'", path))))?;
loop {
let (rest, exp) = parse(&code)?;
let exp = expand(&exp, env)?;
eval(&exp, env)?;
let (rest, _) = parse_eval(&input, env)?;
if rest.is_empty() {
break;
}
code = rest;
input = rest;
}
Ok(Exp::Bool(true))
}

View File

@ -182,16 +182,11 @@ pub fn byte(exp: &Exp) -> Result<u8, Err> {
// REPL
fn parse_eval(exp: &str, env: &mut Rc<RefCell<Env>>) -> Result<Exp, Err> {
let (_, exp) = parse(exp)?;
fn parse_eval(input: &str, env: &mut Rc<RefCell<Env>>) -> Result<(String, Exp), Err> {
let (rest, exp) = parse(input)?;
let exp = expand(&exp, env)?;
let exp = eval(&exp, env)?;
Ok(exp)
}
fn strip_comments(s: &str) -> String {
// FIXME: This doesn't handle `#` inside a string
s.split('#').next().unwrap().into()
Ok((rest, exp))
}
fn lisp_completer(line: &str) -> Vec<String> {
@ -221,33 +216,29 @@ fn repl(env: &mut Rc<RefCell<Env>>) -> Result<(), ExitCode> {
prompt.history.load(history_file);
prompt.completion.set(&lisp_completer);
while let Some(line) = prompt.input(&prompt_string) {
if line == "(quit)" {
while let Some(input) = prompt.input(&prompt_string) {
if input == "(quit)" {
break;
}
if line.is_empty() {
if input.is_empty() {
println!();
continue;
}
match parse_eval(&line, env) {
Ok(res) => {
println!("{}\n", res);
match parse_eval(&input, env) {
Ok((_, exp)) => {
println!("{}\n", exp);
}
Err(e) => match e {
Err::Reason(msg) => println!("{}Error:{} {}\n", csi_error, csi_reset, msg),
},
}
prompt.history.add(&line);
prompt.history.add(&input);
prompt.history.save(history_file);
}
Ok(())
}
pub fn main(args: &[&str]) -> Result<(), ExitCode> {
let line_color = Style::color("Yellow");
let error_color = Style::color("LightRed");
let reset = Style::reset();
let env = &mut default_env();
// Store args in env
@ -269,37 +260,27 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
if args[1] == "-h" || args[1] == "--help" {
return help();
}
let pathname = args[1];
if let Ok(code) = api::fs::read_to_string(pathname) {
let mut block = String::new();
let mut opened = 0;
let mut closed = 0;
for (i, line) in code.split('\n').enumerate() {
let line = strip_comments(line);
if !line.is_empty() {
opened += line.matches('(').count();
closed += line.matches(')').count();
block.push_str(&line);
if closed >= opened {
if let Err(e) = parse_eval(&block, env) {
match e {
Err::Reason(msg) => {
eprintln!("{}Error:{} {}", error_color, reset, msg);
eprintln!();
eprintln!(" {}{}:{} {}", line_color, i, reset, line);
return Err(ExitCode::Failure);
}
}
let path = args[1];
if let Ok(mut input) = api::fs::read_to_string(path) {
loop {
match parse_eval(&input, env) {
Ok((rest, _)) => {
if rest.is_empty() {
break;
}
block.clear();
opened = 0;
closed = 0;
input = rest;
}
Err(Err::Reason(msg)) => {
let csi_error = Style::color("LightRed");
let csi_reset = Style::reset();
eprintln!("{}Error:{} {}", csi_error, csi_reset, msg);
return Err(ExitCode::Failure);
}
}
}
Ok(())
} else {
error!("File not found '{}'", pathname);
error!("File not found '{}'", path);
Err(ExitCode::Failure)
}
}
@ -320,7 +301,7 @@ fn test_lisp() {
macro_rules! eval {
($e:expr) => {
format!("{}", parse_eval($e, env).unwrap())
format!("{}", parse_eval($e, env).unwrap().1)
};
}

View File

@ -4,6 +4,7 @@ use alloc::string::String;
use alloc::string::ToString;
use alloc::vec;
use nom::Err::Error;
use nom::IResult;
use nom::branch::alt;
use nom::bytes::complete::escaped_transform;
@ -91,7 +92,15 @@ fn parse_quasiquote(input: &str) -> IResult<&str, Exp> {
Ok((input, Exp::List(list)))
}
use nom::sequence::pair;
use alloc::format;
fn parse_comment(input: &str) -> IResult<&str, ()> {
value((), pair(char('#'), is_not("\n")))(input)
}
fn parse_exp(input: &str) -> IResult<&str, Exp> {
let (input, _) = opt(parse_comment)(input)?;
delimited(multispace0, alt((
parse_num, parse_bool, parse_str, parse_list, parse_quote, parse_quasiquote, parse_unquote_splice, parse_unquote, parse_splice, parse_sym
)), multispace0)(input)
@ -100,6 +109,10 @@ fn parse_exp(input: &str) -> IResult<&str, Exp> {
pub fn parse(input: &str)-> Result<(String, Exp), Err> {
match parse_exp(input) {
Ok((input, exp)) => Ok((input.to_string(), exp)),
Err(_) => Err(Err::Reason("Could not parse input".to_string())),
Err(Error(err)) if !err.input.is_empty() => {
let line = err.input.lines().next().unwrap();
Err(Err::Reason(format!("Could not parse '{}'", line)))
}
_ => Err(Err::Reason(format!("Could not parse input"))),
}
}

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<title>MOROS Calculator</title>
<link rel="stylesheet" type="text/css" href="/moros.css">
<link rel="stylesheet" type="text/css" href="moros.css">
</head>
<body>
<h1>MOROS Calculator</h1>

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<title>MOROS Editor</title>
<link rel="stylesheet" type="text/css" href="/moros.css">
<link rel="stylesheet" type="text/css" href="moros.css">
</head>
<body>
<h1>MOROS Editor</h1>

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<title>MOROS Filesystem</title>
<link rel="stylesheet" type="text/css" href="/moros.css">
<link rel="stylesheet" type="text/css" href="moros.css">
</head>
<body>
<h1>MOROS Filesystem</h1>

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<title>MOROS: Obscure Rust Operating System</title>
<link rel="stylesheet" type="text/css" href="/moros.css">
<link rel="stylesheet" type="text/css" href="moros.css">
</head>
<body>
<h1>MOROS: Obscure Rust Operating System</h1>

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<title>MOROS Lisp</title>
<link rel="stylesheet" type="text/css" href="/moros.css">
<link rel="stylesheet" type="text/css" href="moros.css">
</head>
<body>
<h1>MOROS Lisp</h1>
@ -220,6 +220,7 @@ language and reading from the filesystem.</p>
<ul>
<li>Rename or add aliases to many functions</li>
<li>Add full support for line and inline comments</li>
</ul>
</body>
</html>

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<title>MOROS Manual</title>
<link rel="stylesheet" type="text/css" href="/moros.css">
<link rel="stylesheet" type="text/css" href="moros.css">
</head>
<body>
<h1>MOROS Manual</h1>

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<title>MOROS Network</title>
<link rel="stylesheet" type="text/css" href="/moros.css">
<link rel="stylesheet" type="text/css" href="moros.css">
</head>
<body>
<h1>MOROS Network</h1>

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<title>MOROS Regular Expression Engine</title>
<link rel="stylesheet" type="text/css" href="/moros.css">
<link rel="stylesheet" type="text/css" href="moros.css">
</head>
<body>
<h1>MOROS Regular Expression Engine</h1>

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<title>MOROS Shell</title>
<link rel="stylesheet" type="text/css" href="/moros.css">
<link rel="stylesheet" type="text/css" href="moros.css">
</head>
<body>
<h1>MOROS Shell</h1>

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<title>MOROS Syscalls</title>
<link rel="stylesheet" type="text/css" href="/moros.css">
<link rel="stylesheet" type="text/css" href="moros.css">
</head>
<body>
<h1>MOROS Syscalls</h1>

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<title>MOROS</title>
<link rel="stylesheet" type="text/css" href="/moros.css">
<link rel="stylesheet" type="text/css" href="moros.css">
</head>
<body>
<h1>MOROS</h1>