Skip to content

Commit

Permalink
fix #19. Implement postfix ++ and --
Browse files Browse the repository at this point in the history
  • Loading branch information
elimirks committed Dec 25, 2021
1 parent cab2526 commit 220e247
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 26 deletions.
6 changes: 4 additions & 2 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,10 @@ impl BinOp {

#[derive(Debug, Clone, PartialEq)]
pub enum UnaryOp {
Increment,
Decrement,
PreIncrement,
PreDecrement,
PostIncrement,
PostDecrement,
Negate,
BitNot,
}
Expand Down
43 changes: 33 additions & 10 deletions src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,23 +429,44 @@ fn gen_pre_op(
Ok((new_lhs_loc, rhs_loc, used_registers))
}

fn gen_unary_op_assign(
c: &mut FunContext, instructions: &mut Vec<String>,
asm_op: &str, expr: &Expr
fn gen_prep_unary_op_incdec(
c: &mut FunContext, instructions: &mut Vec<String>, expr: &Expr
) -> Result<(Loc, RegSet), CompErr> {
let (expr_loc, used_registers) = gen_expr(c, instructions, expr)?;

match expr_loc {
Loc::Register(_) | Loc::Immediate(_) =>
return CompErr::err(&expr.pos(), format!(
"`++` or `--` must operate on a variable")),
"`++` or `--` must operate on a memory location")),
_ => {},
};
Ok((expr_loc, used_registers))
}

instructions.push(format!("{} {}", asm_op, expr_loc));
fn gen_unary_op_pre_incdec(
c: &mut FunContext, instructions: &mut Vec<String>,
op_name: &str, expr: &Expr
) -> Result<(Loc, RegSet), CompErr> {
let (expr_loc, used_registers) = gen_prep_unary_op_incdec(c, instructions, expr)?;
instructions.push(format!("{} {}", op_name, expr_loc));
Ok((expr_loc, used_registers))
}

fn gen_unary_op_post_incdec(
c: &mut FunContext, instructions: &mut Vec<String>,
op_name: &str, expr: &Expr
) -> Result<(Loc, RegSet), CompErr> {
let (expr_loc, used_registers) = gen_prep_unary_op_incdec(c, instructions, expr)?;

// We can pick any register since we know expr_loc MUST NOT be in a register
let dest_reg = Reg::R11;
let dest_loc = Loc::Register(dest_reg);

instructions.push(format!("movq {},{}", expr_loc, dest_loc));
instructions.push(format!("{} {}", op_name, expr_loc));
Ok((dest_loc, used_registers.with(dest_reg)))
}

