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) (defun return-1 () 1)
(assert (= 1 (return-1))) (assert (= 1 (return-1)))
(assert (< 1 2 3 4)) (assert (< 1 2 3 4))
@@ -16,11 +18,26 @@
(setq a 1) (setq a 1)
(assert (= a 1)) (assert (= a 1))
(assert (= 6
(let (a 1) (assert
(let (b 2) (=
(+ a b 3) 6
) ;; Non-sequential let: bindings will be visible only inside the block
(let
(a 1)
(let
(a 100 b (+ a 2))
(+ b 3)
)
) )
)) ;; Sequential let: bindings are visible immediately in the asignments
(assert (/= (let (a 2) a) a)) (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 { struct LocalScope {
start_index: u32, start_index: u32,
locals: Vec<Rc<str>>, locals: Vec<(Rc<str>, bool)>,
} }
pub struct FunctionBlock { pub struct FunctionBlock {
@@ -40,21 +40,26 @@ pub struct LocalBlock<'a> {
} }
impl LocalScope { impl LocalScope {
pub fn get_or_insert(&mut self, value: Rc<str>) -> Result<U<16>, CompileError> { 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 == value) { let index = if let Some(index) = self.locals.iter().position(|v| v.0 == value) {
self.locals[index].1 = visible;
index index
} else { } else {
let index = self.locals.len(); let index = self.locals.len();
self.locals.push(value); self.locals.push((value, visible));
index index
} + self.start_index as usize; } + self.start_index as usize;
Ok(U::new(index as u32).unwrap()) 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>> { pub fn get(&self, value: &str) -> Option<U<16>> {
self.locals self.locals
.iter() .iter()
.position(|v| v.as_ref() == value) .position(|v| v.0.as_ref() == value && v.1)
.map(|v| v + self.start_index as usize) .map(|v| v + self.start_index as usize)
.and_then(|v| U::new(v as u32)) .and_then(|v| U::new(v as u32))
} }
@@ -196,15 +201,16 @@ impl<'a> LocalBlock<'a> {
&mut self, &mut self,
identifier: &Rc<str>, identifier: &Rc<str>,
value: CompileValue, value: CompileValue,
) -> Result<(), CompileError> { visible: bool,
) -> Result<U<16>, CompileError> {
let index = self let index = self
.function .function
.local_scope_mut() .local_scope_mut()
.unwrap() .unwrap()
.get_or_insert(identifier.clone())?; .get_or_insert(identifier.clone(), visible)?;
self.compile_push(value)?; self.compile_push(value)?;
self.function.emit(Instruction::SetLocal(index)); self.function.emit(Instruction::SetLocal(index));
Ok(()) Ok(index)
} }
fn compile_push(&mut self, value: CompileValue) -> Result<(), CompileError> { 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> { fn compile_let(&mut self, binding: &LetExpression) -> Result<CompileValue, CompileError> {
self.function.push_local_scope(); self.function.push_local_scope();
let mut indices = vec![];
for pair in &binding.bindings { for pair in &binding.bindings {
let value = self.compile_expression(&pair.value)?; 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 { for expr in &binding.body.head {
self.compile_statement(expr)?; self.compile_statement(expr)?;
+13 -1
View File
@@ -12,7 +12,7 @@ use lysp::{
CompilationModule, CompileError, Expression, FunctionBody, FunctionSignature, ParseError, CompilationModule, CompileError, Expression, FunctionBody, FunctionSignature, ParseError,
}, },
error::EvalError, error::EvalError,
parse::parse_value, parse::{parse_value, skip_comment_and_whitespace},
vm::{ vm::{
machine::{EvalResult, Machine, MachineError}, machine::{EvalResult, Machine, MachineError},
prelude, prelude,
@@ -57,6 +57,12 @@ fn run_interactive(vm: &mut Machine) -> Result<(), Error> {
let mut i = input.trim_start(); let mut i = input.trim_start();
while !i.is_empty() { while !i.is_empty() {
i = match skip_comment_and_whitespace(i) {
Ok((i, _)) => i,
Err(e) => {
todo!("{e:?}")
}
};
let result = parse_value(i); let result = parse_value(i);
let (o, value) = match result { let (o, value) = match result {
Ok(r) => r, 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(); let mut i = input.trim_start();
while !i.is_empty() { while !i.is_empty() {
i = match skip_comment_and_whitespace(i) {
Ok((i, _)) => i,
Err(e) => {
todo!("{e:?}")
}
};
let result = parse_value(i); let result = parse_value(i);
let (o, value) = match result { let (o, value) = match result {
Ok(r) => r, Ok(r) => r,
+34 -4
View File
@@ -1,10 +1,10 @@
use nom::{ use nom::{
FindToken, IResult, Input, Parser, AsChar, FindToken, IResult, Input, Parser,
branch::alt, branch::alt,
bytes::streaming::tag, bytes::streaming::tag,
character::{ character::{
anychar, anychar,
streaming::{char, multispace0, one_of}, streaming::{char, one_of},
}, },
combinator::{map, map_res, opt, recognize, value}, combinator::{map, map_res, opt, recognize, value},
error::{Error, ErrorKind, FromExternalError, ParseError}, error::{Error, ErrorKind, FromExternalError, ParseError},
@@ -169,8 +169,8 @@ fn parse_list_or_nil(input: &str) -> IResult<&str, Value> {
map( map(
delimited( delimited(
char('('), char('('),
many0(preceded(multispace0, parse_value)), many0(preceded(skip_comment_and_whitespace, parse_value)),
preceded(multispace0, char(')')), preceded(skip_comment_and_whitespace, char(')')),
), ),
Value::list_or_nil, Value::list_or_nil,
) )
@@ -190,6 +190,36 @@ fn parse_boolean(input: &str) -> IResult<&str, Value> {
.parse(input) .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> { pub fn parse_value(input: &str) -> IResult<&str, Value> {
alt(( alt((
parse_list_or_nil, parse_list_or_nil,