Package com.redhat.ceylon.compiler.js

Source Code of com.redhat.ceylon.compiler.js.ValueVisitor

package com.redhat.ceylon.compiler.js;

import com.redhat.ceylon.compiler.typechecker.model.Declaration;
import com.redhat.ceylon.compiler.typechecker.model.MethodOrValue;
import com.redhat.ceylon.compiler.typechecker.model.Setter;
import com.redhat.ceylon.compiler.typechecker.model.TypedDeclaration;
import com.redhat.ceylon.compiler.typechecker.model.Value;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.tree.Visitor;

/**
* Determines if a value is "captured" by
* block nested in the same containing scope.
*
* For example, a captured value in a class
* body is an attribute. A captured value in
* a method body can outlive the execution of
* the method.
*
* @author Gavin King
*
*/
public class ValueVisitor extends Visitor {
   
    private final TypedDeclaration declaration;
    private boolean inCapturingScope = false;
    private int sameScope;
   
    public ValueVisitor(TypedDeclaration declaration) {
        this.declaration = declaration;
    }
   
    private boolean enterCapturingScope() {
        boolean cs = inCapturingScope;
        inCapturingScope = true;
        return cs;
    }
   
    private void exitCapturingScope(boolean cs) {
        inCapturingScope = cs;
    }
   
    @Override public void visit(Tree.BaseMemberExpression that) {
        visitReference(that);
        /*if (that.getIdentifier()!=null) {
            TypedDeclaration d = (TypedDeclaration) getDeclaration(that.getScope(), that.getUnit(), that.getIdentifier(), context);
            visitReference(that, d);
        }*/
    }

    private void visitReference(Tree.Primary that) {
        if (inCapturingScope) {
            capture(that);
        }
    }

    private void capture(Tree.Primary that) {
        if (that instanceof Tree.MemberOrTypeExpression) {
            TypedDeclaration d = (TypedDeclaration) ((Tree.MemberOrTypeExpression) that).getDeclaration();
            if (d==declaration) {
                if (d.isParameter()) {
                    if (!d.getContainer().equals(that.getScope()) || sameScope>0) { //a reference from a default argument
                        //expression of the same parameter
                        //list does not capture a parameter
                        ((MethodOrValue) d).setCaptured(true);
                    }
                } else if (d instanceof Value) {
                    ((Value) d).setCaptured(true);
                }
                /*if (d.isVariable() && !d.isClassMember() && !d.isToplevel()) {
                    that.addError("access to variable local from capturing scope: " + declaration.getName());
                }*/
            }
        }
    }

    @Override
    public void visit(Tree.QualifiedMemberExpression that) {
        super.visit(that);
        if (isSelfReference(that.getPrimary())) {
            visitReference(that);
        }
        else {
            capture(that);
        }
    }

    private boolean isSelfReference(Tree.Primary that) {
        return that instanceof Tree.This || that instanceof Tree.Outer;
    }

    @Override public void visit(Tree.Declaration that) {
        Declaration dm = that.getDeclarationModel();
        if (dm==declaration.getContainer()
                || dm==declaration
                || (dm instanceof Setter && ((Setter) dm).getGetter()==declaration)) {
            inCapturingScope = false;
        }
        super.visit(that);
    }
   
    @Override public void visit(Tree.ClassDefinition that) {
        boolean cs = enterCapturingScope();
        super.visit(that);
        exitCapturingScope(cs);
    }
   
    @Override public void visit(Tree.ObjectDefinition that) {
        boolean cs = enterCapturingScope();
        super.visit(that);
        exitCapturingScope(cs);
    }
   
    @Override public void visit(Tree.MethodDefinition that) {
        boolean cs = enterCapturingScope();
        super.visit(that);
        exitCapturingScope(cs);
    }
   
    @Override public void visit(Tree.AttributeGetterDefinition that) {
        boolean cs = enterCapturingScope();
        super.visit(that);
        exitCapturingScope(cs);
    }
   
    @Override public void visit(Tree.AttributeSetterDefinition that) {
        boolean cs = enterCapturingScope();
        super.visit(that);
        exitCapturingScope(cs);
    }
   
    @Override public void visit(Tree.TypedArgument that) {
        boolean cs = enterCapturingScope();
        super.visit(that);
        exitCapturingScope(cs);
    }
   
    @Override public void visit(Tree.FunctionArgument that) {
        boolean cs = enterCapturingScope();
        super.visit(that);
        exitCapturingScope(cs);
    }   
   
    @Override
    public void visit(Tree.LazySpecifierExpression that) {
        if(that.getExpression() == null)return;
        boolean cs = enterCapturingScope();
        sameScope++;
        that.getExpression().visit(this);
        sameScope--;
        exitCapturingScope(cs);
    }

    @Override
    public void visit(Tree.Parameter that) {
        //Mark all class initializer parameters as captured
        if (that.getParameterModel().getDeclaration() instanceof com.redhat.ceylon.compiler.typechecker.model.Class) {
            that.getParameterModel().getModel().setCaptured(true);
        }
        super.visit(that);
    }

}
TOP

Related Classes of com.redhat.ceylon.compiler.js.ValueVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.