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