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
Next Next commit
feat: while
  • Loading branch information
echosoar committed Feb 15, 2023
commit 9884fcb2726b4f5f7a987cde6fc50837bc360e86
23 changes: 20 additions & 3 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ impl AST{
Token::Var | Token::Let => self.parse_variable_statement(),
Token::If => self.parse_if_statement(),
Token::For => self.parse_for_statement(),
Token::While => self.parse_while_statement(),
Token::Break => self.parse_break_statement(),
Token::Continue => self.parse_continue_statement(),
Token::Function => {
Expand Down Expand Up @@ -238,11 +239,9 @@ impl AST{
}
// TODO: self.check_token_and_next(Token::Semicolon);
let codition = self.parse_expression();
println!("codition: {:?} {:?}", codition, self.token);
self.check_token_and_next(Token::Semicolon);
let incrementor = self.parse_expression();
self.check_token_and_next(Token::RightParenthesis);
println!("incrementor: {:?} {:?}", incrementor , self.token);

let block = self.parse_block_statement();
let statement = ForStatement {
Expand All @@ -254,6 +253,24 @@ impl AST{
return Statement::For(statement);
}

// 解析 while 循环
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();
self.check_token_and_next(Token::RightParenthesis);

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


fn parse_break_statement(&mut self) -> Statement {
self.check_token_and_next(Token::Break);
let mut semicolon = false;
Expand All @@ -264,7 +281,7 @@ impl AST{
}

// for() { break }
if semicolon || self.token == Token::RightBrace {
if semicolon || self.auto_semicolon_when_new_line || self.token == Token::RightBrace {
/*
TODO:
if self.scope.in_iteration || self.scope.in_switch {
Expand Down
3 changes: 2 additions & 1 deletion src/ast_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub enum Statement {
Return(ReturnStatement),
Unknown, // 未知
Var(VariableDeclarationStatement),
While(ForStatement),
}

impl PartialEq for Statement {
Expand Down Expand Up @@ -50,6 +51,7 @@ impl fmt::Debug for Statement {
Statement::Label(_) => { stype = "label"},
Statement::Return(_) => { stype = "return"},
Statement::Var(_) => { stype = "var"},
Statement::While(_) => { stype = "while"},
_ => {
stype = "other"
},
Expand Down Expand Up @@ -135,7 +137,6 @@ pub struct ForStatement {
}



#[derive(Debug, Clone, PartialEq)]
pub struct FunctionDeclaration {
pub is_anonymous: bool,
Expand Down
12 changes: 9 additions & 3 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ impl Context {
label: None,
};
self.call_statement(statement, &mut result_value, &mut last_statement_value, &mut interrupt, call_options);
// println!("interrupt {:?} {:?} {:?}", statement, interrupt, interrupt != Value::Undefined);
if interrupt != Value::Undefined {
break;
}
Expand Down Expand Up @@ -123,6 +122,9 @@ impl Context {
Statement::For(for_statment) => {
self.execute_for(for_statment, result_value, last_statement_value, interrupt, call_options)
},
Statement::While(for_statment) => {
self.execute_for(for_statment, result_value, last_statement_value, interrupt, call_options)
},
Statement::Block(block) => {
self.switch_scope(Some(Rc::clone(&self.cur_scope)));
let result = self.call_block(&vec![], &block.statements);
Expand Down Expand Up @@ -206,6 +208,7 @@ impl Context {
Expression::Identifier(identifier) => {
let name = identifier.literal.clone();
let (value, scope) = get_value_and_scope(Rc::clone(&self.cur_scope), name.clone());
// println!("Identifier value: {:?} {:?}", name, value);
if let Some(val) = value {
ValueInfo{ value: val, name: Some(name.clone()), reference: Some(Value::Scope(Rc::downgrade(&scope))) }
} else {
Expand Down Expand Up @@ -439,6 +442,7 @@ impl Context {

loop {
let condition = &for_statment.codition;

if let Expression::Unknown = condition {
// nothing to do
} else {
Expand All @@ -447,7 +451,6 @@ impl Context {
break;
}
}

// TODO: expression
if let Statement::Block(block) = for_statment.statement.as_ref() {
let result = self.call_block(&vec![], &block.statements);
Expand All @@ -462,6 +465,9 @@ impl Context {
// 向上走,让上层循环继续处理
(*interrupt) = result.2;
}
} else {
// 向上走,让上层循环继续处理
(*interrupt) = result.2;
}
}
break;
Expand All @@ -486,7 +492,7 @@ impl Context {
}

let incrementor = &for_statment.incrementor;
if let Expression::Unknown = condition {
if let Expression::Unknown = incrementor {
// nothing to do
} else {
self.execute_expression(incrementor);
Expand Down
36 changes: 24 additions & 12 deletions tests/confitional_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,49 @@ fn run_if_else() {
}

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

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