Add comment parsing

This commit is contained in:
2026-05-06 10:48:13 +03:00
parent bad52a57c3
commit a9a67acdce
5 changed files with 96 additions and 21 deletions
+24 -7
View File
@@ -1,3 +1,5 @@
;; vi:ft=lisp:sw=2:ts=2
(defun return-1 () 1)
(assert (= 1 (return-1)))
(assert (< 1 2 3 4))
@@ -16,11 +18,26 @@
(setq a 1)
(assert (= a 1))
(assert (= 6
(let (a 1)
(let (b 2)
(+ a b 3)
)
(assert
(=
6
;; Non-sequential let: bindings will be visible only inside the block
(let
(a 1)
(let
(a 100 b (+ a 2))
(+ b 3)
)
)
))
(assert (/= (let (a 2) a) a))
;; Sequential let: bindings are visible immediately in the asignments
(let
(a 100)
(let*
(a 1 b (+ a 2))
(+ b 3)
)
)
)
)
+1
View File
@@ -0,0 +1 @@
;; vi:ft=lisp:sw=2:ts=2
+24 -9
View File
@@ -21,7 +21,7 @@ pub struct CompiledFunction {
struct LocalScope {
start_index: u32,
locals: Vec<Rc<str>>,
locals: Vec<(Rc<str>, bool)>,
}
pub struct FunctionBlock {
@@ -40,21 +40,26 @@ pub struct LocalBlock<'a> {
}
impl LocalScope {
pub fn get_or_insert(&mut self, value: Rc<str>) -> Result<U<16>, CompileError> {
let index = if let Some(index) = self.locals.iter().position(|v| *v == value) {
pub fn get_or_insert(&mut self, value: Rc<str>, visible: bool) -> Result<U<16>, CompileError> {
let index = if let Some(index) = self.locals.iter().position(|v| v.0 == value) {
self.locals[index].1 = visible;
index
} else {
let index = self.locals.len();
self.locals.push(value);
self.locals.push((value, visible));
index
} + self.start_index as usize;
Ok(U::new(index as u32).unwrap())
}
pub fn make_visible(&mut self, index: U<16>) {
self.locals[usize::from(index) - self.start_index as usize].1 = true;
}
pub fn get(&self, value: &str) -> Option<U<16>> {
self.locals
.iter()
.position(|v| v.as_ref() == value)
.position(|v| v.0.as_ref() == value && v.1)
.map(|v| v + self.start_index as usize)
.and_then(|v| U::new(v as u32))
}
@@ -196,15 +201,16 @@ impl<'a> LocalBlock<'a> {
&mut self,
identifier: &Rc<str>,
value: CompileValue,
) -> Result<(), CompileError> {
visible: bool,
) -> Result<U<16>, CompileError> {
let index = self
.function
.local_scope_mut()
.unwrap()
.get_or_insert(identifier.clone())?;
.get_or_insert(identifier.clone(), visible)?;
self.compile_push(value)?;
self.function.emit(Instruction::SetLocal(index));
Ok(())
Ok(index)
}
fn compile_push(&mut self, value: CompileValue) -> Result<(), CompileError> {
@@ -405,9 +411,18 @@ impl<'a> LocalBlock<'a> {
fn compile_let(&mut self, binding: &LetExpression) -> Result<CompileValue, CompileError> {
self.function.push_local_scope();
let mut indices = vec![];
for pair in &binding.bindings {
let value = self.compile_expression(&pair.value)?;
self.compile_set_local(&pair.identifier, value)?;
let index = self.compile_set_local(&pair.identifier, value, binding.sequential)?;
indices.push(index);
}
if !binding.sequential {
// Make let bindings visible
let scope = self.function.local_scope_mut().unwrap();
for index in indices {
scope.make_visible(index);
}
}
for expr in &binding.body.head {
self.compile_statement(expr)?;
+13 -1
View File
@@ -12,7 +12,7 @@ use lysp::{
CompilationModule, CompileError, Expression, FunctionBody, FunctionSignature, ParseError,
},
error::EvalError,
parse::parse_value,
parse::{parse_value, skip_comment_and_whitespace},
vm::{
machine::{EvalResult, Machine, MachineError},
prelude,
@@ -57,6 +57,12 @@ fn run_interactive(vm: &mut Machine) -> Result<(), Error> {
let mut i = input.trim_start();
while !i.is_empty() {
i = match skip_comment_and_whitespace(i) {
Ok((i, _)) => i,
Err(e) => {
todo!("{e:?}")
}
};
let result = parse_value(i);
let (o, value) = match result {
Ok(r) => r,
@@ -148,6 +154,12 @@ fn run_module<P: AsRef<Path>>(vm: &mut Machine, path: P) -> Result<(), Error> {
let mut i = input.trim_start();
while !i.is_empty() {
i = match skip_comment_and_whitespace(i) {
Ok((i, _)) => i,
Err(e) => {
todo!("{e:?}")
}
};
let result = parse_value(i);
let (o, value) = match result {
Ok(r) => r,
+34 -4
View File
@@ -1,10 +1,10 @@
use nom::{
FindToken, IResult, Input, Parser,
AsChar, FindToken, IResult, Input, Parser,
branch::alt,
bytes::streaming::tag,
character::{
anychar,
streaming::{char, multispace0, one_of},
streaming::{char, one_of},
},
combinator::{map, map_res, opt, recognize, value},
error::{Error, ErrorKind, FromExternalError, ParseError},
@@ -169,8 +169,8 @@ fn parse_list_or_nil(input: &str) -> IResult<&str, Value> {
map(
delimited(
char('('),
many0(preceded(multispace0, parse_value)),
preceded(multispace0, char(')')),
many0(preceded(skip_comment_and_whitespace, parse_value)),
preceded(skip_comment_and_whitespace, char(')')),
),
Value::list_or_nil,
)
@@ -190,6 +190,36 @@ fn parse_boolean(input: &str) -> IResult<&str, Value> {
.parse(input)
}
pub fn skip_comment_and_whitespace(mut input: &str) -> IResult<&str, ()> {
let mut in_comment = false;
while let Some(ch) = input.chars().next() {
let next = input.ceil_char_boundary(1);
if next >= input.len() {
break;
}
if ch == ';' {
in_comment = true;
}
if in_comment {
if ch.is_newline() {
in_comment = false;
}
input = &input[next..];
continue;
} else if ch.is_whitespace() || ch.is_newline() {
input = &input[next..];
continue;
}
break;
}
input = input.trim_start();
Ok((input, ()))
}
pub fn parse_value(input: &str) -> IResult<&str, Value> {
alt((
parse_list_or_nil,