Skip to content

Commit

Permalink
allow expression width from ternary conditional; improve some error m…
Browse files Browse the repository at this point in the history
…essages
  • Loading branch information
hlorenzi committed Jan 14, 2019
1 parent 809d72f commit 2b6f420
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 10 deletions.
8 changes: 4 additions & 4 deletions src/asm/cpudef/cpudef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ impl<'t> CpuDefParser<'t>
{
// Check for consecutive parameters without a separating token.
if prev_was_expr_parameter
{ return Err(self.parser.report.error_span("expected a separating token between parameters", &tk.span.before())); }
{ return Err(self.parser.report.error_span("expected a separating token between parameters; try using a `,`", &tk.span.before())); }

prev_was_expr_parameter = self.parse_rule_parameter(rule)?;

Expand All @@ -252,7 +252,7 @@ impl<'t> CpuDefParser<'t>
{
// Check for a stricter set of tokens if an expression parameter came just before.
if prev_was_expr_parameter && !tk.kind.is_allowed_after_pattern_parameter()
{ return Err(self.parser.report.error_span("ambiguous pattern token after parameter", &tk.span)); }
{ return Err(self.parser.report.error_span("potentially ambiguous token after parameter; try using a separating `,`", &tk.span)); }

if tk.kind == TokenKind::Identifier
{ is_allowed_at_beginning = true; }
Expand Down Expand Up @@ -326,11 +326,11 @@ impl<'t> CpuDefParser<'t>
let width = match expr.width()
{
Some(w) => w,
None => return Err(self.parser.report.error_span("width of expression not known; use bit slices", &expr.span()))
None => return Err(self.parser.report.error_span("width of expression not known; try using a bit slice like `x[hi:lo]`", &expr.returned_value_span()))
};

if width % self.bits.unwrap() != 0
{ return Err(self.parser.report.error_span(format!("binary representation width (= {}) is not a multiple of the byte width (= {})", width, self.bits.unwrap()), &expr.span())); }
{ return Err(self.parser.report.error_span(format!("expression width (= {}) is not a multiple of the CPU's byte width (= {})", width, self.bits.unwrap()), &expr.returned_value_span())); }

rule.production = expr;

Expand Down
4 changes: 2 additions & 2 deletions src/diagn/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,10 +321,10 @@ impl Report
for p in 0..(excerpt.len() + 1)
{
// Print markings for spans of zero characters.
if p == col1 && p == col2
if p == col1 && p == col2 && line1 == line2
{ write!(writer, "^").unwrap(); }

let marking = if p >= col1 && p < col2
let marking = if (line > line1 || p >= col1) && (line < line2 || p < col2)
{ "^" }
else
{ " " };
Expand Down
35 changes: 35 additions & 0 deletions src/expr/inspect.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use diagn::Span;
use super::Expression;
use super::BinaryOp;

Expand All @@ -21,6 +22,20 @@ impl Expression

&Expression::BitSlice(_, _, left, right, _) => Some(left + 1 - right),

&Expression::TernaryOp(_, _, ref true_branch, ref false_branch) =>
{
let true_width = true_branch.width();
let false_width = false_branch.width();

if true_width.is_none() || false_width.is_none()
{ return None; }

if true_width.unwrap() != false_width.unwrap()
{ return None; }

Some(true_width.unwrap())
}

&Expression::Block(_, ref exprs) =>
{
match exprs.last()
Expand All @@ -42,6 +57,8 @@ impl Expression
&Expression::BinaryOp(_, _, BinaryOp::Concat, _, _) => self.width().map(|w| (w - 1, 0)),
&Expression::BitSlice(_, _, left, right, _) => Some((left, right)),

&Expression::TernaryOp(_, _, _, _) => self.width().map(|w| (w - 1, 0)),

&Expression::Block(_, ref exprs) =>
{
match exprs.last()
Expand All @@ -54,4 +71,22 @@ impl Expression
_ => None
}
}


pub fn returned_value_span(&self) -> Span
{
match self
{
&Expression::Block(ref span, ref exprs) =>
{
match exprs.last()
{
None => span.clone(),
Some(expr) => expr.returned_value_span()
}
}

_ => self.span()
}
}
}
8 changes: 8 additions & 0 deletions src/test/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ fn test_simple()
test("HALT -> 0x00", "halt", Pass((4, "00")));
test("Halt -> 0x00", "hALT", Pass((4, "00")));
test("hALT -> 0x00", "Halt", Pass((4, "00")));

test("halt -> pc % 2 == 0 ? 0x12 : 0x34", "halt \n halt \n halt", Pass((4, "123412")));
test("halt -> pc ? 0x12 : 0x34", "halt \n halt \n halt", Fail(("cpu", 1, "type")));

test("halt -> pc % 2 == 0 ? 0x12", "halt \n halt \n halt", Fail(("cpu", 1, "width")));
test("halt -> pc ? 0x12", "halt \n halt \n halt", Fail(("cpu", 1, "width")));
test("halt -> (pc % 2 == 0 ? 0x12 )[7:0]", "halt \n halt \n halt", Fail(("cpu", 1, "type")));
test("halt -> (pc ? 0x12 )[7:0]", "halt \n halt \n halt", Fail(("cpu", 1, "type")));
}


Expand Down
11 changes: 7 additions & 4 deletions src/test/cpudef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,16 @@ fn test_rules_simple()
test("halt -> 7'0", Fail(("test", 1, "multiple")));
test("halt -> 8'0 8'0", Fail(("test", 1, "line break")));

test("halt -> 1 == 1 ? 0x12", Fail(("test", 1, "width")));
test("halt -> 1 == 1 ? 0x12 : 0x34", Fail(("test", 1, "width")));

test("halt = 0 -> 8'0x12", Fail(("test", 1, "token")));
test("halt : 0 -> 8'0x12", Fail(("test", 1, "token")));

//test("halt -> (1 == 1)", Fail(("test", 1, "integer")));
test("halt -> pc % 2 == 0 ? 0x12 : 0x34", Pass(()));
test("halt -> pc % 2 == 0 ? 0x12 : 0x345", Fail(("test", 1, "width")));
test("halt -> pc % 2 == 0 ? 12 : 0x34", Fail(("test", 1, "width")));
test("halt -> pc % 2 == 0 ? 0x12", Fail(("test", 1, "width")));

test("halt -> (pc % 2 == 0 ? 0x12 )[7:0]", Pass(()));
test("halt -> (pc % 2 == 0 ? 0x12 : 0x345)[7:0]", Pass(()));
}


Expand Down
Binary file modified webasm/customasm.gc.wasm
Binary file not shown.

0 comments on commit 2b6f420

Please sign in to comment.