From 72baca71be1b0dad59960c3c76b9c6e53bf00f6d Mon Sep 17 00:00:00 2001 From: YSawc Date: Thu, 15 Oct 2020 07:32:08 +0900 Subject: [PATCH] Implement underScore operator. --- src/code_gen/gen_x86_64.rs | 4 ++++ src/error/error.rs | 3 ++- src/fmt/fmt.rs | 6 ++++++ src/node/node.rs | 10 ++++++++++ src/node_arr/node_arr.rs | 13 ++++++++++++- src/parser/error.rs | 1 + src/parser/parser.rs | 29 +++++++++++++++++++++++++++++ src/simplified/simplified.rs | 2 +- src/tests/parser/tests.rs | 36 ++++++++++++++++++++++++++++++++++++ src/token/token.rs | 2 ++ test.sh | 6 +++++- 11 files changed, 108 insertions(+), 4 deletions(-) diff --git a/src/code_gen/gen_x86_64.rs b/src/code_gen/gen_x86_64.rs index 7c098c1..d50b05d 100644 --- a/src/code_gen/gen_x86_64.rs +++ b/src/code_gen/gen_x86_64.rs @@ -38,6 +38,10 @@ fn gen_x86(f: &mut fs::File, ns: NodeSt) -> String { write!(f, " jmp .L.return\n").unwrap(); return l; } + NodeKind::UnderScore => { + unsafe { write!(f, " mov $0, %{}\n", REGS[CC as usize]).unwrap() }; + unsafe { return REGS[CC as usize].to_string() }; + } _ => (), } diff --git a/src/error/error.rs b/src/error/error.rs index 64cf8bc..3aa0b41 100644 --- a/src/error/error.rs +++ b/src/error/error.rs @@ -70,7 +70,8 @@ impl Error { | ParseError::OperatorOutOfFnction(loc, ..) => loc.loc.clone(), ParseError::UndefinedVariable(loc) | ParseError::UnusedVariable(loc) - | ParseError::NotMatchReturnType(loc) => loc.clone(), + | ParseError::NotMatchReturnType(loc) + | ParseError::UnexpectedUnderScoreOperator(loc) => loc.clone(), ParseError::Eof => Loc::new(input.len() as u8, input.len() as u8 + 1), }; (e, loc) diff --git a/src/fmt/fmt.rs b/src/fmt/fmt.rs index 022b974..bbc03bb 100644 --- a/src/fmt/fmt.rs +++ b/src/fmt/fmt.rs @@ -40,6 +40,7 @@ impl fmt::Display for TokenKind { TokenKind::Fn => write!(f, "fn"), TokenKind::LBrace => write!(f, "{{"), TokenKind::RBrace => write!(f, "}}"), + TokenKind::UnderScore => write!(f, "_"), } } } @@ -92,6 +93,11 @@ impl fmt::Display for ParseError { ParseError::UndefinedVariable(loc) => write!(f, "{} Undefined variable detected!", loc), ParseError::UnusedVariable(loc) => write!(f, "{} Unused variable detected!", loc), ParseError::NotMatchReturnType(loc) => write!(f, "{}: Return type is not match.", loc), + ParseError::UnexpectedUnderScoreOperator(loc) => write!( + f, + "{}: Expected under socre as void return, but used as operator.", + loc + ), ParseError::Eof => write!(f, "Expected token, but not detected."), } } diff --git a/src/node/node.rs b/src/node/node.rs index 61c6989..8fd3619 100644 --- a/src/node/node.rs +++ b/src/node/node.rs @@ -25,6 +25,7 @@ pub enum NodeKind { Fn, LBrace, RBrace, + UnderScore, Default, } @@ -113,6 +114,9 @@ impl Node { pub fn mfn(loc: Loc) -> Self { Self::new(NodeKind::Fn, loc) } + pub fn under_score(loc: Loc) -> Self { + Self::new(NodeKind::UnderScore, loc) + } } impl NodeSt { @@ -122,4 +126,10 @@ impl NodeSt { ..Default::default() } } + pub fn under_score(loc: Loc) -> Self { + NodeSt { + c: Node::under_score(loc), + ..Default::default() + } + } } diff --git a/src/node_arr/node_arr.rs b/src/node_arr/node_arr.rs index 00a2961..4011677 100644 --- a/src/node_arr/node_arr.rs +++ b/src/node_arr/node_arr.rs @@ -82,7 +82,7 @@ impl NodeArr { } } else { match l.to_owned()?.to_owned().ret_node_st.c.value { - NodeKind::Default => return l, + NodeKind::UnderScore => return l, _ => { return Err(ParseError::NotMatchReturnType( l.to_owned().unwrap().to_owned().ret_node_st.c.loc, @@ -195,6 +195,17 @@ impl NodeArr { } continue; } + NodeKind::UnderScore => { + if it.peek().unwrap().to_owned().to_owned().value != TokenKind::RBrace { + return Err(ParseError::UnexpectedUnderScoreOperator( + n.to_owned().c.loc, + )); + } + b = true; + let n = NodeSt::under_score(n.c.loc); + r = n.to_owned(); + n + } NodeKind::Ident(s) => match Self::find_l(s, l.to_owned()) { Some(v) => { if it.peek().unwrap().to_owned().to_owned().value == TokenKind::RBrace { diff --git a/src/parser/error.rs b/src/parser/error.rs index 4314bad..e7420fb 100644 --- a/src/parser/error.rs +++ b/src/parser/error.rs @@ -18,6 +18,7 @@ pub enum ParseError { UndefinedVariable(Loc), UnusedVariable(Loc), NotMatchReturnType(Loc), + UnexpectedUnderScoreOperator(Loc), // UnexpectedToken(Token), // NotExpression(Token), // UnclosedOpenParen(Token), diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 876f6c5..5f092b6 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -44,6 +44,12 @@ impl NodeSt { ..Default::default() } } + pub fn new_node(c: Node) -> Self { + Self { + c, + ..Default::default() + } + } } impl NodeSt { @@ -176,6 +182,29 @@ impl NodeSt { _ => return Err(ParseError::NotClosedStmt(et.next().unwrap().to_owned())), } } + Token { + value: TokenKind::UnderScore, + loc, + } => { + let mut et = it.clone(); + it.next().unwrap(); + let u = Node::under_score(loc.to_owned()); + let op = Self::new_node(u); + if it.peek() == None { + et.next(); + return Err(ParseError::NotClosedStmt(et.next().unwrap().to_owned())); + } + match it.peek().unwrap() { + Token { + value: TokenKind::SemiColon, + .. + } => { + it.next(); + } + _ => (), + } + return Ok(op); + } _ => { let lhs = Self::cmp(it)?; match it.peek().unwrap() { diff --git a/src/simplified/simplified.rs b/src/simplified/simplified.rs index 88f4e99..8ed3949 100644 --- a/src/simplified/simplified.rs +++ b/src/simplified/simplified.rs @@ -113,7 +113,7 @@ pub fn exec(ns: NodeSt) -> NodeSt { _ => unreachable!(), } } - NodeKind::Num(_) => return ns, + NodeKind::Num(_) | NodeKind::UnderScore => return ns, _ => unreachable!(), }; } diff --git a/src/tests/parser/tests.rs b/src/tests/parser/tests.rs index e276a83..2d606c1 100644 --- a/src/tests/parser/tests.rs +++ b/src/tests/parser/tests.rs @@ -148,3 +148,39 @@ fn not_match_return_type_test() { }; assert!(l) } + +#[test] +fn match_void_type_test() { + let t = Token::tokenize("fn { _ }").unwrap(); + let l = match NodeArr::w_parser(t) { + Ok(_) => true, + _ => false, + }; + assert!(l) +} + +#[test] +fn not_match_void_type_test() { + let t = Token::tokenize("fn int { _ }").unwrap(); + let l = match NodeArr::w_parser(t) { + Ok(_) => false, + Err(e) => match e { + ParseError::NotMatchReturnType(_) => true, + _ => false, + }, + }; + assert!(l) +} + +#[test] +fn unexpected_underscore_operator_test() { + let t = Token::tokenize("fn int { _; 1 }").unwrap(); + let l = match NodeArr::w_parser(t) { + Ok(_) => false, + Err(e) => match e { + ParseError::UnexpectedUnderScoreOperator(_) => true, + _ => false, + }, + }; + assert!(l) +} diff --git a/src/token/token.rs b/src/token/token.rs index 1820c0b..17206a3 100644 --- a/src/token/token.rs +++ b/src/token/token.rs @@ -30,6 +30,7 @@ pub enum TokenKind { Fn, LBrace, RBrace, + UnderScore, } pub type Token = Annot; @@ -149,6 +150,7 @@ impl Token { map.insert('='.into(), TokenKind::Assign); map.insert('{'.into(), TokenKind::LBrace); map.insert('}'.into(), TokenKind::RBrace); + map.insert('_'.into(), TokenKind::UnderScore); map } diff --git a/test.sh b/test.sh index 4ec00d3..e1348d2 100644 --- a/test.sh +++ b/test.sh @@ -62,10 +62,14 @@ assert 10 'fn int { if (2 == 3) 5; else 10; }' assert 31 'fn int { if (2 == 3) 5+3; else 10+21; }' simplified assert 8 'fn int { if (2 < 3) 5+3; else 10; }' assert 2 'fn int { int a = 3; a; a = 2; a; }' -# assert 5 'fn int { int a = 5; int b = a; a = 2; b }' +assert 5 'fn int { int a = 5; int b = a; a = 2; b }' assert 1 'fn int { 1; }' assert 2 'fn int { 2 }' assert 3 'fn int { return 3; }' +assert 0 'fn { _ }' +assert 0 'fn { int vvv = 55; 0*vvv*0; _ }' +assert 0 'fn { int vvv = 4; 1+2*vvv/4-1; _; }' +assert 0 'fn { int vvv = 4; 1+2*vvv/4-1; _ }' simplified echo "------------------------------" echo "All test passed!"