Skip to content

Commit e58e41e

Browse files
Merge pull request #26 from PoorlyDefinedBehaviour/feat/hook_up_repl
feat/hook up repl
2 parents 8c16731 + 9c2ff33 commit e58e41e

5 files changed

Lines changed: 79 additions & 177 deletions

File tree

README.md

Lines changed: 1 addition & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -6,126 +6,4 @@ Based on: </br>
66
- https://interpreterbook.com/
77
- https://craftinginterpreters.com/
88

9-
```rust
10-
bruno@bruno:~/dev/rust/interpreter_1$ cargo run
11-
Compiling interpreter v0.1.0 (/home/bruno/dev/rust/interpreter_1)
12-
Finished dev [unoptimized + debuginfo] target(s) in 0.23s
13-
Running `target/debug/interpreter`
14-
> x |> f |> g
15-
[src/main.rs:26] program.statements = [
16-
Expression(
17-
Infix(
18-
InfixExpression {
19-
left_operand: Infix(
20-
InfixExpression {
21-
left_operand: Identifier(
22-
"x",
23-
),
24-
operator: Pipe,
25-
right_operand: Identifier(
26-
"f",
27-
),
28-
},
29-
),
30-
operator: Pipe,
31-
right_operand: Identifier(
32-
"g",
33-
),
34-
},
35-
),
36-
),
37-
]
38-
```
39-
40-
```rust
41-
bruno@bruno:~/dev/rust/interpreter_1$ cargo run
42-
Compiling interpreter v0.1.0 (/home/bruno/dev/rust/interpreter_1)
43-
Finished dev [unoptimized + debuginfo] target(s) in 0.28s
44-
Running `target/debug/interpreter`
45-
> let factorial = fn(x) { if(x <= 1) { 1 } else { factorial(x - 1) * x } }
46-
[src/main.rs:26] program.statements = [
47-
Let(
48-
LetStatement {
49-
token: Let,
50-
identifier: Identifier(
51-
"factorial",
52-
),
53-
value: Function(
54-
FunctionExpression {
55-
parameters: [
56-
Identifier(
57-
"x",
58-
),
59-
],
60-
body: Block(
61-
[
62-
Expression(
63-
If(
64-
IfExpression {
65-
condition: Infix(
66-
InfixExpression {
67-
left_operand: Identifier(
68-
"x",
69-
),
70-
operator: LessThanOrEqual,
71-
right_operand: Number(
72-
1.0,
73-
),
74-
},
75-
),
76-
consequence: Block(
77-
[
78-
Expression(
79-
Number(
80-
1.0,
81-
),
82-
),
83-
],
84-
),
85-
alternative: Some(
86-
Block(
87-
[
88-
Expression(
89-
Infix(
90-
InfixExpression {
91-
left_operand: Call(
92-
CallExpression {
93-
function: Identifier(
94-
"factorial",
95-
),
96-
arguments: [
97-
Infix(
98-
InfixExpression {
99-
left_operand: Identifier(
100-
"x",
101-
),
102-
operator: Minus,
103-
right_operand: Number(
104-
1.0,
105-
),
106-
},
107-
),
108-
],
109-
},
110-
),
111-
operator: Star,
112-
right_operand: Identifier(
113-
"x",
114-
),
115-
},
116-
),
117-
),
118-
],
119-
),
120-
),
121-
},
122-
),
123-
),
124-
],
125-
),
126-
},
127-
),
128-
},
129-
),
130-
]
131-
```
9+
![preview](assets/preview.gif)

assets/preview.gif

77.6 KB
Loading

src/interpreter.rs

