Update catalogue files

Update catalogue files

Closes #180

--- app/lib/en_us.coffee
+++ app/lib/en_us.coffee
@@ -415,10 +415,10 @@
 The springtime sublimation process of Mars’ southern seasonal polar CO2 ice cap features dark fan-shaped deposits appearing on the top of the thawing ice sheet. The fan material likely originates from the surface below the ice sheet, brought up via CO2 jets breaking through the seasonal ice cap. Once the dust and dirt is released into the atmosphere, the material may be blown by the surface winds into the dark streaks visible from orbit. The location, size and direction of these fans record a number of parameters important to quantifying seasonal winds and sublimation activity, the most important agent of geological change extant on Mars. We present results of a systematic mapping of these south polar seasonal fans with the Planet Four online citizen science project. Planet Four enlists the general public to map the shapes, directions, and sizes of the seasonal fans visible in orbital images. Over 80,000 volunteers have contributed to the Planet Four project, reviewing 221 images, from Mars Reconnaissance Orbiter’s HiRISE (High Resolution Imaging Science Experiment) camera, taken in southern spring during Mars Years 29 and 30. We provide an overview of Planet Four and detail the processes of combining multiple volunteer assessments together to generate a high fidelity catalog of ∼400,000 south polar seasonal fans. We present the results from analyzing the wind directions at several locations monitored by HiRISE over two Mars years, providing new insights into polar surface winds.

-
Fan catalog: The resulting fan object catalog for MRO HiRISE seasons 2 and 3 (MY29 and 30), with an applied probability cut of 0.5, i.e. when half or more volunteers have marked an object as fan, it enters this catalog.

-
Blotch catalog: The resulting blotch object catalog for MRO HiRISE seasons 2 and 3 (MY29 and 30), with an applied probability cut of 0.5, i.e. when less than half of volunteers have marked an object as fan, it enters this catalog (starting with a catalog that only has fans and blotches).

-
HiRISE observation catalog: This file contains metadata for all HiRISE observations that were used for this catalog.

-
Planet Four tile catalog: This file contains data to locate all Planet Four tiles on a Mars map, using either Mars-centered fixed frame coordinates, or latitude and longitude.

+
Fan catalog: The resulting fan object catalog for MRO HiRISE seasons 2 and 3 (MY29 and 30), with an applied probability cut of 0.5, i.e. when half or more volunteers have marked an object as fan, it enters this catalog.

+
Blotch catalog: The resulting blotch object catalog for MRO HiRISE seasons 2 and 3 (MY29 and 30), with an applied probability cut of 0.5, i.e. when less than half of volunteers have marked an object as fan, it enters this catalog (starting with a catalog that only has fans and blotches).

+
HiRISE observation catalog: This file contains metadata for all HiRISE observations that were used for this catalog.

+
Planet Four tile catalog: This file contains data to locate all Planet Four tiles on a Mars map, using either Mars-centered fixed frame coordinates, or latitude and longitude.

Raw data: Planet Four raw classification data that was used in our reduction pipeline to create the fan and blotch catalog that is linked on this page (described in Appendix C of the paper, linked below). User names have been anonymized for data privacy.

Intermediate data products: These are the products as described in Appendix D of the paper, linked below. A researcher can apply a different cut on the probability of fan vs blotch identification using these products, reproducing a new fan catalog.


tłumaczenia kilku pozycji

tłumaczenia kilku pozycji

--- app/locale/pl.coffee
+++ app/locale/pl.coffee
@@ -1,4 +1,5 @@
 module.exports = nativeDescription: "polski", englishDescription: "Polish", translation:
+  #[ŁL] - proponuję przyjąć jedną konwencję: angielski 'student' to polski 'uczeń'
   new_home:
     slogan: "Najlepsza gra do nauki programowania!"
     classroom_edition: "Wersja szkolna:"
@@ -10,7 +11,7 @@
     classroom_in_a_box: "Gotowy zestaw do nauki programowania."
     codecombat_is: "CodeCombat jest platformą dla uczniów stworzoną do nauki programowania przez granie w ciekawą grę."
     our_courses: "Nasze kursy zostały szczególnie przygotowane do użycia w czasie zajęć, nawet przez nauczycieli bez wcześniejszego doświadczenia w programowaniu."
-#    watch_how: "Watch how CodeCombat is transforming the way people learn computer science."
+    watch_how: "Zobacz jak CodeCombat zmienia sposób w jaki ludzie uczą się komputerów."
     top_screenshots_hint: "Uczniowie piszą kod i od razu widzą jego efekt na ekranie"
     designed_with: "Zaprojektowane z myślą o nauczycielach"
     real_code: "Piszesz prawdziwy kod"
@@ -63,7 +64,7 @@
     want_coco: "Chcesz używać CodeCombat w swojej szkole?"

   nav:
-#    map: "Map"
+    map: "Mapa"
     play: "Poziomy" # The top nav bar entry where players choose which levels to play
     community: "Społeczność"
     courses: "Kursy"
@@ -93,12 +94,12 @@
     open_source: "Open source (GitHub)"
     support: "Wsparcie"
     faqs: "FAQs"
-#    copyright_prefix: "Copyright"
-#    copyright_suffix: "All Rights Reserved."
+    copyright_prefix: "Copyright"
+    copyright_suffix: "Wszystkie prawa zastrzeżone."
     help_pref: "Potrzebujesz pomocy? Wyślij email"
     help_suff: "a my się odezwiemy!"
     resource_hub: "Baza Wiedzy"
-#    apcsp: "AP CS Principles"
+    apcsp: "Zasady AP CS"

   modal:
     close: "Zamknij"
@@ -153,7 +154,7 @@
     brain_pop_challenge: "Zmierz się ponownie z zagadkami, tym razem wybierając inny język programowania!"
     replay: "Graj od nowa"
     back_to_classroom: "Wróć do klasy"
-#    teacher_button: "For Teachers"
+    teacher_button: "Dla nauczycieli"
 #    get_more_codecombat: "Get More CodeCombat"

   code:
@@ -1261,18 +1262,18 @@

   courses:
     create_new_class: "Stwórz nową klasę"
-#    solutions_require_licenses: "Level solutions are available for teachers who have licenses."
+    solutions_require_licenses: "Rozwiązania poziomów dostępne są dla nauczycieli posiadających licencję."
     unnamed_class: "Klasa bez nazwy"
     edit_settings1: "Edytuj ustawienia klasy"
-    add_students: "Dodaj Studentów"
+    add_students: "Dodaj uczniów"
     stats: "Statystyki"
-#    student_email_invite_blurb: "Your students can also use class code __classCode__ when creating a Student Account, no email required."
+    student_email_invite_blurb: "Twoi uczniowie mogą użyć kodu __classCode__ zakładając konto ucznia, bez potrzeby posiadania adresu email."
     total_students: "Ilość uczniów:"
     average_time: "Średni czas gry na poziom:"
     total_time: "Łączny czas gry:"
     average_levels: "Średnio ukończonych poziomów:"
     total_levels: "Łącznie ukończonych poziomów:"
-    students: "Studenci"
+    students: "Uczniowie"
     concepts: "Tematy"
     play_time: "Czas gry:"
     completed: "Ukończono:"
@@ -1288,21 +1289,21 @@
     switch_to: "Przełącz na"
     greetings: "Witamy!"
     back_classrooms: "Wróć do moich klas"
-#    back_classroom: "Back to classroom"
+    back_classroom: "Wróć do klasy"
     back_courses: "Wróć do moich kursów"
     edit_details: "Edytuj detale klasy"
-    purchase_enrollments: "Kup licencje dla studentów"
+    purchase_enrollments: "Kup licencje dla uczniów"
     remove_student: "usuń ucznia"
     assign: "Przydziel"
-    to_assign: "przydziel opłacone kursy."
+    to_assign: "Przydziel opłacone kursy."
     student: "Uczeń"
     teacher: "Nauczyciel"
     arena: "Arena"
     available_levels: "Dostępne poziomy"
-#    started: "started"
-#    complete: "complete"
-#    practice: "practice"
-#    required: "required"
+    started: "rozpoczęty"
+#    complete: "ukończ"
+#    practice: "trenuj"
+    required: "wymagany"
     welcome_to_courses: "Witamy w kursach podróżniku!"
     ready_to_play: "Gotów, by zagrać?"
     start_new_game: "Rozpocznij nową grę"
@@ -1315,7 +1316,7 @@
     my_classes: "Moje klasy"
     class_added: "Udało się dodać klasę!"
     view_levels: "zobacz wszystkie poziomy kursu" # {change}
-#    view_project_gallery: "view my classmates' projects"
+    view_project_gallery: "przeglądaj projekty innych uczniów z klasy"
     join_class: "Dołącz do klasy"
     join_class_2: "Dołącz do klasy"
     ask_teacher_for_code: "Poproś nauczyciela o kod klasy z CodeCombat! Jeśli już go masz, wpisz go poniżej:"
@@ -1334,7 +1335,7 @@
     are_you_sure: "Na pewno chcesz usunąć tego ucznia z klasy?"
     remove_description1: "Uczeń straci dostęp do klasy i przypisanych mu kursów. Postęp w grze natomiast NIE zostanie utracony, uczeń może zostać dołączony do klasy w każdym momencie."
     remove_description2: "Aktywowana licencja nie zostanie zwrócona."
-#    license_will_revoke: "This student's paid license will be revoked and made available to assign to another student."
+    license_will_revoke: "Ta licencja ucznia będzie zablokowana i będzie mozna ją przydzielić innemu uczniowi."
     keep_student: "Zachowaj ucznia"
     removing_user: "Usuwanie użytkownika"
     subtitle: "Zobacz opisy kursów i poziomy" # Flat style redesign
@@ -1541,7 +1542,7 @@
     not_enough_enrollments: "Brak wsytarczającej liczby licencji."
     enrollments_blurb: "Uczniowie potrzebują licencji, aby móc kontynuować naukę po pierwszym kursie."
     how_to_apply_licenses: "Jak zastosować licencję"
-    export_student_progress: "Eksport postępu studentów (do CSV)"
+    export_student_progress: "Eksport postępu uczniów (do CSV)"
     send_email_to: "Wyślij email do odzyskiwania hasła do:"
     email_sent: "Email wysłany"
     send_recovery_email: "Wyślij email do odzyskania hasła"
@@ -1700,30 +1701,30 @@
     choose_course: "Wybierz kurs"
 #    choose_instructions: "Select the course from the dropdown menu you’d like to assign, then click “Assign to Selected Students.”"
 #    push_projects: "We recommend assigning Web Development 1 or Game Development 1 after students have finished Introduction to Computer Science! See our {{resource_hub}} for more details on those courses."
-#    teacher_quest: "Teacher's Quest for Success"
+    teacher_quest: "Wyzwanie dla nauczyciela"
     quests_complete: "Zadania ukonczone"
     teacher_quest_create_classroom: "Stwórz klasę"
-    teacher_quest_add_students: "Dodaj studentów"
-#    teacher_quest_teach_methods: "Help your students learn how to `call methods`."
-#    teacher_quest_teach_methods_step1: "Get 75% of at least one class through the first level, __Dungeons of Kithgard__"
-#    teacher_quest_teach_methods_step2: "Print out the [Student Quick Start Guide](http://files.codecombat.com/docs/resources/StudentQuickStartGuide.pdf) in the Resource Hub."
-#    teacher_quest_teach_strings: "Don't string your students along, teach them `strings`."
-#    teacher_quest_teach_strings_step1: "Get 75% of at least one class through __True Names__"
-#    teacher_quest_teach_strings_step2: "Use the Teacher Level Selector on [Course Guides](/teachers/courses) page to preview __True Names__."
-#    teacher_quest_teach_loops: "Keep your students in the loop about `loops`."
-#    teacher_quest_teach_loops_step1: "Get 75% of at least one class through __Fire Dancing__."
+    teacher_quest_add_students: "Dodaj uczniów"
+    teacher_quest_teach_methods: "Naucz uczniów jak wywoływać metody."
+    teacher_quest_teach_methods_step1: "Niech przynajmniej 75% jednej klasy przejdzie pierwszy poziom, __Dungeons of Kithgard__"
+    teacher_quest_teach_methods_step2: "Wydrukuj [Krótki przewodnik ucznia](http://files.codecombat.com/docs/resources/StudentQuickStartGuide.pdf) z [Bazy wiedzy](/teachers/resources)."
+    teacher_quest_teach_strings: "Naucz uczniów jak budować `stringi`."
+    teacher_quest_teach_strings_step1: "Niech przynajmniej 75% jednej klasy dotrze do __True Names__"
+    teacher_quest_teach_strings_step2: "Użyj przeglądarki poziomów w [Przewodnikach po kursach](/teachers/courses) i przeglądnij poziom __True Names__."
+    teacher_quest_teach_loops: "Niech uczniowie się zapętlą. Naucz ich konstrukcji `loop`."
+    teacher_quest_teach_loops_step1: "Niech przynajmniej 75% jednej klasy dotrze do __Fire Dancing__."
 #    teacher_quest_teach_loops_step2: "Use the __Loops Activity__ in the [CS1 Curriculum guide](/teachers/resources/cs1) to reinforce this concept."
     teacher_quest_teach_variables: "Zmień swoje życie ze `zmiennymi`."
