Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 34 additions & 9 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::collections::HashMap;
use std::{io};

use crate::ast_token::{get_token_keyword, Token, get_token_literal};
use crate::ast_node::{ Expression, NumberLiteral, StringLiteral, Statement, IdentifierLiteral, ExpressionStatement, PropertyAccessExpression, BinaryExpression, ConditionalExpression, CallExpression, Keywords, Parameter, BlockStatement, ReturnStatement, Declaration, PropertyAssignment, ObjectLiteral, ElementAccessExpression, FunctionDeclaration, PostfixUnaryExpression, PrefixUnaryExpression, AssignExpression, GroupExpression, VariableDeclaration, VariableDeclarationStatement, VariableFlag, ClassDeclaration, ClassMethodDeclaration, ArrayLiteral, ComputedPropertyName, IfStatement, ForStatement, BreakStatement, ContinueStatement, LabeledStatement, SwitchStatement, CaseClause, NewExpression, TryCatchStatement, CatchClause, ThrowStatement, TemplateLiteralExpression, SequenceExpression};
use crate::ast_node::{ Expression, NumberLiteral, StringLiteral, Statement, IdentifierLiteral, ExpressionStatement, PropertyAccessExpression, BinaryExpression, ConditionalExpression, CallExpression, Keywords, Parameter, BlockStatement, ReturnStatement, Declaration, PropertyAssignment, ObjectLiteral, ElementAccessExpression, FunctionDeclaration, PostfixUnaryExpression, PrefixUnaryExpression, AssignExpression, GroupExpression, VariableDeclaration, VariableDeclarationStatement, VariableFlag, ClassDeclaration, ClassMethodDeclaration, ArrayLiteral, ComputedPropertyName, IfStatement, ForStatement, BreakStatement, ContinueStatement, LabeledStatement, SwitchStatement, CaseClause, NewExpression, TryCatchStatement, CatchClause, ThrowStatement, TemplateLiteralExpression, SequenceExpression, ForOper};
use crate::ast_utils::{get_hex_number_value, chars_to_string};
use crate::error::{JSIResult, JSIError, JSIErrorType};
pub struct AST {
Expand Down Expand Up @@ -194,12 +194,19 @@ impl AST{
} else {
self.check_token_and_next(Token::Var)?;
}

let var_statement = VariableDeclarationStatement {
list: self.parse_variable_declarations()?,
flag: variable_flag,
};
self.semicolon()?;
let mut is_need_skip_check_semicolon = false;
// for in 和 for of
if self.token == Token::In || self.token == Token::Of {
is_need_skip_check_semicolon = true;
}
if !is_need_skip_check_semicolon {
self.semicolon()?;
}

return Ok(Statement::Var(var_statement));
}

Expand Down Expand Up @@ -306,22 +313,37 @@ impl AST{
// 解析 for 循环
// TODO: for in/ of
fn parse_for_statement(&mut self) -> JSIResult<Statement> {
println!("for");
self.check_token_and_next(Token::For)?;
self.check_token_and_next(Token::LeftParenthesis)?;
// 解析 initializer
// 需要额外处理 var 的情况
let mut initializer = Statement::Unknown;
if self.token == Token::Var || self.token == Token::Let || self.token == Token::Const {
initializer = self.parse_variable_statement()?;
initializer = self.parse_variable_statement()?;
} else if self.token != Token::Semicolon {
initializer = Statement::Expression(ExpressionStatement { expression: self.parse_expression()? });
self.check_token_and_next(Token::Semicolon)?;
}
self.not_declare_function_to_scope = true;
let condition = self.parse_expression()?;
self.not_declare_function_to_scope = false;
self.check_token_and_next(Token::Semicolon)?;
let incrementor = self.parse_expression()?;
let mut condition = Expression::Unknown;
let mut incrementor = Expression::Unknown;
let mut oper = ForOper::For;
if self.token == Token::In || self.token == Token::Of {
if self.token == Token::In {
oper = ForOper::In;
} else {
oper = ForOper::Of;
}
self.next();
condition = self.parse_expression()?;
} else {
self.not_declare_function_to_scope = true;
condition = self.parse_expression()?;
self.not_declare_function_to_scope = false;
self.check_token_and_next(Token::Semicolon)?;
incrementor = self.parse_expression()?;
}

self.check_token_and_next(Token::RightParenthesis)?;

let block = self.parse_block_statement()?;
Expand All @@ -331,6 +353,7 @@ impl AST{
incrementor: incrementor,
statement: Box::new(block),
post_judgment: false,
oper,
};
return Ok(Statement::For(statement));
}
Expand All @@ -351,6 +374,7 @@ impl AST{
incrementor: Expression::Unknown,
statement: Box::new(block),
post_judgment: false,
oper: ForOper::For
};
return Ok(Statement::For(statement));
}
Expand All @@ -372,6 +396,7 @@ impl AST{
incrementor: Expression::Unknown,
statement: Box::new(block),
post_judgment: true,
oper: ForOper::For
};
return Ok(Statement::For(statement));
}
Expand Down
10 changes: 9 additions & 1 deletion src/ast_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,22 @@ pub struct LabeledStatement {
pub statement: Box<Statement>,
}

