1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
mod array;
mod block;
mod break_node;
mod call;
mod conditional;
mod declaration;
mod field;
mod identifier;
mod iteration;
mod new;
mod object;
mod operator;
mod return_smt;
mod spread;
mod statement_list;
mod switch;
mod throw;
mod try_node;
#[cfg(test)]
mod tests;
use crate::{
syntax::ast::{constant::Const, node::Node},
BoaProfiler, Context, Result, Value,
};
pub trait Executable {
fn run(&self, interpreter: &mut Context) -> Result<Value>;
}
#[derive(Debug, Eq, PartialEq)]
pub(crate) enum InterpreterState {
Executing,
Return,
Break(Option<Box<str>>),
Continue(Option<Box<str>>),
}
#[derive(Debug)]
pub struct Interpreter {
state: InterpreterState,
}
impl Default for Interpreter {
fn default() -> Self {
Self::new()
}
}
impl Interpreter {
pub fn new() -> Self {
Self {
state: InterpreterState::Executing,
}
}
#[inline]
pub(crate) fn set_current_state(&mut self, new_state: InterpreterState) {
self.state = new_state
}
#[inline]
pub(crate) fn get_current_state(&self) -> &InterpreterState {
&self.state
}
}
impl Executable for Node {
fn run(&self, interpreter: &mut Context) -> Result<Value> {
let _timer = BoaProfiler::global().start_event("Executable", "exec");
match *self {
Node::Const(Const::Null) => Ok(Value::null()),
Node::Const(Const::Num(num)) => Ok(Value::rational(num)),
Node::Const(Const::Int(num)) => Ok(Value::integer(num)),
Node::Const(Const::BigInt(ref num)) => Ok(Value::from(num.clone())),
Node::Const(Const::Undefined) => Ok(Value::Undefined),
Node::Const(Const::String(ref value)) => Ok(Value::string(value.to_string())),
Node::Const(Const::Bool(value)) => Ok(Value::boolean(value)),
Node::Block(ref block) => block.run(interpreter),
Node::Identifier(ref identifier) => identifier.run(interpreter),
Node::GetConstField(ref get_const_field_node) => get_const_field_node.run(interpreter),
Node::GetField(ref get_field) => get_field.run(interpreter),
Node::Call(ref call) => call.run(interpreter),
Node::WhileLoop(ref while_loop) => while_loop.run(interpreter),
Node::DoWhileLoop(ref do_while) => do_while.run(interpreter),
Node::ForLoop(ref for_loop) => for_loop.run(interpreter),
Node::If(ref if_smt) => if_smt.run(interpreter),
Node::ConditionalOp(ref op) => op.run(interpreter),
Node::Switch(ref switch) => switch.run(interpreter),
Node::Object(ref obj) => obj.run(interpreter),
Node::ArrayDecl(ref arr) => arr.run(interpreter),
Node::FunctionDecl(ref decl) => decl.run(interpreter),
Node::FunctionExpr(ref function_expr) => function_expr.run(interpreter),
Node::ArrowFunctionDecl(ref decl) => decl.run(interpreter),
Node::BinOp(ref op) => op.run(interpreter),
Node::UnaryOp(ref op) => op.run(interpreter),
Node::New(ref call) => call.run(interpreter),
Node::Return(ref ret) => ret.run(interpreter),
Node::Throw(ref throw) => throw.run(interpreter),
Node::Assign(ref op) => op.run(interpreter),
Node::VarDeclList(ref decl) => decl.run(interpreter),
Node::LetDeclList(ref decl) => decl.run(interpreter),
Node::ConstDeclList(ref decl) => decl.run(interpreter),
Node::Spread(ref spread) => spread.run(interpreter),
Node::This => {
Ok(interpreter.realm().environment.get_this_binding())
}
Node::Try(ref try_node) => try_node.run(interpreter),
Node::Break(ref break_node) => break_node.run(interpreter),
Node::Continue(ref continue_node) => continue_node.run(interpreter),
}
}
}