Implement if, for, while and try js codegen
This commit is contained in:
+220
-4
@@ -23,11 +23,27 @@ pub enum Statement {
|
||||
},
|
||||
Return(Expression),
|
||||
Expression(Expression),
|
||||
For,
|
||||
If,
|
||||
While,
|
||||
For {
|
||||
init: Option<Expression>,
|
||||
condition: Option<Expression>,
|
||||
update: Option<Expression>,
|
||||
body: Vec<Statement>,
|
||||
},
|
||||
If {
|
||||
condition: Expression,
|
||||
then_: Vec<Statement>,
|
||||
else_: Option<Vec<Statement>>,
|
||||
},
|
||||
While {
|
||||
condition: Expression,
|
||||
body: Vec<Statement>,
|
||||
},
|
||||
Throw(Expression),
|
||||
Try,
|
||||
Try {
|
||||
body: Vec<Statement>,
|
||||
catch_: Option<(String, Vec<Statement>)>,
|
||||
finally: Option<Vec<Statement>>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<W: Write> Emit<W> for Statement {
|
||||
@@ -63,6 +79,107 @@ impl<W: Write> Emit<W> for Statement {
|
||||
write!(w, "throw ").map_err(EmitError::WriterError)?;
|
||||
e.emit(w)
|
||||
}
|
||||
Statement::Try {
|
||||
body,
|
||||
catch_,
|
||||
finally,
|
||||
} => {
|
||||
write!(w, "try {}", "{").map_err(EmitError::WriterError)?;
|
||||
for (i, st) in body.iter().enumerate() {
|
||||
st.emit(w)?;
|
||||
if i + 1 != body.len() {
|
||||
write!(w, "; ").map_err(EmitError::WriterError)?;
|
||||
}
|
||||
}
|
||||
write!(w, "{}", "}").map_err(EmitError::WriterError)?;
|
||||
if let Some((name, catch_body)) = catch_ {
|
||||
write!(w, " catch ({}) {}", name, "{").map_err(EmitError::WriterError)?;
|
||||
for (i, st) in catch_body.iter().enumerate() {
|
||||
st.emit(w)?;
|
||||
if i + 1 != catch_body.len() {
|
||||
write!(w, "; ").map_err(EmitError::WriterError)?;
|
||||
}
|
||||
}
|
||||
write!(w, "{}", "}").map_err(EmitError::WriterError)?;
|
||||
}
|
||||
if let Some(finally) = finally {
|
||||
write!(w, " finally {}", "{").map_err(EmitError::WriterError)?;
|
||||
for (i, st) in finally.iter().enumerate() {
|
||||
st.emit(w)?;
|
||||
if i + 1 != finally.len() {
|
||||
write!(w, "; ").map_err(EmitError::WriterError)?;
|
||||
}
|
||||
}
|
||||
write!(w, "{}", "}").map_err(EmitError::WriterError)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Statement::If {
|
||||
condition,
|
||||
then_,
|
||||
else_,
|
||||
} => {
|
||||
write!(w, "if (").map_err(EmitError::WriterError)?;
|
||||
condition.emit(w)?;
|
||||
write!(w, ") {}", "{").map_err(EmitError::WriterError)?;
|
||||
for (i, st) in then_.iter().enumerate() {
|
||||
st.emit(w)?;
|
||||
if i + 1 != then_.len() {
|
||||
write!(w, "; ").map_err(EmitError::WriterError)?;
|
||||
}
|
||||
}
|
||||
write!(w, "{}", "}").map_err(EmitError::WriterError)?;
|
||||
if let Some(else_) = else_ {
|
||||
write!(w, " else {}", "{").map_err(EmitError::WriterError)?;
|
||||
for (i, st) in else_.iter().enumerate() {
|
||||
st.emit(w)?;
|
||||
if i + 1 != else_.len() {
|
||||
write!(w, "; ").map_err(EmitError::WriterError)?;
|
||||
}
|
||||
}
|
||||
write!(w, "{}", "}").map_err(EmitError::WriterError)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Statement::For {
|
||||
init,
|
||||
condition,
|
||||
update,
|
||||
body,
|
||||
} => {
|
||||
write!(w, "for (").map_err(EmitError::WriterError)?;
|
||||
if let Some(init) = init {
|
||||
init.emit(w)?;
|
||||
}
|
||||
write!(w, "; ").map_err(EmitError::WriterError)?;
|
||||
if let Some(condition) = condition {
|
||||
condition.emit(w)?;
|
||||
}
|
||||
write!(w, "; ").map_err(EmitError::WriterError)?;
|
||||
if let Some(update) = update {
|
||||
update.emit(w)?;
|
||||
}
|
||||
write!(w, ") {}", "{").map_err(EmitError::WriterError)?;
|
||||
for (i, st) in body.iter().enumerate() {
|
||||
st.emit(w)?;
|
||||
if i + 1 != body.len() {
|
||||
write!(w, "; ").map_err(EmitError::WriterError)?;
|
||||
}
|
||||
}
|
||||
write!(w, "{}", "}").map_err(EmitError::WriterError)
|
||||
}
|
||||
Statement::While { condition, body } => {
|
||||
write!(w, "while (").map_err(EmitError::WriterError)?;
|
||||
condition.emit(w)?;
|
||||
write!(w, ") {}", "{").map_err(EmitError::WriterError)?;
|
||||
for (i, st) in body.iter().enumerate() {
|
||||
st.emit(w)?;
|
||||
if i + 1 != body.len() {
|
||||
write!(w, "; ").map_err(EmitError::WriterError)?;
|
||||
}
|
||||
}
|
||||
write!(w, "{}", "}").map_err(EmitError::WriterError)
|
||||
}
|
||||
_ => todo!("Tehe"),
|
||||
}
|
||||
}
|
||||
@@ -421,3 +538,102 @@ fn throw_emit() {
|
||||
throw.emit(&mut res).unwrap();
|
||||
assert_eq!(res, "throw null")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_try_emit() {
|
||||
let try_ = Statement::Try {
|
||||
body: Vec::new(),
|
||||
catch_: None,
|
||||
finally: None,
|
||||
};
|
||||
let mut res = String::new();
|
||||
try_.emit(&mut res).unwrap();
|
||||
assert_eq!(res, "try {}")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_emit() {
|
||||
let try_ = Statement::Try {
|
||||
body: vec![Statement::Expression(Expression::Null)],
|
||||
catch_: Some((
|
||||
"e".to_owned(),
|
||||
vec![Statement::Expression(Expression::Undefined)],
|
||||
)),
|
||||
finally: Some(vec![Statement::Expression(Expression::Null)]),
|
||||
};
|
||||
let mut res = String::new();
|
||||
try_.emit(&mut res).unwrap();
|
||||
assert_eq!(res, "try {null} catch (e) {undefined} finally {null}")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_for_emit() {
|
||||
let for_ = Statement::For {
|
||||
init: None,
|
||||
condition: None,
|
||||
update: None,
|
||||
body: Vec::new(),
|
||||
};
|
||||
let mut res = String::new();
|
||||
for_.emit(&mut res).unwrap();
|
||||
assert_eq!(res, "for (; ; ) {}")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn for_emit() {
|
||||
let for_ = Statement::For {
|
||||
init: Some(Expression::Null),
|
||||
condition: Some(Expression::Bool(true)),
|
||||
update: Some(Expression::Null),
|
||||
body: vec![Statement::Expression(Expression::Null)],
|
||||
};
|
||||
let mut res = String::new();
|
||||
for_.emit(&mut res).unwrap();
|
||||
assert_eq!(res, "for (null; true; null) {null}")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_while_emit() {
|
||||
let while_ = Statement::While {
|
||||
condition: Expression::Bool(true),
|
||||
body: Vec::new(),
|
||||
};
|
||||
let mut res = String::new();
|
||||
while_.emit(&mut res).unwrap();
|
||||
assert_eq!(res, "while (true) {}")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn while_emit() {
|
||||
let while_ = Statement::While {
|
||||
condition: Expression::Bool(true),
|
||||
body: vec![Statement::Expression(Expression::Null)],
|
||||
};
|
||||
let mut res = String::new();
|
||||
while_.emit(&mut res).unwrap();
|
||||
assert_eq!(res, "while (true) {null}")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_if_emit() {
|
||||
let if_ = Statement::If {
|
||||
condition: Expression::Bool(true),
|
||||
then_: Vec::new(),
|
||||
else_: None,
|
||||
};
|
||||
let mut res = String::new();
|
||||
if_.emit(&mut res).unwrap();
|
||||
assert_eq!(res, "if (true) {}")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn if_emit() {
|
||||
let if_ = Statement::If {
|
||||
condition: Expression::Bool(true),
|
||||
then_: vec![Statement::Expression(Expression::Null)],
|
||||
else_: Some(vec![Statement::Expression(Expression::Undefined)]),
|
||||
};
|
||||
let mut res = String::new();
|
||||
if_.emit(&mut res).unwrap();
|
||||
assert_eq!(res, "if (true) {null} else {undefined}")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user