Skip to content

Commit

Permalink
add the assert directive
Browse files Browse the repository at this point in the history
  • Loading branch information
hlorenzi committed Oct 8, 2024
1 parent 8964895 commit 602919d
Show file tree
Hide file tree
Showing 18 changed files with 206 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/asm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub use parser::{
AstAny,
AstDirectiveAddr,
AstDirectiveAlign,
AstDirectiveAssert,
AstDirectiveBank,
AstDirectiveBankdef,
AstDirectiveBits,
Expand Down
3 changes: 3 additions & 0 deletions src/asm/parser/directive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ pub fn parse(
"subruledef" => Ok(asm::AstAny::DirectiveRuledef(
asm::parser::directive_ruledef::parse(report, walker, true, header_span)?)),

"assert" => Ok(asm::AstAny::DirectiveAssert(
asm::parser::directive_assert::parse(report, walker, header_span)?)),

_ =>
{
report.error_span(
Expand Down
26 changes: 26 additions & 0 deletions src/asm/parser/directive_assert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use crate::*;


#[derive(Clone, Debug)]
pub struct AstDirectiveAssert
{
pub header_span: diagn::Span,
pub condition_expr: expr::Expr,
}


pub fn parse(
report: &mut diagn::Report,
walker: &mut syntax::Walker,
header_span: diagn::Span)
-> Result<AstDirectiveAssert, ()>
{
let expr = expr::parse(report, walker)?;

walker.expect_linebreak(report)?;

Ok(AstDirectiveAssert {
header_span,
condition_expr: expr,
})
}
5 changes: 5 additions & 0 deletions src/asm/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ pub use directive_addr::AstDirectiveAddr;
mod directive_align;
pub use directive_align::AstDirectiveAlign;

mod directive_assert;
pub use directive_assert::AstDirectiveAssert;

mod directive_bank;
pub use directive_bank::AstDirectiveBank;

Expand Down Expand Up @@ -78,6 +81,7 @@ pub enum AstAny
{
DirectiveAddr(AstDirectiveAddr),
DirectiveAlign(AstDirectiveAlign),
DirectiveAssert(AstDirectiveAssert),
DirectiveBank(AstDirectiveBank),
DirectiveBankdef(AstDirectiveBankdef),
DirectiveBits(AstDirectiveBits),
Expand Down Expand Up @@ -327,6 +331,7 @@ impl AstAny
{
AstAny::DirectiveAddr(node) => node.header_span,
AstAny::DirectiveAlign(node) => node.header_span,
AstAny::DirectiveAssert(node) => node.header_span,
AstAny::DirectiveBank(node) => node.header_span,
AstAny::DirectiveBankdef(node) => node.header_span,
AstAny::DirectiveBits(node) => node.header_span,
Expand Down
41 changes: 41 additions & 0 deletions src/asm/resolver/assert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use crate::*;


pub fn resolve_assert(
report: &mut diagn::Report,
opts: &asm::AssemblyOptions,
fileserver: &mut dyn util::FileServer,
ast_assert: &asm::AstDirectiveAssert,
decls: &asm::ItemDecls,
defs: &mut asm::ItemDefs,
ctx: &asm::ResolverContext)
-> Result<asm::ResolutionState, ()>
{
if !ctx.is_last_iteration
{
return Ok(asm::ResolutionState::Unresolved);
}

let value = asm::resolver::eval(
report,
opts,
fileserver,
decls,
defs,
ctx,
&mut expr::EvalContext::new(),
&ast_assert.condition_expr)?;

let satisfied = value.expect_bool(
report,
ast_assert.condition_expr.span())?;

if !satisfied
{
report.error_span(
"assertion failed",
ast_assert.condition_expr.span());
}

Ok(asm::ResolutionState::Resolved)
}
17 changes: 16 additions & 1 deletion src/asm/resolver/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pub enum ResolverNode<'ast>
Res(&'ast asm::AstDirectiveRes),
Align(&'ast asm::AstDirectiveAlign),
Addr(&'ast asm::AstDirectiveAddr),
Assert(&'ast asm::AstDirectiveAssert),
}


Expand Down Expand Up @@ -205,7 +206,21 @@ impl<'ast, 'decls> ResolveIterator<'ast, 'decls>
file_handle_ctx = Some(ast_addr.header_span.file_handle);
}

_ =>
asm::AstAny::DirectiveAssert(ast_assert) =>
{
self.index += 1;
node = ResolverNode::Assert(ast_assert);
file_handle_ctx = Some(ast_assert.header_span.file_handle);
}

asm::AstAny::DirectiveBits(..) |
asm::AstAny::DirectiveFn(..) |
asm::AstAny::DirectiveIf(..) |
asm::AstAny::DirectiveInclude(..) |
asm::AstAny::DirectiveLabelAlign(..) |
asm::AstAny::DirectiveNoEmit(..) |
asm::AstAny::DirectiveOnce(..) |
asm::AstAny::DirectiveRuledef(..) =>
{
self.index += 1;
node = ResolverNode::None;
Expand Down
14 changes: 14 additions & 0 deletions src/asm/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ mod data_block;
mod res;
mod align;
mod addr;
mod assert;

mod directive_if;
pub use directive_if::{
Expand Down Expand Up @@ -263,6 +264,19 @@ pub fn resolve_once(
defs,
&ctx)?);
}

asm::ResolverNode::Assert(ast_assert) =>
{
resolution_state.merge(
assert::resolve_assert(
report,
opts,
fileserver,
ast_assert,
decls,
defs,
&ctx)?);
}
}
}

Expand Down
27 changes: 27 additions & 0 deletions src/expr/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,33 @@ impl Value
}


pub fn expect_error_or_bool(
self,
report: &mut diagn::Report,
span: diagn::Span)
-> Result<expr::Value, ()>
{
match self.coallesce_to_integer().as_ref()
{
value @ expr::Value::Unknown |
value @ expr::Value::FailedConstraint(_) =>
Ok(value.to_owned()),

value @ expr::Value::Bool(_) =>
Ok(value.to_owned()),

_ =>
{
report.error_span(
"expected boolean",
span);

Err(())
}
}
}


pub fn as_usize(&self) -> Option<usize>
{
match self
Expand Down
27 changes: 27 additions & 0 deletions tests/assert/err_addr_convergence.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ruledef test
{
ld {x} =>
{
assert(x <= 0x8)
0x11 @ x`16
}

ld {x} =>
{
assert(x > 0x8)
0x22 @ x`8
}
}
#assert $ == 0x0

ld label
ld label
label:

#assert label == 0x4 ; error: assertion

ld label
ld label
#assert $ == 0x8 ; error: assertion
3 changes: 3 additions & 0 deletions tests/assert/err_constant.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
x = 0xff
#d x
#assert x == 0xee ; error: assertion
3 changes: 3 additions & 0 deletions tests/assert/err_constant_deferred.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#d x
#assert x == 0xee ; error: assertion
x = 0xff
2 changes: 2 additions & 0 deletions tests/assert/err_expected_bool.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#d 0xff
#assert 1 + 1 ; error: expected boolean
2 changes: 2 additions & 0 deletions tests/assert/err_simple.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#d 0xff
#assert 1 + 1 == 5 ; error: assertion
1 change: 1 addition & 0 deletions tests/assert/err_unknown_symbol.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#assert x ; error: unknown symbol
27 changes: 27 additions & 0 deletions tests/assert/ok_addr_convergence.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ruledef test
{
ld {x} =>
{
assert(x <= 0x8)
0x11 @ x`16
}

ld {x} =>
{
assert(x > 0x8)
0x22 @ x`8
}
}
#assert $ == 0x0

ld label ; = 0x110006
ld label ; = 0x110006
label:

#assert label == 0x6

ld label ; = 0x110006
ld label ; = 0x110006
#assert $ == 0xc
3 changes: 3 additions & 0 deletions tests/assert/ok_constant.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
x = 0xff
#d x ; = 0xff
#assert x == 0xff
3 changes: 3 additions & 0 deletions tests/assert/ok_constant_deferred.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#d x ; = 0xff
#assert x == 0xff
x = 0xff
2 changes: 2 additions & 0 deletions tests/assert/ok_simple.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#d 0xff ; = 0xff
#assert 1 + 1 == 2

0 comments on commit 602919d

Please sign in to comment.