package com.redhat.ceylon.compiler.js;

import java.util.Set;

import com.redhat.ceylon.compiler.typechecker.model.Declaration;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.tree.Visitor;

public class Destructurer extends Visitor {

    private final GenerateJsVisitor gen;
    private final JsIdentifierNames names;
    private final String expvar;
    private final Set<Declaration> directAccess;
    private boolean first;

    public Destructurer(final Tree.Pattern that, final GenerateJsVisitor gen,
            final Set<Declaration> directAccess, final String expvar, boolean first) {
        this.gen = gen;
        names = gen.getNames();
        this.directAccess = directAccess;
        this.expvar = expvar;
        this.first=first;
        that.visit(this);
    }

    public void visit(final Tree.TuplePattern that) {
        int idx=0;
        for (Tree.Pattern p : that.getPatterns()) {
            if (p instanceof Tree.VariablePattern) {
                p.visit(this);
                if (((Tree.VariablePattern)p).getVariable().getType() instanceof Tree.SequencedType) {
                    gen.out(".spanFrom(");
                } else {
                    gen.out(".$_get(");
                }
                gen.out(Integer.toString(idx++), ")");
            } else {
                new Destructurer(p, gen, directAccess, expvar+".$_get("+(idx++)+")", first && idx==0);
            }
        }
    }

    public void visit(final Tree.KeyValuePattern that) {
        if (that.getKey() instanceof Tree.VariablePattern) {
            that.getKey().visit(this);
            gen.out(".key");
        } else {
            new Destructurer(that.getKey(), gen, directAccess, expvar+".item", first);
        }
        if (that.getValue() instanceof Tree.VariablePattern) {
            that.getValue().visit(this);
            gen.out(".item");
        } else {
            new Destructurer(that.getValue(), gen, directAccess, expvar+".item", false);
        }
    }

    public void visit(final Tree.VariablePattern that) {
        directAccess.add(that.getVariable().getDeclarationModel());
        if (first) {
            first=false;
        } else {
            gen.out(",");
        }
        gen.out(names.name(that.getVariable().getDeclarationModel()), "=",expvar);
    }

}

@@ -682,16 +682,37 @@
  names =
+ gen == null ? null :
  gen.get
@@ -1052,32 +1052,71 @@
  p.visit(this);%0A
+                if (gen != null) %7B%0A    
                 
@@ -1214,32 +1214,36 @@
                 
+    
 gen.out(%22.spanFr
@@ -1257,32 +1257,36 @@
                 
+    
 %7D else %7B%0A       
@@ -1290,32 +1290,36 @@
                 
+  
+  
 gen.out(%22.$_get(
@@ -1330,34 +1330,41 @@
                 
-%7D%0A
+    %7D%0A   
                 
@@ -1355,32 +1355,33 @@
                 
+ 
 gen.out(Integer.
@@ -1399,24 +1399,42 @@
 x++), %22)%22);%0A
+                %7D%0A
             
@@ -1725,32 +1725,67 @@
 ().visit(this);%0A
+            if (gen != null) %7B%0A    
             gen.
@@ -1793,24 +1793,38 @@
 ut(%22.key%22);%0A
+            %7D%0A
         %7D el
@@ -2021,32 +2021,67 @@
 ().visit(this);%0A
+            if (gen != null) %7B%0A    
             gen.
@@ -2090,24 +2090,38 @@
 t(%22.item%22);%0A
+            %7D%0A
         %7D el
@@ -2408,32 +2408,49 @@
 ;%0A        %7D else
+ if (gen != null)
  %7B%0A            g
@@ -2464,32 +2464,63 @@
 %22,%22);%0A        %7D%0A
+        if (gen != null) %7B%0A    
         gen.out(
@@ -2586,16 +2586,26 @@
 xpvar);%0A
+        %7D%0A
     %7D%0A%0A%7D

allow null generator #464