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: for label
  • Loading branch information
echosoar committed Feb 13, 2023
commit 7322883eeaa928643c39170c254b89eb90b940e8
79 changes: 48 additions & 31 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{rc::{Rc, Weak}, cell::RefCell, ops::Index};

use crate::{ast::Program, ast_node::{Statement, Declaration, ObjectLiteral, AssignExpression, CallContext, ArrayLiteral, ClassType, ForStatement, VariableFlag, PostfixUnaryExpression, IdentifierLiteral}, ast_node::{Expression, CallExpression, Keywords, BinaryExpression}, value::{Value, ValueInfo}, scope::{Scope, get_value_and_scope}, ast_token::Token, builtins::{object::{Object, Property, create_object}, function::{create_function, get_function_this}, global::{new_global_this, get_global_object}, array::create_array}};
use crate::{ast::Program, ast_node::{Statement, Declaration, ObjectLiteral, AssignExpression, CallContext, ArrayLiteral, ClassType, ForStatement, VariableFlag, PostfixUnaryExpression, IdentifierLiteral}, ast_node::{Expression, CallExpression, Keywords, BinaryExpression}, value::{Value, ValueInfo, CallStatementOptions}, scope::{Scope, get_value_and_scope}, ast_token::Token, builtins::{object::{Object, Property, create_object}, function::{create_function, get_function_this}, global::{new_global_this, get_global_object}, array::create_array}};

