Skip to content

Commit f3247a0

Browse files
committed
add command-line defines
1 parent 5759ed6 commit f3247a0

38 files changed

+360
-12
lines changed

src/asm/mod.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,15 @@ pub struct AssemblyOptions
9595
pub debug_iterations: bool,
9696
pub optimize_statically_known: bool,
9797
pub optimize_instruction_matching: bool,
98+
99+
pub driver_symbol_defs: Vec<DriverSymbolDef>,
100+
}
101+
102+
103+
pub struct DriverSymbolDef
104+
{
105+
pub name: String,
106+
pub value: expr::Value,
98107
}
99108

100109

@@ -123,6 +132,8 @@ impl AssemblyOptions
123132
debug_iterations: false,
124133
optimize_statically_known: true,
125134
optimize_instruction_matching: true,
135+
136+
driver_symbol_defs: Vec::new(),
126137
}
127138
}
128139
}
@@ -230,6 +241,11 @@ pub fn assemble<S>(
230241
assembly.decls.as_ref().unwrap(),
231242
assembly.defs.as_ref().unwrap())?);
232243

244+
check_unused_defines(
245+
report,
246+
opts,
247+
assembly.decls.as_ref().unwrap())?;
248+
233249
Ok(())
234250
};
235251

@@ -244,4 +260,42 @@ pub fn assemble<S>(
244260
}
245261

246262
assembly
263+
}
264+
265+
266+
fn check_unused_defines(
267+
report: &mut diagn::Report,
268+
opts: &asm::AssemblyOptions,
269+
decls: &asm::ItemDecls)
270+
-> Result<(), ()>
271+
{
272+
let mut had_error = false;
273+
274+
for symbol_def in &opts.driver_symbol_defs
275+
{
276+
let hierarchy = symbol_def.name
277+
.split(".")
278+
.collect::<Vec<_>>();
279+
280+
let maybe_decl = decls.symbols.try_get_by_name(
281+
&util::SymbolContext::new_global(),
282+
0,
283+
&hierarchy);
284+
285+
if let None = maybe_decl
286+
{
287+
report.error(
288+
format!(
289+
"unused define `{}`",
290+
symbol_def.name));
291+
292+
had_error = true;
293+
}
294+
}
295+
296+
match had_error
297+
{
298+
false => Ok(()),
299+
true => Err(()),
300+
}
247301
}

