Appearance
| 1 | namespace Syntax.Process.Printer is | |
| 2 | use IO.Std; | |
| 3 | ||
| 4 | use Trees; | |
| 5 | use Source; | |
| 6 | ||
| 7 | class Base : StrictVisitor abstract is | |
| 8 | _indent: int; | |
| 9 | _depth: int; | |
| 10 | _run_on: bool; | |
| 11 | _indent_needed: bool; | |
| 12 | _want_locations: bool; | |
| 13 | _current_line: int; | |
| 14 | _result: System.Text.StringBuilder; | |
| 15 | ||
| 16 | init(want_locations: bool) is | |
| 17 | super.init(); | |
| 18 | ||
| 19 | _want_locations = want_locations; | |
| 20 | _depth = 0; | |
| 21 | _indent = 2; | |
| 22 | _result = System.Text.StringBuilder(); | |
| 23 | _current_line = 1; | |
| 24 | si | |
| 25 | ||
| 26 | result: string => _result.to_string(); | |
| 27 | ||
| 28 | write_line(value: string) is | |
| 29 | write(value); | |
| 30 | write_line(); | |
| 31 | si | |
| 32 | ||
| 33 | write(value: string) is | |
| 34 | write_indent(); | |
| 35 | _result.append(value); | |
| 36 | si | |
| 37 | ||
| 38 | write(c: char) is | |
| 39 | write_indent(); | |
| 40 | _result.append(c); | |
| 41 | si | |
| 42 | ||
| 43 | write_line() is | |
| 44 | _current_line = _current_line + 1; | |
| 45 | _indent_needed = true; | |
| 46 | _result.append('\n'); | |
| 47 | si | |
| 48 | ||
| 49 | indent() is | |
| 50 | _depth = _depth + 1; | |
| 51 | si | |
| 52 | ||
| 53 | outdent() is | |
| 54 | _depth = _depth - 1; | |
| 55 | si | |
| 56 | ||
| 57 | write_indent() is | |
| 58 | if _indent_needed then | |
| 59 | let i mut = 0; | |
| 60 | while i < _indent*_depth do | |
| 61 | _result.append(' '); | |
| 62 | i = i + 1; | |
| 63 | od | |
| 64 | _indent_needed = false; | |
| 65 | fi | |
| 66 | si | |
| 67 | ||
| 68 | location(node: Node) is | |
| 69 | location(node.location); | |
| 70 | si | |
| 71 | ||
| 72 | location(location: LOCATION) is | |
| 73 | let new_line = location.start_line; | |
| 74 | if new_line != _current_line then | |
| 75 | _current_line = new_line; | |
| 76 | if _want_locations then | |
| 77 | write("#{_current_line} "); | |
| 78 | fi | |
| 79 | fi | |
| 80 | si | |
| 81 | ||
| 82 | write(node: Node) is | |
| 83 | node.accept(self); | |
| 84 | si | |
| 85 | ||
| 86 | write_name(name: string) is | |
| 87 | write(name); | |
| 88 | si | |
| 89 | ||
| 90 | visit(identifier: Identifiers.Identifier) is | |
| 91 | location(identifier); | |
| 92 | write_name(identifier.name); | |
| 93 | si | |
| 94 | ||
| 95 | visit(identifier: Identifiers.QUALIFIED) is | |
| 96 | location(identifier); | |
| 97 | identifier.qualifier.accept(self); | |
| 98 | write('.'); | |
| 99 | write_name(identifier.name); | |
| 100 | si | |
| 101 | ||
| 102 | visit(modifier: Modifiers.Modifier) is | |
| 103 | location(modifier); | |
| 104 | write(modifier.name); | |
| 105 | si | |
| 106 | ||
| 107 | visit(modifiers: Modifiers.LIST) is | |
| 108 | location(modifiers); | |
| 109 | if let modifiers.access_modifier? then | |
| 110 | access_modifier.accept(self); | |
| 111 | write(' '); | |
| 112 | fi | |
| 113 | if let modifiers.storage_class? then | |
| 114 | storage_class.accept(self); | |
| 115 | write(' '); | |
| 116 | fi | |
| 117 | if modifiers.is_pure then | |
| 118 | write("pure "); | |
| 119 | fi | |
| 120 | si | |
| 121 | ||
| 122 | visit(variables: Variables.LIST) is | |
| 123 | location(variables); | |
| 124 | let first mut = true; | |
| 125 | for v in variables do | |
| 126 | if !first then | |
| 127 | write(", "); | |
| 128 | fi | |
| 129 | v.accept(self); | |
| 130 | first = false; | |
| 131 | od | |
| 132 | si | |
| 133 | ||
| 134 | visit(definitions: Definitions.LIST) is | |
| 135 | location(definitions); | |
| 136 | for d in definitions do | |
| 137 | d.accept(self); | |
| 138 | ||
| 139 | // yuck... | |
| 140 | if isa Variables.VARIABLE(d) then | |
| 141 | let variable = d; | |
| 142 | if let variable.name? /\ name.name.starts_with("$") then | |
| 143 | write_line(";"); | |
| 144 | fi | |
| 145 | fi | |
| 146 | od | |
| 147 | si | |
| 148 | ||
| 149 | visit(`enum: Definitions.ENUM) is | |
| 150 | location(`enum); | |
| 151 | write("enum "); | |
| 152 | `enum.name.accept(self); | |
| 153 | write_line(" is"); | |
| 154 | indent(); | |
| 155 | let seen_any mut = false; | |
| 156 | for member in `enum.members do | |
| 157 | if seen_any then | |
| 158 | write_line(","); | |
| 159 | fi | |
| 160 | member.accept(self); | |
| 161 | seen_any = true; | |
| 162 | od | |
| 163 | write_line(); | |
| 164 | outdent(); | |
| 165 | write_line("si"); | |
| 166 | si | |
| 167 | ||
| 168 | visit(member: Definitions.ENUM_MEMBER) is | |
| 169 | location(member); | |
| 170 | member.name.accept(self); | |
| 171 | if member.initializer? then | |
| 172 | write(" = "); | |
| 173 | member.initializer!.accept(self); | |
| 174 | fi | |
| 175 | si | |
| 176 | ||
| 177 | visit(functions: Definitions.FUNCTION_GROUP) is | |
| 178 | write_line("function group "); | |
| 179 | indent(); | |
| 180 | for f in functions.functions do | |
| 181 | f.accept(self); | |
| 182 | od | |
| 183 | outdent(); | |
| 184 | si | |
| 185 | ||
| 186 | visit(pragma: Pragmas.PRAGMA) is | |
| 187 | write("@"); | |
| 188 | ||
| 189 | pragma.name.accept(self); | |
| 190 | write("("); | |
| 191 | ||
| 192 | pragma.arguments.accept(self); | |
| 193 | write_line(")"); | |
| 194 | si | |
| 195 | ||
| 196 | visit(pragma: Definitions.PRAGMA) is | |
| 197 | pragma.definition.accept(self); | |
| 198 | si | |
| 199 | ||
| 200 | visit(type_expression: TypeExpressions.UNDEFINED) is | |
| 201 | write("???"); | |
| 202 | si | |
| 203 | ||
| 204 | visit(type_expression: TypeExpressions.INFER) is | |
| 205 | write("infer"); | |
| 206 | si | |
| 207 | ||
| 208 | visit(array: TypeExpressions.ARRAY_) is | |
| 209 | array.element.accept(self); | |
| 210 | write("[]"); | |
| 211 | si | |
| 212 | ||
| 213 | visit(pointer: TypeExpressions.POINTER) is | |
| 214 | pointer.element.accept(self); | |
| 215 | write(" ptr"); | |
| 216 | si | |
| 217 | ||
| 218 | visit(optional: TypeExpressions.OPTIONAL) is | |
| 219 | optional.element.accept(self); | |
| 220 | write("?"); | |
| 221 | si | |
| 222 | ||
| 223 | visit(reference: TypeExpressions.REFERENCE) is | |
| 224 | reference.element.accept(self); | |
| 225 | write(" ref"); | |
| 226 | si | |
| 227 | ||
| 228 | pre(member: TypeExpressions.MEMBER) -> bool => true; | |
| 229 | visit(member: TypeExpressions.MEMBER) is | |
| 230 | member.left.walk(self); | |
| 231 | write('.'); | |
| 232 | member.name.walk(self); | |
| 233 | si | |
| 234 | ||
| 235 | visit(functions: TypeExpressions.FUNCTION_GROUP) is | |
| 236 | write("function group "); | |
| 237 | for f in functions.functions do | |
| 238 | f.accept(self); | |
| 239 | write(' '); | |
| 240 | od | |
| 241 | si | |
| 242 | ||
| 243 | visit(named: TypeExpressions.NAMED) is | |
| 244 | location(named); | |
| 245 | named.name.accept(self); | |
| 246 | si | |
| 247 | ||
| 248 | visit(tuple: TypeExpressions.TUPLE) is | |
| 249 | location(tuple); | |
| 250 | write("("); | |
| 251 | tuple.elements.accept(self); | |
| 252 | write(")"); | |
| 253 | si | |
| 254 | ||
| 255 | visit(element: TypeExpressions.NAMED_TUPLE_ELEMENT) is | |
| 256 | location(element); | |
| 257 | element.name.accept(self); | |
| 258 | write(": "); | |
| 259 | element.type_expression.accept(self); | |
| 260 | si | |
| 261 | ||
| 262 | visit(constraint: TypeExpressions.TYPE_PARAMETER_CONSTRAINT) is | |
| 263 | location(constraint); | |
| 264 | write(constraint.keyword); | |
| 265 | si | |
| 266 | ||
| 267 | visit(types: TypeExpressions.LIST) is | |
| 268 | location(types); | |
| 269 | let seen_any mut = false; | |
| 270 | for t in types do | |
| 271 | if seen_any then | |
| 272 | write(','); | |
| 273 | fi | |
| 274 | t.accept(self); | |
| 275 | seen_any = true; | |
| 276 | od | |
| 277 | si | |
| 278 | ||
| 279 | visit(`none: Expressions.Literals.NONE) is | |
| 280 | location(`none); | |
| 281 | write("none"); | |
| 282 | si | |
| 283 | ||
| 284 | visit(identifier: Expressions.IDENTIFIER) is | |
| 285 | location(identifier); | |
| 286 | identifier.identifier.accept(self); | |
| 287 | si | |
| 288 | ||
| 289 | visit(`super: Expressions.SUPER) is | |
| 290 | location(`super); | |
| 291 | write("super"); | |
| 292 | si | |
| 293 | ||
| 294 | visit(`new: Expressions.NEW) is | |
| 295 | location(`new); | |
| 296 | write(""); | |
| 297 | if `new.type_expression? then | |
| 298 | `new.type_expression.accept(self); | |
| 299 | fi | |
| 300 | write('('); | |
| 301 | `new.arguments.accept(self); | |
| 302 | write(')'); | |
| 303 | si | |
| 304 | ||
| 305 | visit(`cast: Expressions.CAST) is | |
| 306 | location(`cast); | |
| 307 | write("cast "); | |
| 308 | `cast.type_expression.accept(self); | |
| 309 | write('('); | |
| 310 | `cast.right.accept(self); | |
| 311 | write(')'); | |
| 312 | si | |
| 313 | ||
| 314 | visit(`isa: Expressions.ISA) is | |
| 315 | location(`isa); | |
| 316 | write("isa "); | |
| 317 | `isa.type_expression.accept(self); | |
| 318 | write('('); | |
| 319 | `isa.right.accept(self); | |
| 320 | write(')'); | |
| 321 | si | |
| 322 | ||
| 323 | visit(`typeof: Expressions.TYPEOF) is | |
| 324 | location(`typeof); | |
| 325 | write("typeof "); | |
| 326 | `typeof.type_expression.accept(self); | |
| 327 | si | |
| 328 | ||
| 329 | visit(`default: Expressions.DEFAULT) is | |
| 330 | location(`default); | |
| 331 | write("_"); | |
| 332 | ||
| 333 | let type_expression = `default.type_expression; | |
| 334 | ||
| 335 | if type_expression? then | |
| 336 | write('['); | |
| 337 | type_expression.accept(self); | |
| 338 | write(']'); | |
| 339 | fi | |
| 340 | si | |
| 341 | ||
| 342 | visit(tuple: Expressions.TUPLE) is | |
| 343 | location(tuple); | |
| 344 | write('('); | |
| 345 | tuple.elements.accept(self); | |
| 346 | write(')'); | |
| 347 | si | |
| 348 | ||
| 349 | visit(call: Expressions.CALL) is | |
| 350 | location(call); | |
| 351 | if call.is_thread_first /\ call.arguments.count >= 1 then | |
| 352 | call.arguments.expressions[0].accept(self); | |
| 353 | write(" |> "); | |
| 354 | call.function.accept(self); | |
| 355 | write('('); | |
| 356 | let seen mut = false; | |
| 357 | for i in 1..call.arguments.count do | |
| 358 | if seen then | |
| 359 | write(','); | |
| 360 | fi | |
| 361 | call.arguments.expressions[i].accept(self); | |
| 362 | seen = true; | |
| 363 | od | |
| 364 | if call.arguments.has_trailing_comma then | |
| 365 | write(','); | |
| 366 | fi | |
| 367 | write(')'); | |
| 368 | else | |
| 369 | call.function.accept(self); | |
| 370 | write('('); | |
| 371 | call.arguments.accept(self); | |
| 372 | write(')'); | |
| 373 | fi | |
| 374 | si | |
| 375 | ||
| 376 | visit(member: Expressions.MEMBER) is | |
| 377 | location(member); | |
| 378 | member.left.accept(self); | |
| 379 | if member.is_coalesce then | |
| 380 | write("?."); | |
| 381 | else | |
| 382 | write('.'); | |
| 383 | fi | |
| 384 | member.identifier.accept(self); | |
| 385 | si | |
| 386 | ||
| 387 | visit(explicit_specialization: Trees.Expressions.EXPLICIT_SPECIALIZATION) is | |
| 388 | location(explicit_specialization); | |
| 389 | explicit_specialization.left.accept(self); | |
| 390 | write("`["); | |
| 391 | explicit_specialization.types.accept(self); | |
| 392 | write("]"); | |
| 393 | si | |
| 394 | ||
| 395 | visit(index: Expressions.INDEX) is | |
| 396 | location(index); | |
| 397 | index.left.accept(self); | |
| 398 | write('['); | |
| 399 | index.index.accept(self); | |
| 400 | write(']'); | |
| 401 | si | |
| 402 | ||
| 403 | visit(unary: Expressions.UNARY) is | |
| 404 | location(unary); | |
| 405 | unary.operation.accept(self); | |
| 406 | write(' '); | |
| 407 | unary.right.accept(self); | |
| 408 | si | |
| 409 | ||
| 410 | visit(binary: Expressions.BINARY) is | |
| 411 | location(binary); | |
| 412 | binary.left.accept(self); | |
| 413 | write(' '); | |
| 414 | ||
| 415 | if binary.actual_operation? then | |
| 416 | write(binary.actual_operation); | |
| 417 | else | |
| 418 | binary.operation.accept(self); | |
| 419 | fi | |
| 420 | ||
| 421 | write(' '); | |
| 422 | binary.right.accept(self); | |
| 423 | si | |
| 424 | ||
| 425 | visit(expressions: Expressions.LIST) is | |
| 426 | location(expressions); | |
| 427 | let seen_any mut = false; | |
| 428 | for e in expressions do | |
| 429 | if seen_any then | |
| 430 | write(','); | |
| 431 | fi | |
| 432 | e.accept(self); | |
| 433 | seen_any = true; | |
| 434 | od | |
| 435 | ||
| 436 | if expressions.has_trailing_comma then | |
| 437 | write(','); | |
| 438 | fi | |
| 439 | si | |
| 440 | ||
| 441 | visit(literal: Expressions.Literals.Literal) is | |
| 442 | location(literal); | |
| 443 | write(literal.value_string); | |
| 444 | si | |
| 445 | ||
| 446 | write_escape_char(c: char) is | |
| 447 | let ci = cast int(c); | |
| 448 | if ci < 32 then | |
| 449 | write("\\{string.format("X", ci)}"); | |
| 450 | elif ci == 34 then | |
| 451 | write("\\"); | |
| 452 | write(cast char(34)); | |
| 453 | elif ci == 39 then | |
| 454 | write("'"); | |
| 455 | elif ci == 92 then | |
| 456 | write("\\\\"); | |
| 457 | else | |
| 458 | write(c); | |
| 459 | fi | |
| 460 | si | |
| 461 | ||
| 462 | visit(`string: Expressions.Literals.STRING) is | |
| 463 | location(`string); | |
| 464 | write(cast char(34)); | |
| 465 | for c in `string.value_string do | |
| 466 | write_escape_char(c); | |
| 467 | od | |
| 468 | write(cast char(34)); | |
| 469 | si | |
| 470 | ||
| 471 | visit(interpolation: Expressions.STRING_INTERPOLATION) is | |
| 472 | location(interpolation); | |
| 473 | ||
| 474 | let in_expression mut = false; | |
| 475 | ||
| 476 | write("\""); | |
| 477 | for e in interpolation.values do | |
| 478 | if in_expression then | |
| 479 | write("{{"); | |
| 480 | ||
| 481 | e.expression.accept(self); | |
| 482 | ||
| 483 | if e.format? then | |
| 484 | write(":{e.format}"); | |
| 485 | fi | |
| 486 | ||
| 487 | if in_expression then | |
| 488 | write("}}"); | |
| 489 | fi | |
| 490 | else | |
| 491 | // TODO: no quotes around string literals | |
| 492 | e.expression.accept(self); | |
| 493 | fi | |
| 494 | ||
| 495 | in_expression = !in_expression; | |
| 496 | od | |
| 497 | write("\""); | |
| 498 | si | |
| 499 | ||
| 500 | visit(integer: Expressions.Literals.INTEGER) is | |
| 501 | location(integer); | |
| 502 | write(integer.value_string); | |
| 503 | si | |
| 504 | ||
| 505 | visit(float: Expressions.Literals.FLOAT) is | |
| 506 | location(float); | |
| 507 | write(float.value_string); | |
| 508 | si | |
| 509 | ||
| 510 | visit(character: Expressions.Literals.CHARACTER) is | |
| 511 | location(character); | |
| 512 | write("'"); | |
| 513 | write_escape_char(character.value_string.get_chars(0)); | |
| 514 | write("'"); | |
| 515 | si | |
| 516 | ||
| 517 | visit(boolean: Expressions.Literals.BOOLEAN) is | |
| 518 | location(boolean); | |
| 519 | write(boolean.value_string); | |
| 520 | si | |
| 521 | ||
| 522 | visit(left: Trees.Expressions.SIMPLE_LEFT_EXPRESSION) is | |
| 523 | left.expression.accept(self); | |
| 524 | si | |
| 525 | ||
| 526 | visit(destructure_left: Trees.Expressions.DESTRUCTURING_LEFT_EXPRESSION) is | |
| 527 | let seen_any mut = false; | |
| 528 | write("("); | |
| 529 | for e in destructure_left.elements do | |
| 530 | if seen_any then | |
| 531 | write(", "); | |
| 532 | fi | |
| 533 | ||
| 534 | e.accept(self); | |
| 535 | ||
| 536 | seen_any = true; | |
| 537 | od | |
| 538 | write(")"); | |
| 539 | si | |
| 540 | ||
| 541 | visit(list: Statements.LIST) is | |
| 542 | location(list); | |
| 543 | for s in list do | |
| 544 | s.accept(self); | |
| 545 | od | |
| 546 | si | |
| 547 | ||
| 548 | visit(assign: Statements.ASSIGNMENT) is | |
| 549 | location(assign); | |
| 550 | assign.left.accept(self); | |
| 551 | write(" = "); | |
| 552 | assign.right.accept(self); | |
| 553 | write_line(";"); | |
| 554 | si | |
| 555 | ||
| 556 | visit(expression: Statements.EXPRESSION) is | |
| 557 | location(expression); | |
| 558 | expression.expression.accept(self); | |
| 559 | write_line(";"); | |
| 560 | si | |
| 561 | ||
| 562 | visit(r: Statements.RETURN) is | |
| 563 | location(r); | |
| 564 | write("return"); | |
| 565 | if r.expression? then | |
| 566 | write(' '); | |
| 567 | r.expression!.accept(self); | |
| 568 | fi | |
| 569 | write_line(";"); | |
| 570 | si | |
| 571 | ||
| 572 | visit(t: Statements.THROW) is | |
| 573 | location(t); | |
| 574 | write("throw"); | |
| 575 | if t.expression? then | |
| 576 | write(' '); | |
| 577 | t.expression!.accept(self); | |
| 578 | fi | |
| 579 | write_line(";"); | |
| 580 | si | |
| 581 | ||
| 582 | visit(y: Statements.YIELD) is | |
| 583 | location(y); | |
| 584 | write("yield"); | |
| 585 | write(' '); | |
| 586 | y.expression.accept(self); | |
| 587 | write_line(";"); | |
| 588 | si | |
| 589 | ||
| 590 | visit(t: Statements.ASSERT) is | |
| 591 | location(t); | |
| 592 | write("assert"); | |
| 593 | write(' '); | |
| 594 | t.expression.accept(self); | |
| 595 | ||
| 596 | if t.message? then | |
| 597 | write(" else "); | |
| 598 | t.message!.accept(self); | |
| 599 | fi | |
| 600 | ||
| 601 | write_line(";"); | |
| 602 | si | |
| 603 | ||
| 604 | visit(i: Statements.IF) is | |
| 605 | location(i); | |
| 606 | let is_first mut = true; | |
| 607 | let seen_else mut = false; | |
| 608 | ||
| 609 | ||
| 610 | for b in i.branches do | |
| 611 | location(b); | |
| 612 | ||
| 613 | if seen_else then | |
| 614 | IoC.CONTAINER.instance.logger.error(b.location, "broken if statement"); | |
| 615 | fi | |
| 616 | ||
| 617 | assert !seen_else; | |
| 618 | ||
| 619 | if let b.condition? then | |
| 620 | if is_first then | |
| 621 | write("if "); | |
| 622 | else | |
| 623 | write("elif "); | |
| 624 | fi | |
| 625 | condition.accept(self); | |
| 626 | write_line(" then"); | |
| 627 | else | |
| 628 | seen_else = true; | |
| 629 | write_line("else"); | |
| 630 | fi | |
| 631 | indent(); | |
| 632 | b.body.accept(self); | |
| 633 | outdent(); | |
| 634 | is_first = false; | |
| 635 | od | |
| 636 | write_line("fi"); | |
| 637 | si | |
| 638 | ||
| 639 | visit(`case: Statements.CASE) is | |
| 640 | location(`case); | |
| 641 | write("case "); | |
| 642 | `case.expression.accept(self); | |
| 643 | write_line(); | |
| 644 | for m in `case.matches do | |
| 645 | m.accept(self); | |
| 646 | od | |
| 647 | write_line("esac"); | |
| 648 | si | |
| 649 | ||
| 650 | visit(match: Statements.CASE_MATCH) is | |
| 651 | location(match); | |
| 652 | if let match.expressions? then | |
| 653 | write("when "); | |
| 654 | expressions.accept(self); | |
| 655 | write_line(":"); | |
| 656 | else | |
| 657 | write_line("default"); | |
| 658 | fi | |
| 659 | indent(); | |
| 660 | match.statements.accept(self); | |
| 661 | outdent(); | |
| 662 | si | |
| 663 | ||
| 664 | visit(`try: Statements.TRY) is | |
| 665 | location(`try); | |
| 666 | write_line("try"); | |
| 667 | indent(); | |
| 668 | `try.body.accept(self); | |
| 669 | outdent(); | |
| 670 | for c in `try.catches do | |
| 671 | c.accept(self); | |
| 672 | od | |
| 673 | let `finally = `try.`finally; | |
| 674 | ||
| 675 | if `finally? then | |
| 676 | write_line("finally"); | |
| 677 | indent(); | |
| 678 | `finally.accept(self); | |
| 679 | outdent(); | |
| 680 | fi | |
| 681 | write_line("yrt"); | |
| 682 | si | |
| 683 | ||
| 684 | visit(`catch: Statements.CATCH) is | |
| 685 | location(`catch); | |
| 686 | write("catch "); | |
| 687 | ||
| 688 | if let `catch.variable? then | |
| 689 | variable.accept(self); | |
| 690 | fi | |
| 691 | write_line(); | |
| 692 | indent(); | |
| 693 | `catch.body.accept(self); | |
| 694 | outdent(); | |
| 695 | si | |
| 696 | ||
| 697 | visit(`do: Statements.DO) is | |
| 698 | location(`do); | |
| 699 | if let `do.binding? then | |
| 700 | write("while let "); | |
| 701 | binding.accept(self); | |
| 702 | write(" "); | |
| 703 | elif let `do.condition? then | |
| 704 | write("while "); | |
| 705 | condition.accept(self); | |
| 706 | write(" "); | |
| 707 | fi | |
| 708 | write_line("do"); | |
| 709 | indent(); | |
| 710 | `do.body.accept(self); | |
| 711 | outdent(); | |
| 712 | write_line("od"); | |
| 713 | si | |
| 714 | ||
| 715 | visit(labelled: Statements.LABELLED) is | |
| 716 | location(labelled); | |
| 717 | labelled.label.accept(self); | |
| 718 | write(": "); | |
| 719 | labelled.statement.accept(self); | |
| 720 | si | |
| 721 | ||
| 722 | visit(`break: Statements.BREAK) is | |
| 723 | location(`break); | |
| 724 | write("break"); | |
| 725 | let label = `break.label; | |
| 726 | ||
| 727 | if label? then | |
| 728 | write(' '); | |
| 729 | label.accept(self); | |
| 730 | fi | |
| 731 | write_line(";"); | |
| 732 | si | |
| 733 | ||
| 734 | visit(`continue: Statements.CONTINUE) is | |
| 735 | location(`continue); | |
| 736 | write("continue"); | |
| 737 | let label = `continue.label; | |
| 738 | ||
| 739 | if label? then | |
| 740 | write(' '); | |
| 741 | label.accept(self); | |
| 742 | fi | |
| 743 | write_line(";"); | |
| 744 | si | |
| 745 | ||
| 746 | visit(pragma: Statements.PRAGMA) is | |
| 747 | if let pragma.statement? then | |
| 748 | statement.accept(self); | |
| 749 | fi | |
| 750 | si | |
| 751 | ||
| 752 | visit(block: Bodies.NULL) is | |
| 753 | write_line(";"); | |
| 754 | si | |
| 755 | si | |
| 756 | si |