-#    teacher_quest_teach_variables_step1: "Get 75% of at least one class through __Known Enemy__."
-#    teacher_quest_teach_variables_step2: "Encourage collaboration by using the [Pair Programming Activity](/teachers/resources/pair-programming)."
+    teacher_quest_teach_variables_step1: "Niech przynajmniej 75% jednej klasy dotrze do __Known Enemy__."
+    teacher_quest_teach_variables_step2: "Wspieraj współpracę. Wypróbuj [Programowanie w parach](/teachers/resources/pair-programming)."
     teacher_quest_kithgard_gates_100: "Ucieknijcie przez Bramy Kithgardu wraz ze swoja klasą."
-#    teacher_quest_kithgard_gates_100_step1: "Get 75% of at least one class through __Kithgard Gates__."
+    teacher_quest_kithgard_gates_100_step1: "Niech przynajmniej 75% jednej klasy dotrze do __Kithgard Gates__."
 #    teacher_quest_kithgard_gates_100_step2: "Guide students to think through hard problems using the [Engineering Cycle Worksheet](http://files.codecombat.com/docs/resources/EngineeringCycleWorksheet.pdf)."
     teacher_quest_wakka_maul_100: "Przygotujcie się na pojedynek w Wakka Maul."
-#    teacher_quest_wakka_maul_100_step1: "Get 75% of at least one class to __Wakka Maul__."
-#    teacher_quest_wakka_maul_100_step2: "See the [Arena Guide](/teachers/resources/arenas) in the [Resource Hub](/teachers/resources) for tips on how to run a successful arena day."
-    teacher_quest_reach_gamedev: "Zwiedzaj noe światy!"
-#    teacher_quest_reach_gamedev_step1: "[Get licenses](/teachers/licenses) so that your students can explore new worlds, like Game Development and Web Development!"
+    teacher_quest_wakka_maul_100_step1: "Niech przynajmniej 75% jednej klasy dotrze do __Wakka Maul__."
+    teacher_quest_wakka_maul_100_step2: "Przeczytaj [Przewodnik po Arenie](/teachers/resources/arenas) w [Bazie wiedzy](/teachers/resources) aby dowiedzieć się jak prowadzić lekcje na Arenie."
+    teacher_quest_reach_gamedev: "Zwiedzaj nowe światy!"
+    teacher_quest_reach_gamedev_step1: "[Uzyskaj licencję](/teachers/licenses) aby Twoi uczniowie mogli zwiedzać nowe światy, jak Programowanie Gier lub Programowanie Www!"
 #    teacher_quest_done: "Want your students to learn even more code? Get in touch with our [school specialists](mailto:schools@codecombat.com) today!"
     teacher_quest_keep_going: "Nie poddawaj się! Jako następne możesz zrobić:"
     teacher_quest_more: "Pokaż wszystkie zadania"
@@ -2296,16 +2297,16 @@
     basic_event_handling: "Podstawy zarzadzania zdarzeniami"
     create_sharable_interactive_web_page: "Stworzysz interaktywną stronę internetową"

-#  anonymous_teacher:
-#    notify_teacher: "Notify Teacher"
-#    create_teacher_account: "Create free teacher account"
-#    enter_student_name: "Your name:"
-#    enter_teacher_email: "Your teacher's email:"
-#    teacher_email_placeholder: "teacher.email@example.com"
-#    student_name_placeholder: "type your name here"
-#    teachers_section: "Teachers:"
-#    students_section: "Students:"
-#    teacher_notified: "We've notified your teacher that you want to play more CodeCombat in your classroom!"
+  anonymous_teacher:
+    notify_teacher: "Powiadom nauczyciela"
+    create_teacher_account: "Utwórz darmowe konto nauczyciela"
+    enter_student_name: "Twoje imię:"
+    enter_teacher_email: "Twój nauczycielski email:"
+    teacher_email_placeholder: "imie.nazwisko@nazwaszkoly.pl"
+    student_name_placeholder: "To wpisz swoje imię"
+    teachers_section: "Nauczyciele:"
+    students_section: "Uczniowie:"
+    teacher_notified: "Poinformowaliśmy Twojego nauczyciela, że chcesz więcej pograć w CodeCombat w klasie!"

   delta:
     added: "Dodano"
@@ -2425,12 +2426,12 @@
     line_no: "Wiersz $1: "
 #    uncaught: "Uncaught $1" # $1 will be an error type, eg "Uncaught SyntaxError"
     reference_error: "ReferenceError (błąd referencji): "
-#    argument_error: "ArgumentError: "
+    argument_error: "Błąd argumentu: "
     type_error: "TypeError (błąd typu): "
-#    syntax_error: "SyntaxError: "
-#    error: "Error: "
+    syntax_error: "Błąd składni: "
+    error: "Błąd: "
     x_not_a_function: "`$1` nie jest funkcją"
-#    x_not_defined: "$1 is not defined"
+    x_not_defined: "nie zdefiniowano: $1"
     spelling_issues: "Sprawdź dobrze pisownię: może chodziło ci o `$1` zamiast `$2`?"
     capitalization_issues: "Uważaj na duże i małe litery: `$1` powinno wyglądać tak: `$2`."
     py_empty_block: "Pusty $1. Wstaw 4 spacje przed instrukcją wewnątrz $2."


Update sk.coffee

Update sk.coffee

editor

--- app/locale/sk.coffee
+++ app/locale/sk.coffee
@@ -1598,49 +1598,49 @@
     ambassador_title: "Ambasador"
     ambassador_title_description: "(Poradca)"
     ambassador_summary: "Kroť použivateľov nášho fóra a nasmeruj na správnu cestu tých, čo sa pýtajú. Naši ambasádori reprezentujú  CodeCombat na celom svete."
-#    teacher_title: "Teacher"
-
-#  editor:
-#    main_title: "CodeCombat Editors"
-#    article_title: "Article Editor"
-#    thang_title: "Thang Editor"
-#    level_title: "Level Editor"
-#    course_title: "Course Editor"
-#    achievement_title: "Achievement Editor"
-#    poll_title: "Poll Editor"
-#    back: "Back"
-#    revert: "Revert"
-#    revert_models: "Revert Models"
-#    pick_a_terrain: "Pick A Terrain"
-#    dungeon: "Dungeon"
-#    indoor: "Indoor"
-#    desert: "Desert"
-#    grassy: "Grassy"
-#    mountain: "Mountain"
-#    glacier: "Glacier"
-#    small: "Small"
-#    large: "Large"
-#    fork_title: "Fork New Version"
-#    fork_creating: "Creating Fork..."
-#    generate_terrain: "Generate Terrain"
-#    more: "More"
-#    wiki: "Wiki"
-#    live_chat: "Live Chat"
-#    thang_main: "Main"
-#    thang_spritesheets: "Spritesheets"
-#    thang_colors: "Colors"
-#    level_some_options: "Some Options?"
-#    level_tab_thangs: "Thangs"
-#    level_tab_scripts: "Scripts"
-#    level_tab_components: "Components"
-#    level_tab_systems: "Systems"
-#    level_tab_docs: "Documentation"
-#    level_tab_thangs_title: "Current Thangs"
-#    level_tab_thangs_all: "All"
-#    level_tab_thangs_conditions: "Starting Conditions"
-#    level_tab_thangs_add: "Add Thangs"
-#    level_tab_thangs_search: "Search thangs"
-#    add_components: "Add Components"
+    teacher_title: "učiteľ"
+
+  editor:
+    main_title: "Editory pre CodeCombat"
+    article_title: "Editor pre článkyr"
+    thang_title: "Editor pre vecičky"
+    level_title: "Editor levelov"
+    course_title: "Editor pre kurz"
+    achievement_title: "Editor úspechov"
+    poll_title: "Editor pre hlasovanie"
+    back: "Späť"
+    revert: "Obnov"
+    revert_models: "Obnov modely"
+    pick_a_terrain: "Vyber si terén"
+    dungeon: "Žalár"
+    indoor: "Vnútro"
+    desert: "Púšť"
+    grassy: "Tráva"
+    mountain: "Hora"
+    glacier: "Ľadovec"
+    small: "Malé"
+    large: "veľké"
+    fork_title: "Vytvor novú verziu"
+    fork_creating: "Vytváram verziu..."
+    generate_terrain: "Vygeneruj terén"
+    more: "Viac"
+    wiki: "Wiki"
+    live_chat: "Live Chat"
+    thang_main: "Hlavné"
+    thang_spritesheets: "Sprajtový hárok"
+    thang_colors: "Farby"
+    level_some_options: "nejaké možnosti?"
+    level_tab_thangs: "Vecičky"
+    level_tab_scripts: "Skripty"
+    level_tab_components: "Komponenty"
+    level_tab_systems: "Systémy"
+    level_tab_docs: "Dokumentácia"
+    level_tab_thangs_title: "Aktuálna vecička"
+    level_tab_thangs_all: "Všetko"
+    level_tab_thangs_conditions: "Počiatočné podmienky"
+    level_tab_thangs_add: "Pridaj vecičky"
+    level_tab_thangs_search: "Hľadaj vecičky"
+    add_components: "Pridaj komponenty"
 #    component_configs: "Component Configurations"
 #    config_thang: "Double click to configure a thang"
 #    delete: "Delete"


nodes: removed some redundancies and unused methods

--- nodes.coffee
+++ nodes.coffee
@@ -42,19 +42,21 @@
   # depending on whether it's being used as part of a larger expression, or is a
   # top-level statement within the function body.
   compile: (o) ->
-    @options = if o then merge o else {}
-    @tab     = o.indent
-    top     = if @topSensitive() then @options.top else del @options, 'top'
-    closure = @isStatement(o) and not @isPureStatement() and not top and
-              not @options.asStatement and this not instanceof Comment
-    code = if closure then @compileClosure(@options) else @compileNode(@options)
-    code
+    o    = if o then merge o else {}
+    top  = if @topSensitive() then o.top else del o, 'top'
+    @tab = o.indent
+    if top or o.asStatement or this instanceof Comment or
+       @isPureStatement() or not @isStatement(o)
+      @compileNode o
+    else
+      @compileClosure o

   # Statements converted into expressions via closure-wrapping share a scope
   # object with their parent closure, to preserve the expected lexical scope.
   compileClosure: (o) ->
+    if @containsPureStatement()
+      throw SyntaxError 'cannot include a pure statement in an expression.'
     o.sharedScope = o.scope
-    throw SyntaxError 'cannot include a pure statement in an expression.' if @containsPureStatement()
     Closure.wrap(this).compile o

   # If the code generation wishes to use the result of a complex expression
@@ -78,7 +80,7 @@
   # Compile to a source/variable pair suitable for looping.
   compileLoopReference: (o, name) ->
     src = tmp = @compile o
-    unless NUMBER.test(src) or (IDENTIFIER.test(src) and o.scope.check(src, immediate: on))
+    unless NUMBER.test(src) or IDENTIFIER.test(src) and o.scope.check(src, immediate: on)
       src = "#{ tmp = o.scope.freeVariable name } = #{src}"
     [src, tmp]

@@ -113,9 +115,6 @@
   containsPureStatement: ->
     @isPureStatement() or @contains (node) -> node.isPureStatement()

-  # Perform an in-order traversal of the AST. Crosses scope boundaries.
-  traverse: (block) -> @traverseChildren true, block
-
   # `toString` representation of the node, for inspecting the parse tree.
   # This is what `coffee --nodes` prints out.
   toString: (idt, override) ->
@@ -124,11 +123,12 @@
     klass = override or @constructor.name + if @soakNode then '?' else ''
     '\n' + idt + klass + children

+  # Passes each child to a function, breaking when the function returns `false`.
   eachChild: (func) ->
-    return unless @children
-    for attr in @children when this[attr]
-      for child in flatten [this[attr]]
-        return if func(child) is false
+    return this unless @children
+    for attr in @children when @[attr]
+      for child in flatten [@[attr]]
+        return this if func(child) is false
     this

   collectChildren: ->
@@ -139,8 +139,7 @@
   traverseChildren: (crossScope, func) ->
     @eachChild (child) ->
       return false if func(child) is false
-      if crossScope or child not instanceof Code
-        child.traverseChildren crossScope, func
+      child.traverseChildren crossScope, func

   invert: -> new Op '!', this

@@ -224,7 +223,7 @@
   # Compile the expressions body for the contents of a function, with
   # declarations of all inner variables pushed up to the top.
   compileWithDeclarations: (o) ->
-    code = @compileNode(o)
+    code = @compileNode o
     if o.scope.hasAssignments this
       code = "#{@tab}var #{ o.scope.compiledAssignments().replace /\n/g, '$&' + @tab };\n#{code}"
     if not o.globals and o.scope.hasDeclarations this
@@ -235,16 +234,16 @@
   # return the result, and it's an expression, simply return it. If it's a
   # statement, ask the statement to do so.
   compileExpression: (node, o) ->
