Search in sources :

Example 56 with Functional

use of org.eclipse.ceylon.model.typechecker.model.Functional in project ceylon by eclipse.

the class AnnotationInvocationVisitor method transformConstructorArgument.

public static JCExpression transformConstructorArgument(ExpressionTransformer exprGen, Tree.InvocationExpression invocation, Parameter classParameter, AnnotationArgument argument, org.eclipse.ceylon.langtools.tools.javac.util.List<AnnotationFieldName> fieldPath) {
    AnnotationInvocation anno = annoCtorModel(invocation);
    AnnotationInvocationVisitor visitor = new AnnotationInvocationVisitor(exprGen, invocation, anno);
    visitor.parameter = classParameter;
    AnnotationTerm term = argument.getTerm();
    if (term instanceof ParameterAnnotationTerm) {
        ParameterAnnotationTerm parameterArgument = (ParameterAnnotationTerm) term;
        Parameter sp = parameterArgument.getSourceParameter();
        int argumentIndex = ((Functional) sp.getDeclaration()).getFirstParameterList().getParameters().indexOf(sp);
        if (invocation.getPositionalArgumentList() != null) {
            java.util.List<Tree.PositionalArgument> positionalArguments = invocation.getPositionalArgumentList().getPositionalArguments();
            if (parameterArgument.isSpread()) {
                visitor.transformSpreadArgument(positionalArguments.subList(argumentIndex, positionalArguments.size()), classParameter);
            } else {
                if (0 <= argumentIndex && argumentIndex < positionalArguments.size()) {
                    Tree.PositionalArgument pargument = positionalArguments.get(argumentIndex);
                    if (pargument.getParameter().isSequenced()) {
                        visitor.transformVarargs(argumentIndex, positionalArguments);
                    } else {
                        visitor.transformArgument(pargument);
                    }
                } else if (sp.isDefaulted()) {
                    visitor.makeDefaultExpr(invocation, parameterArgument, sp);
                } else if (sp.isSequenced()) {
                    visitor.appendBuiltArray(visitor.startArray());
                }
            }
        } else if (invocation.getNamedArgumentList() != null) {
            boolean found = false;
            for (Tree.NamedArgument na : invocation.getNamedArgumentList().getNamedArguments()) {
                Parameter parameter = na.getParameter();
                int parameterIndex = anno.indexOfConstructorParameter(parameter);
                if (parameterIndex == argumentIndex) {
                    visitor.transformArgument(na);
                    found = true;
                    break;
                }
            }
            Tree.SequencedArgument sa = invocation.getNamedArgumentList().getSequencedArgument();
            if (sa != null) {
                Parameter parameter = sa.getParameter();
                int parameterIndex = anno.indexOfConstructorParameter(parameter);
                if (parameterIndex == argumentIndex) {
                    ListBuffer<JCExpression> prevArray = visitor.startArray();
                    for (Tree.PositionalArgument pa : sa.getPositionalArguments()) {
                        if (pa instanceof Tree.ListedArgument) {
                            visitor.transformArgument(pa);
                        } else if (pa instanceof Tree.SpreadArgument) {
                            ListBuffer<JCExpression> listed = visitor.arrayExprs;
                            visitor.arrayExprs = null;
                            ((Tree.SpreadArgument) pa).getExpression().visit(visitor);
                            listed.addAll(((JCNewArray) visitor.argumentExpr).elems);
                            visitor.argumentExpr = null;
                            visitor.arrayExprs = listed;
                        }
                    }
                    visitor.appendBuiltArray(prevArray);
                    found = true;
                }
            }
            if (!found) {
                if (sp.isDefaulted()) {
                    visitor.makeDefaultExpr(invocation, parameterArgument, sp);
                } else if (sp.isSequenced()) {
                    visitor.appendBuiltArray(visitor.startArray());
                } else {
                    visitor.append(exprGen.makeErroneous(invocation, "Unable to find argument"));
                }
            }
        }
    } else if (term instanceof LiteralAnnotationTerm) {
        visitor.append(term.makeAnnotationArgumentValue(visitor.exprGen, visitor.anno, fieldPath.append(argument)));
    } else if (term instanceof InvocationAnnotationTerm) {
        AnnotationInvocation instantiation = ((InvocationAnnotationTerm) term).getInstantiation();
        visitor.append(transformConstructor(visitor.exprGen, invocation, instantiation, fieldPath.append(argument)));
    } else {
        visitor.append(visitor.exprGen.makeErroneous(invocation, "Unable to find argument"));
    }
    return visitor.getExpression();
}
Also used : ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) PositionalArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) Functional(org.eclipse.ceylon.model.typechecker.model.Functional) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) PositionalArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument)

