Skip to content

Commit

Permalink
Implement single block statement.
Browse files Browse the repository at this point in the history
  • Loading branch information
YSawc committed Nov 21, 2020
1 parent 3de8250 commit 1948e97
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 98 deletions.
12 changes: 11 additions & 1 deletion src/code_gen/gen_llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ impl Femitter {
| NodeKind::ReAssignVar(_)
| NodeKind::GVar(_)
| NodeKind::LVar(_)
| NodeKind::If => match ns.c.value {
| NodeKind::If
| NodeKind::LBrace => match ns.c.value {
NodeKind::Num(n) => {
write!(f, " %{} = alloca i32, align 4\n", self.rc).unwrap();
write!(f, " store i32 {}, i32* %{}, align 4\n", n, self.rc).unwrap();
Expand Down Expand Up @@ -269,6 +270,15 @@ impl Femitter {

return ();
}
NodeKind::LBrace => {
let stmts: NodeArr = *ns.to_owned().stmts.to_owned().unwrap();
let mut istmts = stmts.node_st_vec.iter().peekable();

while istmts.peek() != None {
self.emitter(f, istmts.next().unwrap().to_owned())
}
return ();
}
_ => unreachable!(),
},
_ => (),
Expand Down
8 changes: 5 additions & 3 deletions src/node/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub struct NodeSt {
pub cond: Option<Box<NodeSt>>,
pub if_stmts: Option<Box<NodeArr>>,
pub else_if_stmts: Option<Box<NodeArr>>,
pub stmts: Option<Box<NodeArr>>,
}

impl Node {
Expand Down Expand Up @@ -121,6 +122,9 @@ impl Node {
pub fn melse(loc: Loc) -> Self {
Self::new(NodeKind::Else, loc)
}
pub fn st(loc: Loc) -> Self {
Self::new(NodeKind::LBrace, loc)
}
pub fn mfn(loc: Loc) -> Self {
Self::new(NodeKind::Fn, loc)
}
Expand Down Expand Up @@ -207,9 +211,7 @@ impl NodeSt {
| NodeKind::Ident(_)
| NodeKind::GVar(_)
| NodeKind::LVar(_) => true,
| NodeKind::If => {
self.if_stmts.unwrap().ret_node_st.isi()
},
NodeKind::If => self.if_stmts.unwrap().ret_node_st.isi(),
_ => false,
}
}
Expand Down
31 changes: 26 additions & 5 deletions src/node_arr/node_arr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ impl NodeArr {
| NodeKind::NewAssign
| NodeKind::Assign
| NodeKind::UnderScore
| NodeKind::If => {
| NodeKind::If
| NodeKind::LBrace => {
// println!("n.c.value: {:?}", n.c.value);
match n.c.value {
NodeKind::Return => {
Expand Down Expand Up @@ -289,6 +290,30 @@ impl NodeArr {
NodeKind::If => {
a.parse_if(it, n)?;
}
NodeKind::LBrace => {
a.set_imm_env();
let (stmts, uev) =
Self::parse_statement(it, a.imm_env_v.to_owned())?;
a.update_used_variable(uev);
if it.peek_value() == TokenKind::RBrace {
a.set_end_of_node()
}

let stmt_isi = NodeSt::isi(stmts.ret_node_st.to_owned());

if a.end_of_node {
a.ret_node_st = match stmt_isi {
true => stmts.to_owned().ret_node_st,
false => NodeSt::under_score(Loc::default()),
}
}

let mut n = n.to_owned();
println!("n {:?}", n);

n.stmts = Some(Box::new(stmts));
a.node_st_vec.push(n.to_owned());
}
_ => unreachable!(),
}
}
Expand Down Expand Up @@ -351,10 +376,6 @@ impl NodeArr {

impl NodeArr {
pub fn parse_if(&mut self, it: &mut TokenIter, n: NodeSt) -> Result<(), ParseError> {
if it.p.peek() == None {
return Err(ParseError::Eof);
}

self.set_imm_env();

let (if_stmts, uev) = Self::parse_statement(it, self.imm_env_v.to_owned())?;
Expand Down
186 changes: 97 additions & 89 deletions src/parser/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,102 +59,110 @@ impl NodeSt {

pub fn stmt(it: &mut TokenIter) -> Result<NodeSt, ParseError> {
match it.p.peek().unwrap().value {
TokenKind::Return | TokenKind::Int | TokenKind::If | TokenKind::UnderScore => {
match it.p.peek().unwrap() {
Token {
value: TokenKind::Return,
loc,
} => {
it.next_with_shadow();
let op = Node::ret(loc.to_owned());
let mut lhs = Self::cmp(it)?;
lhs = Self::new_unary(op, lhs);
if it.p.peek() == None {
return Err(ParseError::NotClosedStmt(
it.shadow_p.next().unwrap().to_owned(),
));
}
it.expect_token(
TokenKind::SemiColon,
ParseError::NotClosedStmt(
it.p.to_owned().peek().unwrap().to_owned().to_owned(),
),
)?;
return Ok(lhs);
TokenKind::Return
| TokenKind::Int
| TokenKind::If
| TokenKind::LBrace
| TokenKind::UnderScore => match it.p.peek().unwrap() {
Token {
value: TokenKind::Return,
loc,
} => {
it.next_with_shadow();
let op = Node::ret(loc.to_owned());
let mut lhs = Self::cmp(it)?;
lhs = Self::new_unary(op, lhs);
if it.p.peek() == None {
return Err(ParseError::NotClosedStmt(
it.shadow_p.next().unwrap().to_owned(),
));
}
Token {
value: TokenKind::Int,
loc,
} => {
it.p.next().unwrap();
let i = Node::int(loc.to_owned());
let (s, _) = it.expect_ident(ParseError::NotIdent(
it.expect_token(
TokenKind::SemiColon,
ParseError::NotClosedStmt(
it.p.to_owned().peek().unwrap().to_owned().to_owned(),
))?;
let l = Self::new_ident(
s.to_owned(),
it.p.peek().unwrap().to_owned().to_owned(),
);
let l = Self::new_unary(i, l);
it.expect_token(
TokenKind::Assign,
ParseError::NotAssign(
it.p.to_owned().peek().unwrap().to_owned().to_owned(),
),
)?;
let op = Node::new_assign(loc.to_owned());
let lhs = Self::new_unary(op, l);
return Ok(lhs);
}
Token {
value: TokenKind::If,
loc,
} => {
it.p.next().unwrap();
let op = Node::mif(loc.to_owned());
it.expect_token(
TokenKind::LParen,
ParseError::NotOpenedParen(
it.p.to_owned().peek().unwrap().to_owned().to_owned(),
),
)?;
),
)?;
return Ok(lhs);
}
Token {
value: TokenKind::Int,
loc,
} => {
it.p.next().unwrap();
let i = Node::int(loc.to_owned());
let (s, _) = it.expect_ident(ParseError::NotIdent(
it.p.to_owned().peek().unwrap().to_owned().to_owned(),
))?;
let l =
Self::new_ident(s.to_owned(), it.p.peek().unwrap().to_owned().to_owned());
let l = Self::new_unary(i, l);
it.expect_token(
TokenKind::Assign,
ParseError::NotAssign(
it.p.to_owned().peek().unwrap().to_owned().to_owned(),
),
)?;
let op = Node::new_assign(loc.to_owned());
let lhs = Self::new_unary(op, l);
return Ok(lhs);
}
Token {
value: TokenKind::If,
loc,
} => {
it.p.next().unwrap();
let op = Node::mif(loc.to_owned());
it.expect_token(
TokenKind::LParen,
ParseError::NotOpenedParen(
it.p.to_owned().peek().unwrap().to_owned().to_owned(),
),
)?;

let cond = Self::cmp(it)?;
it.expect_token(
TokenKind::RParen,
ParseError::NotClosedStmt(
it.p.to_owned().peek().unwrap().to_owned().to_owned(),
),
)?;
let lhs = Self::new_if(op, cond.to_owned());
return Ok(lhs);
let cond = Self::cmp(it)?;
it.expect_token(
TokenKind::RParen,
ParseError::NotClosedStmt(
it.p.to_owned().peek().unwrap().to_owned().to_owned(),
),
)?;
let lhs = Self::new_if(op, cond.to_owned());
return Ok(lhs);
}
Token {
value: TokenKind::LBrace,
loc,
} => {
let st = Node::st(loc.to_owned());
let lhs = Self::new_node(st);
return Ok(lhs);
}
Token {
value: TokenKind::UnderScore,
loc,
} => {
it.next_with_shadow();
let u = Node::under_score(loc.to_owned());
let op = Self::new_node(u);
if it.p.peek() == None {
it.shadow_p.next();
return Err(ParseError::NotClosedStmt(
it.shadow_p.next().unwrap().to_owned(),
));
}
Token {
value: TokenKind::UnderScore,
loc,
} => {
it.next_with_shadow();
let u = Node::under_score(loc.to_owned());
let op = Self::new_node(u);
if it.p.peek() == None {
it.shadow_p.next();
return Err(ParseError::NotClosedStmt(
it.shadow_p.next().unwrap().to_owned(),
));
}

it.unexpect_token(
TokenKind::SemiColon,
ParseError::UnexpectedUnderScoreOperator(
it.p.to_owned().peek().unwrap().to_owned().to_owned().loc,
),
)?;
it.unexpect_token(
TokenKind::SemiColon,
ParseError::UnexpectedUnderScoreOperator(
it.p.to_owned().peek().unwrap().to_owned().to_owned().loc,
),
)?;

return Ok(op);
}
_ => unreachable!(),
return Ok(op);
}
}
_ => unreachable!(),
},
_ => return Self::cmp(it),
}
}
Expand Down
4 changes: 4 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ assert_llvm 0 'fn { if (1) { 2; 10; } else { 3*4; 5; } }' calc_if_label
assert_llvm 24 'fn int { int i = 4; int j = if (3) { int j = 6*i; j } else { 9 } j }'
assert_llvm 2 'fn int { int i = 1; if (3) { i = 2; } i }'
assert_llvm 1 'fn int { int i = 1; if (0) { i = 2; } i }'
assert_llvm 0 'fn { { _ } }'
assert_llvm 90 'fn int { int i = 3; { int i = i*30; i } }'
assert_llvm 3 'fn int { int i = 3; { i*30 } i }'
# assert_llvm 90 'fn int { int i = 3; i = { i*30 } i }'

echo "------------------------------"
echo "All llvm test passed!\n"

0 comments on commit 1948e97

Please sign in to comment.