Skip to content

Commit

Permalink
feat: support more bitwise operation
Browse files Browse the repository at this point in the history
  • Loading branch information
caelansar committed Nov 27, 2023
1 parent 1d38a1f commit 3ecc9ea
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 13 deletions.
9 changes: 9 additions & 0 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ pub enum Assign {
ModEq,
ShlAssign,
ShrAssign,
BitAndAssign,
BitOrAssign,
BitXorAssign,
}

impl TryFrom<&token::Token> for Assign {
Expand All @@ -149,6 +152,9 @@ impl TryFrom<&token::Token> for Assign {
token::Token::AsteriskEq => Ok(Assign::MultiplyEq),
token::Token::LeftShiftEq => Ok(Assign::ShlAssign),
token::Token::RightShiftEq => Ok(Assign::ShrAssign),
token::Token::BitOrEq => Ok(Assign::BitOrAssign),
token::Token::BitAndEq => Ok(Assign::BitAndAssign),
token::Token::BitXorEq => Ok(Assign::BitXorAssign),
_ => Err("invalid token"),
}
}
Expand All @@ -165,6 +171,9 @@ impl fmt::Display for Assign {
Assign::ModEq => write!(f, "%="),
Assign::ShlAssign => write!(f, "<<="),
Assign::ShrAssign => write!(f, ">>="),
Assign::BitAndAssign => write!(f, "&="),
Assign::BitOrAssign => write!(f, "|="),
Assign::BitXorAssign => write!(f, "^="),
}
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,24 @@ impl Compiler {
self.compile_expression(expr)?;
self.emit(code::Op::LeftShift, &[]);
}
ast::Assign::BitOrAssign => {
self.emit_get(&symbol);

self.compile_expression(expr)?;
self.emit(code::Op::BitOr, &[]);
}
ast::Assign::BitAndAssign => {
self.emit_get(&symbol);

self.compile_expression(expr)?;
self.emit(code::Op::BitAnd, &[]);
}
ast::Assign::BitXorAssign => {
self.emit_get(&symbol);

self.compile_expression(expr)?;
self.emit(code::Op::BitXor, &[]);
}
}
self.emit_set(&symbol);
}
Expand Down
3 changes: 3 additions & 0 deletions src/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ impl Evaluator {
ast::Assign::ModEq => &curr % &exp_val,
ast::Assign::ShlAssign => &curr << &exp_val,
ast::Assign::ShrAssign => &curr >> &exp_val,
ast::Assign::BitAndAssign => &curr & &exp_val,
ast::Assign::BitOrAssign => &curr | &exp_val,
ast::Assign::BitXorAssign => &curr ^ &exp_val,
};