Example 57 with Functional

use of org.eclipse.ceylon.model.typechecker.model.Functional in project ceylon by eclipse.

the class AttributeGenerator method addGetterAndSetterToPrototype.

static void addGetterAndSetterToPrototype(final TypeDeclaration outer, final Tree.AttributeDeclaration that, final GenerateJsVisitor gen, final boolean verboseStitcher) {
    final Value d = that.getDeclarationModel();
    if (!gen.opts.isOptimize() || d.isToplevel())
        return;
    gen.comment(that);
    final String atname = gen.getNames().valueName(d);
    final String outerName = d.isStatic() ? gen.getNames().name(outer) + ".$st$" : gen.getNames().self(outer);
    if (d.isFormal()) {
        generateAttributeMetamodel(that, false, false, gen);
    } else if (that.getSpecifierOrInitializerExpression() == null) {
        gen.defineAttribute(outerName, gen.getNames().name(d));
        gen.out("{");
        if (TypeUtils.isNativeExternal(d)) {
            // this is for native member attribute declaration with no value
            gen.stitchNative(d, that);
        } else {
            if (d.isStatic()) {
                if (d.isLate()) {
                    gen.generateUnitializedAttributeReadCheck(outerName + "." + atname, gen.getNames().name(d), that.getSpecifierOrInitializerExpression());
                    gen.out("return ", outerName, ".", atname, ";");
                } else {
                    gen.out("return ");
                    that.getSpecifierOrInitializerExpression().visit(gen);
                    gen.out(";");
                }
            } else {
                if (d.isLate()) {
                    // Just return the private value #451
                    gen.generateUnitializedAttributeReadCheck("this." + atname, gen.getNames().name(d), that.getSpecifierOrInitializerExpression());
                }
                gen.out("return this.", atname, ";");
            }
        }
        gen.out("},");
        Tree.AttributeSetterDefinition setterDef = null;
        boolean setterDefined = false;
        if (d.isVariable() || d.isLate()) {
            setterDef = gen.associatedSetterDefinition(d);
            if (setterDef == null) {
                setterDefined = true;
                final String par = gen.getNames().createTempVariable();
                gen.out("function(", par, "){");
                gen.generateImmutableAttributeReassignmentCheck(d, "this." + atname, gen.getNames().name(d));
                gen.out("return this.", atname, "=", par, ";}");
            } else if (!gen.stitchNative(setterDef.getDeclarationModel(), that)) {
                gen.out("function(", gen.getNames().name(setterDef.getDeclarationModel().getParameter()), ")");
                setter(setterDef, gen);
                setterDefined = true;
            }
        }
        if (!setterDefined) {
            gen.out("undefined");
        }
        gen.out(",");
        TypeUtils.encodeForRuntime(that, that.getDeclarationModel(), that.getAnnotationList(), gen);
        if (setterDef != null) {
            gen.out(",");
            TypeUtils.encodeForRuntime(setterDef, setterDef.getDeclarationModel(), that.getAnnotationList(), gen);
        }
        gen.out(")");
        gen.endLine(true);
    } else {
        org.eclipse.ceylon.model.typechecker.model.Parameter param = null;
        if (d.isParameter()) {
            param = ((Functional) d.getContainer()).getParameter(d.getName());
        }
        if ((that.getSpecifierOrInitializerExpression() != null) || d.isVariable() || param != null || d.isLate() || TypeUtils.isNativeExternal(d)) {
            if (that.getSpecifierOrInitializerExpression() instanceof LazySpecifierExpression) {
                // attribute is defined by a lazy expression ("=>" syntax)
                gen.defineAttribute(outerName, gen.getNames().name(d));
                gen.beginBlock();
                gen.initSelf(that);
                boolean stitch = TypeUtils.isNativeExternal(d);
                if (stitch) {
                    stitch = gen.stitchNative(d, that);
                    if (stitch && verboseStitcher) {
                        gen.spitOut("Stitching in native getter " + d.getQualifiedNameString() + ", ignoring Ceylon declaration");
                    }
                }
                if (!stitch) {
                    final Expression expr = that.getSpecifierOrInitializerExpression().getExpression();
                    gen.out("return ");
                    if (!gen.isNaturalLiteral(expr.getTerm())) {
                        gen.visitSingleExpression(expr);
                    }
                }
                gen.endBlock();
                Tree.AttributeSetterDefinition setterDef = null;
                if (d.isVariable()) {
                    setterDef = gen.associatedSetterDefinition(d);
                    if (setterDef != null) {
                        gen.out(",function(", gen.getNames().name(setterDef.getDeclarationModel().getParameter()), ")");
                        setter(setterDef, gen);
                    }
                }
                if (setterDef == null) {
                    gen.out(",undefined");
                }
                gen.out(",");
                TypeUtils.encodeForRuntime(that, that.getDeclarationModel(), that.getAnnotationList(), gen);
                if (setterDef != null) {
                    gen.out(",");
                    TypeUtils.encodeForRuntime(setterDef, setterDef.getDeclarationModel(), that.getAnnotationList(), gen);
                }
                gen.out(")");
                gen.endLine(true);
            } else {
                final String privname = param == null ? gen.getNames().privateName(d) : gen.getNames().name(param) + "_";
                gen.defineAttribute(outerName, gen.getNames().name(d));
                gen.out("{");
                if (d.isLate()) {
                    gen.generateUnitializedAttributeReadCheck("this." + privname, gen.getNames().name(d), that.getSpecifierOrInitializerExpression());
                }
                if (TypeUtils.isNativeExternal(d)) {
                    if (gen.stitchNative(d, that)) {
                        if (verboseStitcher) {
                            gen.spitOut("Stitching in native getter " + d.getQualifiedNameString() + ", ignoring Ceylon declaration");
                        }
                    } else {
                        gen.out("return ");
                        gen.visitSingleExpression(that.getSpecifierOrInitializerExpression().getExpression());
                    }
                    gen.out("}");
                } else {
                    if (d.isStatic()) {
                        gen.out("return ");
                        gen.visitSingleExpression(that.getSpecifierOrInitializerExpression().getExpression());
                        gen.out("}");
                    } else {
                        gen.out("return this.", privname, ";}");
                    }
                }
                if (d.isVariable() || d.isLate()) {
                    final String pname = gen.getNames().createTempVariable();
                    gen.out(",function(", pname, "){");
                    gen.generateImmutableAttributeReassignmentCheck(d, "this." + privname, gen.getNames().name(d));
                    gen.out("return this.", privname, "=", pname, ";}");
                } else {
                    gen.out(",undefined");
                }
                gen.out(",");
                TypeUtils.encodeForRuntime(that, that.getDeclarationModel(), that.getAnnotationList(), gen);
                gen.out(")");
                gen.endLine(true);
            }
        }
    }
}
Also used : Functional(org.eclipse.ceylon.model.typechecker.model.Functional) LazySpecifierExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) LazySpecifierExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression)

