Skip to content

Commit d749802

Browse files
authored
Merge pull request #7 from xarantolus/master
Evaluate memory region expressions
2 parents be0c056 + 25b921a commit d749802

File tree

5 files changed

+156
-6
lines changed

5 files changed

+156
-6
lines changed

src/eval.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
use crate::expressions::{BinaryOperator, Expression};
2+
3+
pub fn evaluate_expression(expr: Expression) -> Result<u64, String> {
4+
Ok(match expr {
5+
Expression::Number(n) => n,
6+
Expression::BinaryOp {
7+
left,
8+
operator,
9+
right,
10+
} => {
11+
let left = evaluate_expression(*left)?;
12+
let right = evaluate_expression(*right)?;
13+
match operator {
14+
BinaryOperator::Plus => left.wrapping_add(right),
15+
BinaryOperator::Minus => left.wrapping_sub(right),
16+
BinaryOperator::Multiply => left.wrapping_mul(right),
17+
BinaryOperator::Divide => left.wrapping_div(right),
18+
_ => return Err(format!("Binary operator {:?} not supported", operator)),
19+
}
20+
}
21+
_ => return Err(format!("Expression {:?} not supported", expr)),
22+
})
23+
}
24+
25+
#[cfg(test)]
26+
mod tests {
27+
use super::*;
28+
use nom::combinator::map_res;
29+
use BinaryOperator::*;
30+
31+
#[test]
32+
fn test_evaluate_expression() {
33+
assert_eq!(evaluate_expression(Expression::Number(42)), Ok(42));
34+
35+
assert_eq!(
36+
evaluate_expression(Expression::BinaryOp {
37+
left: Box::new(Expression::Number(42)),
38+
operator: Plus,
39+
right: Box::new(Expression::Number(42))
40+
}),
41+
Ok(84)
42+
);
43+
assert_eq!(
44+
evaluate_expression(Expression::BinaryOp {
45+
left: Box::new(Expression::Number(42)),
46+
operator: Minus,
47+
right: Box::new(Expression::Number(42))
48+
}),
49+
Ok(0)
50+
);
51+
assert_eq!(
52+
evaluate_expression(Expression::BinaryOp {
53+
left: Box::new(Expression::Number(42)),
54+
operator: Multiply,
55+
right: Box::new(Expression::Number(42))
56+
}),
57+
Ok(1764)
58+
);
59+
assert_eq!(
60+
evaluate_expression(Expression::BinaryOp {
61+
left: Box::new(Expression::Number(42)),
62+
operator: Divide,
63+
right: Box::new(Expression::Number(42))
64+
}),
65+
Ok(1)
66+
);
67+
}
68+
69+
fn expr_result(input: &str, expected: u64) {
70+
assert_done!(
71+
map_res(crate::expressions::expression, evaluate_expression)(input),
72+
expected
73+
);
74+
}
75+
76+
#[test]
77+
fn test_parsed_expressions() {
78+
expr_result("42 - (20 + 21)", 1);
79+
expr_result("42 - (4 * 8)", 10);
80+
expr_result("42", 42);
81+
expr_result("42 + 42", 84);
82+
expr_result("42 - 42", 0);
83+
expr_result("42 * 42", 1764);
84+
expr_result("42 / 42", 1);
85+
expr_result("0x2000000 + (4k * 4)", 0x2000000 + (4 * 1024 * 4));
86+
}
87+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ mod utils;
2929
#[macro_use]
3030
mod whitespace;
3131
mod commands;
32+
mod eval;
3233
mod expressions;
3334
mod idents;
3435
mod memory;

src/memory.rs

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ use idents::symbol;
22
use nom::{
33
branch::alt,
44
bytes::complete::{tag, take_until},
5-
combinator::opt,
5+
combinator::{map_res, opt},
66
sequence::{delimited, tuple},
77
IResult,
88
};
9-
use numbers::number;
109
use whitespace::opt_space;
1110

11+
use crate::{eval::evaluate_expression, expressions::expression};
12+
1213
#[derive(Debug, PartialEq)]
1314
pub struct Region {
1415
pub name: String,
@@ -37,15 +38,15 @@ pub fn region(input: &str) -> IResult<&str, Region> {
3738
origin,
3839
wsc!(tag("=")),
3940
))(input)?;
40-
let (input, org) = number(input)?;
41+
let (input, origin) = map_res(expression, evaluate_expression)(input)?;
4142
let (input, _) = tuple((wsc!(tag(",")), length, wsc!(tag("="))))(input)?;
42-
let (input, len) = number(input)?;
43+
let (input, length) = map_res(expression, evaluate_expression)(input)?;
4344
Ok((
4445
input,
4546
Region {
4647
name: name.into(),
47-
origin: org,
48-
length: len,
48+
origin,
49+
length,
4950
},
5051
))
5152
}
@@ -73,4 +74,52 @@ mod tests {
7374
}
7475
);
7576
}
77+
78+
#[test]
79+
fn test_region_expr() {
80+
assert_done!(
81+
region("FLASH : ORIGIN = 0x08000000, LENGTH = 8K"),
82+
Region {
83+
name: "FLASH".into(),
84+
origin: 0x08000000,
85+
length: 8 * 1024,
86+
}
87+
);
88+
89+
assert_done!(
90+
region("RAM : ORIGIN = 0x20000000 + 8K, LENGTH = 640K"),
91+
Region {
92+
name: "RAM".into(),
93+
origin: 0x20000000 + 8 * 1024,
94+
length: 640 * 1024,
95+
}
96+
);
97+
98+
assert_done!(
99+
region("RAM : ORIGIN = 0x20000000, LENGTH = 640K - 8K"),
100+
Region {
101+
name: "RAM".into(),
102+
origin: 0x20000000,
103+
length: 640 * 1024 - 8 * 1024,
104+
}
105+
);
106+
107+
assert_done!(
108+
region("RAM : ORIGIN = 0x20000000 + 8K - 4K, LENGTH = 640K - 8K + 4K"),
109+
Region {
110+
name: "RAM".into(),
111+
origin: 0x20000000 + 4 * 1024,
112+
length: 640 * 1024 - 4 * 1024,
113+
}
114+
);
115+
116+
assert_done!(
117+
region("RAM: ORIGIN = 0x20000000 + 8K - 4K, LENGTH = 640K - 8K + 4K"),
118+
Region {
119+
name: "RAM".into(),
120+
origin: 0x20000000 + 4 * 1024,
121+
length: 640 * 1024 - 4 * 1024,
122+
}
123+
);
124+
}
76125
}

src/script.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ mod tests {
6363
assert_done_vec!(parse(" /* hello */ "), 0);
6464
}
6565

66+
#[test]
67+
fn test_bootloader() {
68+
let input = include_str!("../tests/bootloader.ld");
69+
let res = parse(&input);
70+
assert!(!res.unwrap().1.is_empty());
71+
}
72+
6673
#[test]
6774
fn test_parse() {
6875
for entry in fs::read_dir("tests").unwrap() {

tests/bootloader.ld

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
MEMORY
2+
{
3+
FLASH : ORIGIN = 0x08000000, LENGTH = 8K
4+
5+
RAM : ORIGIN = 0x20000000 + 256K, LENGTH = 640K - 256K
6+
}

0 commit comments

Comments
 (0)