Skip to content

Commit

Permalink
refs #30. Expand constant macros
Browse files Browse the repository at this point in the history
  • Loading branch information
elimirks committed Jan 16, 2022
1 parent 0627c3c commit fa3ab0e
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 2 deletions.
37 changes: 36 additions & 1 deletion src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ enum ScopeEntry {
// Contains the number of args
Fun(usize),
Var(Loc),
// First parameter are the macro args
Define(Vec<String>, Expr),
}

struct FunContext<'a> {
Expand Down Expand Up @@ -606,6 +608,8 @@ fn gen_call(
instructions.push(format!("movq {},%rax", loc));
"*%rax"
},
Some(ScopeEntry::Define(_, _)) =>
todo!("Calling a #defined value isn't supported yet"),
None => return CompErr::err(pos, format!(
"{} not in scope", name)),
},
Expand Down Expand Up @@ -658,6 +662,8 @@ fn gen_reference(
instructions.push(format!("movq ${},%rax", name));
Ok((Loc::Register(dest_reg), RegSet::of(dest_reg)))
},
Some(ScopeEntry::Define(_, _)) => CompErr::err(pos, format!(
"#define value cannot be referenced")),
None => CompErr::err(pos, format!(
"{} not in scope", name)),
}
Expand Down Expand Up @@ -728,6 +734,8 @@ fn gen_expr_ass(
},
Some(ScopeEntry::Fun(_)) =>
CompErr::err(pos, format!("Cannot reassign a function")),
Some(ScopeEntry::Define(_, _)) =>
CompErr::err(pos, format!("Cannot reassign a #define value")),
None =>
CompErr::err(pos, format!("Variable {} not in scope", lhs_name)),
}
Expand Down Expand Up @@ -861,6 +869,18 @@ fn gen_expr(
CompErr::err(pos, format!(
"{} is a function, and can only be called or referenced",
name)),
Some(ScopeEntry::Define(args, body)) => {
if args.is_empty() {
// FIXME: Kinda hate this
// Have to appease the borrow checker...
// not sure if there is a bettery way
let b = body.clone();
gen_expr(c, instructions, &b)
} else {
CompErr::err(pos, format!(
"This macro must take {} args", args.len()))
}
},
None => CompErr::err(pos, format!(
"Variable {} not in scope", name)),
}
Expand Down Expand Up @@ -1257,6 +1277,7 @@ fn gen_fun(
fn root_prepass<'a>(
functions: &Vec<RSFunction>,
variables: &'a Vec<RSVariable>,
defines: Vec<RSDefine>,
) -> Result<(HashMap<String, ScopeEntry>, Vec<&'a Var>), CompErr> {
let mut scope = HashMap::new();
let mut root_vars = Vec::<&Var>::new();
Expand Down Expand Up @@ -1284,6 +1305,16 @@ fn root_prepass<'a>(
scope.insert(name.clone(), ScopeEntry::Fun(function.args.len()));
}

for define in defines {
let name = &define.name;
if scope.contains_key(name) {
return CompErr::err(&define.pos, format!(
"{} already in root scope", name));
}

scope.insert(name.clone(), ScopeEntry::Define(define.args, define.body));
}

Ok((scope, root_vars))
}

Expand Down Expand Up @@ -1382,13 +1413,16 @@ fn gen(
strings: Vec<(usize, Vec<Vec<char>>)>,
functions: Vec<RSFunction>,
variables: Vec<RSVariable>,
defines: Vec<RSDefine>,
writer: &mut dyn Write
) -> Result<(), CompErr> {
let mut w = BufWriter::new(writer);

let (global_scope, root_vars) = root_prepass(
&functions,
&variables)?;
&variables,
defines
)?;

CompErr::from_io_res(generate_data_segment(&root_vars, &mut w))?;
CompErr::from_io_res(generate_strings(&strings, &mut w))?;
Expand Down Expand Up @@ -1525,6 +1559,7 @@ pub fn generate(parse_result: ParseResult, writer: &mut dyn Write) {
parse_result.strings,
parse_result.functions,
parse_result.variables,
parse_result.defines,
writer
) {
Ok(_) => {},
Expand Down
5 changes: 4 additions & 1 deletion src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub struct ParseResult {
pub strings: Vec<(usize, Vec<Vec<char>>)>,
pub functions: Vec<RSFunction>,
pub variables: Vec<RSVariable>,
pub defines: Vec<RSDefine>,
pub errors: Vec<CompErr>,
}

Expand All @@ -27,6 +28,7 @@ impl ParseResult {
strings: vec!(),
functions: vec!(),
variables: vec!(),
defines: vec!(),
errors: vec!(),
}
}
Expand Down Expand Up @@ -885,7 +887,7 @@ fn parse_content(
let mut c = ParseContext {
content: content.as_bytes(),
offset: 0,
file_id: file_id,
file_id,
strings: vec!(),
tok_stack: vec!(),
};
Expand Down Expand Up @@ -1038,6 +1040,7 @@ fn parse_file(
}
guard.result.functions.append(&mut statements.functions);
guard.result.variables.append(&mut statements.variables);
guard.result.defines.append(&mut statements.defines);
guard.result.file_paths.push((path_str, path));
guard.result.strings.push((file_id, strings));
},
Expand Down
13 changes: 13 additions & 0 deletions test/define.b
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#import "../assets/best.b";

#define THE_ANSWER 42;
#define LUCKY (13);
#define SEMIPRIME() 35;
#define BINCEIL(n, m) (n + m) & ~m;

main() {
assert_eq_int(42, THE_ANSWER);
assert_eq_int(13, LUCKY);
assert_eq_int(35, SEMIPRIME);
/* assert_eq_int(8, BINCEIL(3, 7)); */
}

0 comments on commit fa3ab0e

Please sign in to comment.