Add comment parsing
This commit is contained in:
+24
-7
@@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
;; vi:ft=lisp:sw=2:ts=2
|
||||
+24
-9
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user