use super::ast::AST;
pub struct Context {
Expand Down Expand Up @@ -57,15 +57,19 @@ impl Context {
// 中断,类似于 break 、continue 等
let mut interrupt = Value::Undefined;
for statement in body.iter() {
self.call_statement(statement, &mut result_value, &mut last_statement_value, &mut interrupt);
let call_options = CallStatementOptions {
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;
}
}
(result_value, last_statement_value, interrupt)
}

fn call_statement(&mut self, statement: &Statement, result_value: &mut Value, last_statement_value: &mut Value, interrupt: &mut Value) {
fn call_statement(&mut self, statement: &Statement, result_value: &mut Value, last_statement_value: &mut Value, interrupt: &mut Value, call_options: CallStatementOptions) {
match statement {
Statement::Var(var_statement) => {
// var_statement.flag 是 var 还是 let,在上层调用链路中处理
Expand All @@ -91,27 +95,33 @@ impl Context {
},
Statement::If(if_statement) => {
let condition = self.execute_expression(&if_statement.condition);
let call_options = CallStatementOptions {
label: None,
};
if condition.to_boolean() {
if let Statement::Unknown = *if_statement.then_statement {
// no then
} else {
self.call_statement(&if_statement.then_statement, result_value, last_statement_value, interrupt);
self.call_statement(&if_statement.then_statement, result_value, last_statement_value, interrupt, call_options);
}
} else {
if let Statement::Unknown = *if_statement.else_statement {
// no else
} else {
self.call_statement(&if_statement.else_statement, result_value, last_statement_value, interrupt);
self.call_statement(&if_statement.else_statement, result_value, last_statement_value, interrupt, call_options);
}
}
},
Statement::Label(label_statement) => {
let call_options = CallStatementOptions {
label: Some(label_statement.label.literal.clone()),
};
self.cur_scope.borrow_mut().labels.push(label_statement.label.literal.clone());
self.call_statement(&label_statement.statement, result_value, last_statement_value, interrupt);
self.call_statement(&label_statement.statement, result_value, last_statement_value, interrupt, call_options);
self.cur_scope.borrow_mut().labels.pop();
},
Statement::For(for_statment) => {
self.execute_for(for_statment, result_value, last_statement_value, interrupt)
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)));
Expand All @@ -120,9 +130,7 @@ impl Context {
self.close_scope();
},
Statement::Break(break_statement) => {
println!("label: {:?}", break_statement.label);
if let Some(label) = &break_statement.label {

let label_exists = self.cur_scope.borrow_mut().labels.contains(&label.literal);
if !label_exists {
// TODO: throw error label not exists
Expand All @@ -133,9 +141,7 @@ impl Context {
}
},
Statement::Continue(continue_statement) => {
println!("label2: {:?}", continue_statement.label);
if let Some(label) = &continue_statement.label {
println!("label: {:?}", label);
let label_exists = self.cur_scope.borrow_mut().labels.contains(&label.literal);
if !label_exists {
// TODO: throw error label not exists
Expand Down Expand Up @@ -404,24 +410,27 @@ impl Context {
}

// 执行循环
fn execute_for(&mut self, for_statment: &ForStatement, result_value: &mut Value, last_statement_value: &mut Value, interrupt: &mut Value) {
fn execute_for(&mut self, for_statment: &ForStatement, result_value: &mut Value, last_statement_value: &mut Value, interrupt: &mut Value, call_options: CallStatementOptions) {
let mut is_change_scope = false;
let initializer = *for_statment.initializer.clone();
let mut for_result = Value::Undefined;
let mut for_last_statement_value = Value::Undefined;
let mut for_interrupt = Value::Undefined;
let for_call_options = CallStatementOptions {
label: None,
};
if let Statement::Var(var) = &initializer {
if var.flag == VariableFlag::Var {
self.call_statement(&initializer, &mut for_result, &mut for_last_statement_value, &mut for_interrupt)
self.call_statement(&initializer, &mut for_result, &mut for_last_statement_value, &mut for_interrupt, for_call_options)
} else if var.flag == VariableFlag::Let {
self.switch_scope(Some(Rc::clone(&self.cur_scope)));
is_change_scope = true;
self.call_statement(&initializer, &mut for_result, &mut for_last_statement_value, &mut for_interrupt)
self.call_statement(&initializer, &mut for_result, &mut for_last_statement_value, &mut for_interrupt, for_call_options)
}
} else if let Statement::Unknown = &initializer {
// nothing to do
} else {
self.call_statement(&initializer, &mut for_result, &mut for_last_statement_value, &mut for_interrupt)
self.call_statement(&initializer, &mut for_result, &mut for_last_statement_value, &mut for_interrupt, for_call_options)
}

if !is_change_scope {
Expand All @@ -442,26 +451,35 @@ impl Context {
// TODO: expression
if let Statement::Block(block) = for_statment.statement.as_ref() {
let result = self.call_block(&vec![], &block.statements);
let interrupt = result.2;
if let Value::Interrupt(token, expr) = interrupt {
let for_interrupt = result.2.clone();
if let Value::Interrupt(token, expr) = for_interrupt {
if token == Token::Break {
if let Expression::Identifier(identifier) = expr {
println!("for break label {:?}", identifier);
// TODO: break label
} else {
break;
if let Some(last_label_str) = &call_options.label {
if *last_label_str == identifier.literal {
// break 当前循环,无需做任何处理
} else {
// 向上走,让上层循环继续处理
(*interrupt) = result.2;
}
}
}
break;
} else if token == Token::Continue {
if let Expression::Identifier(identifier) = expr {
// TODO: continue label
let last = self.cur_scope.borrow().labels.last();
if let Some(last_label) = last {
// if *last_label == identifier.literal {

// }
}

println!("index: {:?} {:?}", identifier, self.cur_scope.borrow().labels);
if let Some(last_label_str) = &call_options.label {
if *last_label_str == identifier.literal {
// continue 当前循环,无需做任何处理
} else {
// 有 label ,但是不一样,向上走,让上层循环继续处理
(*interrupt) = result.2;
break;
}
} else {
// 当前循环没有 label,向上走,让上层循环继续处理
(*interrupt) = result.2;
break;
}
}
}
}
Expand Down Expand Up @@ -581,7 +599,6 @@ impl Context {
let rc = Rc::clone(scope);
let scope = rc.borrow();
new_scope.labels = scope.labels.clone();
new_scope.labels.push(String::from(""));
}
new_scope.from = Some(Rc::clone(&self.cur_scope));
let scope_rc = Rc::new(RefCell::new(new_scope));
Expand Down
7 changes: 7 additions & 0 deletions src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ impl Clone for Value {
Value::Scope(obj) => {
return Value::Scope(obj.clone());
},
Value::Interrupt(token, expr) => {
return Value::Interrupt(token.clone(), expr.clone());
},
_ => Value::Undefined,
}
}
Expand Down Expand Up @@ -350,4 +353,8 @@ impl Value {
}
}

}

pub struct CallStatementOptions {
pub label: Option<String>,
}
2 changes: 1 addition & 1 deletion tests/confitional_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn run_for() {
}

#[test]
fn run_for_break_continue() {
fn run_for_break_continue_label() {
let mut jsi = JSI::new();
let result = jsi.run(String::from("\
let a = [];
Expand Down