From e48fe8df9061e5c669873f351d3bb042a576fe0f Mon Sep 17 00:00:00 2001 From: hlorenzi Date: Sun, 4 Jun 2023 16:18:58 -0300 Subject: [PATCH] add the `#const` directive and the `noemit` attribute --- src/asm/defs/function.rs | 1 + src/asm/defs/symbol.rs | 2 + src/asm/parser/directive.rs | 3 + src/asm/parser/directive_const.rs | 64 +++++++++++++++++++ src/asm/parser/directive_noemit.rs | 31 ++------- src/asm/parser/mod.rs | 2 + src/asm/parser/symbol.rs | 3 + src/util/symbol_format.rs | 26 ++++---- tests/driver/ok_format_symbol_noemit/main.asm | 39 +++++++++++ tests/driver/ok_format_symbol_noemit/out.txt | 9 +++ .../err_literal_const_invalid_attrb.asm | 8 +++ .../ok_literal_const.asm | 8 +++ .../ok_literal_const_noemit.asm | 8 +++ tests/symbol_constant_simple/ok_nested.asm | 11 ++++ .../ok_nested_const.asm | 11 ++++ 15 files changed, 189 insertions(+), 37 deletions(-) create mode 100644 src/asm/parser/directive_const.rs create mode 100644 tests/driver/ok_format_symbol_noemit/main.asm create mode 100644 tests/driver/ok_format_symbol_noemit/out.txt create mode 100644 tests/symbol_constant_simple/err_literal_const_invalid_attrb.asm create mode 100644 tests/symbol_constant_simple/ok_literal_const.asm create mode 100644 tests/symbol_constant_simple/ok_literal_const_noemit.asm create mode 100644 tests/symbol_constant_simple/ok_nested.asm create mode 100644 tests/symbol_constant_simple/ok_nested_const.asm diff --git a/src/asm/defs/function.rs b/src/asm/defs/function.rs index 167c1275..0e2c6c47 100644 --- a/src/asm/defs/function.rs +++ b/src/asm/defs/function.rs @@ -52,6 +52,7 @@ pub fn define( let symbol = asm::Symbol { item_ref, + no_emit: true, value_statically_known: true, value: expr::Value::Function(fn_ref.0), resolved: true, diff --git a/src/asm/defs/symbol.rs b/src/asm/defs/symbol.rs index 83a53585..0fcc79cf 100644 --- a/src/asm/defs/symbol.rs +++ b/src/asm/defs/symbol.rs @@ -5,6 +5,7 @@ use crate::*; pub struct Symbol { pub item_ref: util::ItemRef, + pub no_emit: bool, pub value_statically_known: bool, pub value: expr::Value, pub resolved: bool, @@ -42,6 +43,7 @@ pub fn define( let symbol = Symbol { item_ref, + no_emit: node.no_emit, value_statically_known, value: expr::Value::Unknown, resolved: false, diff --git a/src/asm/parser/directive.rs b/src/asm/parser/directive.rs index 4be5dcd6..17bd202d 100644 --- a/src/asm/parser/directive.rs +++ b/src/asm/parser/directive.rs @@ -51,6 +51,9 @@ pub fn parse( "bits" => Ok(asm::AstAny::DirectiveBits( asm::parser::directive_bits::parse(report, walker, header_span)?)), + "const" => Ok(asm::AstAny::Symbol( + asm::parser::directive_const::parse(report, walker, header_span)?)), + "fn" => Ok(asm::AstAny::DirectiveFn( asm::parser::directive_fn::parse(report, walker, header_span)?)), diff --git a/src/asm/parser/directive_const.rs b/src/asm/parser/directive_const.rs new file mode 100644 index 00000000..142c7bcb --- /dev/null +++ b/src/asm/parser/directive_const.rs @@ -0,0 +1,64 @@ +use super::*; + + +pub fn parse( + report: &mut diagn::Report, + walker: &mut syntax::TokenWalker, + _header_span: diagn::Span) + -> Result +{ + let mut no_emit = false; + + if let Some(_) = walker.maybe_expect(syntax::TokenKind::ParenOpen) + { + let tk_attrb = walker.expect(report, syntax::TokenKind::Identifier)?; + let attrb = tk_attrb.excerpt.as_ref().unwrap(); + + match attrb.as_ref() + { + "noemit" => no_emit = true, + _ => + { + report.error_span( + format!("invalid attribute `{}`", attrb), + tk_attrb.span); + + return Err(()); + } + } + + walker.expect(report, syntax::TokenKind::ParenClose)?; + } + + + let mut decl_span = diagn::Span::new_dummy(); + let mut hierarchy_level = 0; + + while let Some(tk_dot) = walker.maybe_expect(syntax::TokenKind::Dot) + { + hierarchy_level += 1; + decl_span = decl_span.join(tk_dot.span); + } + + let tk_name = walker.expect(report, syntax::TokenKind::Identifier)?; + let name = tk_name.excerpt.clone().unwrap(); + decl_span = decl_span.join(tk_name.span); + + + walker.expect(report, syntax::TokenKind::Equal)?; + + let expr = expr::parse(report, walker)?; + walker.expect_linebreak(report)?; + + Ok(AstSymbol { + decl_span, + hierarchy_level, + name, + kind: AstSymbolKind::Constant(AstSymbolConstant { + expr, + }), + no_emit, + + item_ref: None, + }) +} \ No newline at end of file diff --git a/src/asm/parser/directive_noemit.rs b/src/asm/parser/directive_noemit.rs index 7763da53..54a13dff 100644 --- a/src/asm/parser/directive_noemit.rs +++ b/src/asm/parser/directive_noemit.rs @@ -11,32 +11,13 @@ pub struct AstDirectiveNoEmit pub fn parse( report: &mut diagn::Report, - walker: &mut syntax::TokenWalker, + _walker: &mut syntax::TokenWalker, header_span: diagn::Span) -> Result { - let tk_status = walker.expect(report, syntax::TokenKind::Identifier)?; - let status = tk_status.excerpt.as_ref().unwrap().to_ascii_lowercase(); - - walker.expect_linebreak(report)?; - - let status = match status.as_ref() - { - "on" => true, - "off" => false, - _ => - { - report.error_span( - "unknown noemit state", - tk_status.span, - ); - - return Err(()); - } - }; - - Ok(AstDirectiveNoEmit { - header_span, - status, - }) + report.error_span( + "`#noemit` is deprecated; use `#const(noemit)` at each constant declaration", + header_span); + + Err(()) } \ No newline at end of file diff --git a/src/asm/parser/mod.rs b/src/asm/parser/mod.rs index 24e381a0..de104221 100644 --- a/src/asm/parser/mod.rs +++ b/src/asm/parser/mod.rs @@ -28,6 +28,8 @@ pub use directive_bits::{ AstDirectiveBits, }; +mod directive_const; + mod directive_data; pub use directive_data::{ AstDirectiveData, diff --git a/src/asm/parser/symbol.rs b/src/asm/parser/symbol.rs index 358b79ad..920fc966 100644 --- a/src/asm/parser/symbol.rs +++ b/src/asm/parser/symbol.rs @@ -8,6 +8,7 @@ pub struct AstSymbol pub hierarchy_level: usize, pub name: String, pub kind: AstSymbolKind, + pub no_emit: bool, pub item_ref: Option>, } @@ -59,6 +60,7 @@ pub fn parse( kind: AstSymbolKind::Constant(AstSymbolConstant { expr, }), + no_emit: false, item_ref: None, })) @@ -73,6 +75,7 @@ pub fn parse( hierarchy_level, name, kind: AstSymbolKind::Label, + no_emit: false, item_ref: None, })) diff --git a/src/util/symbol_format.rs b/src/util/symbol_format.rs index 8f4436dd..2f39cfbd 100644 --- a/src/util/symbol_format.rs +++ b/src/util/symbol_format.rs @@ -126,29 +126,31 @@ impl util::SymbolManager hierarchy.push(child_name.clone()); - // TODO: Respect the #noemit directive let symbol_decl = self.get(*child_ref); let symbol = defs.symbols.get(symbol_decl.item_ref); - match symbol.value + if !symbol.no_emit { - expr::Value::Integer(ref bigint) => + match symbol.value { - let mut name = String::new(); - - for i in 0..hierarchy.len() + expr::Value::Integer(ref bigint) => { - if i > 0 + let mut name = String::new(); + + for i in 0..hierarchy.len() { - name.push_str("."); + if i > 0 + { + name.push_str("."); + } + + name.push_str(&format!("{}", hierarchy[i])); } - name.push_str(&format!("{}", hierarchy[i])); + formatter(result, symbol_decl, &name, &bigint); } - - formatter(result, symbol_decl, &name, &bigint); + _ => {} } - _ => {} } diff --git a/tests/driver/ok_format_symbol_noemit/main.asm b/tests/driver/ok_format_symbol_noemit/main.asm new file mode 100644 index 00000000..0a80c6fc --- /dev/null +++ b/tests/driver/ok_format_symbol_noemit/main.asm @@ -0,0 +1,39 @@ +#ruledef test +{ + ld {x: u8} => 0x55 @ x +} + +#fn add1(x) => x + 1 + +start: +x1 = add1(0x10) +ld x1 + +#const x2 = 0x11 +ld x2 + +#const(noemit) x3 = 0x11 +ld x3 + +loop: +#const y1 = 0x22 +ld y1 + +#const y2 = 0x22 +ld y2 + +#const(noemit) y3 = 0x22 +ld y3 + +.inner: +.z1 = 0x33 +ld .z1 + +#const .z2 = 0x33 +ld .z2 + +#const(noemit) .z3 = 0x33 +ld .z3 + +; command: main.asm -f symbols -o out.txt +; output: out.txt \ No newline at end of file diff --git a/tests/driver/ok_format_symbol_noemit/out.txt b/tests/driver/ok_format_symbol_noemit/out.txt new file mode 100644 index 00000000..1fbb9ab3 --- /dev/null +++ b/tests/driver/ok_format_symbol_noemit/out.txt @@ -0,0 +1,9 @@ +start = 0x0 +x1 = 0x11 +x2 = 0x11 +loop = 0x6 +y1 = 0x22 +y2 = 0x22 +y3.inner = 0xc +y3.z1 = 0x33 +y3.z2 = 0x33 diff --git a/tests/symbol_constant_simple/err_literal_const_invalid_attrb.asm b/tests/symbol_constant_simple/err_literal_const_invalid_attrb.asm new file mode 100644 index 00000000..28298717 --- /dev/null +++ b/tests/symbol_constant_simple/err_literal_const_invalid_attrb.asm @@ -0,0 +1,8 @@ +#ruledef test +{ + ld {x} => 0x55 @ x`8 +} + + +#const(invalid) val = 0xaa ; error: invalid attribute +ld val \ No newline at end of file diff --git a/tests/symbol_constant_simple/ok_literal_const.asm b/tests/symbol_constant_simple/ok_literal_const.asm new file mode 100644 index 00000000..e318884f --- /dev/null +++ b/tests/symbol_constant_simple/ok_literal_const.asm @@ -0,0 +1,8 @@ +#ruledef test +{ + ld {x} => 0x55 @ x`8 +} + + +#const val = 0xaa +ld val ; = 0x55aa \ No newline at end of file diff --git a/tests/symbol_constant_simple/ok_literal_const_noemit.asm b/tests/symbol_constant_simple/ok_literal_const_noemit.asm new file mode 100644 index 00000000..1451cd67 --- /dev/null +++ b/tests/symbol_constant_simple/ok_literal_const_noemit.asm @@ -0,0 +1,8 @@ +#ruledef test +{ + ld {x} => 0x55 @ x`8 +} + + +#const(noemit) val = 0xaa +ld val ; = 0x55aa \ No newline at end of file diff --git a/tests/symbol_constant_simple/ok_nested.asm b/tests/symbol_constant_simple/ok_nested.asm new file mode 100644 index 00000000..387e9574 --- /dev/null +++ b/tests/symbol_constant_simple/ok_nested.asm @@ -0,0 +1,11 @@ +#ruledef test +{ + ld {x}, {y}, {z} => 0x55 @ x`8 @ y`8 @ z`8 +} + + +x = 0x11 +.y = 0x22 +..z = 0x33 +ld x, .y, ..z ; = 0x55112233 +ld x, x.y, x.y.z ; = 0x55112233 \ No newline at end of file diff --git a/tests/symbol_constant_simple/ok_nested_const.asm b/tests/symbol_constant_simple/ok_nested_const.asm new file mode 100644 index 00000000..0fb9b601 --- /dev/null +++ b/tests/symbol_constant_simple/ok_nested_const.asm @@ -0,0 +1,11 @@ +#ruledef test +{ + ld {x}, {y}, {z} => 0x55 @ x`8 @ y`8 @ z`8 +} + + +#const x = 0x11 +#const .y = 0x22 +#const ..z = 0x33 +ld x, .y, ..z ; = 0x55112233 +ld x, x.y, x.y.z ; = 0x55112233 \ No newline at end of file