self.env.borrow_mut().set(ident.clone(), val);
Expand Down
39 changes: 26 additions & 13 deletions src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,11 @@ impl<'a> Lexer<'a> {
Token::GtEq
}
Some('>') => {
self.read_char();
if let Some('=') = self.peek_char() {
self.read_char();
Token::RightShiftEq
} else {
self.read_char();
Token::RightShift
}
}
Expand All @@ -135,11 +135,11 @@ impl<'a> Lexer<'a> {
Token::LtEq
}
Some('<') => {
self.read_char();
if let Some('=') = self.peek_char() {
self.read_char();
Token::LeftShiftEq
} else {
self.read_char();
Token::LeftShift
}
}
Expand Down Expand Up @@ -189,23 +189,36 @@ impl<'a> Lexer<'a> {
Token::Mod
}
}
'&' => {
if let Some('&') = self.peek_char() {
'&' => match self.peek_char() {
Some('&') => {
self.read_char();
Token::And
} else {
Token::BitAnd
}
}
'|' => {
if let Some('|') = self.peek_char() {
Some('=') => {
self.read_char();
Token::BitAndEq
}
_ => Token::BitAnd,
},
'|' => match self.peek_char() {
Some('|') => {
self.read_char();
Token::Or
} else {
Token::BitOr
}
}
',' | ';' | ':' | '(' | ')' | '{' | '}' | '[' | ']' | '^' => {
Some('=') => {
self.read_char();
Token::BitOrEq
}
_ => Token::BitOr,
},
'^' => match self.peek_char() {
Some('=') => {
self.read_char();
Token::BitXorEq
}
_ => Token::BitXor,
},
',' | ';' | ':' | '(' | ')' | '{' | '}' | '[' | ']' => {
Token::from_str(token.to_string().as_str()).unwrap()
}
_ => {
Expand Down
10 changes: 10 additions & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ impl From<&token::Token> for Precedence {
token::Token::AsteriskEq => Precedence::Assign,
token::Token::SlashEq => Precedence::Assign,
token::Token::ModEq => Precedence::Assign,
token::Token::RightShiftEq => Precedence::Assign,
token::Token::LeftShiftEq => Precedence::Assign,
token::Token::BitOrEq => Precedence::Assign,
token::Token::BitXorEq => Precedence::Assign,
token::Token::BitAndEq => Precedence::Assign,
token::Token::Ne => Precedence::Equals,
token::Token::Lt => Precedence::LessGreater,
token::Token::Gt => Precedence::LessGreater,
Expand Down Expand Up @@ -173,6 +178,11 @@ impl<'a> Parser<'a> {
token::Token::SlashEq=> parse_assign,
token::Token::ModEq=> parse_assign,
token::Token::Lbracket=> parse_index,
token::Token::BitOrEq=> parse_assign,
token::Token::BitAndEq=> parse_assign,
token::Token::BitXorEq=> parse_assign,
token::Token::LeftShiftEq=> parse_assign,
token::Token::RightShiftEq=> parse_assign,
});
}

Expand Down
6 changes: 6 additions & 0 deletions src/token/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,11 @@ pub enum Token {
RightShift,
RightShiftEq,
BitAnd,
BitAndEq,
BitOr,
BitOrEq,
BitXor,
BitXorEq,
Null,
}

Expand Down Expand Up @@ -174,8 +177,11 @@ impl fmt::Display for Token {
Token::RightShift => write!(f, ">>"),
Token::RightShiftEq => write!(f, ">>="),
Token::BitAnd => write!(f, "&"),
Token::BitAndEq => write!(f, "&="),
Token::BitOr => write!(f, "|"),
Token::BitOrEq => write!(f, "|="),
Token::BitXor => write!(f, "^"),
Token::BitXorEq => write!(f, "^="),
Token::Eof => write!(f, "EOF"),
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,11 @@ mod test {
("1 << 2", Some(object::Object::Int(4))),
("4 >> 2", Some(object::Object::Int(1))),
("null", Some(object::Object::Null)),
("10 | 2", Some(object::Object::Int(10))),
("10 ^ 2", Some(object::Object::Int(8))),
("10 & 2", Some(object::Object::Int(2))),
("10 << 2", Some(object::Object::Int(40))),
("10 >> 2", Some(object::Object::Int(2))),
];

tests.into_iter().for_each(|test| run(test.0, test.1))
Expand Down Expand Up @@ -591,6 +596,11 @@ mod test {
("let a = 10 + 2; a *= 1+1; a", Some(object::Object::Int(24))),
("let a = 10 + 2; a -= 2; a", Some(object::Object::Int(10))),
("let a = 10 + 2; a %= 2; a", Some(object::Object::Int(0))),
("let a = 10; a |= 2; a", Some(object::Object::Int(10))),
("let a = 10; a ^= 2; a", Some(object::Object::Int(8))),
("let a = 10; a &= 2; a", Some(object::Object::Int(2))),
("let a = 10; a <<= 2; a", Some(object::Object::Int(40))),
("let a = 10; a >>= 2; a", Some(object::Object::Int(2))),
];
tests.into_iter().for_each(|test| run(test.0, test.1))
}
Expand Down

0 comments on commit 3ecc9ea

Please sign in to comment.