Lines changed: 53 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::ast::{Expression, Program, Statement};
1+
use crate::ast::{CallExpression, Expression, Program, Statement};
22
use crate::token::Token;
33
use std::collections::HashMap;
44
use std::fmt;
@@ -234,38 +234,7 @@ impl Interpreter {
234234
Expression::Call(expression) => {
235235
self.environment.create_scope();
236236

237-
let (parameters, function_body) = match *expression.function {
238-
Expression::Function(function) => (function.parameters, function.body),
239-
Expression::Identifier(identifier) => match self.environment.get_binding(&identifier) {
240-
Some(Object::Function(function)) => {
241-
(function.parameters.clone(), function.body.clone())
242-
}
243-
_ => return Err(format!("identifier not found: {}", identifier)),
244-
},
245-
_ => unreachable!(),
246-
};
247-
248-
if expression.arguments.len() != parameters.len() {
249-
return Err(format!(
250-
"expected {} arguments, got {}",
251-
parameters.len(),
252-
expression.arguments.len(),
253-
));
254-
}
255-
256-
let mut arguments = Vec::new();
257-
258-
for argument in expression.arguments {
259-
arguments.push(self.eval_expression(argument)?);
260-
}
261-
262-
for (parameter, argument) in parameters.iter().zip(arguments.iter()) {
263-
self
264-
.environment
265-
.set_binding(parameter.clone(), argument.clone())?;
266-
}
267-
268-
let return_value = self.eval_statements(function_body)?;
237+
let return_value = self.evaluate_function_call(expression)?;
269238

270239
self.environment.destroy_current_scope();
271240

@@ -275,6 +244,42 @@ impl Interpreter {
275244
}
276245
}
277246

247+
fn evaluate_function_call(
248+
&mut self,
249+
expression: CallExpression,
250+
) -> Result<Object, InterpreterError> {
251+
let (parameters, function_body) = match *expression.function {
252+
Expression::Function(function) => (function.parameters, function.body),
253+
Expression::Identifier(identifier) => match self.environment.get_binding(&identifier) {
254+
Some(Object::Function(function)) => (function.parameters.clone(), function.body.clone()),
255+
_ => return Err(format!("identifier not found: {}", identifier)),
256+
},
257+
expression => return Err(format!("expression is not a function: {}", expression)),
258+
};
259+
260+
if expression.arguments.len() != parameters.len() {
261+
return Err(format!(
262+
"expected {} arguments, got {}",
263+
parameters.len(),
264+
expression.arguments.len(),
265+
));
266+
}
267+
268+
let mut arguments = Vec::new();
269+
270+
for argument in expression.arguments {
271+
arguments.push(self.eval_expression(argument)?);
272+
}
273+
274+
for (parameter, argument) in parameters.iter().zip(arguments.iter()) {
275+
self
276+
.environment
277+
.set_binding(parameter.clone(), argument.clone())?;
278+
}
279+
280+
Ok(self.eval_statements(function_body)?)
281+
}
282+
278283
fn to_boolean(&self, object: &Object) -> Object {
279284
match object {
280285
Object::Boolean(boolean) => Object::Boolean(*boolean),
@@ -467,19 +472,14 @@ mod tests {
467472
("false / true", "unexpected infix expression: false / true"),
468473
("true / true", "unexpected infix expression: true / true"),
469474
("true / false", "unexpected infix expression: true / false"),
470-
(
471-
"false |> false",
472-
"unexpected infix expression: false |> false",
473-
),
474-
(
475-
"false |> true",
476-
"unexpected infix expression: false |> true",
477-
),
478-
("true |> true", "unexpected infix expression: true |> true"),
479-
(
480-
"true |> false",
481-
"unexpected infix expression: true |> false",
482-
),
475+
("false |> false", "expression is not a function: false"),
476+
("false |> true", "expression is not a function: true"),
477+
("true |> true", "expression is not a function: true"),
478+
("true |> false", "expression is not a function: false"),
479+
("true |> 10", "expression is not a function: 10"),
480+
("true |> 32", "expression is not a function: 32"),
481+
("true |> -1", "expression is not a function: (- 1)"),
482+
("10 |> 0", "expression is not a function: 0"),
483483
];
484484

485485
for (input, expected) in test_cases {
@@ -666,6 +666,13 @@ mod tests {
666666
Object::Number(120.0),
667667
),
668668
("fn(x) { x }(3)", Object::Number(3.0)),
669+
(
670+
"
671+
let double = fn(x) { x * 2 }
672+
2 |> double |> double
673+
",
674+
Object::Number(8.0),
675+
),
669676
];
670677

671678
for (input, expected) in test_cases {

src/main.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
use interpreter::interpreter::Interpreter;
12
use interpreter::lexer::Lexer;
23
use interpreter::parser::Parser;
34
use std::io::{self, Write};
45

56
fn main() {
7+
let mut interpreter = Interpreter::new();
8+
69
loop {
710
print!("> ");
811

@@ -21,9 +24,18 @@ fn main() {
2124
let program = parser.parse();
2225

2326
if program.has_errors() {
24-
dbg!(program.errors);
27+
dbg!(&program.errors);
2528
} else {
26-
dbg!(program.statements);
29+
dbg!(&program.statements);
30+
31+
match interpreter.evaluate(program) {
32+
Ok(result) => {
33+
println!("{}", result);
34+
}
35+
Err(message) => {
36+
dbg!(message);
37+
}
38+
}
2739
}
2840
}
2941
}

src/parser.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,13 @@ impl Parser {
276276
.parse_expression_statement(token_precedence(Some(token)))
277277
.unwrap();
278278

279+
if matches!(token, Token::Pipe) {
280+
return Expression::Call(CallExpression {
281+
function: Box::new(right_operand),
282+
arguments: vec![left_operand],
283+
});
284+
}
285+
279286
Expression::Infix(InfixExpression {
280287
left_operand: Box::new(left_operand),
281288
operator: token.clone(),
@@ -588,10 +595,10 @@ mod tests {
588595
("5 != 5", "(5 != 5)"),
589596
("5 <= 5", "(5 <= 5)"),
590597
("5 >= 5", "(5 >= 5)"),
591-
("x |> f", "(x |> f)"),
592-
("a <= b |> f", "(a <= (b |> f))"),
593-
("a |> f |> g", "((a |> f) |> g)"),
594-
("a |> f > x", "((a |> f) > x)"),
598+
("x |> f", "(f(x))"),
599+
("a <= b |> f", "(a <= (f(b)))"),
600+
("a |> f |> g", "(g((f(a))))"),
601+
("a |> f > x", "((f(a)) > x)"),
595602
("a + b + c", "((a + b) + c)"),
596603
("a + b - c", "((a + b) - c)"),
597604
("a * b * c", "((a * b) * c)"),
@@ -607,8 +614,6 @@ mod tests {
607614

608615
let program = parser.parse();
609616

610-
dbg!(&program.errors);
611-
612617
assert!(!program.has_errors());
613618

614619
assert_eq!(program.to_string(), expected);

0 commit comments

Comments
 (0)