compiler/
lib/
examples/
std/
arch/
char/
collections/
graph/
lang/
alloc/
ast/
printer.rad
26.0 KiB
gen/
il/
module/
parser/
resolver/
scanner/
alloc.rad
7.1 KiB
ast.rad
26.9 KiB
gen.rad
513 B
il.rad
20.4 KiB
lower.rad
321.7 KiB
module.rad
17.3 KiB
package.rad
1.3 KiB
parser.rad
92.2 KiB
resolver.rad
511.1 KiB
scanner.rad
17.9 KiB
sexpr.rad
6.7 KiB
strings.rad
2.2 KiB
types.rad
1.6 KiB
sys/
arch.rad
68 B
char.rad
855 B
collections.rad
39 B
fmt.rad
8.3 KiB
graph.rad
4.3 KiB
intrinsics.rad
467 B
io.rad
1.7 KiB
lang.rad
276 B
mem.rad
2.3 KiB
sys.rad
179 B
testing.rad
2.4 KiB
tests.rad
15.7 KiB
vec.rad
3.2 KiB
std.rad
299 B
scripts/
seed/
sublime/
test/
vim/
.gitignore
336 B
.gitsigners
112 B
CELL_PERMISSIONS
6.8 KiB
CONTRIBUTING
2.1 KiB
LICENSE
1.1 KiB
Makefile
5.4 KiB
README
2.5 KiB
STYLE
2.5 KiB
std.lib
1.5 KiB
std.lib.test
808 B
lib/std/lang/ast/printer.rad
raw
| 1 | //! AST pretty printer using S-expression syntax. |
| 2 | |
| 3 | use std::io; |
| 4 | use std::lang::sexpr; |
| 5 | use std::lang::alloc; |
| 6 | |
| 7 | /// Return the symbol for a binary operator. |
| 8 | fn binOpName(op: super::BinaryOp) -> *[u8] { |
| 9 | match op { |
| 10 | case super::BinaryOp::Add => return "+", |
| 11 | case super::BinaryOp::Sub => return "-", |
| 12 | case super::BinaryOp::Mul => return "*", |
| 13 | case super::BinaryOp::Div => return "/", |
| 14 | case super::BinaryOp::Mod => return "%", |
| 15 | case super::BinaryOp::BitAnd => return "&", |
| 16 | case super::BinaryOp::BitOr => return "|", |
| 17 | case super::BinaryOp::BitXor => return "^", |
| 18 | case super::BinaryOp::Shl => return "<<", |
| 19 | case super::BinaryOp::Shr => return ">>", |
| 20 | case super::BinaryOp::Eq => return "==", |
| 21 | case super::BinaryOp::Ne => return "<>", |
| 22 | case super::BinaryOp::Lt => return "<", |
| 23 | case super::BinaryOp::Gt => return ">", |
| 24 | case super::BinaryOp::Lte => return "<=", |
| 25 | case super::BinaryOp::Gte => return ">=", |
| 26 | case super::BinaryOp::And => return "and", |
| 27 | case super::BinaryOp::Or => return "or", |
| 28 | case super::BinaryOp::Xor => return "xor", |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | /// Return the symbol for a unary operator. |
| 33 | fn unOpName(op: super::UnaryOp) -> *[u8] { |
| 34 | match op { |
| 35 | case super::UnaryOp::Not => return "not", |
| 36 | case super::UnaryOp::Neg => return "-", |
| 37 | case super::UnaryOp::BitNot => return "~", |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | /// Return the name for a builtin. |
| 42 | fn builtinName(kind: super::Builtin) -> *[u8] { |
| 43 | match kind { |
| 44 | case super::Builtin::SizeOf => return "@sizeOf", |
| 45 | case super::Builtin::AlignOf => return "@alignOf", |
| 46 | case super::Builtin::SliceOf => return "@sliceOf", |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | /// Return the name for an integer type. |
| 51 | fn intTypeName(width: u8, sign: super::Signedness) -> *[u8] { |
| 52 | if let case super::Signedness::Signed = sign { |
| 53 | match width { |
| 54 | case 1 => return "i8", |
| 55 | case 2 => return "i16", |
| 56 | case 4 => return "i32", |
| 57 | case 8 => return "i64", |
| 58 | else => panic, |
| 59 | } |
| 60 | } else { |
| 61 | match width { |
| 62 | case 1 => return "u8", |
| 63 | case 2 => return "u16", |
| 64 | case 4 => return "u32", |
| 65 | case 8 => return "u64", |
| 66 | else => panic, |
| 67 | } |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | /// Return the S-expression head for a pointer class. |
| 72 | fn pointerClassHead( |
| 73 | class: super::PointerClass, |
| 74 | ownedHead: *[u8], |
| 75 | refHead: *[u8], |
| 76 | unsafeHead: *[u8], |
| 77 | ) -> *[u8] { |
| 78 | match class { |
| 79 | case super::PointerClass::Owned => return ownedHead, |
| 80 | case super::PointerClass::Ref => return refHead, |
| 81 | case super::PointerClass::Unsafe => return unsafeHead, |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | /// Convert a type signature to an S-expression. |
| 86 | unsafe fn typeSigToExpr(a: &mut alloc::Arena, sig: super::TypeSig) -> sexpr::Expr { |
| 87 | match sig { |
| 88 | case super::TypeSig::Void => return sexpr::sym("void"), |
| 89 | case super::TypeSig::Never => return sexpr::sym("!"), |
| 90 | case super::TypeSig::Opaque => return sexpr::sym("opaque"), |
| 91 | case super::TypeSig::Bool => return sexpr::sym("bool"), |
| 92 | case super::TypeSig::Integer { width, sign } => return sexpr::sym(intTypeName(width, sign)), |
| 93 | case super::TypeSig::Array { itemType, length } => |
| 94 | return sexpr::list(a, "array", &[toExpr(a, itemType), toExpr(a, length)]), |
| 95 | case super::TypeSig::Slice { class, itemType, mutable } => { |
| 96 | let head = pointerClassHead(class, "slice", "slice-ref", "unsafe-slice"); |
| 97 | return sexpr::list(a, head, &[sexpr::sym("mut"), toExpr(a, itemType)]) if mutable |
| 98 | else sexpr::list(a, head, &[toExpr(a, itemType)]); |
| 99 | } |
| 100 | case super::TypeSig::Pointer { class, valueType, mutable } => { |
| 101 | let head = pointerClassHead(class, "ptr", "ref", "unsafe-ptr"); |
| 102 | return sexpr::list(a, head, &[sexpr::sym("mut"), toExpr(a, valueType)]) if mutable |
| 103 | else sexpr::list(a, head, &[toExpr(a, valueType)]); |
| 104 | } |
| 105 | case super::TypeSig::Optional { valueType } => |
| 106 | return sexpr::list(a, "?", &[toExpr(a, valueType)]), |
| 107 | case super::TypeSig::Cell { class, permission, payload } => { |
| 108 | let head = pointerClassHead(class, "cell-ptr", "cell-ref", "unsafe-cell-ptr"); |
| 109 | if let region = permission { |
| 110 | return sexpr::list(a, head, &[toExpr(a, region), toExpr(a, payload)]); |
| 111 | } |
| 112 | return sexpr::list(a, head, &[toExpr(a, payload)]); |
| 113 | } |
| 114 | case super::TypeSig::Nominal(name) => return toExpr(a, name), |
| 115 | case super::TypeSig::RegionRef { region, type } => |
| 116 | return sexpr::list(a, "region-ref", &[toExpr(a, region), toExpr(a, type)]), |
| 117 | case super::TypeSig::Applied { name, regions } => |
| 118 | return sexpr::list(a, "apply", &[toExpr(a, name), sexpr::list(a, "regions", nodeListToExprs(a, regions))]), |
| 119 | case super::TypeSig::Record { fields, .. } => |
| 120 | return sexpr::list(a, "record", nodeListToExprs(a, fields)), |
| 121 | case super::TypeSig::Fn { sig, isUnsafe } => { |
| 122 | let mut ret = sexpr::sym("void"); |
| 123 | if let rt = sig.returnType { |
| 124 | set ret = toExpr(a, rt); |
| 125 | } |
| 126 | let head = "unsafe-fn" if isUnsafe else "fn"; |
| 127 | return sexpr::list(a, head, &[sexpr::list(a, "params", nodeListToExprs(a, sig.params)), ret]); |
| 128 | } |
| 129 | case super::TypeSig::TraitObject { class, traitName, mutable } => { |
| 130 | let head = pointerClassHead(class, "obj", "obj-ref", "unsafe-obj"); |
| 131 | return sexpr::list(a, head, &[sexpr::sym("mut"), toExpr(a, traitName)]) if mutable |
| 132 | else sexpr::list(a, head, &[toExpr(a, traitName)]); |
| 133 | } |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | /// Convert a node slice to a slice of expressions. |
| 138 | unsafe fn nodeListToExprs(a: &mut alloc::Arena, nodes: &[*super::Node]) -> *[sexpr::Expr] { |
| 139 | if nodes.len == 0 { |
| 140 | return &[]; |
| 141 | } |
| 142 | let buf = try! sexpr::allocExprs(a, nodes.len as u32); |
| 143 | for node, i in nodes { |
| 144 | set buf[i] = toExpr(a, node); |
| 145 | } |
| 146 | return buf; |
| 147 | } |
| 148 | |
| 149 | /// Convert optional attributes to an attribute list expression. |
| 150 | unsafe fn attributesToExpr(a: &mut alloc::Arena, attrs: ?super::Attributes) -> sexpr::Expr { |
| 151 | let mut exprs: *[sexpr::Expr] = &[]; |
| 152 | if let list = attrs { |
| 153 | set exprs = nodeListToExprs(a, list.list); |
| 154 | } |
| 155 | return sexpr::list(a, "attrs", exprs); |
| 156 | } |
| 157 | |
| 158 | /// Convert an optional node to an expression, or return placeholder. |
| 159 | unsafe fn toExprOpt(a: &mut alloc::Arena, opt: ?*super::Node) -> sexpr::Expr { |
| 160 | if let n = opt { |
| 161 | return toExpr(a, n); |
| 162 | } |
| 163 | return sexpr::sym("_"); |
| 164 | } |
| 165 | |
| 166 | /// Convert an optional node to an expression, or return `Null`. |
| 167 | unsafe fn toExprOrNull(a: &mut alloc::Arena, opt: ?*super::Node) -> sexpr::Expr { |
| 168 | if let n = opt { |
| 169 | return toExpr(a, n); |
| 170 | } |
| 171 | return sexpr::Expr::Null; |
| 172 | } |
| 173 | |
| 174 | /// Convert an optional guard. |
| 175 | unsafe fn guardExpr(a: &mut alloc::Arena, guard: ?*super::Node) -> sexpr::Expr { |
| 176 | if let g = guard { |
| 177 | return sexpr::list(a, "guard", &[toExpr(a, g)]); |
| 178 | } |
| 179 | return sexpr::Expr::Null; |
| 180 | } |
| 181 | |
| 182 | /// Convert a list of match prongs to expressions. |
| 183 | unsafe fn prongListToExprs(a: &mut alloc::Arena, nodes: &[*super::Node]) -> *[sexpr::Expr] { |
| 184 | if nodes.len == 0 { |
| 185 | return &[]; |
| 186 | } |
| 187 | let buf = try! sexpr::allocExprs(a, nodes.len as u32); |
| 188 | for prong, i in nodes { |
| 189 | match prong.value { |
| 190 | case super::NodeValue::MatchProng(p) => { |
| 191 | set buf[i] = prongToExpr(a, p); |
| 192 | } |
| 193 | else => { |
| 194 | set buf[i] = sexpr::sym("<invalid>"); |
| 195 | } |
| 196 | } |
| 197 | } |
| 198 | return buf; |
| 199 | } |
| 200 | |
| 201 | /// Convert a match prong to an S-expression. |
| 202 | unsafe fn prongToExpr(a: &mut alloc::Arena, p: super::MatchProng) -> sexpr::Expr { |
| 203 | match p.arm { |
| 204 | case super::ProngArm::Case(patterns) => { |
| 205 | return sexpr::block(a, "case", &[ |
| 206 | sexpr::list(a, "patterns", nodeListToExprs(a, patterns)), |
| 207 | guardExpr(a, p.guard) |
| 208 | ], &[toExpr(a, p.body)]); |
| 209 | } |
| 210 | case super::ProngArm::Else => { |
| 211 | return sexpr::block(a, "else", &[guardExpr(a, p.guard)], &[toExpr(a, p.body)]); |
| 212 | } |
| 213 | case super::ProngArm::Binding(pat) => { |
| 214 | if let g = p.guard { |
| 215 | return sexpr::block(a, "let", &[toExpr(a, pat), guardExpr(a, p.guard)], &[toExpr(a, p.body)]); |
| 216 | } |
| 217 | return sexpr::block(a, "bind", &[toExpr(a, pat)], &[toExpr(a, p.body)]); |
| 218 | } |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | /// Convert a record field declaration to an S-expression. |
| 223 | unsafe fn fieldToExpr( |
| 224 | a: &mut alloc::Arena, |
| 225 | field: ?*super::Node, |
| 226 | type: *super::Node, |
| 227 | value: ?*super::Node |
| 228 | ) -> sexpr::Expr { |
| 229 | return sexpr::list(a, ":", &[toExprOpt(a, field), toExpr(a, type), toExprOrNull(a, value)]); |
| 230 | } |
| 231 | |
| 232 | /// Convert a list of record fields to expressions. |
| 233 | unsafe fn fieldListToExprs(a: &mut alloc::Arena, nodes: &[*super::Node]) -> *[sexpr::Expr] { |
| 234 | if nodes.len == 0 { |
| 235 | return &[]; |
| 236 | } |
| 237 | let buf = try! sexpr::allocExprs(a, nodes.len as u32); |
| 238 | for node, i in nodes { |
| 239 | match node.value { |
| 240 | case super::NodeValue::RecordField { field, type, value } => { |
| 241 | set buf[i] = fieldToExpr(a, field, type, value); |
| 242 | } |
| 243 | else => { |
| 244 | set buf[i] = sexpr::sym("<invalid>"); |
| 245 | } |
| 246 | } |
| 247 | } |
| 248 | return buf; |
| 249 | } |
| 250 | |
| 251 | /// Convert a union variant to an S-expression. |
| 252 | unsafe fn variantToExpr(a: &mut alloc::Arena, name: *super::Node, type: ?*super::Node) -> sexpr::Expr { |
| 253 | return sexpr::list(a, "variant", &[toExpr(a, name), toExprOrNull(a, type)]); |
| 254 | } |
| 255 | |
| 256 | /// Convert a list of union variants to expressions. |
| 257 | unsafe fn variantListToExprs(a: &mut alloc::Arena, nodes: &[*super::Node]) -> *[sexpr::Expr] { |
| 258 | if nodes.len == 0 { |
| 259 | return &[]; |
| 260 | } |
| 261 | let buf = try! sexpr::allocExprs(a, nodes.len as u32); |
| 262 | for node, i in nodes { |
| 263 | match node.value { |
| 264 | case super::NodeValue::UnionDeclVariant(v) => { |
| 265 | set buf[i] = variantToExpr(a, v.name, v.type); |
| 266 | } |
| 267 | else => { |
| 268 | set buf[i] = sexpr::sym("<invalid>"); |
| 269 | } |
| 270 | } |
| 271 | } |
| 272 | return buf; |
| 273 | } |
| 274 | |
| 275 | /// Convert an AST node to an S-expression. |
| 276 | export unsafe fn toExpr(a: &mut alloc::Arena, node: *super::Node) -> sexpr::Expr { |
| 277 | match node.value { |
| 278 | case super::NodeValue::Placeholder => return sexpr::sym("_"), |
| 279 | case super::NodeValue::Nil => return sexpr::sym("nil"), |
| 280 | case super::NodeValue::Undef => return sexpr::sym("undefined"), |
| 281 | case super::NodeValue::Bool(v) => { |
| 282 | if v { |
| 283 | return sexpr::sym("true"); |
| 284 | } |
| 285 | return sexpr::sym("false"); |
| 286 | } |
| 287 | case super::NodeValue::Char(c) => return sexpr::Expr::Char(c), |
| 288 | case super::NodeValue::String(s) => return sexpr::Expr::Str(s), |
| 289 | case super::NodeValue::Ident(name) => return sexpr::sym(name), |
| 290 | case super::NodeValue::Number(lit) => return sexpr::sym(lit.text), |
| 291 | case super::NodeValue::Super => return sexpr::sym("super"), |
| 292 | case super::NodeValue::Break => return sexpr::list(a, "break", &[]), |
| 293 | case super::NodeValue::Continue => return sexpr::list(a, "continue", &[]), |
| 294 | case super::NodeValue::Range(r) => |
| 295 | return sexpr::list(a, "range", &[toExprOpt(a, r.start), toExprOpt(a, r.end)]), |
| 296 | case super::NodeValue::BinOp(b) => |
| 297 | return sexpr::list(a, binOpName(b.op), &[toExpr(a, b.left), toExpr(a, b.right)]), |
| 298 | case super::NodeValue::UnOp(u) => |
| 299 | return sexpr::list(a, unOpName(u.op), &[toExpr(a, u.value)]), |
| 300 | case super::NodeValue::Call(c) => { |
| 301 | let buf = try! sexpr::allocExprs(a, c.args.len as u32 + 1); |
| 302 | set buf[0] = toExpr(a, c.callee); |
| 303 | for arg, i in c.args { set buf[i + 1] = toExpr(a, arg); } |
| 304 | return sexpr::Expr::List { head: "call", tail: buf, multiline: false }; |
| 305 | } |
| 306 | case super::NodeValue::BuiltinCall { kind, args } => |
| 307 | return sexpr::list(a, builtinName(kind), nodeListToExprs(a, args)), |
| 308 | case super::NodeValue::Subscript { container, index } => |
| 309 | return sexpr::list(a, "[]", &[toExpr(a, container), toExpr(a, index)]), |
| 310 | case super::NodeValue::FieldAccess(acc) => |
| 311 | return sexpr::list(a, ".", &[toExpr(a, acc.parent), toExpr(a, acc.child)]), |
| 312 | case super::NodeValue::ScopeAccess(acc) => |
| 313 | return sexpr::list(a, "::", &[toExpr(a, acc.parent), toExpr(a, acc.child)]), |
| 314 | case super::NodeValue::AddressOf(addr) => { |
| 315 | if addr.kind == super::AddressKind::Cell { |
| 316 | if let permission = addr.permission { |
| 317 | return sexpr::list(a, "&cell", &[ |
| 318 | toExpr(a, permission), |
| 319 | toExpr(a, addr.target), |
| 320 | ]); |
| 321 | } |
| 322 | return sexpr::list(a, "&cell", &[toExpr(a, addr.target)]); |
| 323 | } |
| 324 | return sexpr::list(a, "&mut", &[toExpr(a, addr.target)]) |
| 325 | if addr.kind == super::AddressKind::Mutable |
| 326 | else sexpr::list(a, "&", &[toExpr(a, addr.target)]); |
| 327 | } |
| 328 | case super::NodeValue::Deref(target) => |
| 329 | return sexpr::list(a, "deref", &[toExpr(a, target)]), |
| 330 | case super::NodeValue::As(cast) => |
| 331 | return sexpr::list(a, "as", &[toExpr(a, cast.value), toExpr(a, cast.type)]), |
| 332 | case super::NodeValue::ArrayLit(elems) => |
| 333 | return sexpr::list(a, "array", nodeListToExprs(a, elems)), |
| 334 | case super::NodeValue::ArrayRepeatLit(rep) => |
| 335 | return sexpr::list(a, "array-repeat", &[toExpr(a, rep.item), toExpr(a, rep.count)]), |
| 336 | case super::NodeValue::RecordLit(lit) => { |
| 337 | let mut total: u32 = lit.fields.len as u32; |
| 338 | if let _ = lit.typeName { |
| 339 | set total += 1; |
| 340 | } |
| 341 | let buf = try! sexpr::allocExprs(a, total); |
| 342 | let mut idx: u32 = 0; |
| 343 | if let tn = lit.typeName { |
| 344 | set buf[idx] = toExpr(a, tn); set idx = idx + 1; |
| 345 | } |
| 346 | for field, i in lit.fields { |
| 347 | set buf[idx + i] = toExpr(a, field); |
| 348 | } |
| 349 | return sexpr::Expr::List { head: "record-lit", tail: buf, multiline: lit.fields.len > 2 }; |
| 350 | } |
| 351 | case super::NodeValue::RecordLitField(f) => |
| 352 | return sexpr::list(a, "field", &[toExprOpt(a, f.label), toExpr(a, f.value)]), |
| 353 | case super::NodeValue::TypeSig(sig) => return typeSigToExpr(a, sig), |
| 354 | case super::NodeValue::FnParam(p) => |
| 355 | return sexpr::list(a, "param", &[toExpr(a, p.name), toExpr(a, p.type)]), |
| 356 | case super::NodeValue::Attribute(attr) => { |
| 357 | match attr { |
| 358 | case super::Attribute::Export => return sexpr::sym("@export"), |
| 359 | case super::Attribute::Default => return sexpr::sym("@default"), |
| 360 | case super::Attribute::Extern => return sexpr::sym("@extern"), |
| 361 | case super::Attribute::Test => return sexpr::sym("@test"), |
| 362 | case super::Attribute::Intrinsic => return sexpr::sym("@intrinsic"), |
| 363 | case super::Attribute::Unsafe => return sexpr::sym("@unsafe"), |
| 364 | case super::Attribute::Opaque => return sexpr::sym("@opaque"), |
| 365 | } |
| 366 | } |
| 367 | case super::NodeValue::Try(t) => { |
| 368 | let mut head = "try"; |
| 369 | if t.shouldPanic { set head = "try!"; } |
| 370 | if t.catches.len > 0 { |
| 371 | let catches = nodeListToExprs(a, t.catches); |
| 372 | return sexpr::list(a, head, &[toExpr(a, t.expr), sexpr::block(a, "catches", &[], catches)]); |
| 373 | } |
| 374 | return sexpr::list(a, head, &[toExpr(a, t.expr)]); |
| 375 | } |
| 376 | case super::NodeValue::CatchClause(clause) => { |
| 377 | let mut head = "catch"; |
| 378 | let mut children: [sexpr::Expr; 3] = undefined; |
| 379 | let mut len: u32 = 0; |
| 380 | if let b = clause.binding { |
| 381 | set children[len] = toExpr(a, b); |
| 382 | set len += 1; |
| 383 | } |
| 384 | if let t = clause.typeNode { |
| 385 | set children[len] = toExpr(a, t); |
| 386 | set len += 1; |
| 387 | } |
| 388 | set children[len] = toExpr(a, clause.body); |
| 389 | set len += 1; |
| 390 | return sexpr::list(a, head, &children[..len]); |
| 391 | } |
| 392 | case super::NodeValue::Block(blk) => { |
| 393 | let children = nodeListToExprs(a, blk.statements); |
| 394 | let name = "unsafe" if blk.isUnsafe else "block"; |
| 395 | return sexpr::block(a, name, &[], children); |
| 396 | } |
| 397 | case super::NodeValue::Let(decl) => { |
| 398 | let mut head = "let"; |
| 399 | if decl.mutable { set head = "let-mut"; } |
| 400 | return sexpr::list(a, head, &[ |
| 401 | toExpr(a, decl.ident), |
| 402 | toExprOrNull(a, decl.type), |
| 403 | toExpr(a, decl.value) |
| 404 | ]); |
| 405 | } |
| 406 | case super::NodeValue::ConstDecl(decl) => |
| 407 | return sexpr::list(a, "constant", &[toExpr(a, decl.ident), toExpr(a, decl.type), toExpr(a, decl.value)]), |
| 408 | case super::NodeValue::StaticDecl(decl) => |
| 409 | return sexpr::list(a, "static", &[toExpr(a, decl.ident), toExpr(a, decl.type), toExpr(a, decl.value)]), |
| 410 | case super::NodeValue::Assign(a_) => |
| 411 | return sexpr::list(a, "assign", &[toExpr(a, a_.left), toExpr(a, a_.right)]), |
| 412 | case super::NodeValue::Return { value } => |
| 413 | return sexpr::list(a, "return", &[toExprOrNull(a, value)]), |
| 414 | case super::NodeValue::Throw { expr } => |
| 415 | return sexpr::list(a, "throw", &[toExpr(a, expr)]), |
| 416 | case super::NodeValue::Panic { message } => |
| 417 | return sexpr::list(a, "panic", &[toExprOrNull(a, message)]), |
| 418 | case super::NodeValue::Assert { condition, message } => |
| 419 | return sexpr::list(a, "assert", &[toExpr(a, condition), toExprOrNull(a, message)]), |
| 420 | case super::NodeValue::If(c) => |
| 421 | return sexpr::block(a, "if", &[toExpr(a, c.condition)], |
| 422 | &[toExpr(a, c.thenBranch), toExprOrNull(a, c.elseBranch)]), |
| 423 | case super::NodeValue::IfLet(c) => { |
| 424 | let label = "if-let-mut" if c.pattern.mutable else "if-let"; |
| 425 | return sexpr::block(a, label, &[ |
| 426 | toExpr(a, c.pattern.pattern), |
| 427 | toExpr(a, c.pattern.scrutinee), |
| 428 | guardExpr(a, c.pattern.guard) |
| 429 | ], &[ |
| 430 | toExpr(a, c.thenBranch), |
| 431 | toExprOrNull(a, c.elseBranch) |
| 432 | ]); |
| 433 | } |
| 434 | case super::NodeValue::LetElse(l) => { |
| 435 | let label = "let-mut-else" if l.pattern.mutable else "let-else"; |
| 436 | return sexpr::block(a, label, &[ |
| 437 | toExpr(a, l.pattern.pattern), |
| 438 | toExpr(a, l.pattern.scrutinee), |
| 439 | guardExpr(a, l.pattern.guard) |
| 440 | ], &[toExpr(a, l.elseBranch)]); |
| 441 | } |
| 442 | case super::NodeValue::While(w) => |
| 443 | return sexpr::block(a, "while", &[ |
| 444 | toExpr(a, w.condition) |
| 445 | ], &[ |
| 446 | toExpr(a, w.body), |
| 447 | toExprOrNull(a, w.elseBranch) |
| 448 | ]), |
| 449 | case super::NodeValue::WhileLet(w) => { |
| 450 | let label = "while-let-mut" if w.pattern.mutable else "while-let"; |
| 451 | return sexpr::block(a, label, &[ |
| 452 | toExpr(a, w.pattern.pattern), |
| 453 | toExpr(a, w.pattern.scrutinee), |
| 454 | guardExpr(a, w.pattern.guard) |
| 455 | ], &[ |
| 456 | toExpr(a, w.body), |
| 457 | toExprOrNull(a, w.elseBranch) |
| 458 | ]); |
| 459 | } |
| 460 | case super::NodeValue::For(f) => |
| 461 | return sexpr::block(a, "for", &[ |
| 462 | toExpr(a, f.binding), |
| 463 | toExprOrNull(a, f.index), |
| 464 | toExpr(a, f.iterable) |
| 465 | ], &[toExpr(a, f.body), toExprOrNull(a, f.elseBranch)]), |
| 466 | case super::NodeValue::Loop { body } => |
| 467 | return sexpr::block(a, "loop", &[], &[toExpr(a, body)]), |
| 468 | case super::NodeValue::Match(m) => { |
| 469 | let children = prongListToExprs(a, m.prongs); |
| 470 | return sexpr::block(a, "match", &[toExpr(a, m.subject)], children); |
| 471 | } |
| 472 | case super::NodeValue::MatchProng(p) => { |
| 473 | return prongToExpr(a, p); |
| 474 | } |
| 475 | case super::NodeValue::RegionApply { value, regions } => |
| 476 | return sexpr::list(a, "apply", &[toExpr(a, value), sexpr::list(a, "regions", nodeListToExprs(a, regions))]), |
| 477 | case super::NodeValue::RegionBinding(b) => |
| 478 | return sexpr::list(a, "binding", &[toExprOrNull(a, b.label), toExpr(a, b.value)]), |
| 479 | case super::NodeValue::Region { name, parent } => { |
| 480 | if let p = parent { |
| 481 | return sexpr::list(a, "region", &[sexpr::sym(name), toExpr(a, p)]); |
| 482 | } |
| 483 | return sexpr::sym(name); |
| 484 | } |
| 485 | case super::NodeValue::RegionBlock { region, bindings, body, isSession } => { |
| 486 | let head = "use-region" if isSession else "let-region"; |
| 487 | return sexpr::block(a, head, &[toExpr(a, region), sexpr::list(a, "bindings", nodeListToExprs(a, bindings))], &[toExpr(a, body)]); |
| 488 | } |
| 489 | case super::NodeValue::FnDecl(f) => { |
| 490 | let params = sexpr::list(a, "params", nodeListToExprs(a, f.sig.params)); |
| 491 | let ret = toExprOrNull(a, f.sig.returnType); |
| 492 | if f.regions.len > 0 { |
| 493 | let regions = sexpr::list(a, "regions", nodeListToExprs(a, f.regions)); |
| 494 | if let body = f.body { |
| 495 | return sexpr::block(a, "fn", &[toExpr(a, f.name), regions, params, ret], &[toExpr(a, body)]); |
| 496 | } |
| 497 | return sexpr::list(a, "fn", &[toExpr(a, f.name), regions, params, ret]); |
| 498 | } |
| 499 | if let body = f.body { |
| 500 | return sexpr::block(a, "fn", &[toExpr(a, f.name), params, ret], &[toExpr(a, body)]); |
| 501 | } |
| 502 | return sexpr::list(a, "fn", &[toExpr(a, f.name), params, ret]); |
| 503 | } |
| 504 | case super::NodeValue::Mod(m) => return sexpr::list(a, "mod", &[toExpr(a, m.name)]), |
| 505 | case super::NodeValue::Use(u_) => return sexpr::list(a, "use", &[toExpr(a, u_.path)]), |
| 506 | case super::NodeValue::RecordDecl(r) => { |
| 507 | let children = fieldListToExprs(a, r.fields); |
| 508 | let mut head = "record"; |
| 509 | if let attrs = r.attrs; super::attributesContains(&attrs, super::Attribute::Opaque) { |
| 510 | set head = "opaque-record"; |
| 511 | } |
| 512 | if r.regions.len > 0 or r.derives.len > 0 { |
| 513 | return sexpr::block(a, head, &[ |
| 514 | toExpr(a, r.name), |
| 515 | sexpr::list(a, "regions", nodeListToExprs(a, r.regions)), |
| 516 | sexpr::list(a, "derives", nodeListToExprs(a, r.derives)), |
| 517 | ], children); |
| 518 | } |
| 519 | return sexpr::block(a, head, &[toExpr(a, r.name)], children); |
| 520 | } |
| 521 | case super::NodeValue::RecordField { field, type, value } => { |
| 522 | return fieldToExpr(a, field, type, value); |
| 523 | } |
| 524 | case super::NodeValue::UnionDecl(u_) => { |
| 525 | let children = variantListToExprs(a, u_.variants); |
| 526 | if u_.regions.len > 0 or u_.derives.len > 0 { |
| 527 | return sexpr::block(a, "union", &[ |
| 528 | toExpr(a, u_.name), |
| 529 | sexpr::list(a, "regions", nodeListToExprs(a, u_.regions)), |
| 530 | sexpr::list(a, "derives", nodeListToExprs(a, u_.derives)), |
| 531 | ], children); |
| 532 | } |
| 533 | return sexpr::block(a, "union", &[toExpr(a, u_.name)], children); |
| 534 | } |
| 535 | case super::NodeValue::UnionDeclVariant(v) => { |
| 536 | return variantToExpr(a, v.name, v.type); |
| 537 | } |
| 538 | case super::NodeValue::ExprStmt(e) => return toExpr(a, e), |
| 539 | case super::NodeValue::TraitDecl { name, supertraits, methods, .. } => { |
| 540 | let children = nodeListToExprs(a, methods); |
| 541 | let supers = sexpr::list(a, "supertraits", nodeListToExprs(a, supertraits)); |
| 542 | return sexpr::block(a, "trait", &[toExpr(a, name), supers], children); |
| 543 | } |
| 544 | case super::NodeValue::TraitMethodSig { name, modifiers, receiver, sig } => { |
| 545 | let regions = modifiers.regions; |
| 546 | let attrs = modifiers.attrs; |
| 547 | let params = sexpr::list(a, "params", nodeListToExprs(a, sig.params)); |
| 548 | let ret = toExprOrNull(a, sig.returnType); |
| 549 | let attributes = attributesToExpr(a, attrs); |
| 550 | return sexpr::list( |
| 551 | a, |
| 552 | "methodSig", |
| 553 | &[ |
| 554 | attributes, |
| 555 | toExpr(a, receiver), |
| 556 | toExpr(a, name), |
| 557 | sexpr::list(a, "regions", nodeListToExprs(a, regions)), |
| 558 | params, |
| 559 | ret, |
| 560 | ], |
| 561 | ); |
| 562 | } |
| 563 | case super::NodeValue::InstanceDecl { traitName, targetType, regions, methods } => { |
| 564 | let children = nodeListToExprs(a, methods); |
| 565 | return sexpr::block(a, "instance", &[ |
| 566 | toExpr(a, traitName), |
| 567 | toExpr(a, targetType), |
| 568 | sexpr::list(a, "regions", nodeListToExprs(a, regions)), |
| 569 | ], children); |
| 570 | } |
| 571 | case super::NodeValue::MethodDecl { |
| 572 | name, modifiers, receiverName, receiverType, sig, body, |
| 573 | } => { |
| 574 | let regions = modifiers.regions; |
| 575 | let attrs = modifiers.attrs; |
| 576 | let params = sexpr::list(a, "params", nodeListToExprs(a, sig.params)); |
| 577 | let ret = toExprOrNull(a, sig.returnType); |
| 578 | let attributes = attributesToExpr(a, attrs); |
| 579 | return sexpr::block( |
| 580 | a, |
| 581 | "method", |
| 582 | &[ |
| 583 | attributes, |
| 584 | toExpr(a, receiverType), |
| 585 | toExpr(a, receiverName), |
| 586 | toExpr(a, name), |
| 587 | sexpr::list(a, "regions", nodeListToExprs(a, regions)), |
| 588 | params, |
| 589 | ret, |
| 590 | ], |
| 591 | &[toExpr(a, body)], |
| 592 | ); |
| 593 | } |
| 594 | else => return sexpr::sym("?"), |
| 595 | } |
| 596 | } |
| 597 | |
| 598 | /// Dump the tree rooted at `root`, using the provided arena for allocation. |
| 599 | export unsafe fn printTree(root: *super::Node, arena: &mut alloc::Arena) { |
| 600 | match root.value { |
| 601 | case super::NodeValue::Block(blk) => { |
| 602 | for stmt, i in blk.statements { |
| 603 | sexpr::print(toExpr(arena, stmt), 0); |
| 604 | if i < blk.statements.len - 1 { io::print("\n\n"); } |
| 605 | } |
| 606 | io::print("\n"); |
| 607 | } |
| 608 | else => { |
| 609 | sexpr::print(toExpr(arena, root), 0); |
| 610 | io::print("\n"); |
| 611 | } |
| 612 | } |
| 613 | } |