Example 58 with Functional

use of org.eclipse.ceylon.model.typechecker.model.Functional in project ceylon by eclipse.

the class BmeGenerator method generateBme.

static void generateBme(final Tree.BaseMemberExpression bme, final GenerateJsVisitor gen, boolean nonNull) {
    final boolean forInvoke = bme.getDirectlyInvoked();
    Declaration decl = bme.getDeclaration();
    if (decl != null) {
        String name = decl.getName();
        Package pkg = decl.getUnit().getPackage();
        // map Ceylon true/false/null directly to JS true/false/null
        if (pkg.isLanguagePackage()) {
            if ("true".equals(name) || "false".equals(name) || "null".equals(name)) {
                gen.out(name);
                return;
            }
        }
        if (ModelUtil.isConstructor(decl)) {
            Constructor cd = TypeUtils.getConstructor(decl);
            Declaration cdc = (Declaration) cd.getContainer();
            if (!gen.qualify(bme, cd)) {
                gen.out(gen.getNames().name(cdc), gen.getNames().constructorSeparator(decl));
            }
            if (decl instanceof Value) {
                gen.out(gen.getNames().name(decl));
            } else {
                gen.out(gen.getNames().name(cd));
            }
            if (!forInvoke && decl instanceof Value) {
                gen.out("()");
            }
            return;
        }
    }
    String exp = gen.memberAccess(bme, null);
    if (decl == null && gen.isInDynamicBlock()) {
        if ("undefined".equals(exp)) {
            gen.out(exp);
        } else if (nonNull) {
            gen.out("(typeof ", exp, "==='undefined'||", exp, "===null?");
            gen.generateThrow(null, "Undefined or null reference: " + exp, bme);
            gen.out(":", exp, ")");
        } else {
            gen.out(exp);
        }
    } else {
        final boolean isCallable = !forInvoke && (decl instanceof Functional || bme.getUnit().getCallableDeclaration().equals(bme.getTypeModel().getDeclaration()));
        final boolean hasTparms = hasTypeParameters(bme);
        if (isCallable && (decl.isParameter() || (decl.isToplevel() && !hasTparms))) {
            // Callables passed as arguments are already wrapped in JsCallable
            gen.out(exp);
            return;
        }
        String who = isCallable && decl.isMember() ? gen.getMember(bme, null) : null;
        if (who == null || who.isEmpty()) {
            // We may not need to wrap this in certain cases
            ClassOrInterface cont = ModelUtil.getContainingClassOrInterface(bme.getScope());
            who = cont == null ? "0" : gen.getNames().self(cont);
        }
        if (isCallable && (who != null || hasTparms)) {
            if (hasTparms) {
                // Function refs with type arguments must be passed as a special function
                printGenericMethodReference(gen, bme, who, exp);
            } else {
                // Member methods must be passed as JsCallables
                gen.out(gen.getClAlias(), "jsc$3(", who, ",", exp, ")");
            }
        } else {
            gen.out(exp);
        }
    }
}
Also used : Functional(org.eclipse.ceylon.model.typechecker.model.Functional) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) Value(org.eclipse.ceylon.model.typechecker.model.Value) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) Package(org.eclipse.ceylon.model.typechecker.model.Package)

Aggregations

Functional (org.eclipse.ceylon.model.typechecker.model.Functional)58 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)30 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)28 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)28 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)27 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)25 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)24 ParameterList (org.eclipse.ceylon.model.typechecker.model.ParameterList)24 Type (org.eclipse.ceylon.model.typechecker.model.Type)22 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)13 TypedReference (org.eclipse.ceylon.model.typechecker.model.TypedReference)13 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)12 Value (org.eclipse.ceylon.model.typechecker.model.Value)12 AnalyzerUtil.getTypedDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration)11 Class (org.eclipse.ceylon.model.typechecker.model.Class)11 Function (org.eclipse.ceylon.model.typechecker.model.Function)11 Reference (org.eclipse.ceylon.model.typechecker.model.Reference)11 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)10 ModelUtil.intersectionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType)9 AnalyzerUtil.checkCasesDisjoint (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.checkCasesDisjoint)8