fn gen_unary_op_non_assign(
c: &mut FunContext, instructions: &mut Vec<String>,
asm_op: &str, expr: &Expr
Expand Down Expand Up @@ -474,10 +495,12 @@ fn gen_unary_op(
op: &UnaryOp, expr: &Expr
) -> Result<(Loc, RegSet), CompErr> {
match op {
UnaryOp::Increment => gen_unary_op_assign(c, instructions, "incq", expr),
UnaryOp::Decrement => gen_unary_op_assign(c, instructions, "decq", expr),
UnaryOp::BitNot => gen_unary_op_non_assign(c, instructions, "notq", expr),
UnaryOp::Negate => gen_unary_op_non_assign(c, instructions, "negq", expr),
UnaryOp::PreIncrement => gen_unary_op_pre_incdec(c, instructions, "incq", expr),
UnaryOp::PreDecrement => gen_unary_op_pre_incdec(c, instructions, "decq", expr),
UnaryOp::PostIncrement => gen_unary_op_post_incdec(c, instructions, "incq", expr),
UnaryOp::PostDecrement => gen_unary_op_post_incdec(c, instructions, "decq", expr),
UnaryOp::BitNot => gen_unary_op_non_assign(c, instructions, "notq", expr),
UnaryOp::Negate => gen_unary_op_non_assign(c, instructions, "negq", expr),
}
}

Expand Down Expand Up @@ -1378,7 +1401,7 @@ pub fn generate(parse_result: ParseResult, writer: &mut dyn Write) {
) {
Ok(_) => {},
Err(err) => {
print_comp_error(&parse_result.file_contents, &err);
print_comp_error(&parse_result.file_paths, &err);
std::process::exit(1);
},
}
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ fn parse_or_die(inputs: &Vec<String>) -> ParseResult {
let parse_result = parse_files(inputs);

for err in &parse_result.errors {
print_comp_error(&parse_result.file_contents, &err);
print_comp_error(&parse_result.file_paths, &err);
}
if !parse_result.errors.is_empty() {
std::process::exit(1);
Expand Down
47 changes: 34 additions & 13 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use std::thread;

pub struct ParseResult {
// Stored in order of file_id (in Pos)
// Stores (file_name, file_contents)
pub file_contents: Vec<(String, String)>,
// Stores (file_name, file_paths)
pub file_paths: Vec<(String, PathBuf)>,
// Stores (file_id, strings_vec)
pub strings: Vec<(usize, Vec<Vec<char>>)>,
pub functions: Vec<RSFunction>,
Expand All @@ -23,7 +23,7 @@ pub struct ParseResult {
impl ParseResult {
fn new() -> ParseResult {
ParseResult {
file_contents: vec!(),
file_paths: vec!(),
strings: vec!(),
functions: vec!(),
variables: vec!(),
Expand Down Expand Up @@ -475,7 +475,8 @@ fn get_lr_op_precedence(op: &BinOp) -> u8 {
fn parse_expr_prec(
c: &mut ParseContext, precedence: u8
) -> Result<Expr, CompErr> {
let mut expr = parse_expr_unchained(c)?;
let unchained = parse_expr_unchained(c)?;
let mut expr = parse_postfix(c, unchained)?;
loop {
match parse_op(c)? {
(pos, tok, Some(binop)) => {
Expand Down Expand Up @@ -664,9 +665,9 @@ fn parse_expr_unchained(c: &mut ParseContext) -> Result<Expr, CompErr> {
Token::Asterisk => Ok(Expr::Dereference(
pos, Box::new(parse_expr_unchained(c)?))),
Token::PlusPlus => Ok(Expr::UnaryOperator(
pos, UnaryOp::Increment, Box::new(parse_expr_unchained(c)?))),
pos, UnaryOp::PreIncrement, Box::new(parse_expr_unchained(c)?))),
Token::MinusMinus => Ok(Expr::UnaryOperator(
pos, UnaryOp::Decrement, Box::new(parse_expr_unchained(c)?))),
pos, UnaryOp::PreDecrement, Box::new(parse_expr_unchained(c)?))),
Token::Minus => Ok(Expr::UnaryOperator(
pos, UnaryOp::Negate, Box::new(parse_expr_unchained(c)?))),
Token::Tilde => Ok(Expr::UnaryOperator(
Expand All @@ -682,6 +683,26 @@ fn parse_expr_unchained(c: &mut ParseContext) -> Result<Expr, CompErr> {
}
}

fn parse_postfix(c: &mut ParseContext, expr: Expr) -> Result<Expr, CompErr> {
let (pos, tok) = pop_tok(c)?;
match tok {
Token::MinusMinus => {
let next = parse_postfix(c, expr)?;
Ok(Expr::UnaryOperator(
pos, UnaryOp::PostDecrement, Box::new(next)))
},
Token::PlusPlus => {
let next = parse_postfix(c, expr)?;
Ok(Expr::UnaryOperator(
pos, UnaryOp::PostIncrement, Box::new(next)))
},
_ => {
push_tok(c, (pos, tok));
Ok(expr)
},
}
}

// Assumes the rparen has already been parsed
fn parse_expr_call(
c: &mut ParseContext, fun_id_pos: Pos, name: String
Expand Down Expand Up @@ -750,11 +771,12 @@ fn get_parse_position(content: &Vec<char>, offset: usize) -> (String, usize, usi
(line.to_string(), row, col)
}

pub fn print_comp_error(file_contents: &Vec<(String, String)>, err: &CompErr) {
pub fn print_comp_error(file_paths: &Vec<(String, PathBuf)>, err: &CompErr) {
println!("Compile error: {}", err.message);
match &err.pos {
Some(pos) => {
let (file_name, content) = &file_contents[pos.file_id];
let (file_name, path_buf) = &file_paths[pos.file_id];
let content = std::fs::read_to_string(&path_buf).unwrap();
println!("In file: {}", file_name);

let (line, row, col) = get_parse_position(
Expand All @@ -774,9 +796,8 @@ pub fn print_comp_error(file_contents: &Vec<(String, String)>, err: &CompErr) {
}

fn parse_content(
file_id: usize, content: &String
file_id: usize, content: String
) -> Result<(RootStatements, Vec<Vec<char>>), CompErr> {
// TODO: Validate `content` is valid ASCII first
let mut c = ParseContext {
content: content.as_bytes(),
offset: 0,
Expand Down Expand Up @@ -912,7 +933,7 @@ fn parse_file(

let (mutex, cvar) = parse_state.as_ref();

let parsed_content = parse_content(file_id, &content);
let parsed_content = parse_content(file_id, content);
let mut guard = match mutex.lock() {
Ok(guard) => guard,
_ => return, // Poison pill!
Expand All @@ -931,12 +952,12 @@ fn parse_file(
}
guard.result.functions.append(&mut statements.functions);
guard.result.variables.append(&mut statements.variables);
guard.result.file_contents.push((path_str, content));
guard.result.file_paths.push((path_str, path));
guard.result.strings.push((file_id, strings));
},
Err(error) => {
guard.result.errors.push(error);
guard.result.file_contents.push((path_str, content));
guard.result.file_paths.push((path_str, path));
},
}
guard.running_parsers -= 1;
Expand Down

0 comments on commit 220e247

Please sign in to comment.