-    @tab = o.indent
-    node.tags.front = true
-    compiledNode = node.compile merge o, top: true
-    if node.isStatement(o) then compiledNode else "#{@idt()}#{compiledNode};"
-
-# Wrap up the given nodes as an **Expressions**, unless it already happens
-# to be one.
-Expressions.wrap = (nodes) ->
-  return nodes[0] if nodes.length is 1 and nodes[0] instanceof Expressions
-  new Expressions(nodes)
+    o.top = node.tags.front = on
+    @tab  = o.indent
+    code  = node.compile o
+    if node.isStatement o then code else @tab + code + ';'
+
+  # Wrap up the given nodes as an **Expressions**, unless it already happens
+  # to be one.
+  @wrap: (nodes) ->
+    return nodes[0] if nodes.length is 1 and nodes[0] instanceof Expressions
+    new Expressions nodes

 #### Literal

@@ -261,22 +260,16 @@

   # Break and continue must be treated as pure statements -- they lose their
   # meaning when wrapped in a closure.
-  isStatement: ->
-    @value in ['break', 'continue', 'debugger']
+  isStatement    : -> @value in ['break', 'continue', 'debugger']
   isPureStatement: Literal::isStatement

   isComplex: NO

-  isReserved: ->
-    !!@value.reserved
-
   assigns: (name) -> name is @value

-  compileNode: (o) ->
-    idt = if @isStatement o then @idt()          else ''
-    end = if @isStatement o then ';'             else ''
-    val = if @isReserved()  then "\"#{@value}\"" else @value
-    idt + val + end
+  compileNode: ->
+    val = if @value.reserved then "\"#{@value}\"" else @value
+    if @isStatement() then @tab + val + ';' else val

   toString: -> ' "' + @value + '"'

@@ -298,15 +291,14 @@

   compile: (o) ->
     expr = @expression?.makeReturn()
-    return expr.compile o if expr and expr not instanceof Return
-    super o
+    if expr and expr not instanceof Return then expr.compile o else super o

   compileNode: (o) ->
     expr = ''
     if @expression
-      o.asStatement = true if @expression.isStatement(o)
+      o.asStatement = true if @expression.isStatement o
       expr = ' ' + @expression.compileBare o
-    "#{@tab}return#{expr};"
+    @tab + 'return' + expr + ';'

 #### Value

@@ -320,7 +312,7 @@
   constructor: (@base, props, tag) ->
     super()
     @properties = props or []
-    @tags[tag] = yes if tag
+    @tags[tag]  = yes if tag

   # Add a property access to the list.
   push: (prop) ->
@@ -369,8 +361,7 @@
   # `a()[b()] ?= c` -> `(_base = a())[_name = b()] ? _base[_name] = c`
   cacheReference: (o) ->
     name = last @properties
-    if not @base.isComplex() and @properties.length < 2 and
-       not name?.isComplex()
+    if @properties.length < 2 and not @base.isComplex() and not name?.isComplex()
       return [this, this]  # `a` `a.b`
     base = new Value @base, @properties.slice 0, -1
     if base.isComplex()  # `a().b`
@@ -386,7 +377,7 @@
   # Override compile to unwrap the value when possible.
   compile: (o) ->
     @base.tags.front = @tags.front
-    if not o.top or @properties.length then super(o) else @base.compile(o)
+    if not o.top or @properties.length then super o else @base.compile o

   # We compile a value to JavaScript by compiling and joining each property.
   # Things get much more insteresting if the chain of properties has *soak*
@@ -869,8 +860,8 @@

   constructor: (@params, @body, tag) ->
     super()
-    @params   or= []
-    @body     or= new Expressions
+    @params or= []
+    @body   or= new Expressions
     @bound    = tag is 'boundfunc'
     @context  = 'this' if @bound

@@ -923,8 +914,8 @@
     return "#{utility 'bind'}(#{func}, #{@context})" if @bound
     if @tags.front then "(#{func})" else func

-  # Short-circuit traverseChildren method to prevent it from crossing scope boundaries
-  # unless crossScope is true
+  # Short-circuit `traverseChildren` method to prevent it from crossing scope boundaries
+  # unless `crossScope` is `true`.
   traverseChildren: (crossScope, func) -> super(crossScope, func) if crossScope

 #### Param


Finishing off the docs for nodes.coffee -- almost ready to roll.

--- nodes.coffee
+++ nodes.coffee
@@ -940,7 +940,7 @@

 #### ThrowNode

-# Throw an exception.
+# Simple node to throw an exception.
 exports.ThrowNode: class ThrowNode extends BaseNode
   type: 'Throw'

@@ -952,8 +952,11 @@

 statement ThrowNode

-
-# Check an expression for existence (meaning not null or undefined).
+#### ExistenceNode
+
+# Checks a variable for existence -- not *null* and not *undefined*. This is
+# similar to `.nil?` in Ruby, and avoids having to consult a JavaScript truth
+# table.
 exports.ExistenceNode: class ExistenceNode extends BaseNode
   type: 'Existence'

@@ -963,6 +966,9 @@
   compile_node: (o) ->
     ExistenceNode.compile_test(o, @expression)

+# The meat of the **ExistenceNode** is in this static `compile_test` method
+# because other nodes like to check the existence of their variables as well.
+# Be careful not to double-evaluate anything.
 ExistenceNode.compile_test: (o, variable) ->
   [first, second]: [variable, variable]
   if variable instanceof CallNode or (variable instanceof ValueNode and variable.has_properties())
@@ -970,8 +976,13 @@
   [first, second]: [first.compile(o), second.compile(o)]
   "(typeof $first !== \"undefined\" && $second !== null)"

-
-# An extra set of parentheses, specified explicitly in the source.
+#### ParentheticalNode
+
+# An extra set of parentheses, specified explicitly in the source. At one time
+# we tried to clean up the results by detecting and removing redundant
+# parentheses, but no longer -- you can put in as many as you please.
+#
+# Parentheses are a good way to force any statement to become an expression.
 exports.ParentheticalNode: class ParentheticalNode extends BaseNode
   type: 'Paren'

@@ -988,11 +999,15 @@
     code: code.substr(o, l-1) if code.substr(l-1, 1) is ';'
     "($code)"

-
-# The replacement for the for loop is an array comprehension (that compiles)
-# into a for loop. Also acts as an expression, able to return the result
-# of the comprehenion. Unlike Python array comprehensions, it's able to pass
-# the current index of the loop as a second parameter.
+#### ForNode
+
+# CoffeeScript's replacement for the *for* loop is our array and object
+# comprehensions, that compile into *for* loops here. They also act as an
+# expression, able to return the result of each filtered iteration.
+#
+# Unlike Python array comprehensions, they can be multi-line, and you can pass
+# the current index of the loop as a second parameter. Unlike Ruby blocks,
+# you can map and filter in a single pass.
 exports.ForNode: class ForNode extends BaseNode
   type: 'For'

@@ -1010,6 +1025,10 @@
   top_sensitive: ->
     true

+  # Welcome to the hairiest method in all of CoffeeScript. Handles the inner
+  # loop, filtering, stepping, and result saving for array, object, and range
+  # comprehensions. Some of the generated code can be shared in common, and
+  # some cannot.
   compile_node: (o) ->
     top_level:      del(o, 'top') and not o.returns
     range:          @source instanceof ValueNode and @source.base instanceof RangeNode and not @source.properties.length
@@ -1059,11 +1078,13 @@

 statement ForNode

-
-# If/else statements. Switch/whens get compiled into these. Acts as an
-# expression by pushing down requested returns to the expression bodies.
-# Single-expression IfNodes are compiled into ternary operators if possible,
-# because ternaries are first-class returnable assignable expressions.
+#### IfNode
+
+# *If/else* statements. Our *switch/when* will be compiled into this. Acts as an
+# expression by pushing down requested returns to the last line of each clause.
+#
+# Single-expression **IfNodes** are compiled into ternary operators if possible,
+# because ternaries are already proper expressions, and don't need conversion.
 exports.IfNode: class IfNode extends BaseNode
   type: 'If'

@@ -1076,6 +1097,8 @@
     @multiple:  true if @condition instanceof Array
     @condition: new OpNode('!', new ParentheticalNode(@condition)) if @tags.invert

+  # Add a new *else* clause to this **IfNode**, or push it down to the bottom
+  # of the chain recursively.
   push: (else_body) ->
     eb: else_body.unwrap()
     if @else_body then @else_body.push(eb) else @else_body: eb
@@ -1085,12 +1108,14 @@
     @tags.statement: true
     this

-  # Tag a chain of IfNodes with their switch condition for equality.
+  # Tag a chain of **IfNodes** with their object(s) to switch on for equality
+  # tests. `rewrite_switch` will perform the actual change at compile time.
   rewrite_condition: (expression) ->
     @switcher: expression
     this

-  # Rewrite a chain of IfNodes with their switch condition for equality.
+  # Rewrite a chain of **IfNodes** with their switch condition for equality.
+  # Ensure that the switch expression isn't evaluated more than once.
   rewrite_switch: (o) ->
     assigner: @switcher
     if not (@switcher.unwrap() instanceof LiteralNode)
@@ -1105,7 +1130,7 @@
     @else_body.rewrite_condition(@switcher) if @is_chain()
     this

-  # Rewrite a chain of IfNodes to add a default case as the final else.
+  # Rewrite a chain of **IfNodes** to add a default case as the final *else*.
   add_else: (exprs, statement) ->
     if @is_chain()
       @else_body.add_else exprs, statement
@@ -1114,12 +1139,12 @@
       @children.push @else_body: exprs
     this

-  # If the else_body is an IfNode itself, then we've got an if-else chain.
+  # If the `else_body` is an **IfNode** itself, then we've got an *if-else* chain.
   is_chain: ->
     @chain ||= @else_body and @else_body instanceof IfNode

-  # The IfNode only compiles into a statement if either of the bodies needs
-  # to be a statement.
+  # The **IfNode** only compiles into a statement if either of its bodies needs
+  # to be a statement. Otherwise a ternary is safe.
   is_statement: ->
     @statement ||= !!(@comment or @tags.statement or @body.is_statement() or (@else_body and @else_body.is_statement()))

@@ -1129,8 +1154,8 @@
   compile_node: (o) ->
     if @is_statement() then @compile_statement(o) else @compile_ternary(o)

-  # Compile the IfNode as a regular if-else statement. Flattened chains
-  # force sub-else bodies into statement form.
+  # Compile the **IfNode** as a regular *if-else* statement. Flattened chains
+  # force inner *else* bodies into statement form.
   compile_statement: (o) ->
     @rewrite_switch(o) if @switcher
     child:        del o, 'chain_child'
@@ -1150,7 +1175,7 @@
       " else {\n${ Expressions.wrap([@else_body]).compile(o) }\n$@tab}"
     "$if_part$else_part"

-  # Compile the IfNode into a ternary operator.
+  # Compile the IfNode as a ternary operator.
   compile_ternary: (o) ->
     if_part:    @condition.compile(o) + ' ? ' + @body.compile(o)
     else_part:  if @else_body then @else_body.compile(o) else 'null'
@@ -1161,15 +1186,20 @@

 # Tabs are two spaces for pretty printing.
 TAB: '  '
+
+# Trim out all trailing whitespace, so that the generated code plays nice
+# with Git.
 TRAILING_WHITESPACE: /\s+$/gm

-# Keep the identifier regex in sync with the Lexer.
-IDENTIFIER:   /^[a-zA-Z$_](\w|\$)*$/
+# Keep this identifier regex in sync with the Lexer.
+IDENTIFIER: /^[a-zA-Z$_](\w|\$)*$/

 # Utility Functions
 # -----------------

-# Merge objects.
+# Merge objects, returning a fresh copy with attributes from both sides.
+# Used every time `compile` is called, to allow properties in the options hash
+# to propagate down the tree without polluting other branches.
 merge: (options, overrides) ->
   fresh: {}
   (fresh[key]: val) for key, val of options
@@ -1179,19 +1209,21 @@
 # Trim out all falsy values from an array.
 compact: (array) -> item for item in array when item

-# Return a completely flattened version of an array.
+# Return a completely flattened version of an array. Handy for getting a
+# list of `children`.
 flatten: (array) ->
   memo: []
   for item in array
     if item instanceof Array then memo: memo.concat(item) else memo.push(item)
   memo

-# Delete a key from an object, returning the value.
+# Delete a key from an object, returning the value. Useful when a node is
+# looking for a particular method in an options hash.
 del: (obj, key) ->
   val: obj[key]
   delete obj[key]
   val

-# Quickie helper for a generated LiteralNode.
+# Handy helper for a generating LiteralNode.
 literal: (name) ->
   new LiteralNode(name)


First draft of recompiling examples for 0.9.9

