use crate::ast::*;
use crate::error::Result;
use crate::gen_sexp::gen::Generator;
use crate::gen_sexp::helpers::*;
use crate::sexp::SExp;
impl Generator {
pub fn generate_block(&self, block: &Block) -> Result<SExp> {
let mut fields = kwargs(vec![
kwarg("stmts", self.generate_stmts(&block.stmts)?),
kwarg("id", self.generate_node_id(block.id)),
kwarg("rules", self.generate_block_check_mode(block.rules)),
kwarg("span", self.generate_span(block.span)),
]);
if block.tokens.is_some() {
fields.extend(kwarg("tokens", sym("nil")));
}
fields.extend(kwarg(
"could-be-bare-literal",
sym(if block.could_be_bare_literal { "true" } else { "false" }),
));
Ok(typed_node("Block", fields))
}
fn generate_block_check_mode(&self, mode: BlockCheckMode) -> SExp {
match mode {
BlockCheckMode::Default => sym("Default"),
BlockCheckMode::Unsafe => sym("Unsafe"),
}
}
fn generate_stmts(&self, stmts: &[Stmt]) -> Result<SExp> {
let stmt_sexps: Result<Vec<SExp>> =
stmts.iter().map(|stmt| self.generate_stmt(stmt)).collect();
Ok(list(stmt_sexps?))
}
pub fn generate_expr(&self, expr: &Expr) -> Result<SExp> {
let mut fields = kwargs(vec![
kwarg("id", self.generate_node_id(expr.id)),
kwarg("kind", self.generate_expr_kind(&expr.kind)?),
kwarg("span", self.generate_span(expr.span)),
kwarg("attrs", self.generate_attr_vec(&expr.attrs)?),
]);
if expr.tokens.is_some() {
fields.extend(kwarg("tokens", sym("nil")));
}
Ok(typed_node("Expr", fields))
}
fn generate_expr_kind(&self, kind: &ExprKind) -> Result<SExp> {
match kind {
ExprKind::MacCall(mac_call) => {
Ok(list(vec![sym("MacCall"), self.generate_mac_call(mac_call)?]))
}
ExprKind::Lit(lit) => Ok(list(vec![sym("Lit"), self.generate_lit(lit)])),
ExprKind::Path(qself, path) => {
let qself_sexp = if qself.is_some() {
sym("TODO") } else {
sym("nil")
};
Ok(list(vec![sym("Path"), qself_sexp, self.generate_path(path)]))
}
ExprKind::If { cond, then_branch, else_branch } => {
let mut fields = kwargs(vec![
kwarg("cond", self.generate_expr(cond)?),
kwarg("then", self.generate_block(then_branch)?),
]);
if let Some(else_expr) = else_branch {
fields.extend(kwarg("else", self.generate_expr(else_expr)?));
} else {
fields.extend(kwarg("else", sym("nil")));
}
Ok(list(vec![sym("If")].into_iter().chain(fields).collect()))
}
ExprKind::Match { expr, arms } => {
let arms_sexp = list(arms.iter().map(|arm| self.generate_arm(arm)).collect());
Ok(list(vec![
sym("Match"),
kw("expr"),
self.generate_expr(expr)?,
kw("arms"),
arms_sexp,
]))
}
ExprKind::While { label, cond, body } => {
let label_sexp =
label.as_ref().map(|l| self.generate_label(l)).unwrap_or_else(|| sym("nil"));
Ok(list(vec![
sym("While"),
kw("label"),
label_sexp,
kw("cond"),
self.generate_expr(cond)?,
kw("body"),
self.generate_block(body)?,
]))
}
ExprKind::ForLoop { label, pat, iter, body } => {
let label_sexp =
label.as_ref().map(|l| self.generate_label(l)).unwrap_or_else(|| sym("nil"));
Ok(list(vec![
sym("ForLoop"),
kw("label"),
label_sexp,
kw("pat"),
self.generate_pat(pat)?,
kw("iter"),
self.generate_expr(iter)?,
kw("body"),
self.generate_block(body)?,
]))
}
ExprKind::Loop { label, body } => {
let label_sexp =
label.as_ref().map(|l| self.generate_label(l)).unwrap_or_else(|| sym("nil"));
Ok(list(vec![
sym("Loop"),
kw("label"),
label_sexp,
kw("body"),
self.generate_block(body)?,
]))
}
ExprKind::Binary { left, op, right } => Ok(list(vec![
sym("Binary"),
kw("left"),
self.generate_expr(left)?,
kw("op"),
self.generate_binop(*op),
kw("right"),
self.generate_expr(right)?,
])),
ExprKind::Unary { op, expr } => Ok(list(vec![
sym("Unary"),
kw("op"),
self.generate_unop(*op),
kw("expr"),
self.generate_expr(expr)?,
])),
ExprKind::Call { func, args } => {
let args_sexp = list(
args.iter().map(|arg| self.generate_expr(arg)).collect::<Result<Vec<_>>>()?,
);
Ok(list(vec![
sym("Call"),
kw("func"),
self.generate_expr(func)?,
kw("args"),
args_sexp,
]))
}
ExprKind::MethodCall { receiver, method, args } => {
let args_sexp = list(
args.iter().map(|arg| self.generate_expr(arg)).collect::<Result<Vec<_>>>()?,
);
Ok(list(vec![
sym("MethodCall"),
kw("receiver"),
self.generate_expr(receiver)?,
kw("method"),
self.generate_ident(method),
kw("args"),
args_sexp,
]))
}
ExprKind::Array(elems) => {
let elems_sexp =
list(elems.iter().map(|e| self.generate_expr(e)).collect::<Result<Vec<_>>>()?);
Ok(list(vec![sym("Array"), elems_sexp]))
}
ExprKind::Tuple(elems) => {
let elems_sexp =
list(elems.iter().map(|e| self.generate_expr(e)).collect::<Result<Vec<_>>>()?);
Ok(list(vec![sym("Tuple"), elems_sexp]))
}
ExprKind::Field { expr, field } => Ok(list(vec![
sym("Field"),
kw("expr"),
self.generate_expr(expr)?,
kw("field"),
self.generate_ident(field),
])),
ExprKind::Index { expr, index } => Ok(list(vec![
sym("Index"),
kw("expr"),
self.generate_expr(expr)?,
kw("index"),
self.generate_expr(index)?,
])),
ExprKind::Assign { left, right } => Ok(list(vec![
sym("Assign"),
kw("left"),
self.generate_expr(left)?,
kw("right"),
self.generate_expr(right)?,
])),
ExprKind::Struct { path, fields } => {
let fields_sexp = list(
fields
.iter()
.map(|f| self.generate_expr_field(f))
.collect::<Result<Vec<_>>>()?,
);
Ok(list(vec![
sym("Struct"),
kw("path"),
self.generate_path(path),
kw("fields"),
fields_sexp,
]))
}
ExprKind::Closure { params, body } => {
let params_sexp = list(
params.iter().map(|p| self.generate_param(p)).collect::<Result<Vec<_>>>()?,
);
Ok(list(vec![
sym("Closure"),
kw("params"),
params_sexp,
kw("body"),
self.generate_expr(body)?,
]))
}
ExprKind::Range { start, end, inclusive } => {
let start_sexp =
if let Some(s) = start { self.generate_expr(s)? } else { sym("nil") };
let end_sexp = if let Some(e) = end { self.generate_expr(e)? } else { sym("nil") };
Ok(list(vec![
sym("Range"),
kw("start"),
start_sexp,
kw("end"),
end_sexp,
kw("inclusive"),
sym(if *inclusive { "true" } else { "false" }),
]))
}
ExprKind::Paren(expr) => Ok(list(vec![sym("Paren"), self.generate_expr(expr)?])),
ExprKind::Try(expr) => Ok(list(vec![sym("Try"), self.generate_expr(expr)?])),
ExprKind::Cast { expr, ty } => Ok(list(vec![
sym("Cast"),
kw("expr"),
self.generate_expr(expr)?,
kw("ty"),
self.generate_ty(ty)?,
])),
ExprKind::Break { label, value } => {
let label_sexp =
if let Some(l) = label { self.generate_label(l) } else { sym("nil") };
let value_sexp =
if let Some(v) = value { self.generate_expr(v)? } else { sym("nil") };
Ok(list(vec![sym("Break"), kw("label"), label_sexp, kw("value"), value_sexp]))
}
ExprKind::Continue { label } => {
let label_sexp =
if let Some(l) = label { self.generate_label(l) } else { sym("nil") };
Ok(list(vec![sym("Continue"), kw("label"), label_sexp]))
}
ExprKind::Return { value } => {
let value_sexp =
if let Some(v) = value { self.generate_expr(v)? } else { sym("nil") };
Ok(list(vec![sym("Return"), kw("value"), value_sexp]))
}
ExprKind::Async { capture, body } => {
let capture_sexp = match capture {
CaptureBy::Value => sym("Value"),
CaptureBy::Ref => sym("Ref"),
};
Ok(list(vec![
sym("Async"),
kw("capture"),
capture_sexp,
kw("body"),
self.generate_block(body)?,
]))
}
ExprKind::Await { expr } => {
Ok(list(vec![sym("Await"), kw("expr"), self.generate_expr(expr)?]))
}
ExprKind::Let { pat, expr } => Ok(list(vec![
sym("Let"),
kw("pat"),
self.generate_pat(pat)?,
kw("expr"),
self.generate_expr(expr)?,
])),
ExprKind::Repeat { expr, count } => Ok(list(vec![
sym("Repeat"),
kw("expr"),
self.generate_expr(expr)?,
kw("count"),
self.generate_expr(count)?,
])),
ExprKind::Unsafe { body } => {
Ok(list(vec![sym("Unsafe"), kw("body"), self.generate_block(body)?]))
}
ExprKind::Yield { value } => {
let value_sexp =
if let Some(v) = value { self.generate_expr(v)? } else { sym("nil") };
Ok(list(vec![sym("Yield"), kw("value"), value_sexp]))
}
ExprKind::Const { body } => {
Ok(list(vec![sym("Const"), kw("body"), self.generate_block(body)?]))
}
}
}
pub fn generate_mac_call(&self, mac_call: &MacCall) -> Result<SExp> {
let mut fields = kwargs(vec![
kwarg("path", self.generate_path(&mac_call.path)),
kwarg("args", self.generate_mac_args(&mac_call.args)?),
]);
if mac_call.prior_type_ascription.is_some() {
fields.extend(kwarg("prior-type-ascription", sym("TODO")));
} else {
fields.extend(kwarg("prior-type-ascription", sym("nil")));
}
Ok(typed_node("MacCall", fields))
}
pub(crate) fn generate_mac_args(&self, args: &MacArgs) -> Result<SExp> {
match args {
MacArgs::Empty => Ok(sym("Empty")),
MacArgs::Delimited { dspan, delim, tokens } => {
let fields = kwargs(vec![
kwarg("dspan", self.generate_del_span(*dspan)),
kwarg("delim", self.generate_delimiter(*delim)),
kwarg("tokens", self.generate_token_stream(tokens)),
]);
Ok(typed_node("Delimited", fields))
}
MacArgs::Eq { eq_span, tokens } => {
let fields = kwargs(vec![
kwarg("eq-span", self.generate_span(*eq_span)),
kwarg("tokens", self.generate_token_stream(tokens)),
]);
Ok(typed_node("Eq", fields))
}
}
}
fn generate_del_span(&self, dspan: DelSpan) -> SExp {
let fields = kwargs(vec![
kwarg("open", self.generate_span(dspan.open)),
kwarg("close", self.generate_span(dspan.close)),
]);
typed_node("DelSpan", fields)
}
fn generate_delimiter(&self, delim: Delimiter) -> SExp {
match delim {
Delimiter::Paren => sym("Paren"),
Delimiter::Brace => sym("Brace"),
Delimiter::Bracket => sym("Bracket"),
Delimiter::Invisible => sym("Invisible"),
}
}
fn generate_token_stream(&self, tokens: &TokenStream) -> SExp {
match tokens {
TokenStream::Source(source) => {
let fields = kwargs(vec![kwarg("source", string(source))]);
typed_node("TokenStream", fields)
}
TokenStream::Empty => sym("Empty"),
}
}
fn generate_lit(&self, lit: &Lit) -> SExp {
let fields = kwargs(vec![
kwarg("kind", self.generate_lit_kind(&lit.kind)),
kwarg("span", self.generate_span(lit.span)),
]);
typed_node("Lit", fields)
}
fn generate_lit_kind(&self, kind: &LitKind) -> SExp {
match kind {
LitKind::Str(s) => list(vec![sym("Str"), string(s)]),
LitKind::Int(i) => list(vec![sym("Int"), num(*i)]),
LitKind::Bool(b) => list(vec![sym("Bool"), sym(if *b { "true" } else { "false" })]),
LitKind::Float(f) => list(vec![sym("Float"), string(f)]),
LitKind::Char(c) => list(vec![sym("Char"), string(c.to_string())]),
LitKind::Byte(b) => list(vec![sym("Byte"), num(*b as i128)]),
LitKind::ByteStr(bytes) => {
let bytes_sexp = list(bytes.iter().map(|b| num(*b as i128)).collect());
list(vec![sym("ByteStr"), bytes_sexp])
}
LitKind::CStr(bytes) => {
let bytes_sexp = list(bytes.iter().map(|b| num(*b as i128)).collect());
list(vec![sym("CStr"), bytes_sexp])
}
LitKind::Verbatim(s) => list(vec![sym("Verbatim"), string(s)]),
}
}
fn generate_arm(&self, arm: &Arm) -> SExp {
let mut fields = kwargs(vec![
kwarg("pat", self.generate_pat(&arm.pat).unwrap_or_else(|_| sym("ERROR"))),
kwarg("body", self.generate_expr(&arm.body).unwrap_or_else(|_| sym("ERROR"))),
]);
if let Some(guard) = &arm.guard {
fields
.extend(kwarg("guard", self.generate_expr(guard).unwrap_or_else(|_| sym("ERROR"))));
} else {
fields.extend(kwarg("guard", sym("nil")));
}
fields.extend(kwargs(vec![
kwarg("id", num(arm.id.0 as i128)),
kwarg("span", self.generate_span(arm.span)),
]));
typed_node("Arm", fields)
}
fn generate_label(&self, label: &Label) -> SExp {
typed_node("Label", kwargs(vec![kwarg("ident", self.generate_ident(&label.ident))]))
}
fn generate_binop(&self, op: BinOp) -> SExp {
sym(match op {
BinOp::Add => "Add",
BinOp::Sub => "Sub",
BinOp::Mul => "Mul",
BinOp::Div => "Div",
BinOp::Rem => "Rem",
BinOp::And => "And",
BinOp::Or => "Or",
BinOp::BitAnd => "BitAnd",
BinOp::BitOr => "BitOr",
BinOp::BitXor => "BitXor",
BinOp::Shl => "Shl",
BinOp::Shr => "Shr",
BinOp::Eq => "Eq",
BinOp::Ne => "Ne",
BinOp::Lt => "Lt",
BinOp::Le => "Le",
BinOp::Gt => "Gt",
BinOp::Ge => "Ge",
})
}
fn generate_unop(&self, op: UnOp) -> SExp {
sym(match op {
UnOp::Not => "Not",
UnOp::Neg => "Neg",
UnOp::Deref => "Deref",
UnOp::Ref => "Ref",
UnOp::RefMut => "RefMut",
})
}
fn generate_expr_field(&self, field: &ExprField) -> Result<SExp> {
Ok(typed_node(
"ExprField",
kwargs(vec![
kwarg("attrs", sym("nil")), kwarg("ident", self.generate_ident(&field.ident)),
kwarg("expr", self.generate_expr(&field.expr)?),
kwarg("is-shorthand", sym(if field.is_shorthand { "true" } else { "false" })),
kwarg("span", self.generate_span(field.span)),
]),
))
}
}