#[derive(Debug, Clone, PartialEq)]
pub enum ForOper {
For,
In,
Of
}

#[derive(Debug, Clone, PartialEq)]
pub struct ForStatement {
pub initializer: Box<Statement>,
pub condition: Expression,
pub incrementor: Expression,
pub statement: Box<Statement>,
// 是否为后置检查
pub post_judgment: bool,
pub oper: ForOper,
}


Expand Down Expand Up @@ -389,7 +397,7 @@ pub struct PropertyAssignment {
#[derive(Debug, Clone, PartialEq)]
pub struct VariableDeclaration {
pub name: String,
pub initializer: Box<Expression>
pub initializer: Box<Expression>,
}


Expand Down
1 change: 1 addition & 0 deletions src/ast_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub enum Token {
In,
Instanceof,
New,
Of,
Return,
Super,
Switch,
Expand Down
28 changes: 27 additions & 1 deletion src/context.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{rc::{Rc, Weak}, cell::RefCell};

use crate::{ast::Program, ast_node::{Statement, Declaration, ObjectLiteral, AssignExpression, CallContext, ArrayLiteral, ClassType, ForStatement, VariableFlag, PostfixUnaryExpression, IdentifierLiteral, PrefixUnaryExpression, SwitchStatement}, ast_node::{Expression, CallExpression, Keywords, BinaryExpression, NewExpression}, 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, get_builtin_function_name}, global::{new_global_this, get_global_object, IS_GLOABL_OBJECT, bind_global}, array::{create_array}, console::create_console}, error::{JSIResult, JSIError, JSIErrorType}, constants::{GLOBAL_OBJECT_NAME_LIST, PROTO_PROPERTY_NAME}};
use crate::{ast::Program, ast_node::{Statement, Declaration, ObjectLiteral, AssignExpression, CallContext, ArrayLiteral, ClassType, ForStatement, VariableFlag, PostfixUnaryExpression, IdentifierLiteral, PrefixUnaryExpression, SwitchStatement}, ast_node::{Expression, CallExpression, Keywords, BinaryExpression, NewExpression, ForOper}, 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, get_builtin_function_name}, global::{new_global_this, get_global_object, IS_GLOABL_OBJECT, bind_global}, array::{create_array}, console::create_console}, error::{JSIResult, JSIError, JSIErrorType}, constants::{GLOBAL_OBJECT_NAME_LIST, PROTO_PROPERTY_NAME}};


use super::ast::AST;
Expand Down Expand Up @@ -686,6 +686,32 @@ impl Context {
self.switch_scope(Some(Rc::clone(&self.cur_scope)));
}

// TODO: for in / for of
if for_statment.oper == ForOper::In || for_statment.oper == ForOper::Of {
// 创建迭代器,迭代器的返回值
/*
iterator.next = (index) => {
var xxx = indexList[i]
if (for_statment.oper == ForOper::In) {
return xxx;
}
return obj[indexList[i]];
}

iterator.iterator = () => {
index = index + 1;
}

for(let i; i < indexList.length;i ++) {
// for in === var xxx = indexList[i];
// for of === var xxx = obj[indexList[i]];
}
*/

println!("{:?}", for_statment);
return Ok(true)
}

loop {
if !for_statment.post_judgment {
let condition = &for_statment.condition;
Expand Down
1 change: 0 additions & 1 deletion tests/ast_lexer_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,6 @@ fn ast_lexer_priority_between_exponentiation_shift() {
})]);
}


#[test]
fn ast_lexer_complex() {
let mut jsi_vm = JSI::new();
Expand Down
14 changes: 14 additions & 0 deletions tests/confitional_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,20 @@ fn run_for_break_continue_label() {
assert_eq!(result , Value::String(String::from("0:0:0:0:0:0:2:4")));
}


#[test]
fn run_for_in() {
let mut jsi = JSI::new();
let result = jsi.run(String::from("\
const obj = { name: 'abc', age: 123};
const a = [];
for(var name in obj) {
a.push(name);
}
a.join(',')")).unwrap();
assert_eq!(result , Value::String(String::from("name,age")));
}

#[test]
fn run_while_break_continue_label() {
let mut jsi = JSI::new();
Expand Down
4 changes: 3 additions & 1 deletion tests/test262_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,14 +223,16 @@ fn test_all_262() {
load_harness("harness/assert.js"),
load_harness("harness/sta.js"),
load_harness("harness/compareArray.js"),
load_harness("harness/propertyHelper.js"),
];
let prelaod = preload_list.join("\n");
let ignore_list: Vec<PathBuf> =vec![
make_dir(&String::from("test262/test/annexB")),
make_dir(&String::from("test262/test/intl402")),
];
let only_list: Vec<PathBuf> =vec![
// make_dir(&String::from("test262/test/built-ins/String/prototype/charAt/pos-coerce-err.js")),
make_dir(&String::from("test262/test/built-ins/String/prototype/charAt/name.js")),
// make_dir(&String::from("test262/test/language/arguments-object/10.6-13-a-2.js")),
];
let mut test262 = Test262Dir::new(String::from("base"), String::from("test262/test"));
test262.run(prelaod.as_str(), &ignore_list, &only_list);
Expand Down