--- nodes.coffee
+++ nodes.coffee
@@ -1,1569 +0,0 @@
-# `nodes.coffee` contains all of the node classes for the syntax tree. Most
-# nodes are created as the result of actions in the [grammar](grammar.html),
-# but some are created by other nodes as a method of code generation. To convert
-# the syntax tree into a string of JavaScript code, call `compile()` on the root.
-
-{Scope} = require './scope'
-
-# Import the helpers we plan to use.
-{compact, flatten, extend, merge, del, starts, ends, last} = require './helpers'
-
-exports.extend = extend  # for parser
-
-# Constant functions for nodes that don't need customization.
-YES  = -> yes
-NO   = -> no
-THIS = -> this
-
-#### Base
-
-# The **Base** is the abstract base class for all nodes in the syntax tree.
-# Each subclass implements the `compileNode` method, which performs the
-# code generation for that node. To compile a node to JavaScript,
-# call `compile` on it, which wraps `compileNode` in some generic extra smarts,
-# to know when the generated code needs to be wrapped up in a closure.
-# An options hash is passed and cloned throughout, containing information about
-# the environment from higher in the tree (such as if a returned value is
-# being requested by the surrounding function), information about the current
-# scope, and indentation level.
-exports.Base = class Base
-
-  constructor: -> @tags = {}
-
-  # Common logic for determining whether to wrap this node in a closure before
-  # compiling it, or to compile directly. We need to wrap if this node is a
-  # *statement*, and it's not a *pureStatement*, and we're not at
-  # the top level of a block (which would be unnecessary), and we haven't
-  # already been asked to return the result (because statements know how to
-  # return results).
-  compile: (o, lvl) ->
-    o        = if o then extend {}, o else {}
-    o.level  = lvl if lvl?
-    node     = @unfoldSoak(o) or this
-    node.tab = o.indent
-    if o.level is LEVEL_TOP or node.isPureStatement() or not node.isStatement(o)
-      node.compileNode o
-    else
-      node.compileClosure o
-
-  # Statements converted into expressions via closure-wrapping share a scope
-  # object with their parent closure, to preserve the expected lexical scope.
-  compileClosure: (o) ->
-    if @containsPureStatement()
-      throw SyntaxError 'cannot include a pure statement in an expression.'
-    o.sharedScope = o.scope
-    Closure.wrap(this).compileNode o
-
-  # If the code generation wishes to use the result of a complex expression
-  # in multiple places, ensure that the expression is only ever evaluated once,
-  # by assigning it to a temporary variable. Pass a level to precompile.
-  cache: (o, level, reused) ->
-    unless @isComplex()
-      ref = if level then @compile o, level else this
-      [ref, ref]
-    else
-      ref = new Literal reused or o.scope.freeVariable 'ref'
-      sub = new Assign ref, this
-      if level then [sub.compile(o, level), ref.value] else [sub, ref]
-
-  # Compile to a source/variable pair suitable for looping.
-  compileLoopReference: (o, name) ->
-    src = tmp = @compile o, LEVEL_LIST
-    unless NUMBER.test(src) or IDENTIFIER.test(src) and o.scope.check(src, immediate: on)
-      src = "#{ tmp = o.scope.freeVariable name } = #{src}"
-    [src, tmp]
-
-  # Convenience method to grab the current indentation level, plus tabbing in.
-  idt: (tabs) ->
-    (@tab or '') + Array((tabs or 0) + 1).join TAB
-
-  # Construct a node that returns the current node's result.
-  # Note that this is overridden for smarter behavior for
-  # many statement nodes (eg If, For)...
-  makeReturn: -> new Return this
-
-  # Does this node, or any of its children, contain a node of a certain kind?
-  # Recursively traverses down the *children* of the nodes, yielding to a block
-  # and returning true when the block finds a match. `contains` does not cross
-  # scope boundaries.
-  contains: (block, arg) ->
-    contains = no
-    @traverseChildren false, (node, arg) ->
-      if (rearg = block node, arg) is true then not contains = true else if arg? then rearg
-    , arg
-    contains
-
-  # Is this node of a certain type, or does it contain the type?
-  containsType: (type) ->
-    this instanceof type or @contains (node) -> node instanceof type
-
-  # Convenience for the most common use of contains. Does the node contain
-  # a pure statement?
-  containsPureStatement: ->
-    @isPureStatement() or @contains (node, func) ->
-      func(node) or if node instanceof While or node instanceof For
-        (node) -> node instanceof Return
-      else func
-    , (node) -> node.isPureStatement()
-
-  # `toString` representation of the node, for inspecting the parse tree.
-  # This is what `coffee --nodes` prints out.
-  toString: (idt, override) ->
-    idt or= ''
-    children = (child.toString idt + TAB for child in @collectChildren()).join('')
-    klass = override or @constructor.name + if @soakNode then '?' else ''
-    '\n' + idt + klass + children
-
-  # Passes each child to a function, breaking when the function returns `false`.
-  eachChild: (func) ->
-    return this unless @children
-    for attr in @children when @[attr]
-      for child in flatten [@[attr]]
-        return this if func(child) is false
-    this
-
-  collectChildren: ->
-    nodes = []
-    @eachChild (node) -> nodes.push node
-    nodes
-
-  traverseChildren: (crossScope, func, arg) ->
-    @eachChild (child) ->
-      return false if (arg = func child, arg) is false
-      child.traverseChildren crossScope, func, arg
-
-  invert: -> new Op '!', this
-
-  unwrapAll: ->
-    node = this
-    continue until node is node = node.unwrap()
-    node
-
-  # Default implementations of the common node properties and methods. Nodes
-  # will override these with custom logic, if needed.
-  children: []
-
-  isStatement     : NO
-  isPureStatement : NO
-  isComplex       : YES
-  isChainable     : NO
-  isAssignable    : NO
-
-  unwrap     : THIS
-  unfoldSoak : NO
-
-  # Is this node used to assign a certain variable?
-  assigns: NO
-
-#### Expressions
-
-# The expressions body is the list of expressions that forms the body of an
-# indented block of code -- the implementation of a function, a clause in an
-# `if`, `switch`, or `try`, and so on...
-exports.Expressions = class Expressions extends Base
-
-  children: ['expressions']
-
-  isStatement: YES
-
-  constructor: (nodes) ->
-    super()
-    @expressions = compact flatten nodes or []
-
-  # Tack an expression on to the end of this expression list.
-  push: (node) ->
-    @expressions.push node
-    this
-
-  # Remove and return the last expression of this expression list.
-  pop: -> @expressions.pop()
-
-  # Add an expression at the beginning of this expression list.
-  unshift: (node) ->
-    @expressions.unshift node
-    this
-
-  # If this Expressions consists of just a single node, unwrap it by pulling
-  # it back out.
-  unwrap: -> if @expressions.length is 1 then @expressions[0] else this
-
-  # Is this an empty block of code?
-  isEmpty: -> not @expressions.length
-
-  # An Expressions node does not return its entire body, rather it
-  # ensures that the final expression is returned.
-  makeReturn: ->
-    for end, idx in @expressions by -1 when end not instanceof Comment
-      @expressions[idx] = end.makeReturn()
-      break
-    this
-
-  # An **Expressions** is the only node that can serve as the root.
-  compile: (o, level) ->
-    o or= {}
-    if o.scope then super o, level else @compileRoot o
-
-  compileNode: (o) ->
-    @tab = o.indent
-    (@compileExpression node, o for node in @expressions).join '\n'
-
-  # If we happen to be the top-level **Expressions**, wrap everything in
-  # a safety closure, unless requested not to.
-  # It would be better not to generate them in the first place, but for now,
-  # clean up obvious double-parentheses.
-  compileRoot: (o) ->
-    o.indent = @tab = if o.bare then '' else TAB
-    o.scope  = new Scope null, this, null
-    o.level  = LEVEL_TOP
-    code     = @compileWithDeclarations o
-    code     = code.replace TRAILING_WHITESPACE, ''
-    if o.bare then code else "(function() {\n#{code}\n}).call(this);\n"
-
-  # Compile the expressions body for the contents of a function, with
-  # declarations of all inner variables pushed up to the top.
-  compileWithDeclarations: (o) ->
-    code    = @compileNode o
-    {scope} = o
-    if scope.hasAssignments this
-      code = "#{@tab}var #{ multident scope.compiledAssignments(), @tab };\n#{code}"
-    if not o.globals and o.scope.hasDeclarations this
-      code = "#{@tab}var #{ scope.compiledDeclarations() };\n#{code}"
-    code
-
-  # Compiles a single expression within the expressions body. If we need to
-  # return the result, and it's an expression, simply return it. If it's a
-  # statement, ask the statement to do so.
-  compileExpression: (node, o) ->
-    node = node.unwrapAll()
-    node = node.unfoldSoak(o) or node
-    node.tags.front = on
-    o.level = LEVEL_TOP
-    code    = node.compile o
-    if node.isStatement o then code else @tab + code + ';'
-
-  # Wrap up the given nodes as an **Expressions**, unless it already happens
-  # to be one.
-  @wrap: (nodes) ->
-    return nodes[0] if nodes.length is 1 and nodes[0] instanceof Expressions
-    new Expressions nodes
-
-#### Literal
-
-# Literals are static values that can be passed through directly into
-# JavaScript without translation, such as: strings, numbers,
-# `true`, `false`, `null`...
-exports.Literal = class Literal extends Base
-
-  constructor: (@value) -> super()
-
-  makeReturn: -> if @isStatement() then this else super()
-
-  # Break and continue must be treated as pure statements -- they lose their
-  # meaning when wrapped in a closure.
-  isPureStatement: -> @value in ['break', 'continue', 'debugger']
-
-  isAssignable: -> IDENTIFIER.test @value
-
-  isComplex: NO
-
-  assigns: (name) -> name is @value
-
-  compile: -> if @value.reserved then "\"#{@value}\"" else @value
-
-  toString: -> ' "' + @value + '"'
-
-#### Return
-
-# A `return` is a *pureStatement* -- wrapping it in a closure wouldn't
-# make sense.
-exports.Return = class Return extends Base
-
-  children: ['expression']
-
-  isStatement    : YES
-  isPureStatement: YES
-
-  constructor: (@expression) -> super()
-
-  makeReturn: THIS
-
-  compile: (o, level) ->
-    expr = @expression?.makeReturn()
-    if expr and expr not instanceof Return then expr.compile o, level else super o, level
-
-  compileNode: (o) ->
-    o.level = LEVEL_PAREN
-    @tab + "return#{ if @expression then ' ' + @expression.compile o else '' };"
-
-#### Value
-
-# A value, variable or literal or parenthesized, indexed or dotted into,
-# or vanilla.
-exports.Value = class Value extends Base
-
-  children: ['base', 'properties']
-
-  # A **Value** has a base and a list of property accesses.
-  constructor: (base, props, tag) ->
-    return base if not props and base instanceof Value
-    @base       = base
-    @properties = props or []
-    @tags       = if tag then {(tag): on} else {}
-
-  # Add a property access to the list.
-  push: (prop) ->
-    @properties.push prop
-    this
-
-  hasProperties: -> !!@properties.length
-
-  # Some boolean checks for the benefit of other nodes.
-  isArray        : -> not @properties.length and @base instanceof Arr
-  isObject       : -> not @properties.length and @base instanceof Obj
-  isComplex      : -> @hasProperties() or @base.isComplex()
-  isAssignable   : -> @hasProperties() or @base.isAssignable()
-  isSimpleNumber : -> @base instanceof Literal and SIMPLENUM.test @base.value
-  isAtomic       : ->
-    for node in @properties.concat @base
-      return no if node.soakNode or node instanceof Call
-    yes
-
-  isStatement : (o)    -> not @properties.length and @base.isStatement o
-  assigns     : (name) -> not @properties.length and @base.assigns name
-
-  makeReturn: -> if @properties.length then super() else @base.makeReturn()
-
-  # The value can be unwrapped as its inner node, if there are no attached
-  # properties.
-  unwrap: -> if @properties.length then this else @base
-
-  # A reference has base part (`this` value) and name part.
-  # We cache them separately for compiling complex expressions.
-  # `a()[b()] ?= c` -> `(_base = a())[_name = b()] ? _base[_name] = c`
-  cacheReference: (o) ->
-    name = last @properties
-    if @properties.length < 2 and not @base.isComplex() and not name?.isComplex()
-      return [this, this]  # `a` `a.b`
-    base = new Value @base, @properties.slice 0, -1
-    if base.isComplex()  # `a().b`
-      bref = new Literal o.scope.freeVariable 'base'
-      base = new Value new Parens new Assign bref, base
-    return [base, bref] unless name  # `a()`
-    if name.isComplex()  # `a[b()]`
-      nref = new Literal o.scope.freeVariable 'name'
-      name = new Index new Assign nref, name.index
-      nref = new Index nref
-    [base.push(name), new Value(bref or base.base, [nref or name])]
-
-  # We compile a value to JavaScript by compiling and joining each property.
-  # Things get much more insteresting if the chain of properties has *soak*
-  # operators `?.` interspersed. Then we have to take care not to accidentally
-  # evaluate anything twice when building the soak chain.
-  compileNode: (o) ->
-    @base.tags.front = @tags.front
-    props = @properties
-    code  = @base.compile o, if props.length then LEVEL_ACCESS else null
-    code  = "(#{code})" if props[0] instanceof Accessor and @isSimpleNumber()
-    code += prop.compile o for prop in props
-    code
-
-  # Unfold a soak into an `If`: `a?.b` -> `a.b if a?`
-  unfoldSoak: (o) ->
-    if ifn = @base.unfoldSoak o
-      Array::push.apply ifn.body.properties, @properties
-      return ifn
-    for prop, i in @properties when prop.soakNode
-      prop.soakNode = off
-      fst = new Value @base, @properties.slice 0, i
-      snd = new Value @base, @properties.slice i
-      if fst.isComplex()
-        ref = new Literal o.scope.freeVariable 'ref'
-        fst = new Parens new Assign ref, fst
-        snd.base = ref
-      return new If new Existence(fst), snd, soak: on
-    null
-
-#### Comment
-
-# CoffeeScript passes through block comments as JavaScript block comments
-# at the same position.
-exports.Comment = class Comment extends Base
-
-  isPureStatement: YES
-
-  constructor: (@comment) -> super()
-
-  makeReturn: THIS
-
-  compileNode: (o) -> @tab + '/*' + multident(@comment, @tab) + '*/'
-
-#### Call
-
-# Node for a function invocation. Takes care of converting `super()` calls into
-# calls against the prototype's function of the same name.
-exports.Call = class Call extends Base
-
-  children: ['variable', 'args']
-
-  constructor: (variable, @args, @soakNode) ->
-    super()
-    @isNew    = false
-    @isSuper  = variable is 'super'
-    @variable = if @isSuper then null else variable
-    @args   or= []
-
-  # Tag this invocation as creating a new instance.
-  newInstance: ->
-    @isNew = true
-    this
-
-  # Grab the reference to the superclass' implementation of the current method.
-  superReference: (o) ->
-    {method} = o.scope
-    throw SyntaxError 'cannot call super outside of a function.' unless method
-    {name} = method
-    throw SyntaxError 'cannot call super on an anonymous function.' unless name
-    if method.klass
-      "#{method.klass}.__super__.#{name}"
-    else
-      "#{name}.__super__.constructor"
-
-  # Soaked chained invocations unfold into if/else ternary structures.
-  unfoldSoak: (o) ->
-    if @soakNode
-      if @variable
-        return ifn if ifn = If.unfoldSoak o, this, 'variable'
-        [left, rite] = new Value(@variable).cacheReference o
-      else
-        left = new Literal @superReference o
-        rite = new Value left
-      rite = new Call rite, @args
-      rite.isNew = @isNew
-      left = new Literal "typeof #{ left.compile o } === \"function\""
-      return new If left, new Value(rite), soak: yes
-    call = this
-    list = []
-    loop
-      if call.variable instanceof Call
-        list.push call
-        call = call.variable
-        continue
-      break unless call.variable instanceof Value
-      list.push call
-      break unless (call = call.variable.base) instanceof Call
-    for call in list.reverse()
-      if ifn
-        if call.variable instanceof Call
-          call.variable = ifn
-        else
-          call.variable.base = ifn
-      ifn = If.unfoldSoak o, call, 'variable'
-    ifn
-
-  # Compile a vanilla function call.
-  compileNode: (o) ->
-    @variable?.tags.front = @tags.front
-    for arg in @args when arg instanceof Splat
-      return @compileSplat o
-    args = (arg.compile o, LEVEL_LIST for arg in @args).join ', '
-    if @isSuper
-      @compileSuper args, o
-    else
-      (if @isNew then 'new ' else '') + @variable.compile(o, LEVEL_ACCESS) + "(#{args})"
-
-  # `super()` is converted into a call against the superclass's implementation
-  # of the current function.
-  compileSuper: (args, o) ->
-    "#{@superReference(o)}.call(this#{ if args.length then ', ' else '' }#{args})"
-
-  # If you call a function with a splat, it's converted into a JavaScript
-  # `.apply()` call to allow an array of arguments to be passed.
-  # If it's a constructor, then things get real tricky. We have to inject an
-  # inner constructor in order to be able to pass the varargs.
-  compileSplat: (o) ->
-    splatargs = Splat.compileSplattedArray @args, o
-    return "#{ @superReference o }.apply(this, #{splatargs})" if @isSuper
-    unless @isNew
-      base = new Value @variable
-      if (name = base.properties.pop()) and base.isComplex()
-        ref = o.scope.freeVariable 'this'
-        fun = "(#{ref} = #{ base.compile o, LEVEL_LIST })#{ name.compile o }"
-      else
-        fun = ref = base.compile o, LEVEL_ACCESS
-        fun += name.compile o if name
-      return "#{fun}.apply(#{ref}, #{splatargs})"
-    idt = @idt 1
-    """
-    (function(func, args, ctor) {
-    #{idt}ctor.prototype = func.prototype;
-    #{idt}var child = new ctor, result = func.apply(child, args);
-    #{idt}return typeof result === "object" ? result : child;
-    #{@tab}})(#{ @variable.compile o, LEVEL_LIST }, #{splatargs}, function() {})
-    """
-
-#### Extends
-
-# Node to extend an object's prototype with an ancestor object.
-# After `goog.inherits` from the
-# [Closure Library](http://closure-library.googlecode.com/svn/docs/closureGoogBase.js.html).
-exports.Extends = class Extends extends Base
-
-  children: ['child', 'parent']
-
-  constructor: (@child, @parent) -> super()
-
-  # Hooks one constructor into another's prototype chain.
-  compile: (o) ->
-    new Call(new Value(new Literal utility 'extends'), [@child, @parent]).compile o
-
-#### Accessor
-
-# A `.` accessor into a property of a value, or the `::` shorthand for
-# an accessor into the object's prototype.
-exports.Accessor = class Accessor extends Base
-
-  children: ['name']
-
-  constructor: (@name, tag) ->
-    super()
-    @proto    = if tag is 'prototype' then '.prototype' else ''
-    @soakNode = tag is 'soak'
-
-  compile: (o) ->
-    name = @name.compile o
-    @proto + if IS_STRING.test name then "[#{name}]" else ".#{name}"
-
-  isComplex: NO
-
-#### Index
-
-# A `[ ... ]` indexed accessor into an array or object.
-exports.Index = class Index extends Base
-
-  children: ['index']
-
-  constructor: (@index) -> super()
-
-  compile: (o) ->
-    (if @proto then '.prototype' else '') + "[#{ @index.compile o, LEVEL_PAREN }]"
-
-  isComplex: -> @index.isComplex()
-
-#### Obj
-
-# An object literal, nothing fancy.
-exports.Obj = class Obj extends Base
-
-  children: ['properties']
-
-  constructor: (props) ->
-    super()
-    @objects = @properties = props or []
-
-  compileNode: (o) ->
-    for prop, i in @properties when (prop.variable or prop).base instanceof Parens
-      return @compileDynamic o, i
-    o.indent = @idt 1
-    nonComments = (prop for prop in @properties when prop not instanceof Comment)
-    lastNoncom  = last nonComments
-    props = for prop, i in @properties
-      join = if i is @properties.length - 1
-        ''
-      else if prop is lastNoncom or prop instanceof Comment
-        '\n'
-      else
-        ',\n'
-      indent = if prop instanceof Comment then '' else @idt 1
-      if prop instanceof Value and prop.tags.this
-        prop = new Assign prop.properties[0].name, prop, 'object'
-      else if prop not instanceof Assign and prop not instanceof Comment
-        prop = new Assign prop, prop, 'object'
-      indent + prop.compile(o) + join
-    props = props.join ''
-    obj   = "{#{ if props then '\n' + props + '\n' + @idt() else '' }}"
-    if @tags.front then "(#{obj})" else obj
-
-  compileDynamic: (o, idx) ->
-    obj  = o.scope.freeVariable 'obj'
-    code = "#{obj} = #{ new Obj(@properties.slice 0, idx).compile o }, "
-    for prop, i in @properties.slice idx
-      if prop instanceof Assign
-        key   = prop.variable.compile o, LEVEL_PAREN
-        code += "#{obj}[#{key}] = #{ prop.value.compile o, LEVEL_LIST }, "
-        continue
-      if prop instanceof Comment
-        code += prop.compile(o) + ' '
-        continue
-      [sub, ref] = prop.base.cache o, LEVEL_LIST, ref
-      code += "#{obj}[#{sub}] = #{ref}, "
-    code += obj
-    if o.level <= LEVEL_PAREN then code else "(#{code})"
-
-  assigns: (name) ->
-    for prop in @properties when prop.assigns name then return yes
-    no
-
-#### Arr
-
-# An array literal.
-exports.Arr = class Arr extends Base
-
-  children: ['objects']
-
-  constructor: (objs) ->
-    super()
-    @objects = objs or []
-
-  compileNode: (o) ->
-    o.indent = @idt 1
-    for obj in @objects when obj instanceof Splat
-      return Splat.compileSplattedArray @objects, o
-    objects = []
-    for obj, i in @objects
-      code = obj.compile o, LEVEL_LIST
-      objects.push (if obj instanceof Comment
-        "\n#{code}\n#{o.indent}"
-      else if i is @objects.length - 1
-        code
-      else
-        code + ', '
-      )
-    objects = objects.join ''
-    if 0 < objects.indexOf '\n'
-      "[\n#{o.indent}#{objects}\n#{@tab}]"
-    else
-      "[#{objects}]"
-
-  assigns: (name) ->
-    for obj in @objects when obj.assigns name then return yes
-    no
-
-#### Class
-
-# The CoffeeScript class definition.
-exports.Class = class Class extends Base
-
-  children: ['variable', 'parent', 'properties']
-
-  isStatement: YES
-
-  # Initialize a **Class** with its name, an optional superclass, and a
-  # list of prototype property assignments.
-  constructor: (@variable, @parent, props) ->
-    super()
-    @properties = props or []
-    @returns    = false
-
-  makeReturn: ->
-    @returns = true
-    this
-
-  # Instead of generating the JavaScript string directly, we build up the
-  # equivalent syntax tree and compile that, in pieces. You can see the
-  # constructor, property assignments, and inheritance getting built out below.
-  compileNode: (o) ->
-    variable   = @variable or new Literal o.scope.freeVariable 'ctor'
-    extension  = @parent  and new Extends variable, @parent
-    props      = new Expressions
-    me         = null
-    className  = variable.compile o
-    constScope = null
-
-    if @parent
-      applied = new Value @parent, [new Accessor new Literal 'apply']
-      constructor = new Code [], new Expressions [
-        new Call applied, [new Literal('this'), new Literal('arguments')]
-      ]
-    else
-      constructor = new Code [], new Expressions [new Return new Literal 'this']
-
-    for prop in @properties
-      {variable: pvar, value: func} = prop
-      if pvar and pvar.base.value is 'constructor'
-        if func not instanceof Code
-          [func, ref] = func.cache o
-          props.push func if func isnt ref
-          apply = new Call new Value(ref, [new Accessor new Literal 'apply']),
-                           [new Literal('this'), new Literal('arguments')]
-          func  = new Code [], new Expressions([apply])
-        throw SyntaxError 'cannot define a constructor as a bound function.' if func.bound
-        func.name = className
-        func.body.push new Return new Literal 'this'
-        variable = new Value variable
-        variable.namespaced = 0 < className.indexOf '.'
-        constructor = func
-        constructor.comment = props.expressions.pop() if last(props.expressions) instanceof Comment
-        continue
-      if func instanceof Code and func.bound
-        if prop.context is 'this'
-          func.context = className
-        else
-          func.bound = false
-          constScope or= new Scope o.scope, constructor.body, constructor
-          me or= constScope.freeVariable 'this'
-          pname = pvar.compile o
-          constructor.body.push    new Return new Literal 'this' if constructor.body.isEmpty()
-          constructor.body.unshift new Literal "this.#{pname} = function(){ return #{className}.prototype.#{pname}.apply(#{me}, arguments); }"
-      if pvar
-        access = if prop.context is 'this' then pvar.properties[0] else new Accessor(pvar, 'prototype')
-        val    = new Value variable, [access]
-        prop   = new Assign val, func
-      props.push prop
-
-    constructor.className = className.match /[$\w]+$/
-    constructor.body.unshift new Literal "#{me} = this" if me
-    o.sharedScope = constScope
-    construct  = @tab + new Assign(variable, constructor).compile(o) + ';'
-    construct += '\n' + @tab + extension.compile(o) + ';' if extension
-    construct += '\n' + props.compile o                   if !props.isEmpty()
-    construct += '\n' + new Return(variable).compile o    if @returns
-    construct
-
-#### Assign
-
-# The **Assign** is used to assign a local variable to value, or to set the
-# property of an object -- including within object literals.
-exports.Assign = class Assign extends Base
-
-  # Matchers for detecting class/method names
-  METHOD_DEF: /^(?:(\S+)\.prototype\.)?([$A-Za-z_][$\w]*)$/
-
-  children: ['variable', 'value']
-
-  constructor: (@variable, @value, @context) -> super()
-
-  assigns: (name) ->
-    @[if @context is 'object' then 'value' else 'variable'].assigns name
-
-  unfoldSoak: (o) -> If.unfoldSoak o, this, 'variable'
-
-  # Compile an assignment, delegating to `compilePatternMatch` or
-  # `compileSplice` if appropriate. Keep track of the name of the base object
-  # we've been assigned to, for correct internal references. If the variable
-  # has not been seen yet within the current scope, declare it.
-  compileNode: (o) ->
-    if isValue = @variable instanceof Value
-      return @compilePatternMatch o if @variable.isArray() or @variable.isObject()
-      return @compileConditional  o if @context in ['||=', '&&=', '?=']
-    name = @variable.compile o, LEVEL_LIST
-    if @value instanceof Code and match = @METHOD_DEF.exec name
-      @value.name  = match[2]
-      @value.klass = match[1]
-    val = @value.compile o, LEVEL_LIST
-    return "#{name}: #{val}" if @context is 'object'
-    unless @variable.isAssignable()
-      throw SyntaxError "\"#{ @variable.compile o }\" cannot be assigned."
-    o.scope.find name unless isValue and (@variable.hasProperties() or @variable.namespaced)
-    val = name + " #{ @context or '=' } " + val
-    if o.level <= LEVEL_LIST then val else "(#{val})"
-
-  # Brief implementation of recursive pattern matching, when assigning array or
-  # object literals to a value. Peeks at their properties to assign inner names.
-  # See the [ECMAScript Harmony Wiki](http://wiki.ecmascript.org/doku.php?id=harmony:destructuring)
-  # for details.
-  compilePatternMatch: (o) ->
-    top       = o.level is LEVEL_TOP
-    {value}   = this
-    {objects} = @variable.base
-    return value.compile o unless olength = objects.length
-    isObject = @variable.isObject()
-    if top and olength is 1 and (obj = objects[0]) not instanceof Splat
-      # Unroll simplest cases: `{v} = x` -> `v = x.v`
-      if obj instanceof Assign
-        {variable: {base: idx}, value: obj} = obj
-      else
-        if obj.base instanceof Parens
-          [obj, idx] = new Value(obj.unwrapAll()).cacheReference o
-        else
-          idx = if isObject
-            if obj.tags.this then obj.properties[0].name else obj
-          else
-            new Literal 0
-      acc   = IDENTIFIER.test idx.unwrap().value or 0
-      value = new Value value
-      value.properties.push new (if acc then Accessor else Index) idx
-      return new Assign(obj, value).compile o
-    valVar  = value.compile o, LEVEL_LIST
-    assigns = []
-    splat   = false
-    if not IDENTIFIER.test(valVar) or @variable.assigns(valVar)
-      assigns.push "#{ ref = o.scope.freeVariable 'ref' } = #{valVar}"
-      valVar = ref
-    for obj, i in objects
-      # A regular array pattern-match.
-      idx = i
-      if isObject
-        if obj instanceof Assign
-          # A regular object pattern-match.
-          {variable: {base: idx}, value: obj} = obj
-        else
-          # A shorthand `{a, b, @c} = val` pattern-match.
-          if obj.base instanceof Parens
-            [obj, idx] = new Value(obj.unwrapAll()).cacheReference o
-          else
-            idx = if obj.tags.this then obj.properties[0].name else obj
-      if not splat and obj instanceof Splat
-        val   = new Literal obj.compileValue o, valVar, i, olength - i - 1
-        splat = true
-      else
-        if typeof idx isnt 'object'
-          idx = new Literal(if splat then "#{valVar}.length - #{ olength - idx }" else idx)
-          acc = no
-        else
-          acc = isObject and IDENTIFIER.test idx.unwrap().value or 0
-        val = new Value new Literal(valVar), [new (if acc then Accessor else Index) idx]
-      assigns.push new Assign(obj, val).compile o, LEVEL_LIST
-    assigns.push valVar unless top
-    code = assigns.join ', '
-    if o.level < LEVEL_LIST then code else "(#{code})"
-
-  # When compiling a conditional assignment, take care to ensure that the
-  # operands are only evaluated once, even though we have to reference them
-  # more than once.
-  compileConditional: (o) ->
-    [left, rite] = @variable.cacheReference o
-    return new Op(@context.slice(0, -1), left, new Assign(rite, @value)).compile o
-
-#### Code
-
-# A function definition. This is the only node that creates a new Scope.
-# When for the purposes of walking the contents of a function body, the Code
-# has no *children* -- they're within the inner scope.
-exports.Code = class Code extends Base
-
-  children: ['params', 'body']
-
-  constructor: (params, body, tag) ->
-    super()
-    @params  = params or []
-    @body    = body   or new Expressions
-    @bound   = tag is 'boundfunc'
-    @context = 'this' if @bound
-
-  # Compilation creates a new scope unless explicitly asked to share with the
-  # outer scope. Handles splat parameters in the parameter list by peeking at
-  # the JavaScript `arguments` objects. If the function is bound with the `=>`
-  # arrow, generates a wrapper that saves the current value of `this` through
-  # a closure.
-  compileNode: (o) ->
-    sharedScope = del o, 'sharedScope'
-    o.scope     = scope = sharedScope or new Scope o.scope, @body, this
-    o.indent    = @idt 1
-    empty       = @body.expressions.length is 0
-    delete o.bare
-    delete o.globals
-    splat = undefined
-    params = []
-    for param, i in @params
-      if splat
-        if param.attach
-          param.assign = new Assign new Value new Literal('this'), [new Accessor param.value]
-          @body.expressions.splice splat.index + 1, 0, param.assign
-        splat.trailings.push param
-      else
-        if param.attach
-          {value} = param
-          [param, param.splat] = [new Literal(scope.freeVariable 'arg'), param.splat]
-          @body.unshift new Assign new Value(new Literal('this'), [new Accessor value]), param
-        if param.splat
-          splat           = new Splat param.value
-          splat.index     = i
-          splat.trailings = []
-          splat.arglength = @params.length
-          @body.unshift splat
-        else
-          params.push param
-    scope.startLevel()
-    @body.makeReturn() unless empty or @noReturn
-    params = for param in params
-      scope.parameter param = param.compile o
-      param
-    comm  = if @comment then @comment.compile(o) + '\n' else ''
-    o.indent = @idt 2 if @className
-    idt  = @idt 1
-    code = if @body.expressions.length then "\n#{ @body.compileWithDeclarations o }\n" else ''
-    if @className
-      open  = "(function() {\n#{comm}#{idt}function #{@className}("
-      close = "#{ code and idt }}\n#{idt}return #{@className};\n#{@tab}})()"
-    else
-      open  = "function("
-      close = "#{ code and @tab }}"
-    func = "#{open}#{ params.join ', ' }) {#{code}#{close}"
-    scope.endLevel()
-    return "#{ utility 'bind' }(#{func}, #{@context})" if @bound
-    if @tags.front then "(#{func})" else func
-
-  # Short-circuit `traverseChildren` method to prevent it from crossing scope boundaries
-  # unless `crossScope` is `true`.
-  traverseChildren: (crossScope, func) -> super(crossScope, func) if crossScope
-
-#### Param
-
-# A parameter in a function definition. Beyond a typical Javascript parameter,
-# these parameters can also attach themselves to the context of the function,
-# as well as be a splat, gathering up a group of parameters into an array.
-exports.Param = class Param extends Base
-
-  children: ['name']
-
-  constructor: (name, @attach, @splat) ->
-    super()
-    @value = new Literal @name = name
-
-  compile: (o) -> @value.compile o, LEVEL_LIST
-
-  toString: ->
-    {name} = this
-    name   = '@' + name if @attach
-    name  += '...'      if @splat
-    new Literal(name).toString()
-
-#### Splat
-
-# A splat, either as a parameter to a function, an argument to a call,
-# or as part of a destructuring assignment.
-exports.Splat = class Splat extends Base
-
-  children: ['name']
-
-  isAssignable: YES
-
-  constructor: (name) ->
-    super()
-    @name = if name.compile then name else new Literal name
-
-  assigns: (name) -> @name.assigns name
-
-  compile: (o) -> if @index? then @compileParam o else @name.compile o
-
-  # Compiling a parameter splat means recovering the parameters that succeed
-  # the splat in the parameter list, by slicing the arguments object.
-  compileParam: (o) ->
-    name = @name.compile o
-    o.scope.find name
-    end = ''
-    if @trailings.length
-      len = o.scope.freeVariable 'len'
-      o.scope.assign len, 'arguments.length'
-      variadic = o.scope.freeVariable 'result'
-      o.scope.assign variadic, len + ' >= ' + @arglength
-      end = if @trailings.length then ", #{len} - #{@trailings.length}"
-      for trailing, idx in @trailings
-        if trailing.attach
-          assign        = trailing.assign
-          trailing      = new Literal o.scope.freeVariable 'arg'
-          assign.value  = trailing
-        pos = @trailings.length - idx
-        o.scope.assign trailing.compile(o),
-          "arguments[#{variadic} ? #{len} - #{pos} : #{ @index + idx }]"
-    "#{name} = #{ utility 'slice' }.call(arguments, #{@index}#{end})"
-
-  # A compiling a splat as a destructuring assignment means slicing arguments
-  # from the right-hand-side's corresponding array.
-  compileValue: (o, name, index, trailings) ->
-    trail = if trailings then ", #{name}.length - #{trailings}" else ''
-    "#{ utility 'slice' }.call(#{name}, #{index}#{trail})"
-
-  # Utility function that converts arbitrary number of elements, mixed with
-  # splats, to a proper array
-  @compileSplattedArray: (list, o) ->
-    args = []
-    end  = -1
-    for arg, i in list
-      code = arg.compile o, LEVEL_LIST
-      prev = args[end]
-      if arg not instanceof Splat
-        if prev and starts(prev, '[') and ends(prev, ']')
-          args[end] = "#{prev.slice 0, -1}, #{code}]"
-          continue
-        if prev and starts(prev, '.concat([') and ends(prev, '])')
-          args[end] = "#{prev.slice 0, -2}, #{code}])"
-          continue
-        code = "[#{code}]"
-      args[++end] = if i is 0 then code else ".concat(#{code})"
-    args.join ''
-
-#### While
-
-# A while loop, the only sort of low-level loop exposed by CoffeeScript. From
-# it, all other loops can be manufactured. Useful in cases where you need more
-# flexibility or more speed than a comprehension can provide.
-exports.While = class While extends Base
-
-  children: ['condition', 'guard', 'body']
-
-  isStatement: YES
-
-  constructor: (condition, opts) ->
-    super()
-    @condition = if opts?.invert then condition.invert() else condition
-    @guard     = opts?.guard
-
-  addBody: (body) ->
-    @body = body
-    this
-
-  makeReturn: ->
-    @returns = true
-    this
-
-  # The main difference from a JavaScript *while* is that the CoffeeScript
-  # *while* can be used as a part of a larger expression -- while loops may
-  # return an array containing the computed result of each iteration.
-  compileNode: (o) ->
-    o.indent = @idt 1
-    set      = ''
-    {body}   = this
-    if body.isEmpty()
-      body = ''
-    else
-      if o.level > LEVEL_TOP or @returns
-        rvar = o.scope.freeVariable 'result'
-        set  = "#{@tab}#{rvar} = [];\n"
-        body = Push.wrap rvar, body if body
-      body = Expressions.wrap [new If @guard, body] if @guard
-      body = "\n#{ body.compile o, LEVEL_TOP }\n#{@tab}"
-    code = set + @tab + "while (#{ @condition.compile o, LEVEL_PAREN }) {#{body}}"
-    if @returns
-      o.indent = @tab
-      code += '\n' + new Return(new Literal rvar).compile o
-    code
-
-#### Op
-
-# Simple Arithmetic and logical operations. Performs some conversion from
-# CoffeeScript operations into their JavaScript equivalents.
-exports.Op = class Op extends Base
-
-  # The map of conversions from CoffeeScript to JavaScript symbols.
-  CONVERSIONS:
-    '==': '==='
-    '!=': '!=='
-    'of': 'in'
-
-  # The map of invertible operators.
-  INVERSIONS:
-    '!==': '==='
-    '===': '!=='
-
-  children: ['first', 'second']
-
-  constructor: (op, first, second, flip) ->
-    return new In first, second if op is 'in'
-    if op is 'new'
-      return first.newInstance() if first instanceof Call
-      first = new Parens first   if first instanceof Code and first.bound
-    super()
-    @operator = @CONVERSIONS[op] or op
-    @first    = first
-    @second   = second
-    @flip     = !!flip
-
-  isUnary: -> not @second
-
-  # Am I capable of
-  # [Python-style comparison chaining](http://docs.python.org/reference/expressions.html#notin)?
-  isChainable: -> @operator in ['<', '>', '>=', '<=', '===', '!==']
-
-  invert: ->
-    if op = @INVERSIONS[@operator]
-      @operator = op
-      this
-    else if @second
-      new Parens(this).invert()
-    else
-      super()
-
-  unfoldSoak: (o) ->
-    @operator in ['++', '--', 'delete'] and If.unfoldSoak o, this, 'first'
-
-  compileNode: (o) ->
-    return @compileUnary     o if @isUnary()
-    return @compileChain     o if @isChainable() and @first.isChainable()
-    return @compileExistence o if @operator is '?'
-    @first.tags.front = @tags.front
-    "#{ @first.compile o, LEVEL_OP } #{@operator} #{ @second.compile o, LEVEL_OP }"
-
-  # Mimic Python's chained comparisons when multiple comparison operators are
-  # used sequentially. For example:
-  #
-  #     bin/coffee -e 'console.log 50 < 65 > 10'
-  #     true
-  compileChain: (o) ->
-    [@first.second, shared] = @first.second.cache o
-    fst  = @first .compile o, LEVEL_OP
-    fst  = fst.slice 1, -1 if fst.charAt(0) is '('
-    code = "#{fst} && #{ shared.compile o } #{@operator} #{ @second.compile o, LEVEL_OP }"
-    if o.level < LEVEL_OP then code else "(#{code})"
-
-  compileExistence: (o) ->
-    if @first.isComplex()
-      ref = o.scope.freeVariable 'ref'
-      fst = new Parens new Assign new Literal(ref), @first
-    else
-      fst = @first
-      ref = fst.compile o
-    new Existence(fst).compile(o) + " ? #{ref} : #{ @second.compile o, LEVEL_LIST }"
-
-  # Compile a unary **Op**.
-  compileUnary: (o) ->
-    parts = [op = @operator]
-    parts.push ' ' if op in ['new', 'typeof', 'delete'] or
-                      op in ['+', '-'] and @first instanceof Op and @first.operator is op
-    parts.push @first.compile o, LEVEL_OP
-    parts.reverse() if @flip
-    parts.join ''
-
-  toString: (idt) -> super idt, @constructor.name + ' ' + @operator
-
-#### In
-exports.In = class In extends Base
-
-  children: ['object', 'array']
-
-  constructor: (@object, @array) -> super()
-
-  invert: ->
-    @negated = not @negated
-    this
-
-  compileNode: (o) ->
-    if @array instanceof Value and @array.isArray()
-      @compileOrTest o
-    else
-      @compileLoopTest o
-
-  compileOrTest: (o) ->
-    [sub, ref] = @object.cache o, LEVEL_OP
-    [cmp, cnj] = if @negated then [' !== ', ' && '] else [' === ', ' || ']
-    tests = for item, i in @array.base.objects
-      (if i then ref else sub) + cmp + item.compile o
-    tests = tests.join cnj
-    if o.level < LEVEL_OP then tests else "(#{tests})"
-
-  compileLoopTest: (o) ->
-    [sub, ref] = @object.cache o, LEVEL_LIST
-    code = utility('indexOf') + ".call(#{ @array.compile o }, #{ref}) " +
-           if @negated then '< 0' else '>= 0'
-    return code if sub is ref
-    code = sub + ', ' + code
-    if o.level < LEVEL_LIST then code else "(#{code})"
-
-  toString: (idt) ->
-    super idt, @constructor.name + if @negated then '!' else ''
-
-#### Try
-
-# A classic *try/catch/finally* block.
-exports.Try = class Try extends Base
-
-  children: ['attempt', 'recovery', 'ensure']
-
-  isStatement: YES
-
-  constructor: (@attempt, @error, @recovery, @ensure) -> super()
-
-  makeReturn: ->
-    @attempt  = @attempt .makeReturn() if @attempt
-    @recovery = @recovery.makeReturn() if @recovery
-    this
-
-  # Compilation is more or less as you would expect -- the *finally* clause
-  # is optional, the *catch* is not.
-  compileNode: (o) ->
-    o.indent  = @idt 1
-    errorPart = if @error then " (#{ @error.compile o }) " else ' '
-    catchPart = if @recovery
-      " catch#{errorPart}{\n#{ @recovery.compile o, LEVEL_TOP }\n#{@tab}}"
-    else unless @ensure or @recovery
-      ' catch (_e) {}'
-    """
-    #{@tab}try {
-    #{ @attempt.compile o, LEVEL_TOP }
-    #{@tab}}#{ catchPart or '' }
-    """ + if @ensure then " finally {\n#{ @ensure.compile o, LEVEL_TOP }\n#{@tab}}" else ''
-
-#### Throw
-
-# Simple node to throw an exception.
-exports.Throw = class Throw extends Base
-
-  children: ['expression']
-
-  isStatement: YES
-
-  constructor: (@expression) -> super()
-
-  # A **Throw** is already a return, of sorts...
-  makeReturn: THIS
-
-  compileNode: (o) -> @tab + "throw #{ @expression.compile o };"
-
-#### Existence
-
-# Checks a variable for existence -- not *null* and not *undefined*. This is
-# similar to `.nil?` in Ruby, and avoids having to consult a JavaScript truth
-# table.
-exports.Existence = class Existence extends Base
-
-  children: ['expression']
-
-  constructor: (@expression) -> super()
-
-  compileNode: (o) ->
-    code = @expression.compile o
-    code = if IDENTIFIER.test(code) and not o.scope.check code
-      "typeof #{code} !== \"undefined\" && #{code} !== null"
-    else
-      "#{code} != null"
-    if o.level <= LEVEL_COND then code else "(#{code})"
-
-#### Parens
-
-# An extra set of parentheses, specified explicitly in the source. At one time
-# we tried to clean up the results by detecting and removing redundant
-# parentheses, but no longer -- you can put in as many as you please.
-#
-# Parentheses are a good way to force any statement to become an expression.
-exports.Parens = class Parens extends Base
-
-  children: ['expression']
-
-  constructor: (@expression) -> super()
-
-  unwrap    : -> @expression
-  isComplex : -> @expression.isComplex()
-  makeReturn: -> @expression.makeReturn()
-
-  compileNode: (o) ->
-    expr = @expression
-    if expr instanceof Value and expr.isAtomic()
-      expr.tags.front = @tags.front
-      return expr.compile o
-    bare = o.level < LEVEL_OP and (expr instanceof Op or expr instanceof Call)
-    code = expr.compile o, LEVEL_PAREN
-    if bare then code else "(#{code})"
-
-#### For
-
-# CoffeeScript's replacement for the *for* loop is our array and object
-# comprehensions, that compile into *for* loops here. They also act as an
-# expression, able to return the result of each filtered iteration.
-#
-# Unlike Python array comprehensions, they can be multi-line, and you can pass
-# the current index of the loop as a second parameter. Unlike Ruby blocks,
-# you can map and filter in a single pass.
-exports.For = class For extends Base
-
-  children: ['body', 'source', 'guard', 'step', 'from', 'to']
-
-  isStatement: YES
-
-  constructor: (@body, head) ->
-    if head.index instanceof Value
-      throw SyntaxError 'index cannot be a pattern matching expression'
-    super()
-    extend this, head
-    @step  or= new Literal 1 unless @object
-    @pattern = @name instanceof Value
-    @returns = false
-
-  makeReturn: ->
-    @returns = true
-    this
-
-  compileReturnValue: (val, o) ->
-    return '\n' + new Return(new Literal val).compile o if @returns
-    return '\n' + val if val
-    ''
-
-  # Welcome to the hairiest method in all of CoffeeScript. Handles the inner
-  # loop, filtering, stepping, and result saving for array, object, and range
-  # comprehensions. Some of the generated code can be shared in common, and
-  # some cannot.
-  compileNode: (o) ->
-    {scope} = o
-    name    = not @pattern and @name?.compile o
-    index   = @index?.compile o
-    ivar    = if not index then scope.freeVariable 'i' else index
-    varPart = guardPart = defPart = retPart = ''
-    body    = Expressions.wrap [@body]
-    idt     = @idt 1
-    scope.find(name,  immediate: yes) if name
-    scope.find(index, immediate: yes) if index
-    [step, pvar] = @step.compileLoopReference o, 'step' if @step
-    if @from
-      [tail, tvar] = @to.compileLoopReference o, 'to'
-      vars  = ivar + ' = ' + @from.compile o
-      vars += ', ' + tail if tail isnt tvar
-      cond = if +pvar
-        "#{ivar} #{ if pvar < 0 then '>' else '<' }= #{tvar}"
-      else
-        "#{pvar} < 0 ? #{ivar} >= #{tvar} : #{ivar} <= #{tvar}"
-    else
-      if name or @object and not @raw
-        [sourcePart, svar] = @source.compileLoopReference o, 'ref'
-      else
-        sourcePart = svar = @source.compile o, LEVEL_PAREN
-      namePart = if @pattern
-        new Assign(@name, new Literal "#{svar}[#{ivar}]").compile o, LEVEL_TOP
-      else if name
-        "#{name} = #{svar}[#{ivar}]"
-      unless @object
-        if 0 > pvar and (pvar | 0) is +pvar  # negative int
-          vars = "#{ivar} = #{svar}.length - 1"
-          cond = "#{ivar} >= 0"
-        else
-          lvar = scope.freeVariable 'len'
-          vars = "#{ivar} = 0, #{lvar} = #{svar}.length"
-          cond = "#{ivar} < #{lvar}"
-    if @object
-      forPart   = ivar + ' in ' + sourcePart
-      guardPart = if @raw then '' else
-        idt + "if (!#{ utility 'hasProp' }.call(#{svar}, #{ivar})) continue;\n"
-    else
-      vars   += ', ' + step if step isnt pvar
-      defPart = @tab + sourcePart + ';\n' if svar isnt sourcePart
-      forPart = vars + "; #{cond}; " + ivar + switch +pvar
-        when  1 then '++'
-        when -1 then '--'
-        else (if pvar < 0 then ' -= ' + pvar.slice 1 else ' += ' + pvar)
-    varPart = idt + namePart + ';\n' if namePart
-    code = guardPart + varPart
-    unless body.isEmpty()
-      if o.level > LEVEL_TOP or @returns
-        rvar     = scope.freeVariable 'result'
-        defPart += @tab + rvar + ' = [];\n'
-        retPart  = @compileReturnValue rvar, o
-        body     = Push.wrap rvar, body
-      body     = Expressions.wrap [new If @guard, body] if @guard
-      o.indent = idt
-      code    += body.compile o, LEVEL_TOP
-    code = '\n' + code + '\n' + @tab if code
-    defPart + @tab + "for (#{forPart}) {#{code}}" + retPart
-
-#### Switch
-
-# A JavaScript *switch* statement. Converts into a returnable expression on-demand.
-exports.Switch = class Switch extends Base
-
-  children: ['subject', 'cases', 'otherwise']
-
-  isStatement: YES
-
-  constructor: (@subject, @cases, @otherwise) -> super()
-
-  makeReturn: ->
-    pair[1].makeReturn() for pair in @cases
-    @otherwise?.makeReturn()
-    this
-
-  compileNode: (o) ->
-    idt1 = @idt 1
-    idt2 = o.indent = @idt 2
-    code = @tab + "switch (#{ @subject?.compile(o, LEVEL_PAREN) or false }) {\n"
-    for [conditions, block], i in @cases
-      for cond in flatten [conditions]
-        cond  = cond.invert() unless @subject
-        code += idt1 + "case #{ cond.compile o, LEVEL_PAREN }:\n"
-      code += block.compile(o, LEVEL_TOP) + '\n'
-      break if i is @cases.length - 1 and not @otherwise
-      for expr in block.expressions by -1 when expr not instanceof Comment
-        code += idt2 + 'break;\n' unless expr instanceof Return
-        break
-    code += idt1 + "default:\n#{ @otherwise.compile o, LEVEL_TOP }\n" if @otherwise
-    code +  @tab + '}'
-
-#### If
-
-# *If/else* statements. Acts as an expression by pushing down requested returns
-# to the last line of each clause.
-#
-# Single-expression **Ifs** are compiled into conditional operators if possible,
-# because ternaries are already proper expressions, and don't need conversion.
-exports.If = class If extends Base
-
-  children: ['condition', 'body', 'elseBody']
-
-  constructor: (condition, @body, tags) ->
-    @tags      = tags or= {}
-    @condition = if tags.invert then condition.invert() else condition
-    @soakNode  = tags.soak
-    @elseBody  = null
-    @isChain   = false
-
-  bodyNode: -> @body?.unwrap()
-  elseBodyNode: -> @elseBody?.unwrap()
-
-  # Rewrite a chain of **Ifs** to add a default case as the final *else*.
-  addElse: (elseBody) ->
-    if @isChain
-      @elseBodyNode().addElse elseBody
-    else
-      @isChain  = elseBody instanceof If
-      @elseBody = @ensureExpressions elseBody
-    this
-
-  # The **If** only compiles into a statement if either of its bodies needs
-  # to be a statement. Otherwise a conditional operator is safe.
-  isStatement: (o) ->
-    o?.level is LEVEL_TOP or
-      @bodyNode().isStatement(o) or @elseBodyNode()?.isStatement(o)
-
-  compileNode: (o) ->
-    if @isStatement o then @compileStatement o else @compileExpression o
-
-  makeReturn: ->
-    if @isStatement()
-      @body     and= @ensureExpressions @body.makeReturn()
-      @elseBody and= @ensureExpressions @elseBody.makeReturn()
-      this
-    else
-      new Return this
-
-  ensureExpressions: (node) ->
-    if node instanceof Expressions then node else new Expressions [node]
-
-  # Compile the **If** as a regular *if-else* statement. Flattened chains
-  # force inner *else* bodies into statement form.
-  compileStatement: (o) ->
-    child    = del o, 'chainChild'
-    cond     = @condition.compile o, LEVEL_PAREN
-    o.indent = @idt 1
-    body     = @ensureExpressions(@body).compile o
-    ifPart   = "if (#{cond}) {\n#{body}\n#{@tab}}"
-    ifPart   = @tab + ifPart unless child
-    return ifPart unless @elseBody
-    ifPart + ' else ' + if @isChain
-       @elseBodyNode().compile merge o, indent: @tab, chainChild: true
-    else
-      "{\n#{ @elseBody.compile o, LEVEL_TOP }\n#{@tab}}"
-
-  # Compile the If as a conditional operator.
-  compileExpression: (o) ->
-    code = @condition .compile(o, LEVEL_COND) + ' ? ' +
-           @bodyNode().compile(o, LEVEL_LIST) + ' : ' +
-           @elseBodyNode()?.compile o, LEVEL_LIST
-    if o.level >= LEVEL_COND then "(#{code})" else code
-
-  unfoldSoak: -> @soakNode and this
-
-  # Unfold a node's child if soak, then tuck the node under created `If`
-  @unfoldSoak: (o, parent, name) ->
-    return unless ifn = parent[name].unfoldSoak o
-    parent[name] = ifn.body
-    ifn.body     = new Value parent
-    ifn
-
-# Faux-Nodes
-# ----------
-# Faux-nodes are never created by the grammar, but are used during code
-# generation to generate other combinations of nodes.
-
-#### Push
-
-# The **Push** creates the tree for `array.push(value)`,
-# which is helpful for recording the result arrays from comprehensions.
-Push =
-  wrap: (name, exps) ->
-    return exps if exps.isEmpty() or last(exps.expressions).containsPureStatement()
-    exps.push new Call \
-      new Value(new Literal(name), [new Accessor new Literal 'push']), [exps.pop()]
-
-#### Closure
-
-# A faux-node used to wrap an expressions body in a closure.
-Closure =
-
-  # Wrap the expressions body, unless it contains a pure statement,
-  # in which case, no dice. If the body mentions `this` or `arguments`,
-  # then make sure that the closure wrapper preserves the original values.
-  wrap: (expressions, statement, noReturn) ->
-    return expressions if expressions.containsPureStatement()
-    func = new Parens new Code [], Expressions.wrap [expressions]
-    args = []
-    if (mentionsArgs = expressions.contains @literalArgs) or
-       (               expressions.contains @literalThis)
-      meth = new Literal if mentionsArgs then 'apply' else 'call'
-      args = [new Literal 'this']
-      args.push new Literal 'arguments' if mentionsArgs
-      func = new Value func, [new Accessor meth]
-      func.noReturn = noReturn
-    call = new Call func, args
-    if statement then Expressions.wrap [call] else call
-
-  literalArgs: (node) -> node instanceof Literal and node.value is 'arguments'
-  literalThis: (node) -> node instanceof Literal and node.value is 'this' or
-                         node instanceof Code    and node.bound
-
-# Constants
-# ---------
-
-UTILITIES =
-
-  # Correctly set up a prototype chain for inheritance, including a reference
-  # to the superclass for `super()` calls. See:
-  # [goog.inherits](http://closure-library.googlecode.com/svn/docs/closureGoogBase.js.source.html#line1206).
-  extends: '''
-    function(child, parent) {
-      function ctor() { this.constructor = child; }
-      ctor.prototype = parent.prototype;
-      child.prototype = new ctor;
-      if (typeof parent.extended === "function") parent.extended(child);
-      child.__super__ = parent.prototype;
-    }
-  '''
-
-  # Create a function bound to the current value of "this".
-  bind: '''
-    function(func, context) {
-      return function() { return func.apply(context, arguments); };
-    }
-  '''
-
-  # Discover if an item is in an array.
-  indexOf: '''
-    Array.prototype.indexOf || function(item) {
-      for (var i = 0, l = this.length; i < l; i++) {
-        if (this[i] === item) return i;
-      }
-      return -1;
-    }
-  '''
-
-  # Shortcuts to speed up the lookup time for native functions.
-  hasProp: 'Object.prototype.hasOwnProperty'
-  slice  : 'Array.prototype.slice'
-
-# Levels indicates a node's position in the AST.
-LEVEL_TOP    = 0  # ...;
-LEVEL_PAREN  = 1  # (...)
-LEVEL_LIST   = 2  # [...]
-LEVEL_COND   = 3  # ... ? x : y
-LEVEL_OP     = 4  # !...
-LEVEL_ACCESS = 5  # ...[0]
-
-# Tabs are two spaces for pretty printing.
-TAB = '  '
-
-# Trim out all trailing whitespace, so that the generated code plays nice
-# with Git.
-TRAILING_WHITESPACE = /[ \t]+$/gm
-
-IDENTIFIER = /^[$A-Za-z_][$\w]*$/
-NUMBER     = /// ^ -? (?: 0x[\da-f]+ | (?:\d+(\.\d+)?|\.\d+)(?:e[+-]?\d+)? ) $ ///i
-SIMPLENUM  = /^[+-]?\d+$/
-
-# Is a literal value a string?
-IS_STRING = /^['"]/
-
-# Utility Functions
-# -----------------
-
-# Helper for ensuring that utility functions are assigned at the top level.
-utility = (name) ->
-  ref = "__#{name}"
-  Scope.root.assign ref, UTILITIES[name]
-  ref
-
-multident = (code, tab) -> code.replace /\n/g, '$&' + tab


fixes #1385: property access on parenthesized number literals

--- nodes.coffee
+++ nodes.coffee
@@ -402,7 +402,7 @@
     @base.front = @front
     props = @properties
     code  = @base.compile o, if props.length then LEVEL_ACCESS else null
-    code  = "(#{code})" if props[0] instanceof Access and @isSimpleNumber()
+    code  = "#{code}." if (@base instanceof Parens or props.length) and SIMPLENUM.test code
     code += prop.compile o for prop in props
     code


не работает

не работает

--- libs/emt_base.coffee
+++ libs/emt_base.coffee
@@ -13,31 +13,31 @@
 ###
 class EMTBase
   Lib: new require( './emt_lib').EMTLib
-    _text : ""
-    inited : false
-    #
-    # Список Трэтов, которые надо применить к типогрфированию
-    #
-    # @var array
-    #
-    trets_index: []
-    trets: []
-    tret_objects: {}
-
-    ok             : false
-    debug_enabled  : false
-    logging        : false
-    logs           : []
-    errors         : []
-    debug_info     : []
-
-    use_layout : false
-    class_layout_prefix : false
-    use_layout_set : false
-    disable_notg_replace : false
-    remove_notg : false
-    settings : {}
-    _safe_blocks : {}
+  _text : ""
+  inited : false
+  #
+  # Список Трэтов, которые надо применить к типогрфированию
+  #
+  # @var array
+  #
+  trets_index: []
+  trets: []
+  tret_objects: {}
+
+  ok             : false
+  debug_enabled  : false
+  logging        : false
+  logs           : []
+  errors         : []
+  debug_info     : []
+
+  use_layout : false
+  class_layout_prefix : false
+  use_layout_set : false
+  disable_notg_replace : false
+  remove_notg : false
+  settings : {}
+  _safe_blocks : {}

   log: (xstr, data)->
     return unless @logging
@@ -238,6 +238,8 @@
         ''
         )
     @inited = true
