Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: condition #6

Merged
merged 14 commits into from
Feb 20, 2023
Prev Previous commit
feat: so while
  • Loading branch information
echosoar committed Feb 20, 2023
commit d753cd099b98bc181761ff3d66ba307348c5fd61
31 changes: 26 additions & 5 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ impl AST{
Token::Switch => self.parse_switch_statement(),
Token::For => self.parse_for_statement(),
Token::While => self.parse_while_statement(),
Token::Do => self.parse_do_while_statement(),
Token::Break => self.parse_break_statement(),
Token::Continue => self.parse_continue_statement(),
Token::Function => {
Expand Down Expand Up @@ -239,7 +240,6 @@ impl AST{
if self.token == Token::EOF || self.token == Token::RightBrace {
break;
}
let mut is_default = false;
let mut clause = CaseClause {
condition: None,
statements: vec![],
Expand Down Expand Up @@ -290,17 +290,18 @@ impl AST{
initializer = Statement::Expression(ExpressionStatement { expression: self.parse_expression() });
self.check_token_and_next(Token::Semicolon);
}
let codition = self.parse_expression();
let condition = self.parse_expression();
self.check_token_and_next(Token::Semicolon);
let incrementor = self.parse_expression();
self.check_token_and_next(Token::RightParenthesis);

let block = self.parse_block_statement();
let statement = ForStatement {
initializer: Box::new(initializer),
codition: codition,
condition: condition,
incrementor: incrementor,
statement: Box::new(block),
post_judgment: false,
};
return Statement::For(statement);
}
Expand All @@ -309,15 +310,35 @@ impl AST{
fn parse_while_statement(&mut self) -> Statement {
self.check_token_and_next(Token::While);
self.check_token_and_next(Token::LeftParenthesis);
let codition = self.parse_expression();
let condition = self.parse_expression();
self.check_token_and_next(Token::RightParenthesis);

let block = self.parse_block_statement();
let statement = ForStatement {
initializer: Box::new(Statement::Unknown),
codition: codition,
condition: condition,
incrementor: Expression::Unknown,
statement: Box::new(block),
post_judgment: false,
};
return Statement::For(statement);
}


// 解析 do while 循环
fn parse_do_while_statement(&mut self) -> Statement {
self.check_token_and_next(Token::Do);
let block = self.parse_block_statement();
self.check_token_and_next(Token::While);
self.check_token_and_next(Token::LeftParenthesis);
let condition = self.parse_expression();
self.check_token_and_next(Token::RightParenthesis);
let statement = ForStatement {
initializer: Box::new(Statement::Unknown),
condition: condition,
incrementor: Expression::Unknown,
statement: Box::new(block),
post_judgment: true,
};
return Statement::For(statement);
}
Expand Down
3 changes: 2 additions & 1 deletion src/ast_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,10 @@ pub struct LabeledStatement {
#[derive(Debug, Clone, PartialEq)]
pub struct ForStatement {
pub initializer: Box<Statement>,
pub codition: Expression,
pub condition: Expression,
pub incrementor: Expression,
pub statement: Box<Statement>,
pub post_judgment: bool,
}


Expand Down
31 changes: 24 additions & 7 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,16 +466,19 @@ impl Context {
}

loop {
let condition = &for_statment.codition;
if !for_statment.post_judgment {
let condition = &for_statment.condition;

if let Expression::Unknown = condition {
// nothing to do
} else {
let value = self.execute_expression(condition);
if !value.to_boolean() {
break;
if let Expression::Unknown = condition {
// nothing to do
} else {
let value = self.execute_expression(condition);
if !value.to_boolean() {
break;
}
}
}

// TODO: expression
if let Statement::Block(block) = for_statment.statement.as_ref() {
let result = self.call_block(&vec![], &block.statements);
Expand Down Expand Up @@ -522,6 +525,20 @@ impl Context {
} else {
self.execute_expression(incrementor);
}

// post judegment: for do while
if for_statment.post_judgment {
let condition = &for_statment.condition;

if let Expression::Unknown = condition {
// nothing to do
} else {
let value = self.execute_expression(condition);
if !value.to_boolean() {
break;
}
}
}
}

self.close_scope();
Expand Down
26 changes: 26 additions & 0 deletions tests/confitional_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,30 @@ fn run_while_break_continue_label() {
}
a.join(':')"));
assert_eq!(result , Value::String(String::from("2:4")));
}

#[test]
fn run_dowhile_break_continue_label() {
let mut jsi = JSI::new();
let result = jsi.run(String::from("\
let a = [];
let i = 0;
outer:
do {
i ++;
let j = 0
do {
j ++;
if (j == 1 && i == 1) {
continue outer
}
if (j == 4) break
if (j == 3 && i == 2) {
break outer
}
a.push(i * j);
} while (j < 5);
} while (i < 3);
a.join(':')"));
assert_eq!(result , Value::String(String::from("2:4")));
}