src/asm/resolver/constant.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,20 @@ fn resolve_constant_simple(
6262
let asm::AstSymbolKind::Constant(ref ast_const) = ast_symbol.kind
6363
else { unreachable!() };
6464

65+
66+
// Overwrite with a value from the command-line, if present
67+
let symbol_decl = decls.symbols.get(item_ref);
68+
if let Some(driver_def) = opts.driver_symbol_defs
69+
.iter()
70+
.find(|s| s.name == symbol_decl.name)
71+
{
72+
let symbol = defs.symbols.get_mut(item_ref);
73+
symbol.value = driver_def.value.clone();
74+
symbol.resolved = true;
75+
return Ok(asm::ResolutionState::Resolved);
76+
}
77+
78+
6579
let value = asm::resolver::eval_simple(
6680
report,
6781
decls,

src/driver.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,13 @@ fn make_opts() -> getopts::Options
242242
"q", "quiet",
243243
"Suppress progress reports.");
244244

245+
opts.opt(
246+
"d", "define",
247+
"Defines a constant.",
248+
"VALUE",
249+
getopts::HasArg::Yes,
250+
getopts::Occur::Multi);
251+
245252
opts.opt(
246253
"", "color",
247254
"Style the output with colors. [on/off]",
@@ -337,6 +344,14 @@ fn parse_command(
337344
command.show_version |= parsed.opt_present("v");
338345
command.show_help |= parsed.opt_present("h");
339346

347+
for define_arg in parsed.opt_strs("d")
348+
{
349+
command.opts.driver_symbol_defs.push(
350+
parse_define_arg(
351+
report,
352+
&define_arg)?);
353+
}
354+
340355
command.opts.debug_iterations |=
341356
parsed.opt_present("debug-iters");
342357

@@ -619,6 +634,85 @@ pub fn parse_output_format(
619634
}
620635

621636

637+
fn parse_define_arg(
638+
report: &mut diagn::Report,
639+
raw_str: &str)
640+
-> Result<asm::DriverSymbolDef, ()>
641+
{
642+
let split = raw_str
643+
.split('=')
644+
.collect::<Vec<_>>();
645+
646+
let name = split[0].to_string();
647+
648+
if split.len() == 1
649+
{
650+
return Ok(asm::DriverSymbolDef {
651+
name,
652+
value: expr::Value::make_bool(true),
653+
});
654+
}
655+
656+
if split.len() != 2
657+
{
658+
report.error(
659+
format!(
660+
"invalid define argument `{}`",
661+
raw_str));
662+
663+
return Err(());
664+
}
665+
666+
let value_str = split[1];
667+
668+
let value = {
669+
if value_str == "true"
670+
{
671+
expr::Value::make_bool(true)
672+
}
673+
else if value_str == "false"
674+
{
675+
expr::Value::make_bool(false)
676+
}
677+
else
678+
{
679+
let has_negative_sign = split[1].chars().next() == Some('-');
680+
681+
let maybe_value = syntax::excerpt_as_bigint(
682+
None,
683+
diagn::Span::new_dummy(),
684+
if has_negative_sign { split[1].get(1..).unwrap() } else { split[1] });
685+
686+
687+
use std::ops::Neg;
688+
689+
match maybe_value
690+
{
691+
Ok(value) =>
692+
expr::Value::make_integer(
693+
if has_negative_sign { value.neg() } else { value }),
694+
695+
Err(()) =>
696+
{
697+
report.error(
698+
format!(
699+
"invalid value for define `{}`",
700+
name));
701+
702+
return Err(());
703+
}
704+
}
705+
}
706+
};
707+
708+
709+
Ok(asm::DriverSymbolDef {
710+
name,
711+
value,
712+
})
713+
}
714+
715+
622716
pub fn format_output(
623717
fileserver: &dyn util::FileServer,
624718
decls: &asm::ItemDecls,

src/expr/expression.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,12 @@ impl Value
129129
}
130130

131131

132+
pub fn make_bool(value: bool) -> Value
133+
{
134+
Value::Bool(value)
135+
}
136+
137+
132138
pub fn make_string<T: Into<String>, S: Into<String>>(value: T, encoding: S) -> Value
133139
{
134140
Value::String(ExprString

src/expr/parser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ impl<'a, 'tokens> ExpressionParser<'a, 'tokens>
574574
let number = tk_number.excerpt.clone().unwrap();
575575

576576
let bigint = syntax::excerpt_as_bigint(
577-
self.report,
577+
Some(self.report),
578578
tk_number.span,
579579
&number)?;
580580

src/syntax/excerpt.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ pub fn excerpt_as_usize(
169169

170170

171171
pub fn excerpt_as_bigint(
172-
report: &mut diagn::Report,
172+
report: Option<&mut diagn::Report>,
173173
span: diagn::Span,
174174
excerpt: &str)
175175
-> Result<util::BigInt, ()>
@@ -195,9 +195,12 @@ pub fn excerpt_as_bigint(
195195
Some(d) => d,
196196
None =>
197197
{
198-
report.error_span(
199-
"invalid digits",
200-
span);
198+
if let Some(report) = report
199+
{
200+
report.error_span(
201+
"invalid digits",
202+
span);
203+
}
201204

202205
return Err(());
203206
}
@@ -211,9 +214,12 @@ pub fn excerpt_as_bigint(
211214

212215
if digit_num == 0
213216
{
214-
report.error_span(
215-
"invalid value",
216-
span);
217+
if let Some(report) = report
218+
{
219+
report.error_span(
220+
"invalid value",
221+
span);
222+
}
217223

218224
return Err(());
219225
}

src/test/file.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub fn extract_expectations(
4949
{
5050
let value =
5151
syntax::excerpt_as_bigint(
52-
&mut diagn::Report::new(),
52+
None,
5353
diagn::Span::new_dummy(),
5454
value_str)
5555
.unwrap();

src/usage_help.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,15 @@ Examples:
2222
* `-h, --help`
2323
Display this information.
2424
* `-t, --iters=NUM`
25-
The max number of resolution iterations to attempt. (Default: 10)
25+
The maximum number of resolution iterations to attempt.
26+
(Default: 10)
27+
* `-dNAME, --define=NAME`
28+
* `-dNAME=VALUE, --define=NAME=VALUE`
29+
Overwrites a constant definition with the given value,
30+
or `true` if none is given.
2631
* `--color=on/off`
27-
Whether to style the output with colors. (Default: on)
32+
Whether to style the output with colors.
33+
(Default: on)
2834
* `--debug-iters`
2935
Print debug info during resolution iterations.
3036
* `--debug-no-optimize-static`
@@ -54,7 +60,7 @@ Examples:
5460
* `binary`
5561

5662
* `annotated,base:16,group:2`
57-
Annotate the output data with snippets
63+
Annotates the output data with snippets
5864
of the source code.
5965

6066
* `annotatedbin`
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ruledef test
2+
{
3+
ld {x: u8} => 0x55 @ x
4+
}
5+
6+
val = 0
7+
ld val
8+
9+
; command: main.asm -o out.bin -dval=abc=123
10+
; error: invalid define argument `val=abc=123`
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ruledef test
2+
{
3+
ld {x: u8} => 0x55 @ x
4+
}
5+
6+
val = 0
7+
ld val
8+
9+
; command: main.asm -o out.bin -d123=123
10+
; error: unused define `123`

0 commit comments

Comments
 (0)