Skip to content

Commit a0d2fbe

Browse files
committed
Allow numbers and keywords, as well as computed expressions as class
keys
1 parent 25c81c0 commit a0d2fbe

File tree

7 files changed

+223
-42
lines changed

7 files changed

+223
-42
lines changed

core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ratel"
3-
version = "0.5.3"
3+
version = "0.5.4"
44
authors = ["Maciej Hirsz <[email protected]>"]
55
license = "MIT/Apache-2.0"
66
description = "JavaScript transpiler in Rust"

core/src/codegen.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -561,14 +561,14 @@ impl Code for ClassMember {
561561

562562
ClassMember::Method {
563563
is_static,
564-
ref name,
564+
ref key,
565565
ref params,
566566
ref body,
567567
} => {
568568
if is_static {
569569
gen.write_bytes(b"static ");
570570
}
571-
gen.write(name);
571+
gen.write(key);
572572
gen.write_byte(b'(');
573573
gen.write_list(params);
574574
gen.write_min(b") {", b"){");
@@ -578,13 +578,13 @@ impl Code for ClassMember {
578578

579579
ClassMember::Property {
580580
is_static,
581-
ref name,
581+
ref key,
582582
ref value,
583583
} => {
584584
if is_static {
585585
gen.write_bytes(b"static ");
586586
}
587-
gen.write(name);
587+
gen.write(key);
588588
gen.write_min(b" = ", b"=");
589589
gen.write(value);
590590
gen.write_byte(b';');
@@ -593,6 +593,24 @@ impl Code for ClassMember {
593593
}
594594
}
595595

596+
impl Code for ClassKey {
597+
fn to_code(&self, gen: &mut Generator) {
598+
match *self {
599+
ClassKey::Literal(ref name) => gen.write(name),
600+
601+
ClassKey::Number(ref name) => gen.write(name),
602+
603+
ClassKey::Binary(ref num) => gen.write(num),
604+
605+
ClassKey::Computed(ref expr) => {
606+
gen.write_byte(b'[');
607+
gen.write(expr);
608+
gen.write_byte(b']');
609+
}
610+
}
611+
}
612+
}
613+
596614
impl Code for VariableDeclarator {
597615
#[inline]
598616
fn to_code(&self, gen: &mut Generator) {

core/src/grammar.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,17 +431,36 @@ pub enum ClassMember {
431431
},
432432
Method {
433433
is_static: bool,
434-
name: OwnedSlice,
434+
key: ClassKey,
435435
params: Vec<Parameter>,
436436
body: Vec<Statement>,
437437
},
438438
Property {
439439
is_static: bool,
440-
name: OwnedSlice,
440+
key: ClassKey,
441441
value: Expression,
442442
}
443443
}
444444

445+
#[derive(Debug, PartialEq, Clone)]
446+
pub enum ClassKey {
447+
Computed(Expression),
448+
Literal(OwnedSlice),
449+
Number(OwnedSlice),
450+
Binary(u64),
451+
}
452+
453+
impl ClassKey {
454+
#[inline]
455+
pub fn is_constructor(&self) -> bool {
456+
match *self {
457+
ClassKey::Literal(ref name) => name.as_str() == "constructor",
458+
459+
_ => false
460+
}
461+
}
462+
}
463+
445464
#[derive(Debug, PartialEq, Clone, Copy)]
446465
pub enum VariableDeclarationKind {
447466
Var,

core/src/parser.rs

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -891,18 +891,18 @@ impl<'a> Parser<'a> {
891891
})
892892
}
893893

894-
fn class_member(&mut self, name: OwnedSlice, is_static: bool) -> Result<ClassMember> {
894+
fn class_member(&mut self, key: ClassKey, is_static: bool) -> Result<ClassMember> {
895895
Ok(match next!(self) {
896896
ParenOpen => {
897-
if !is_static && name.as_str() == "constructor" {
897+
if !is_static && key.is_constructor() {
898898
ClassMember::Constructor {
899899
params: try!(self.parameter_list()),
900900
body: try!(self.block_body()),
901901
}
902902
} else {
903903
ClassMember::Method {
904904
is_static: is_static,
905-
name: name,
905+
key: key,
906906
params: try!(self.parameter_list()),
907907
body: try!(self.block_body()),
908908
}
@@ -911,7 +911,7 @@ impl<'a> Parser<'a> {
911911
Operator(Assign) => {
912912
ClassMember::Property {
913913
is_static: is_static,
914-
name: name,
914+
key: key,
915915
value: try!(self.expression(0)),
916916
}
917917
},
@@ -937,17 +937,47 @@ impl<'a> Parser<'a> {
937937
let mut members = Vec::new();
938938

939939
loop {
940-
members.push(match next!(self) {
941-
Identifier(name) => try!(self.class_member(name, false)),
942-
Static => {
943-
let name = expect_identifier!(self);
940+
let mut token = next!(self);
941+
942+
let is_static = match token {
943+
Static => {
944+
token = next!(self);
944945

945-
try!(self.class_member(name, true))
946+
true
946947
},
947-
Semicolon => continue,
948-
BraceClose => break,
949-
_ => unexpected_token!(self)
950-
});
948+
949+
_ => false
950+
};
951+
952+
let key = match token {
953+
Semicolon => continue,
954+
955+
BraceClose => break,
956+
957+
Literal(Value::Number(num)) => ClassKey::Number(num),
958+
959+
Literal(Value::Binary(num)) => ClassKey::Binary(num),
960+
961+
Identifier(key) => ClassKey::Literal(key),
962+
963+
BracketOpen => {
964+
let expr = try!(self.sequence_or_expression());
965+
966+
expect!(self, BracketClose);
967+
968+
ClassKey::Computed(expr)
969+
}
970+
971+
_ => {
972+
// Allow word tokens such as "null" and "typeof" as identifiers
973+
match token.as_word() {
974+
Some(key) => ClassKey::Literal(key.into()),
975+
_ => unexpected_token!(self)
976+
}
977+
}
978+
};
979+
980+
members.push(try!(self.class_member(key, is_static)));
951981
}
952982

953983
Ok(Statement::Class {

core/src/transformer.rs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -533,14 +533,14 @@ fn add_props_to_body(body: &mut Vec<Statement>, mut props: Vec<ClassMember>) {
533533
for prop in props.iter_mut().rev() {
534534
if let &mut ClassMember::Property {
535535
// ref is_static,
536-
ref name,
536+
ref mut key,
537537
ref mut value,
538538
..
539539
} = prop {
540540
body.insert(
541541
0,
542542
Expression::binary(
543-
Expression::member(Expression::This, *name),
543+
class_key_to_member(Expression::This, key),
544544
Assign,
545545
value.take(),
546546
).into()
@@ -549,6 +549,30 @@ fn add_props_to_body(body: &mut Vec<Statement>, mut props: Vec<ClassMember>) {
549549
}
550550
}
551551

552+
#[inline]
553+
fn class_key_to_member(object: Expression, key: &mut ClassKey) -> Expression {
554+
let expr = match *key {
555+
ClassKey::Literal(ref name) => {
556+
return Expression::member(object, *name);
557+
},
558+
559+
ClassKey::Computed(ref mut expr) => expr.take(),
560+
561+
ClassKey::Number(ref num) => {
562+
Expression::Literal(Value::Number(*num))
563+
},
564+
565+
ClassKey::Binary(ref num) => {
566+
Expression::Literal(Value::Binary(*num))
567+
}
568+
};
569+
570+
Expression::ComputedMember {
571+
object: Box::new(object),
572+
property: Box::new(expr),
573+
}
574+
}
575+
552576
impl Transformable for Statement {
553577
fn transform(&mut self, settings: &Settings) {
554578
*self = match *self {
@@ -671,20 +695,19 @@ impl Transformable for Statement {
671695

672696
for method in methods.iter_mut() {
673697
if let &mut ClassMember::Method {
674-
name: ref method_name,
698+
key: ref mut method_key,
675699
params: ref mut method_params,
676700
body: ref mut method_body,
677701
..
678702
} = method {
703+
let proto = Expression::member(name, "prototype");
704+
679705
body.push(
680706
Expression::binary(
681-
Expression::member(
682-
Expression::member(name, "prototype"),
683-
*method_name
684-
),
707+
class_key_to_member(proto, method_key),
685708
Assign,
686709
Expression::Function {
687-
name: Some(*method_name),
710+
name: None,
688711
params: method_params.take(),
689712
body: method_body.take(),
690713
},

core/tests/codegen.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@ fn dont_touch_var_in_global_scope() {
3232
assert_compile!("var pi = 3.14;", "var pi=3.14;");
3333
}
3434

35+
#[test]
36+
fn convert_let_to_var_in_block() {
37+
let program = "if(true) {
38+
let pi = 3.14;
39+
}";
40+
41+
let expected = "if(!0){var pi=3.14;}";
42+
43+
assert_compile!(program, expected);
44+
}
45+
3546
#[test]
3647
fn template_strings_plain() {
3748
assert_compile!("`foobar`;", r#""foobar";"#);
@@ -67,14 +78,4 @@ fn template_strings_tagged() {
6778
assert_compile!("foo`bar${1}baz${2}`;", r#"foo(["bar","baz",""],1,2);"#);
6879
}
6980

70-
#[test]
71-
fn convert_let_to_var_in_block() {
72-
let program = "if(true) {
73-
let pi = 3.14;
74-
}";
75-
76-
let expected = "if(!0){var pi=3.14;}";
77-
78-
assert_compile!(program, expected);
79-
}
8081

0 commit comments

Comments
 (0)