1
0

Add example; Implement AST

This commit is contained in:
Jeff 2023-09-29 05:45:15 -04:00
parent 4907dd9f8f
commit 8250d3cb8e
3 changed files with 124 additions and 28 deletions

15
examples/clue_solver.ds Normal file
View File

@ -0,0 +1,15 @@
suspects = ("White", "Green");
rooms = ("Library", "Kitchen");
weapons = ("Rope", "Lead Pipe");
make_guess = {
current_room = input.0;
if length(suspects) == 1
&& length(rooms) == 1
&& length(weapons) == 1
then
output 'It was ' + suspects.0 + ' in the ' + rooms.0 + ' with the ' + weapons.0 '!';
else
output 'I accuse ' + random(suspects) + ' in the ' + current_room + ' with the ' + random(weapons) '!';
};

View File

@ -47,18 +47,25 @@ pub fn eval_with_context(source: &str, context: &mut VariableMap) -> Vec<Result<
let tree = parser.parse(source, None).unwrap(); let tree = parser.parse(source, None).unwrap();
let sexp = tree.root_node().to_sexp(); let sexp = tree.root_node().to_sexp();
let evaluator = Evaluator::new(tree.clone(), source).unwrap();
let mut cursor = tree.walk(); let mut cursor = tree.walk();
let results = evaluator.run(context, &mut cursor, source);
println!("{sexp}"); println!("{sexp}");
let evaluator = Evaluator::new(tree.clone(), source).unwrap();
println!("{evaluator:?}"); println!("{evaluator:?}");
let results = evaluator.run(context, &mut cursor, source);
println!("{results:?}"); println!("{results:?}");
println!("{context:?}"); println!("{context:?}");
results results
} }
/// A collection of statements and comments interpreted from a syntax tree.
///
/// The Evaluator turns a tree sitter concrete syntax tree into a vector of
/// trees that can be run to execute the source code. Each of these trees is an
/// [Item][] in the evaluator.
#[derive(Debug)] #[derive(Debug)]
struct Evaluator { struct Evaluator {
items: Vec<Item>, items: Vec<Item>,
@ -66,14 +73,11 @@ struct Evaluator {
impl Evaluator { impl Evaluator {
fn new(tree: Tree, source: &str) -> Result<Self> { fn new(tree: Tree, source: &str) -> Result<Self> {
let mut cursor = tree.walk(); let root_node = tree.root_node();
let root_node = cursor.node();
let mut items = Vec::new(); let mut items = Vec::new();
for node in root_node.children(&mut cursor) { let item = Item::new(root_node, source)?;
let item = Item::new(node, source)?;
items.push(item); items.push(item);
}
Ok(Evaluator { items }) Ok(Evaluator { items })
} }
@ -99,6 +103,11 @@ impl Evaluator {
} }
} }
/// An abstractiton of an independent unit of source code.
///
/// Items are either comments, which do nothing, or statements, which can be run
/// to produce a single value or interact with a context by creating or
/// referencing variables.
#[derive(Debug)] #[derive(Debug)]
enum Item { enum Item {
Comment(String), Comment(String),
@ -107,12 +116,21 @@ enum Item {
impl Item { impl Item {
fn new(node: Node, source: &str) -> Result<Self> { fn new(node: Node, source: &str) -> Result<Self> {
if node.kind() == "comment" { if node.kind() != "item" {
return Err(Error::UnexpectedSourceNode {
expected: "item",
actual: node.kind(),
});
}
let child = node.child(0).unwrap();
if child.kind() == "comment" {
let byte_range = node.byte_range(); let byte_range = node.byte_range();
let value_string = &source[byte_range]; let value_string = &source[byte_range];
Ok(Item::Comment(value_string.to_string())) Ok(Item::Comment(value_string.to_string()))
} else if node.kind() == "statement" { } else if child.kind() == "statement" {
let child = node.child(0).unwrap(); let child = node.child(0).unwrap();
Ok(Item::Statement(Statement::new(child, source)?)) Ok(Item::Statement(Statement::new(child, source)?))
} else { } else {
@ -134,7 +152,7 @@ impl Statement {
fn new(node: Node, source: &str) -> Result<Self> { fn new(node: Node, source: &str) -> Result<Self> {
let child = node.child(0).unwrap(); let child = node.child(0).unwrap();
match node.kind() { match child.kind() {
"closed_statement" => Ok(Statement::Closed(Expression::new(child, source)?)), "closed_statement" => Ok(Statement::Closed(Expression::new(child, source)?)),
"open_statement" => Ok(Self::Open(Expression::new(child, source)?)), "open_statement" => Ok(Self::Open(Expression::new(child, source)?)),
_ => Err(Error::UnexpectedSourceNode { _ => Err(Error::UnexpectedSourceNode {
@ -165,19 +183,13 @@ impl Statement {
enum Expression { enum Expression {
Identifier(String), Identifier(String),
Value(Value), Value(Value),
Operation(Operation), Operation(Box<Operation>),
ControlFlow(Box<ControlFlow>),
} }
impl Expression { impl Expression {
fn new(node: Node, source: &str) -> Result<Self> { fn new(node: Node, source: &str) -> Result<Self> {
if node.kind() != "expression" { let child = node.child(0).unwrap().child(0).unwrap();
return Err(Error::UnexpectedSourceNode {
expected: "expression",
actual: node.kind(),
});
}
let child = node.child(0).unwrap();
if child.kind() == "identifier" { if child.kind() == "identifier" {
let byte_range = child.byte_range(); let byte_range = child.byte_range();
@ -187,10 +199,16 @@ impl Expression {
} else if child.kind() == "value" { } else if child.kind() == "value" {
Ok(Expression::Value(Value::new(child, source)?)) Ok(Expression::Value(Value::new(child, source)?))
} else if child.kind() == "operation" { } else if child.kind() == "operation" {
Ok(Expression::Operation(Operation::new(child, source)?)) Ok(Expression::Operation(Box::new(Operation::new(
child, source,
)?)))
} else if child.kind() == "control_flow" {
Ok(Expression::ControlFlow(Box::new(ControlFlow::new(
child, source,
)?)))
} else { } else {
Err(Error::UnexpectedSourceNode { Err(Error::UnexpectedSourceNode {
expected: "identifier, operation or value", expected: "identifier, operation, control_flow or value",
actual: child.kind(), actual: child.kind(),
}) })
} }
@ -214,25 +232,28 @@ impl Expression {
} }
Expression::Value(value) => Ok(value.clone()), Expression::Value(value) => Ok(value.clone()),
Expression::Operation(operation) => operation.run(context, &mut cursor, source), Expression::Operation(operation) => operation.run(context, &mut cursor, source),
Expression::ControlFlow(control_flow) => control_flow.run(context, &mut cursor, source),
} }
} }
} }
#[derive(Debug)] #[derive(Debug)]
struct Operation { struct Operation {
left: Box<Expression>, left: Expression,
operator: String, operator: String,
right: Box<Expression>, right: Expression,
} }
impl Operation { impl Operation {
fn new(node: Node, source: &str) -> Result<Self> { fn new(node: Node, source: &str) -> Result<Self> {
println!("{node:?}");
let first_child = node.child(0).unwrap(); let first_child = node.child(0).unwrap();
let second_child = node.child(1).unwrap(); let second_child = node.child(1).unwrap();
let third_child = node.child(2).unwrap(); let third_child = node.child(2).unwrap();
let left = { Box::new(Expression::new(first_child, source)?) }; let left = Expression::new(first_child, source)?;
let operator = { second_child.child(0).unwrap().kind().to_string() }; let operator = second_child.child(0).unwrap().kind().to_string();
let right = { Box::new(Expression::new(third_child, source)?) }; let right = Expression::new(third_child, source)?;
Ok(Operation { Ok(Operation {
left, left,
@ -252,7 +273,7 @@ impl Operation {
let result = match self.operator.as_str() { let result = match self.operator.as_str() {
"+" => left + right, "+" => left + right,
"=" => { "=" => {
if let Expression::Identifier(key) = self.left.as_ref() { if let Expression::Identifier(key) = &self.left {
context.set_value(key, right)?; context.set_value(key, right)?;
} }
@ -265,6 +286,53 @@ impl Operation {
} }
} }
#[derive(Debug)]
struct ControlFlow {
if_expression: Expression,
then_statement: Statement,
else_statement: Option<Statement>,
}
impl ControlFlow {
fn new(node: Node, source: &str) -> Result<Self> {
let second_child = node.child(1).unwrap();
let fourth_child = node.child(3).unwrap();
let fifth_child = node.child(4);
println!("{second_child:?} {fourth_child:?} {fifth_child:?}");
let else_statement = if let Some(child) = fifth_child {
Some(Statement::new(child, source)?)
} else {
None
};
Ok(ControlFlow {
if_expression: Expression::new(second_child, source)?,
then_statement: Statement::new(fourth_child, source)?,
else_statement,
})
}
fn run(
&self,
context: &mut VariableMap,
mut cursor: &mut TreeCursor,
source: &str,
) -> Result<Value> {
let if_boolean = self
.if_expression
.run(context, &mut cursor, source)?
.as_boolean()?;
if if_boolean {
self.then_statement.run(context, &mut cursor, source)
} else if let Some(statement) = &self.else_statement {
statement.run(context, &mut cursor, source)
} else {
Ok(Value::Empty)
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -285,4 +353,12 @@ mod tests {
fn evaluate_string() { fn evaluate_string() {
assert_eq!(eval("'one'"), vec![Ok(Value::String("one".to_string()))]); assert_eq!(eval("'one'"), vec![Ok(Value::String("one".to_string()))]);
} }
#[test]
fn if_else() {
assert_eq!(
eval("if true then 'true'"),
vec![Ok(Value::String("true".to_string()))]
);
}
} }

View File

@ -71,6 +71,11 @@ impl Value {
Ok(Value::String(without_quotes.to_string())) Ok(Value::String(without_quotes.to_string()))
} }
"boolean" => {
let raw = value_snippet.parse::<bool>().unwrap_or_default();
Ok(Value::Boolean(raw))
}
"empty" => Ok(Value::Empty), "empty" => Ok(Value::Empty),
_ => Err(Error::UnexpectedSourceNode { _ => Err(Error::UnexpectedSourceNode {
expected: "raw value", expected: "raw value",