+
+
   ###
   Добавить Трэт,
   @param [array] $class - имя класса трета, или сам объект
@@ -245,7 +247,7 @@
   если хотим например иметь два одинаоковых терта в обработке
   @return [unknown]
   ###
-  add_tret:( xclass, altname)->
+  add_tret:(xclass, altname)->
     altname ?= false
     if typeof xclass is 'string'
       obj = @create_object xclass
@@ -256,8 +258,211 @@
       @tret_objects[idx] = obj
       @trets.push idx
       return true
-
-
-
-
-
+      ###
+      @todo
+      try
+        unless issubclass(xclass, EMT_Tret):
+          self.error("You are adding Tret that doesn't inherit
+          base class EMT_Tret", xclass.__class__.__name__)
+          return False
+          xclass.EMT     = self
+          xclass.logging = self.logging
+          self.tret_objects[ altname
+            if altname else xclass.__class__.__name__] = xclass
+          self.trets.append(altname if altname else xclass.__class__.__name__)
+          return True
+      except:
+          self.error("Чтобы добавить трэт необходимо передать имя или объект")
+      ###
+      return false
+  ###
+  Получаем ТРЕТ по идентивикатору, т.е. заванию класса
+  @param unknown_type $name
+  ###
+  get_tret:(name)->
+    return @tret_objects[name] if @tret_objects[name]
+    @error("Трэт с идентификатором #{name} не найден")
+    return false
+    ###
+    @todo
+    for tret in @trets
+      if tret is name
+
+        @todo
+        ```
+        self._init()
+        @tret_objects[name]
+        ```
+    ###
+
+  ###
+  Задаём текст для применения типографа
+  @param string $text
+  ###
+  set_text:(@_text)->
+
+  ###
+  Запустить типограф на выполнение
+  ###
+  apply:(trets)->
+    @ok = false
+    atrets = @trets
+    if typeof trets is 'string'
+      atrets = [trets]
+    else if @Lib.isArray trets
+      atrets = trets
+
+    # self.debug(self, 'init', self._text)
+
+    # self._text = self.safe_blocks(self._text, True)
+
+    # self.debug(self, 'safe_blocks', self._text)
+
+    # self._text = EMT_Lib.safe_tag_chars(self._text, True)
+    # self.debug(self, 'safe_tag_chars', self._text)
+
+    # self._text = EMT_Lib.clear_special_chars(self._text)
+    # self.debug(self, 'clear_special_chars', self._text)
+    ###
+    @current
+    ###
+
+
+  ###
+  Получить содержимое  при использовании классов
+  @param [bool] $list False - вернуть в виде строки для style или как массив
+  @param [bool] $compact не выводить пустые классы
+  @return [string]|[array]
+  ###
+  get_style:( xlist, compact)->
+    res = {}
+    for tret in @trets
+      arr = @tret_objects[tret].classes
+      continue unless @Lib.isArray arr
+      # for classname in arr
+      ###
+      @todo
+      ###
+
+
+  ###
+  Установить режим разметки,
+    EMT_Lib::LAYOUT_STYLE - с помощью стилей
+    EMT_Lib::LAYOUT_CLASS - с помощью классов
+    EMT_Lib::LAYOUT_STYLE|EMT_Lib::LAYOUT_CLASS - оба метода
+
+  @param [int] $layout
+  ###
+  set_tag_layout:(layout)->
+    layout ?= @Lib.LAYOUT_STYLE
+    @use_layout = layout
+    @use_layout_set = true
+
+
+  ###
+  Установить префикс для классов
+  @param [string]|bool $prefix
+  если True то префикс 'emt_', иначе то, что передали
+  ###
+  set_class_layout_prefix:(prefix)->
+    prefix = "emt_" if prefix is true
+    @class_layout_prefix = prefix || "emt_"
+
+  ###
+  Включить/отключить правила, согласно карте
+  Формат карты:
+     'Название трэта 1' => array ( 'правило1', 'правило2' , ...  )
+     'Название трэта 2' => array ( 'правило1', 'правило2' , ...  )
+  # *
+  @param array $map
+  @param boolean $disable если ложно,
+  то $map соотвествует тем правилам,
+  которые надо включить иначе это список правил,
+  которые надо выключить
+  @param boolean $strict строго, т.е. те
+  которые не в списку будут тоже обработаны
+  ###
+  set_enable_map:(xmap, disable, xstrict)->
+    return unless @Lib.isArray xmaps
+    xstrict ?= true
+    trets = []
+    for tret in xmap
+      xlist = tret
+      ###
+      @todo
+      ###
+
+  ###
+  Установлена ли настройка
+  @param string $key
+  ###
+  is_on:(key)->
+    return false unless @settings[key]
+    kk = @settings[key]
+    return true if kk.lower() is "on"
+    return true if kk is "1"
+    return true if kk is 1
+    return true if kk is true
+    return false
+
+
+  ###
+  Установить настройку
+  @param mixed $selector
+  @param string $setting
+  @param mixed $value
+  ###
+  doset:(selector, key, value)->
+    rule_pattern = tret_pattern = false
+    if typeof selector is 'string'
+      if selector.find(".") is -1
+        tret_pattern = selector
+      else
+        pa = selector.split(".")
+        tret_pattern = pa[0]
+    ###
+    @todo
+    ###
+
+
+  ###
+  Установить настройки для тертов и правил
+  1. если селектор является массивом,
+    то тогда утсановка правил будет выполнена для каждого
+    элемента этого массива, как отдельного селектора.
+  2. Если $key не является массивом, то эта настрока будет проставлена
+  согласно селектору
+  3. Если $key массив
+  - то будет задана группа настроек
+  - если $value массив , то настройки определяются по ключам из массива
+  $key, а значения из $value
+  - иначе, $key содержит ключ-значение как массив
+  @param mixed $selector
+  @param mixed $key
+  @param mixed $value
+  ###
+  set:(self, selector, key , value)->
+    if @Lib.isArray selector
+      for val in selector
+        @set val, key, value
+      return
+    ###
+    @todo
+    if selector is object
+    ###
+
+  ###
+  Возвращает список текущих третов, которые установлены
+  ###
+  get_trets_list:->
+    @trets
+
+  ###
+  Установить настройки
+  @param [array] $setupmap
+  ###
+  setup:(setupmap)->
+    ###
+    @todo
+    ###
+