Browse Source

updates

pull/5/head
Jason Williams 6 years ago
parent
commit
582327da04
  1. 198
      src/lib/exec.rs
  2. 11
      src/lib/js/array.rs
  3. 24
      src/lib/js/console.rs
  4. 11
      src/lib/js/function.rs
  5. 12
      src/lib/js/json.rs
  6. 74
      src/lib/js/math.rs
  7. 52
      src/lib/js/object.rs
  8. 19
      src/lib/js/string.rs
  9. 158
      src/lib/js/value.rs
  10. 2
      src/lib/syntax/ast/constant.rs
  11. 4
      src/lib/syntax/ast/expr.rs
  12. 12
      src/lib/syntax/ast/op.rs

198
src/lib/exec.rs

@ -1,9 +1,13 @@
use gc::Gc;
use js::value::{to_value, ResultValue, Value, ValueData};
use gc::{Gc, GcCell};
use js::function::{Function, RegularFunction};
use js::object::{INSTANCE_PROTOTYPE, PROTOTYPE};
use js::value::{from_value, to_value, ResultValue, Value, ValueData};
use js::{array, console, function, json, math, object, string};
use std::borrow::Borrow;
use std::collections::HashMap;
use syntax::ast::constant::Const;
use syntax::ast::expr::{Expr, ExprDef};
use syntax::ast::op::BinOp;
/// A variable scope
pub struct Scope {
/// The value of `this` in the scope
@ -36,9 +40,9 @@ pub struct Interpreter {
pub scopes: Vec<Scope>,
}
impl Executor<Expr> for Interpreter {
impl Executor for Interpreter {
fn new() -> Interpreter {
let global = Value::new_obj(None);
let global = ValueData::new_obj(None);
object::init(global);
console::init(global);
math::init(global);
@ -66,7 +70,7 @@ impl Executor<Expr> for Interpreter {
fn make_scope(&mut self, this: Value) -> Scope {
let scope = Scope {
this: this,
vars: Value::new_obj(None),
vars: ValueData::new_obj(None),
};
self.scopes.push(scope);
scope
@ -76,14 +80,10 @@ impl Executor<Expr> for Interpreter {
self.scopes.pop().unwrap()
}
fn compile<'a>(&self, expr: &'a Expr) -> &'a Expr {
expr
}
fn run(&mut self, expr: &Expr) -> ResultValue {
match expr.def {
ExprDef::ConstExpr(Const::Null) => Ok(to_value(None)),
ExprDef::ConstExpr(Const::Undefined) => Ok(Value::undefined()),
ExprDef::ConstExpr(Const::Undefined) => Ok(Gc::new(ValueData::Undefined)),
ExprDef::ConstExpr(Const::Num(num)) => Ok(to_value(num)),
ExprDef::ConstExpr(Const::Int(num)) => Ok(to_value(num)),
ExprDef::ConstExpr(Const::String(str)) => Ok(to_value(str)),
@ -100,11 +100,11 @@ impl Executor<Expr> for Interpreter {
Ok(obj)
}
ExprDef::LocalExpr(ref name) => {
let mut val = Value::undefined();
let mut val = Gc::new(ValueData::Undefined);
for scope in self.scopes.iter().rev() {
let vars = scope.vars;
let vars_ptr = vars.borrow();
match *vars_ptr.ptr {
match *vars_ptr.clone() {
ValueData::Object(ref obj) => match obj.borrow().get(name) {
Some(v) => {
val = v.value;
@ -143,18 +143,18 @@ impl Executor<Expr> for Interpreter {
for arg in args.iter() {
v_args.push(try!(self.run(arg)));
}
match *func.borrow().ptr {
match *func {
ValueData::Function(ref func) => match *func.borrow() {
NativeFunc(ref ntv) => {
Function::NativeFunc(ref ntv) => {
let func = ntv.data;
func(this, try!(self.run(*callee)), v_args)
func(this, try!(self.run(callee)), v_args)
}
RegularFunc(ref data) => {
Function::RegularFunc(ref data) => {
let scope = self.make_scope(this);
let scope_vars_ptr = scope.vars.borrow();
for i in range(0, data.args.len()) {
let name = data.args.get(i);
let expr = v_args.get(i);
for i in 0..data.args.len() {
let name = data.args.get(i).unwrap();
let expr = v_args.get(i).unwrap();
scope_vars_ptr.set_field(name.clone(), *expr);
}
let result = self.run(&data.expr);
@ -162,30 +162,32 @@ impl Executor<Expr> for Interpreter {
result
}
},
_ => Err(Gc::new(VUndefined)),
_ => Err(Gc::new(ValueData::Undefined)),
}
}
WhileLoopExpr(ref cond, ref expr) => {
let mut result = Gc::new(VUndefined);
while try!(self.run(*cond)).borrow().is_true() {
result = try!(self.run(*expr));
ExprDef::WhileLoopExpr(ref cond, ref expr) => {
let mut result = Gc::new(ValueData::Undefined);
while try!(self.run(cond)).borrow().is_true() {
result = try!(self.run(expr));
}
Ok(result)
}
IfExpr(ref cond, ref expr, None) => Ok(if try!(self.run(*cond)).borrow().is_true() {
try!(self.run(*expr))
ExprDef::IfExpr(ref cond, ref expr, None) => {
Ok(if try!(self.run(cond)).borrow().is_true() {
try!(self.run(expr))
} else {
Gc::new(VUndefined)
}),
IfExpr(ref cond, ref expr, Some(ref else_e)) => {
Ok(if try!(self.run(*cond)).borrow().is_true() {
try!(self.run(*expr))
Gc::new(ValueData::Undefined)
})
}
ExprDef::IfExpr(ref cond, ref expr, Some(ref else_e)) => {
Ok(if try!(self.run(cond)).borrow().is_true() {
try!(self.run(expr))
} else {
try!(self.run(*else_e))
try!(self.run(else_e))
})
}
SwitchExpr(ref val_e, ref vals, ref default) => {
let val = try!(self.run(*val_e)).borrow().clone();
ExprDef::SwitchExpr(ref val_e, ref vals, ref default) => {
let val = try!(self.run(val_e)).borrow().clone();
let mut result = Gc::new(ValueData::Null);
let mut matched = false;
for tup in vals.iter() {
@ -205,61 +207,63 @@ impl Executor<Expr> for Interpreter {
}
}
if !matched && default.is_some() {
result = try!(self.run(*default.as_ref().unwrap()));
result = try!(self.run(default.as_ref().unwrap()));
}
Ok(result)
}
ObjectDeclExpr(ref map) => {
ExprDef::ObjectDeclExpr(ref map) => {
let obj = ValueData::new_obj(Some(self.global));
for (key, val) in map.iter() {
obj.borrow().set_field(key.clone(), try!(self.run(val)));
}
Ok(obj)
}
ArrayDeclExpr(ref arr) => {
ExprDef::ArrayDeclExpr(ref arr) => {
let arr_map = ValueData::new_obj(Some(self.global));
let mut index: i32 = 0;
for val in arr.iter() {
let val = try!(self.run(val));
arr_map.borrow().set_field(index.to_str(), val);
arr_map.borrow().set_field(index.to_string(), val);
index += 1;
}
arr_map.borrow().set_field_slice(
INSTANCE_PROTOTYPE,
self.get_global("Array".into_strbuf())
self.get_global("Array".to_string())
.borrow()
.get_field_slice(PROTOTYPE),
);
arr_map.borrow().set_field_slice("length", to_value(index));
Ok(arr_map)
}
FunctionDeclExpr(ref name, ref args, ref expr) => {
let function = RegularFunc(RegularFunction::new(*expr.clone(), args.clone()));
let val = Gc::new(VFunction(RefCell::new(function)));
ExprDef::FunctionDeclExpr(ref name, ref args, ref expr) => {
let function =
Function::RegularFunc(RegularFunction::new(*expr.clone(), args.clone()));
let val = Gc::new(ValueData::Function(GcCell::new(function)));
if name.is_some() {
self.global.borrow().set_field(name.clone().unwrap(), val);
}
Ok(val)
}
ArrowFunctionDeclExpr(ref args, ref expr) => {
let function = RegularFunc(RegularFunction::new(*expr.clone(), args.clone()));
Ok(Gc::new(VFunction(RefCell::new(function))))
ExprDef::ArrowFunctionDeclExpr(ref args, ref expr) => {
let function =
Function::RegularFunc(RegularFunction::new(*expr.clone(), args.clone()));
Ok(Gc::new(ValueData::Function(GcCell::new(function))))
}
BinOpExpr(BinNum(ref op), ref a, ref b) => {
let v_r_a = try!(self.run(*a));
let v_r_b = try!(self.run(*b));
let v_a = v_r_a.borrow();
let v_b = v_r_b.borrow();
ExprDef::BinOpExpr(BinOp::Num(ref op), ref a, ref b) => {
let v_r_a = try!(self.run(a));
let v_r_b = try!(self.run(b));
let v_a = *v_r_a;
let v_b = *v_r_b;
Ok(Gc::new(match *op {
OpAdd => *v_a + *v_b,
OpSub => *v_a - *v_b,
OpMul => *v_a * *v_b,
OpDiv => *v_a / *v_b,
OpMod => *v_a % *v_b,
OpAdd => v_a + *v_b,
OpSub => v_a - *v_b,
OpMul => v_a * *v_b,
OpDiv => v_a / *v_b,
OpMod => v_a % *v_b,
}))
}
UnaryOpExpr(ref op, ref a) => {
let v_r_a = try!(self.run(*a));
ExprDef::UnaryOpExpr(ref op, ref a) => {
let v_r_a = try!(self.run(a));
let v_a = v_r_a.borrow();
Ok(match *op {
UnaryMinus => to_value(-v_a.to_num()),
@ -268,32 +272,32 @@ impl Executor<Expr> for Interpreter {
_ => unreachable!(),
})
}
BinOpExpr(BinBit(ref op), ref a, ref b) => {
let v_r_a = try!(self.run(*a));
let v_r_b = try!(self.run(*b));
let v_a = v_r_a.borrow();
let v_b = v_r_b.borrow();
ExprDef::BinOpExpr(BinOp::Bit(ref op), ref a, ref b) => {
let v_r_a = try!(self.run(a));
let v_r_b = try!(self.run(b));
let v_a = *v_r_a;
let v_b = *v_r_b;
Ok(Gc::new(match *op {
BitAnd => *v_a & *v_b,
BitOr => *v_a | *v_b,
BitXor => *v_a ^ *v_b,
BitShl => *v_a << *v_b,
BitShr => *v_a >> *v_b,
BitAnd => v_a & v_b,
BitOr => v_a | v_b,
BitXor => v_a ^ v_b,
BitShl => v_a << v_b,
BitShr => v_a >> v_b,
}))
}
BinOpExpr(BinComp(ref op), ref a, ref b) => {
let v_r_a = try!(self.run(*a));
let v_r_b = try!(self.run(*b));
ExprDef::BinOpExpr(BinOp::Comp(ref op), ref a, ref b) => {
let v_r_a = try!(self.run(a));
let v_r_b = try!(self.run(b));
let v_a = v_r_a.borrow();
let v_b = v_r_b.borrow();
Ok(to_value(match *op {
CompEqual if v_a.is_object() => v_r_a.ptr_eq(&v_r_b),
CompEqual if v_a.is_object() => v_r_a == v_r_b,
CompEqual => v_a == v_b,
CompNotEqual if v_a.is_object() => !v_r_a.ptr_eq(&v_r_b),
CompNotEqual if v_a.is_object() => v_r_a != v_r_b,
CompNotEqual => v_a != v_b,
CompStrictEqual if v_a.is_object() => v_r_a.ptr_eq(&v_r_b),
CompStrictEqual if v_a.is_object() => v_r_a == v_r_b,
CompStrictEqual => v_a == v_b,
CompStrictNotEqual if v_a.is_object() => !v_r_a.ptr_eq(&v_r_b),
CompStrictNotEqual if v_a.is_object() => v_r_a != v_r_b,
CompStrictNotEqual => v_a != v_b,
CompGreaterThan => v_a.to_num() > v_b.to_num(),
CompGreaterThanOrEqual => v_a.to_num() >= v_b.to_num(),
@ -301,30 +305,30 @@ impl Executor<Expr> for Interpreter {
CompLessThanOrEqual => v_a.to_num() <= v_b.to_num(),
}))
}
BinOpExpr(BinLog(ref op), ref a, ref b) => {
let v_a = from_value::<bool>(try!(self.run(*a))).unwrap();
let v_b = from_value::<bool>(try!(self.run(*b))).unwrap();
ExprDef::BinOpExpr(BinOp::Log(ref op), ref a, ref b) => {
let v_a = from_value::<bool>(try!(self.run(a))).unwrap();
let v_b = from_value::<bool>(try!(self.run(b))).unwrap();
Ok(match *op {
LogAnd => to_value(v_a && v_b),
LogOr => to_value(v_a || v_b),
})
}
ConstructExpr(ref callee, ref args) => {
let func = try!(self.run(*callee));
ExprDef::ConstructExpr(ref callee, ref args) => {
let func = try!(self.run(callee));
let mut v_args = Vec::with_capacity(args.len());
for arg in args.iter() {
v_args.push(try!(self.run(arg)));
}
let this = Gc::new(VObject(RefCell::new(TreeMap::new())));
let this = Gc::new(ValueData::Object(GcCell::new(HashMap::new())));
this.borrow()
.set_field_slice(INSTANCE_PROTOTYPE, func.borrow().get_field_slice(PROTOTYPE));
match *func.borrow() {
VFunction(ref func) => match *func.borrow() {
NativeFunc(ref ntv) => {
match *func {
ValueData::Function(ref func) => match *func {
Function::NativeFunc(ref ntv) => {
let func = ntv.data;
func(this, try!(self.run(*callee)), v_args)
func(this, try!(self.run(callee)), v_args)
}
RegularFunc(ref data) => {
Function::RegularFunc(ref data) => {
let scope = self.make_scope(this);
let scope_vars_ptr = scope.vars.borrow();
for i in range(0, data.args.len()) {
@ -337,16 +341,16 @@ impl Executor<Expr> for Interpreter {
result
}
},
_ => Ok(Gc::new(VUndefined)),
_ => Ok(Gc::new(ValueData::Undefined)),
}
}
ReturnExpr(ref ret) => match *ret {
Some(ref v) => self.run(*v),
None => Ok(Gc::new(VUndefined)),
ExprDef::ReturnExpr(ref ret) => match *ret {
Some(ref v) => self.run(v),
None => Ok(Gc::new(ValueData::Undefined)),
},
ThrowExpr(ref ex) => Err(try!(self.run(*ex))),
AssignExpr(ref ref_e, ref val_e) => {
let val = try!(self.run(*val_e));
ExprDef::ThrowExpr(ref ex) => Err(try!(self.run(*ex))),
ExprDef::AssignExpr(ref ref_e, ref val_e) => {
let val = try!(self.run(val_e));
match ref_e.def {
LocalExpr(ref name) => {
self.scope().vars.borrow().set_field(name.clone(), val);
@ -359,7 +363,7 @@ impl Executor<Expr> for Interpreter {
}
Ok(val)
}
VarDeclExpr(ref vars) => {
ExprDef::VarDeclExpr(ref vars) => {
let scope_vars = self.scope().vars;
let scope_vars_ptr = scope_vars.borrow();
for var in vars.iter() {
@ -370,17 +374,17 @@ impl Executor<Expr> for Interpreter {
};
scope_vars_ptr.set_field(name.clone(), val);
}
Ok(Gc::new(VUndefined))
Ok(Gc::new(ValueData::Undefined))
}
TypeOfExpr(ref val_e) => {
ExprDef::TypeOfExpr(ref val_e) => {
let val = try!(self.run(*val_e));
Ok(to_value(match *val.borrow() {
VUndefined => "undefined",
ValueData::Undefined => "undefined",
ValueData::Null | VObject(_) => "object",
VBoolean(_) => "boolean",
VNumber(_) | VInteger(_) => "number",
VString(_) => "string",
VFunction(_) => "function",
ValueData::Function(_) => "function",
}))
}
}

11
src/lib/js/array.rs

@ -1,14 +1,15 @@
use js::function::Function;
use js::value::{to_value, ResultValue, Value};
use gc::Gc;
use js::value::{to_value, ResultValue, Value, ValueData};
/// Create a new array
pub fn make_array(_: Vec<Value>, _: Value, _: Value, this: Value) -> ResultValue {
this.set_field_slice("length", to_value(0i32));
Ok(Value::undefined())
let this_ptr = *this;
this_ptr.set_field_slice("length", to_value(0i32));
Ok(Gc::new(ValueData::Undefined))
}
/// Create a new `Array` object
pub fn _create() -> Value {
let array = Function::make(make_array, &[]);
let array = to_value(make_array);
array
}
/// Initialise the global object with the `Array` object

24
src/lib/js/console.rs

@ -1,15 +1,13 @@
use js::function::Function;
use js::value::{from_value, ResultValue, Value};
use gc::Gc;
use js::value::{from_value, to_value, ResultValue, Value, ValueData};
use std::iter::FromIterator;
use time::{now, strftime};
/// Print a javascript value to the standard output stream
pub fn log(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
let args: Vec<String> = FromIterator::from_iter(
args.iter()
.map(|x| from_value::<String>(x.clone()).unwrap()),
);
pub fn log(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
let args: Vec<String> =
FromIterator::from_iter(args.iter().map(|x| from_value::<String>(*x).unwrap()));
println!("{}: {}", strftime("%X", &now()).unwrap(), args.join(" "));
Ok(Value::undefined())
Ok(Gc::new(ValueData::Undefined))
}
/// Print a javascript value to the standard error stream
pub fn error(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
@ -18,14 +16,14 @@ pub fn error(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
.map(|x| from_value::<String>(x.clone()).unwrap()),
);
eprintln!("{}: {}", strftime("%X", &now()).unwrap(), args.join(" "));
Ok(Value::undefined())
Ok(Gc::new(ValueData::Undefined))
}
/// Create a new `console` object
pub fn _create(global: Value) -> Value {
let console = Value::new_obj(Some(global));
console.set_field_slice("log", Function::make(log, &["object"]));
console.set_field_slice("error", Function::make(error, &["error"]));
console.set_field_slice("exception", Function::make(error, &["error"]));
let console = ValueData::new_obj(Some(global));
console.set_field_slice("log", to_value(log));
console.set_field_slice("error", to_value(error));
console.set_field_slice("exception", to_value(error));
console
}
/// Initialise the global object with the `console` object

11
src/lib/js/function.rs

@ -4,7 +4,6 @@ use js::value::{to_value, ResultValue, Value, ValueData};
use std::collections::HashMap;
use syntax::ast::expr::Expr;
pub type FunctionData = fn(Vec<Value>, Value, Value, Value) -> ResultValue;
pub type NativeFunctionData = fn(Value, Value, Vec<Value>) -> ResultValue;
/// A Javascript function
/// A member of the Object type that may be invoked as a subroutine
@ -12,7 +11,7 @@ pub type NativeFunctionData = fn(Value, Value, Vec<Value>) -> ResultValue;
/// In our implementation, Function is extending Object by holding an object field which some extra data
/// A Javascript function
#[derive(Trace, Finalize, Debug)]
#[derive(Trace, Finalize, Debug, Clone)]
pub enum Function {
/// A native javascript function
NativeFunc(NativeFunction),
@ -21,7 +20,7 @@ pub enum Function {
}
/// Represents a regular javascript function in memory
#[derive(Trace, Finalize, Debug)]
#[derive(Trace, Finalize, Debug, Clone)]
pub struct RegularFunction {
/// The fields associated with the function
pub object: ObjectData,
@ -47,7 +46,7 @@ impl RegularFunction {
}
}
#[derive(Trace, Finalize, Debug)]
#[derive(Trace, Finalize, Debug, Clone)]
/// Represents a native javascript function in memory
pub struct NativeFunction {
/// The fields associated with the function
@ -73,6 +72,6 @@ pub fn _create() -> Value {
}
/// Initialise the global object with the `Function` object
pub fn init(global: Value) {
let global_ptr = global.borrow();
global_ptr.set_field_slice("Function", _create(global));
let global_ptr = &global;
global_ptr.set_field_slice("Function", _create());
}

12
src/lib/js/json.rs

@ -1,19 +1,19 @@
use js::function::Function;
/// The JSON Object
/// https://tc39.github.io/ecma262/#sec-json-object
use js::value::{to_value, ResultValue, Value};
use js::value::{to_value, ResultValue, Value, ValueData};
use serde_json::{self, to_string_pretty, Value as JSONValue};
/// Parse a JSON string into a Javascript object
/// https://tc39.github.io/ecma262/#sec-json.parse
pub fn parse(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn parse(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
match serde_json::from_str::<JSONValue>(&args.get(0).unwrap().clone().to_string()) {
Ok(json) => Ok(to_value(json)),
Err(err) => Err(to_value(err.to_string())),
}
}
/// Process a Javascript object into a JSON string
pub fn stringify(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn stringify(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
let obj = args.get(0).unwrap();
let json = obj.to_json();
Ok(to_value(to_string_pretty(&json).unwrap()))
@ -21,9 +21,9 @@ pub fn stringify(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue
/// Create a new `JSON` object
pub fn _create(global: Value) -> Value {
let object = Value::new_obj(Some(global));
object.set_field_slice("stringify", Function::make(stringify, &["JSON"]));
object.set_field_slice("parse", Function::make(parse, &["JSON_string"]));
let object = ValueData::new_obj(Some(global));
object.set_field_slice("stringify", to_value(stringify));
object.set_field_slice("parse", to_value(parse));
object
}

74
src/lib/js/math.rs

@ -4,7 +4,7 @@ use rand::random;
use std::f64;
/// Get the absolute value of a number
pub fn abs(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn abs(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
@ -14,7 +14,7 @@ pub fn abs(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
}))
}
/// Get the arccos of a number
pub fn acos(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn acos(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
@ -24,7 +24,7 @@ pub fn acos(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
}))
}
/// Get the arcsine of a number
pub fn asin(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn asin(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
@ -34,7 +34,7 @@ pub fn asin(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
}))
}
/// Get the arctangent of a number
pub fn atan(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn atan(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
@ -44,7 +44,7 @@ pub fn atan(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
}))
}
/// Get the arctangent of a numbers
pub fn atan2(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn atan2(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
@ -54,7 +54,7 @@ pub fn atan2(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
}))
}
/// Get the cubic root of a number
pub fn cbrt(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn cbrt(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
@ -64,7 +64,7 @@ pub fn cbrt(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
}))
}
/// Get lowest integer above a number
pub fn ceil(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn ceil(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
@ -74,7 +74,7 @@ pub fn ceil(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
}))
}
/// Get the cosine of a number
pub fn cos(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn cos(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
@ -84,7 +84,7 @@ pub fn cos(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
}))
}
/// Get the power to raise the natural logarithm to get the number
pub fn exp(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn exp(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
@ -94,7 +94,7 @@ pub fn exp(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
}))
}
/// Get the highest integer below a number
pub fn floor(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn floor(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
@ -104,7 +104,7 @@ pub fn floor(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
}))
}
/// Get the natural logarithm of a number
pub fn log(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn log(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
@ -114,7 +114,7 @@ pub fn log(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
}))
}
/// Get the maximum of several numbers
pub fn max(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn max(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
let mut max = f64::NEG_INFINITY;
for arg in args.iter() {
let num = arg.to_num();
@ -123,7 +123,7 @@ pub fn max(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(max))
}
/// Get the minimum of several numbers
pub fn min(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn min(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
let mut max = f64::INFINITY;
for arg in args.iter() {
let num = arg.to_num();
@ -132,7 +132,7 @@ pub fn min(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(max))
}
/// Raise a number to a power
pub fn pow(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn pow(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 2 {
let num: f64 = from_value(args.get(0).unwrap().clone()).unwrap();
let power: f64 = from_value(args.get(1).unwrap().clone()).unwrap();
@ -146,7 +146,7 @@ pub fn _random(_: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(to_value(random::<f64>()))
}
/// Round a number to the nearest integer
pub fn round(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn round(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
@ -156,7 +156,7 @@ pub fn round(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
}))
}
/// Get the sine of a number
pub fn sin(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn sin(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
@ -166,7 +166,7 @@ pub fn sin(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
}))
}
/// Get the square root of a number
pub fn sqrt(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn sqrt(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
@ -176,7 +176,7 @@ pub fn sqrt(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
}))
}
/// Get the tangent of a number
pub fn tan(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn tan(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(to_value(if args.len() >= 1 {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
@ -196,25 +196,25 @@ pub fn _create(global: Value) -> Value {
math.set_field_slice("SQRT1_2", to_value(0.5f64.sqrt()));
math.set_field_slice("SQRT2", to_value(f64::consts::SQRT_2));
math.set_field_slice("PI", to_value(f64::consts::PI));
math.set_field_slice("abs", Function::make(abs, &["num1", "num2"]));
math.set_field_slice("acos", Function::make(acos, &["num1", "num2"]));
math.set_field_slice("asin", Function::make(asin, &["num1", "num2"]));
math.set_field_slice("atan", Function::make(atan, &["num1", "num2"]));
math.set_field_slice("atan2", Function::make(atan2, &["num1", "num2"]));
math.set_field_slice("cbrt", Function::make(cbrt, &["num1", "num2"]));
math.set_field_slice("ceil", Function::make(ceil, &["num1", "num2"]));
math.set_field_slice("cos", Function::make(cos, &["num1", "num2"]));
math.set_field_slice("exp", Function::make(exp, &["num1", "num2"]));
math.set_field_slice("floor", Function::make(floor, &["num"]));
math.set_field_slice("log", Function::make(log, &["num1", "num2"]));
math.set_field_slice("max", Function::make(max, &["num1", "num2"]));
math.set_field_slice("min", Function::make(min, &["num1", "num2"]));
math.set_field_slice("pow", Function::make(pow, &["num1", "num2"]));
math.set_field_slice("random", Function::make(_random, &[]));
math.set_field_slice("round", Function::make(round, &["num"]));
math.set_field_slice("sin", Function::make(sin, &["num"]));
math.set_field_slice("sqrt", Function::make(sqrt, &["num"]));
math.set_field_slice("tan", Function::make(tan, &["num"]));
math.set_field_slice("abs", to_value(abs));
math.set_field_slice("acos", to_value(acos));
math.set_field_slice("asin", to_value(asin));
math.set_field_slice("atan", to_value(atan));
math.set_field_slice("atan2", to_value(atan2));
math.set_field_slice("cbrt", to_value(cbrt));
math.set_field_slice("ceil", to_value(ceil));
math.set_field_slice("cos", to_value(cos));
math.set_field_slice("exp", to_value(exp));
math.set_field_slice("floor", to_value(floor, &["num"]));
math.set_field_slice("log", to_value(log));
math.set_field_slice("max", to_value(max));
math.set_field_slice("min", to_value(min));
math.set_field_slice("pow", to_value(pow));
math.set_field_slice("random", to_value(_random));
math.set_field_slice("round", to_value(round));
math.set_field_slice("sin", to_value(sin));
math.set_field_slice("sqrt", to_value(sqrt));
math.set_field_slice("tan", to_value(tan));
math
}
/// Initialise the `Math` object on the global object

52
src/lib/js/object.rs

@ -1,5 +1,5 @@
use js::function::Function;
use js::value::{from_value, to_value, FromValue, ResultValue, ToValue, Value};
use gc::Gc;
use js::value::{from_value, to_value, FromValue, ResultValue, ToValue, Value, ValueData};
use std::collections::HashMap;
pub static PROTOTYPE: &'static str = "prototype";
pub static INSTANCE_PROTOTYPE: &'static str = "__proto__";
@ -33,15 +33,15 @@ impl Property {
enumerable: false,
writable: false,
value: value,
get: Value::undefined(),
set: Value::undefined(),
get: Gc::new(ValueData::Undefined),
set: Gc::new(ValueData::Undefined),
}
}
}
impl ToValue for Property {
fn to_value(&self) -> Value {
let prop = Value::new_obj(None);
let prop = ValueData::new_obj(None);
prop.set_field_slice("configurable", to_value(self.configurable));
prop.set_field_slice("enumerable", to_value(self.enumerable));
prop.set_field_slice("writable", to_value(self.writable));
@ -67,17 +67,17 @@ impl FromValue for Property {
/// Create a new object
pub fn make_object(_: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
Ok(Value::undefined())
Ok(Gc::new(ValueData::Undefined))
}
/// Get the prototype of an object
pub fn get_proto_of(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn get_proto_of(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
let obj = args.get(0).unwrap();
Ok(obj.get_field_slice(INSTANCE_PROTOTYPE))
}
/// Set the prototype of an object
pub fn set_proto_of(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn set_proto_of(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
let obj = args.get(0).unwrap().clone();
let proto = args.get(1).unwrap().clone();
obj.set_field_slice(INSTANCE_PROTOTYPE, proto);
@ -85,21 +85,21 @@ pub fn set_proto_of(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultVal
}
/// Define a property in an object
pub fn define_prop(args: Vec<Value>, _: Value, _: Value, _: Value) -> ResultValue {
pub fn define_prop(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
let obj = args.get(0).unwrap();
let prop = from_value::<String>(args.get(1).unwrap().clone()).unwrap();
let desc = from_value::<Property>(args.get(2).unwrap().clone()).unwrap();
obj.set_prop(prop, desc);
Ok(Value::undefined())
Ok(Gc::new(ValueData::Undefined))
}
/// To string
pub fn to_string(_: Vec<Value>, _: Value, _: Value, this: Value) -> ResultValue {
pub fn to_string(this: Value, _: Value, _: Vec<Value>) -> ResultValue {
Ok(to_value(this.to_string()))
}
/// Check if it has a property
pub fn has_own_prop(args: Vec<Value>, _: Value, _: Value, this: Value) -> ResultValue {
pub fn has_own_prop(this: Value, _: Value, args: Vec<Value>) -> ResultValue {
let prop = if args.len() == 0 {
None
} else {
@ -112,24 +112,16 @@ pub fn has_own_prop(args: Vec<Value>, _: Value, _: Value, this: Value) -> Result
/// Create a new `Object` object
pub fn _create(global: Value) -> Value {
let object = Function::make(make_object, &[]);
let prototype = Value::new_obj(Some(global));
prototype.set_field_slice(
"hasOwnProperty",
Function::make(has_own_prop, &["property"]),
);
prototype.set_field_slice("toString", Function::make(to_string, &[]));
object.set_field_slice("length", to_value(1i32));
object.set_field_slice(PROTOTYPE, prototype);
object.set_field_slice(
"setPrototypeOf",
Function::make(get_proto_of, &["object", "prototype"]),
);
object.set_field_slice("getPrototypeOf", Function::make(get_proto_of, &["object"]));
object.set_field_slice(
"defineProperty",
Function::make(define_prop, &["object", "property"]),
);
let object = to_value(make_object);
let object_ptr = object;
let prototype = ValueData::new_obj(Some(global));
prototype.set_field_slice("hasOwnProperty", to_value(has_own_prop));
prototype.set_field_slice("toString", to_value(to_string));
object_ptr.set_field_slice("length", to_value(1i32));
object_ptr.set_field_slice(PROTOTYPE, prototype);
object_ptr.set_field_slice("setPrototypeOf", to_value(set_proto_of));
object_ptr.set_field_slice("getPrototypeOf", to_value(get_proto_of));
object_ptr.set_field_slice("defineProperty", to_value(define_prop));
object
}

19
src/lib/js/string.rs

@ -1,28 +1,29 @@
use gc::Gc;
use js::function::Function;
use js::object::{Property, PROTOTYPE};
use js::value::{from_value, to_value, ResultValue, Value};
use js::value::{from_value, to_value, ResultValue, Value, ValueData};
/// Create new string
pub fn make_string(_: Vec<Value>, _: Value, _: Value, this: Value) -> ResultValue {
pub fn make_string(this: Value, _: Value, _: Vec<Value>) -> ResultValue {
this.set_field_slice("length", to_value(0i32));
Ok(Value::undefined())
Ok(Gc::new(ValueData::Undefined))
}
/// Get a string's length
pub fn get_string_length(_: Vec<Value>, _: Value, _: Value, this: Value) -> ResultValue {
pub fn get_string_length(this: Value, _: Value, _: Vec<Value>) -> ResultValue {
let this_str: String = from_value(this).unwrap();
Ok(to_value::<i32>(this_str.len() as i32))
}
/// Create a new `String` object
pub fn _create(global: Value) -> Value {
let string = Function::make(make_string, &["string"]);
let proto = Value::new_obj(Some(global));
let string = to_value(make_string);
let proto = ValueData::new_obj(Some(global));
let prop = Property {
configurable: false,
enumerable: false,
writable: false,
value: Value::undefined(),
get: Function::make(get_string_length, &[]),
set: Value::undefined(),
value: Gc::new(ValueData::Undefined),
get: to_value(get_string_length),
set: Gc::new(ValueData::Undefined),
};
proto.set_prop_slice("length", prop);
string.set_field_slice(PROTOTYPE, proto);

158
src/lib/js/value.rs

@ -1,17 +1,20 @@
use gc::{Gc, GcCell};
use js::function::Function;
use js::function::{Function, NativeFunction, NativeFunctionData};
use js::object::{ObjectData, Property, INSTANCE_PROTOTYPE, PROTOTYPE};
use serde_json::map::Map;
use serde_json::Number as JSONNumber;
use serde_json::Value as JSONValue;
use std::collections::HashMap;
use std::f64::NAN;
use std::fmt;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::iter::FromIterator;
use std::ops::Deref;
use std::ops::DerefMut;
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Rem, Shl, Shr, Sub};
use std::str::FromStr;
#[must_use]
/// The result of a Javascript expression is represented like this so it can succeed (`Ok`) or fail (`Err`)
pub type ResultValue = Result<Value, Value>;
/// A Garbage-collected Javascript value as represented in the interpreter
@ -295,7 +298,7 @@ impl ValueData {
}
impl Display for ValueData {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ValueData::Null => write!(f, "null"),
ValueData::Undefined => write!(f, "undefined"),
@ -305,10 +308,9 @@ impl Display for ValueData {
f,
"{}",
match v {
// https://tc39.github.io/ecma262/#sec-tostring-applied-to-the-number-type
_ if v.is_nan() => "NaN".to_string(),
_ if v.is_infinite() && v.is_sign_positive() => "Infinity".to_string(),
_ if v.is_infinite() && v.is_sign_negative() => "-Infinity".to_string(),
std::f64::INFINITY => "Infinity".to_string(),
std::f64::NEG_INFINITY => "-Infinity".to_string(),
_ => v.to_string(),
}
),
@ -317,7 +319,7 @@ impl Display for ValueData {
match v.borrow().iter().last() {
Some((last_key, _)) => {
for (key, val) in v.borrow().iter() {
try!(write!(f, "{}: {}", key, val.value));
try!(write!(f, "{}: {}", key, val.value.clone()));
if key != last_key {
try!(write!(f, "{}", ", "));
}
@ -328,13 +330,18 @@ impl Display for ValueData {
write!(f, "{}", "}")
}
ValueData::Integer(v) => write!(f, "{}", v),
ValueData::Function(ref v) => write!(f, "function({})", v.borrow().args.join(", ")),
ValueData::Function(ref v) => match *v.borrow() {
Function::NativeFunc(_) => write!(f, "{}", "function() { [native code] }"),
Function::RegularFunc(rf) => {
write!(f, "function({}){}", rf.args.join(", "), rf.expr)
}
},
}
}
}
impl PartialEq for Value {
fn eq(&self, other: &Value) -> bool {
impl PartialEq for ValueData {
fn eq(&self, other: &ValueData) -> bool {
match (self.clone().deref(), other.clone().deref()) {
// TODO: fix this
// _ if self.ptr.to_inner() == &other.ptr.to_inner() => true,
@ -356,6 +363,68 @@ impl PartialEq for Value {
}
}
impl Add for ValueData {
type Output = ValueData;
fn add(self, other: ValueData) -> ValueData {
return match (self, other) {
(ValueData::String(s), other) | (other, ValueData::String(s)) => {
ValueData::String(s.clone().append(other.to_string()))
}
(_, _) => ValueData::Number(self.to_num() + other.to_num()),
};
}
}
impl Sub for ValueData {
fn sub(&self, other: &ValueData) -> ValueData {
ValueData::Number(self.to_num() - other.to_num())
}
}
impl Mul for ValueData {
fn mul(&self, other: &ValueData) -> ValueData {
ValueData::Number(self.to_num() * other.to_num())
}
}
impl Div for ValueData {
fn div(&self, other: &ValueData) -> ValueData {
ValueData::Number(self.to_num() / other.to_num())
}
}
impl Rem for ValueData {
fn rem(&self, other: ValueData) -> ValueData {
ValueData::Number(self.to_num() % other.to_num())
}
}
impl BitAnd for ValueData {
fn bitand(&self, other: ValueData) -> ValueData {
ValueData::Integer(self.to_int() & other.to_int())
}
}
impl BitOr for ValueData {
fn bitor(&self, other: &ValueData) -> ValueData {
ValueData::Integer(self.to_int() | other.to_int())
}
}
impl BitXor for ValueData {
fn bitxor(&self, other: &ValueData) -> ValueData {
ValueData::Integer(self.to_int() ^ other.to_int())
}
}
impl Shl for ValueData {
fn shl(&self, other: &ValueData) -> ValueData {
ValueData::Integer(self.to_int() << other.to_int())
}
}
impl Shr for ValueData {
fn shr(&self, other: &ValueData) -> ValueData {
ValueData::Integer(self.to_int() >> other.to_int())
}
}
impl Not for ValueData {
fn not(&self) -> ValueData {
ValueData::Boolean(!self.is_true())
}
}
/// Conversion to Javascript values from Rust values
pub trait ToValue {
/// Convert this value to a Rust value
@ -371,7 +440,7 @@ pub trait FromValue {
impl ToValue for String {
fn to_value(&self) -> Value {
Gc::new(ValueData::String(self.clone())),
Gc::new(ValueData::String(self.clone()))
}
}
@ -383,17 +452,13 @@ impl FromValue for String {
impl<'s> ToValue for &'s str {
fn to_value(&self) -> Value {
Value {
ptr: Gc::new(ValueData::String(String::from_str(*self).unwrap())),
}
Gc::new(ValueData::String(String::from_str(*self).unwrap()))
}
}
impl ToValue for char {
fn to_value(&self) -> Value {
Value {
ptr: Gc::new(ValueData::String(self.to_string())),
}
Gc::new(ValueData::String(self.to_string()))
}
}
impl FromValue for char {
@ -404,9 +469,7 @@ impl FromValue for char {
impl ToValue for f64 {
fn to_value(&self) -> Value {
Value {
ptr: Gc::new(ValueData::Number(*self)),
}
Gc::new(ValueData::Number(*self))
}
}
impl FromValue for f64 {
@ -417,9 +480,7 @@ impl FromValue for f64 {
impl ToValue for i32 {
fn to_value(&self) -> Value {
Value {
ptr: Gc::new(ValueData::Integer(*self)),
}
Gc::new(ValueData::Integer(*self))
}
}
impl FromValue for i32 {
@ -430,9 +491,7 @@ impl FromValue for i32 {
impl ToValue for bool {
fn to_value(&self) -> Value {
Value {
ptr: Gc::new(ValueData::Boolean(*self)),
}
Gc::new(ValueData::Boolean(*self))
}
}
impl FromValue for bool {
@ -477,19 +536,18 @@ impl<T: FromValue> FromValue for Vec<T> {
impl ToValue for ObjectData {
fn to_value(&self) -> Value {
Value {
ptr: Gc::new(ValueData::Object(GcCell::new(self.clone()))),
}
Gc::new(ValueData::Object(GcCell::new(self.clone())))
}
}
impl FromValue for ObjectData {
fn from_value(v: Value) -> Result<ObjectData, &'static str> {
match *v.ptr {
ValueData::Object(ref obj) => {
let obj_data = obj.clone().into_inner();
Ok(obj_data)
}
ValueData::Function(ref func) => Ok(func.borrow().object.clone()),
match *v {
ValueData::Object(ref obj) => Ok(obj.clone().borrow().deref().clone()),
ValueData::Function(ref func) => Ok(match *func.borrow().deref() {
Function::NativeFunc(ref data) => data.object.clone(),
Function::RegularFunc(ref data) => data.object.clone(),
}),
_ => Err("Value is not a valid object"),
}
}
@ -497,11 +555,10 @@ impl FromValue for ObjectData {
impl ToValue for JSONValue {
fn to_value(&self) -> Value {
Value {
ptr: Gc::new(Value::from_json(self.clone())),
}
Gc::new(ValueData::from_json(self.clone()))
}
}
impl FromValue for JSONValue {
fn from_value(v: Value) -> Result<JSONValue, &'static str> {
Ok(v.to_json())
@ -510,9 +567,7 @@ impl FromValue for JSONValue {
impl ToValue for () {
fn to_value(&self) -> Value {
Value {
ptr: Gc::new(ValueData::Null),
}
Gc::new(ValueData::Null)
}
}
impl FromValue for () {
@ -525,9 +580,7 @@ impl<T: ToValue> ToValue for Option<T> {
fn to_value(&self) -> Value {
match *self {
Some(ref v) => v.to_value(),
None => Value {
ptr: Gc::new(ValueData::Null),
},
None => Gc::new(ValueData::Null),
}
}
}
@ -541,6 +594,25 @@ impl<T: FromValue> FromValue for Option<T> {
}
}
impl ToValue for NativeFunctionData {
fn to_value(&self) -> Value {
Gc::new(ValueData::Function(GcCell::new(Function::NativeFunc(
NativeFunction::new(*self),
))))
}
}
impl FromValue for NativeFunctionData {
fn from_value(v: Value) -> Result<NativeFunctionData, &'static str> {
match *v {
ValueData::Function(ref func) => match *func.borrow() {
Function::NativeFunc(ref data) => Ok(data.data),
_ => Err("Value is not a native function"),
},
_ => Err("Value is not a function"),
}
}
}
/// A utility function that just calls FromValue::from_value
pub fn from_value<A: FromValue>(v: Value) -> Result<A, &'static str> {
FromValue::from_value(v)

2
src/lib/syntax/ast/constant.rs

@ -1,6 +1,6 @@
use std::fmt::{Display, Formatter, Result};
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
/// A Javascript Constant
pub enum Const {
/// A UTF-8 string, such as `"Hello, world"`

4
src/lib/syntax/ast/expr.rs

@ -3,7 +3,7 @@ use std::fmt::{Display, Formatter, Result};
use syntax::ast::constant::Const;
use syntax::ast::op::{BinOp, Operator, UnaryOp};
#[derive(Clone, Trace, Debug, PartialEq)]
#[derive(Clone, Trace, Finalize, Debug, PartialEq)]
pub struct Expr {
/// The expression definition
pub def: ExprDef,
@ -22,7 +22,7 @@ impl Display for Expr {
}
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
/// A Javascript Expression
pub enum ExprDef {
/// Run a operation between 2 expressions

12
src/lib/syntax/ast/op.rs

@ -12,7 +12,7 @@ pub trait Operator {
}
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
/// A numeric operation between 2 values
pub enum NumOp {
/// `a + b` - Addition
@ -43,7 +43,7 @@ impl Display for NumOp {
}
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
/// A unary operation on a single value
pub enum UnaryOp {
/// `a++` - increment the value
@ -78,7 +78,7 @@ impl Display for UnaryOp {
}
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
/// A bitwise operation between 2 values
pub enum BitOp {
/// `a & b` - Bitwise and
@ -109,7 +109,7 @@ impl Display for BitOp {
}
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
/// A comparitive operation between 2 values
pub enum CompOp {
/// `a == b` - Equality
@ -149,7 +149,7 @@ impl Display for CompOp {
}
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
/// A logical operation between 2 boolean values
pub enum LogOp {
/// `a && b` - Logical and
@ -171,7 +171,7 @@ impl Display for LogOp {
}
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
/// A binary operation between 2 values
pub enum BinOp {
/// Numeric operation

Loading…
Cancel
Save