Search in sources :

Example 26 with FunctionOrValue

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

the class ExpressionVisitor method visit.

@Override
public void visit(Tree.TypedDeclaration that) {
    super.visit(that);
    TypedDeclaration d = that.getDeclarationModel();
    Type type = d.getType();
    FunctionOrValue fov = (FunctionOrValue) d;
    if (fov.isSmall() && type != null && !type.isInteger() && !type.isFloat() && !type.isCharacter() && !that.getType().hasErrors()) {
        that.addError("type may not be annotated 'small': '" + d.getName() + "' has type '" + type.asString(that.getUnit()) + "' (only an 'Integer', 'Float', or 'Character' may be small)");
    }
}
Also used : AnalyzerUtil.getPackageTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypedDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.unionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.unionType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) ModelUtil.genericFunctionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.genericFunctionType) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 27 with FunctionOrValue

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

the class PartialImpl method initializeObject.

protected <Id> void initializeObject(TypeDescriptor $reified$Id, DeserializationContextImpl<Id> context, Serializable instance) {
    NativeMap<ReachableReference, Id> state = (NativeMap<ReachableReference, Id>) getState();
    // TODO If it were a map of java.lang.String we'd avoid pointless extra boxing
    java.util.Collection<ReachableReference> reachables = instance.$references$();
    int numLate = 0;
    for (ReachableReference r : reachables) {
        if (r instanceof Member && ((Member) r).getAttribute().getLate()) {
            numLate++;
        } else if (r instanceof Outer) {
            numLate++;
        }
    }
    if (state.getSize() < reachables.size() - numLate) {
        HashSet<ReachableReference> missingNames = new HashSet<ReachableReference>();
        java.util.Iterator<ReachableReference> it = reachables.iterator();
        while (it.hasNext()) {
            missingNames.add(it.next());
        }
        ceylon.language.Iterator<? extends ReachableReference> it2 = state.getKeys().iterator();
        Object next;
        while (((next = it2.next()) instanceof ReachableReference)) {
            missingNames.remove(next);
        }
        throw insufficiantState(missingNames);
    }
    for (ReachableReference reference : reachables) {
        if (reference instanceof Member) {
            Member member = (Member) reference;
            if (member.getAttribute().getLate() && !state.contains(member) || state.get(member) == uninitializedLateValue_.get_()) {
                continue;
            }
            TypeDescriptor.Class classTypeDescriptor = getClassTypeDescriptor();
            Entry<TypeDescriptor.Class, String> cacheKey = new Entry<TypeDescriptor.Class, String>(TypeDescriptor.klass(TypeDescriptor.Class.class), String.$TypeDescriptor$, classTypeDescriptor, String.instance(member.getAttribute().getQualifiedName()));
            Type memberType = (Type) context.getMemberTypeCache().get(cacheKey);
            if (memberType == null) {
                Type pt = Metamodel.getModuleManager().getCachedType(classTypeDescriptor);
                while (!pt.getDeclaration().getQualifiedNameString().equals(((ClassDeclaration) member.getAttribute().getContainer()).getQualifiedName())) {
                    pt = pt.getExtendedType();
                }
                FunctionOrValue attributeDeclaration = (FunctionOrValue) ((TypeDeclaration) pt.getDeclaration()).getMember(member.getAttribute().getName(), null, false);
                TypedReference attributeType = pt.getTypedMember(attributeDeclaration, Collections.<Type>emptyList(), true);
                memberType = attributeType.getType();
                context.getMemberTypeCache().put(cacheKey, memberType);
            }
            Object referredInstance = getReferredInstance(context, state, member);
            if (referredInstance instanceof Tuple) {
                // Because tuples are special wrt reified types...
                Id referredId = state.get(member);
                Object r = context.leakInstance(referredId);
                if (r instanceof PartialImpl) {
                    ((PartialImpl) r).initialize($reified$Id, context);
                }
            }
            Type instanceType = Metamodel.getModuleManager().getCachedType(Metamodel.getTypeDescriptor(referredInstance));
            if (!instanceType.isSubtypeOf(memberType)) {
                throw notAssignable(member, memberType, instanceType);
            }
            instance.$set$(member, referredInstance);
        // the JVM will check the assignability, but we need to
        // check assignability at the ceylon level, so we need to know
        // / type of the attribute an the type that we're assigning.
        // XXX this check is really expensive!
        // we should cache the attribute type on the context
        // when can we avoid this check.
        // XXX we can cache MethodHandle setters on the context!
        } else if (reference instanceof Outer) {
            // instantiating member classes
            continue;
        } else {
            throw new AssertionError("unexpected ReachableReference " + reference);
        }
    }
}
Also used : TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) String(ceylon.language.String) Entry(ceylon.language.Entry) AssertionError(ceylon.language.AssertionError) HashSet(java.util.HashSet) Type(org.eclipse.ceylon.model.typechecker.model.Type) ReifiedType(org.eclipse.ceylon.compiler.java.runtime.model.ReifiedType) ClassDeclaration(ceylon.language.meta.declaration.ClassDeclaration) TypeDescriptor(org.eclipse.ceylon.compiler.java.runtime.model.TypeDescriptor) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Tuple(ceylon.language.Tuple)

Example 28 with FunctionOrValue

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

the class GenerateJsVisitor method specifierStatement.

private void specifierStatement(final TypeDeclaration outer, final Tree.SpecifierStatement specStmt) {
    final Tree.Expression expr = specStmt.getSpecifierExpression().getExpression();
    final Tree.Term term = specStmt.getBaseMemberExpression();
    final Tree.StaticMemberOrTypeExpression smte = term instanceof Tree.StaticMemberOrTypeExpression ? (Tree.StaticMemberOrTypeExpression) term : null;
    if (isInDynamicBlock() && ModelUtil.isTypeUnknown(term.getTypeModel())) {
        if (smte != null && smte.getDeclaration() == null) {
            out(smte.getIdentifier().getText());
        } else {
            term.visit(this);
            if (term instanceof BaseMemberExpression) {
                Declaration dec = ((BaseMemberExpression) term).getDeclaration();
                if (dec instanceof Value) {
                    Value v = (Value) dec;
                    if (v.isMember()) {
                        // Assignment to dynamic member
                        out("_");
                    }
                }
            }
        }
        out("=");
        int box = boxUnboxStart(expr, term);
        expr.visit(this);
        if (box == 4)
            out("/*TODO: callable targs 6.1*/");
        boxUnboxEnd(box);
        out(";");
        return;
    }
    if (smte != null) {
        final Declaration bmeDecl = smte.getDeclaration();
        if (specStmt.getSpecifierExpression() instanceof LazySpecifierExpression) {
            // attr => expr;
            final boolean property = AttributeGenerator.defineAsProperty(bmeDecl);
            if (property) {
                defineAttribute(qualifiedPath(specStmt, bmeDecl), names.name(bmeDecl));
            } else {
                if (bmeDecl.isMember()) {
                    qualify(specStmt, bmeDecl);
                } else {
                    out("var ");
                }
                out(names.getter(bmeDecl, false), "=function()");
            }
            beginBlock();
            if (outer != null) {
                initSelf(specStmt);
            }
            out("return ");
            if (!isNaturalLiteral(specStmt.getSpecifierExpression().getExpression().getTerm())) {
                specStmt.getSpecifierExpression().visit(this);
            }
            out(";");
            endBlock();
            if (property) {
                out(",undefined,");
                TypeUtils.encodeForRuntime(specStmt, bmeDecl, this);
                out(")");
            }
            endLine(true);
            directAccess.remove(bmeDecl);
        } else if (outer != null) {
            // since #451 we now generate an attribute here
            if (outer instanceof Constructor || bmeDecl.isMember() && bmeDecl instanceof Value && bmeDecl.isActual()) {
                assignment(outer, bmeDecl, expr);
            }
        } else if (bmeDecl instanceof FunctionOrValue) {
            // "attr = expr;" in an initializer or method
            final FunctionOrValue moval = (FunctionOrValue) bmeDecl;
            if (moval.isVariable() || moval.isLate()) {
                // simple assignment to a variable attribute
                BmeGenerator.generateMemberAccess(smte, new GenerateCallback() {

                    @Override
                    public void generateValue() {
                        int boxType = boxUnboxStart(expr.getTerm(), moval);
                        if (isInDynamicBlock() && !ModelUtil.isTypeUnknown(moval.getType()) && ModelUtil.isTypeUnknown(expr.getTypeModel())) {
                            TypeUtils.generateDynamicCheck(expr, moval.getType(), GenerateJsVisitor.this, false, expr.getTypeModel().getTypeArguments());
                        } else {
                            expr.visit(GenerateJsVisitor.this);
                        }
                        if (boxType == 4) {
                            out(",");
                            if (moval instanceof Function) {
                                // Add parameters
                                TypeUtils.encodeParameterListForRuntime(true, specStmt, ((Function) moval).getFirstParameterList(), GenerateJsVisitor.this);
                                out(",");
                            } else {
                                // TODO extract parameters from Value
                                final Type ps = moval.getUnit().getCallableTuple(moval.getType());
                                if (ps == null || ps.isSubtypeOf(moval.getUnit().getEmptyType())) {
                                    out("[],");
                                } else {
                                    out("[/*VALUE Callable params ", ps.asString() + "*/],");
                                }
                            }
                            TypeUtils.printTypeArguments(expr, expr.getTypeModel().getTypeArguments(), GenerateJsVisitor.this, false, expr.getTypeModel().getVarianceOverrides());
                        }
                        boxUnboxEnd(boxType);
                    }
                }, qualifiedPath(smte, moval), this);
                out(";");
            } else if (moval.isMember()) {
                if (moval instanceof Function) {
                    // same as fat arrow
                    qualify(specStmt, bmeDecl);
                    if (expr.getTerm() instanceof Tree.FunctionArgument) {
                        ((Tree.FunctionArgument) expr.getTerm()).getDeclarationModel().setRefinedDeclaration(moval);
                        out(names.name(moval), "=");
                        specStmt.getSpecifierExpression().visit(this);
                        out(";");
                    } else {
                        out(names.name(moval), "=function ", names.name(moval), "(");
                        // Build the parameter list, we'll use it several times
                        final StringBuilder paramNames = new StringBuilder();
                        final List<Parameter> params = ((Function) moval).getFirstParameterList().getParameters();
                        for (Parameter p : params) {
                            if (paramNames.length() > 0)
                                paramNames.append(",");
                            paramNames.append(names.name(p));
                        }
                        out(paramNames.toString());
                        out("){");
                        for (Parameter p : params) {
                            if (p.isDefaulted()) {
                                out("if(", names.name(p), "===undefined)", names.name(p), "=");
                                qualify(specStmt, moval);
                                out(names.name(moval), "$defs$", p.getName(), "(", paramNames.toString(), ")");
                                endLine(true);
                            }
                        }
                        out("return ");
                        if (!isNaturalLiteral(specStmt.getSpecifierExpression().getExpression().getTerm())) {
                            specStmt.getSpecifierExpression().visit(this);
                        }
                        out("(", paramNames.toString(), ");}");
                        endLine(true);
                    }
                } else {
                    // declaration itself can be omitted), so generate the attribute.
                    if (opts.isOptimize()) {
                        // #451
                        out(names.self(ModelUtil.getContainingClassOrInterface(moval.getScope())), ".", names.valueName(moval), "=");
                        specStmt.getSpecifierExpression().visit(this);
                        endLine(true);
                    } else {
                        AttributeGenerator.generateAttributeGetter(null, moval, specStmt.getSpecifierExpression(), null, this, directAccess, verboseStitcher);
                    }
                }
            } else {
                // Specifier for some other attribute, or for a method.
                if (opts.isOptimize() || bmeDecl.isMember() && bmeDecl instanceof Function) {
                    qualify(specStmt, bmeDecl);
                }
                out(names.name(bmeDecl), "=");
                if (isInDynamicBlock() && ModelUtil.isTypeUnknown(expr.getTypeModel()) && !ModelUtil.isTypeUnknown(((FunctionOrValue) bmeDecl).getType())) {
                    TypeUtils.generateDynamicCheck(expr, ((FunctionOrValue) bmeDecl).getType(), this, false, expr.getTypeModel().getTypeArguments());
                } else {
                    if (expr.getTerm() instanceof Tree.FunctionArgument) {
                        Function fun = ((Tree.FunctionArgument) expr.getTerm()).getDeclarationModel();
                        if (fun.isAnonymous()) {
                            fun.setRefinedDeclaration(moval);
                        }
                    }
                    specStmt.getSpecifierExpression().visit(this);
                }
                out(";");
            }
        }
    } else if ((term instanceof Tree.ParameterizedExpression) && (specStmt.getSpecifierExpression() != null)) {
        final Tree.ParameterizedExpression paramExpr = (Tree.ParameterizedExpression) term;
        if (paramExpr.getPrimary() instanceof BaseMemberExpression) {
            // func(params) => expr;
            final BaseMemberExpression bme2 = (BaseMemberExpression) paramExpr.getPrimary();
            final Declaration bmeDecl = bme2.getDeclaration();
            if (bmeDecl.isMember()) {
                qualify(specStmt, bmeDecl);
            } else {
                out("var ");
            }
            out(names.name(bmeDecl), "=");
            FunctionHelper.singleExprFunction(paramExpr.getParameterLists(), expr, bmeDecl instanceof Scope ? (Scope) bmeDecl : null, true, true, this);
            out(";");
        }
    }
}
Also used : Term(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) Function(org.eclipse.ceylon.model.typechecker.model.Function) IntersectionType(org.eclipse.ceylon.model.typechecker.model.IntersectionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) ExtendedType(org.eclipse.ceylon.compiler.typechecker.tree.Tree.ExtendedType) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) StaticMemberOrTypeExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.StaticMemberOrTypeExpression) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) Value(org.eclipse.ceylon.model.typechecker.model.Value) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) List(java.util.List) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) BaseMemberExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) AttributeDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration) LazySpecifierExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 29 with FunctionOrValue

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

the class GenerateJsVisitor method generateAttributeForParameter.

void generateAttributeForParameter(Node node, Class d, Parameter p) {
    if (p.getDeclaration() instanceof Function && ModelUtil.isConstructor(p.getDeclaration())) {
        return;
    }
    final FunctionOrValue pdec = p.getModel();
    final String privname = names.valueName(pdec);
    defineAttribute(names.self(d), names.name(pdec));
    out("{");
    if (pdec.isLate()) {
        generateUnitializedAttributeReadCheck("this." + privname, names.name(p), null);
    }
    out("return this.", privname, ";}");
    if (pdec.isVariable() || pdec.isLate()) {
        final String param = names.createTempVariable();
        out(",function(", param, "){");
        // Because of this one case, we need to pass 3 args to this method
        generateImmutableAttributeReassignmentCheck(pdec, "this." + privname, names.name(p));
        out("return this.", privname, "=", param, ";}");
    } else {
        out(",undefined");
    }
    out(",");
    TypeUtils.encodeForRuntime(node, pdec, this);
    out(")");
    endLine(true);
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 30 with FunctionOrValue

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

the class MethodOrValueReferenceVisitor method visit.

@Override
public void visit(Tree.ClassDefinition that) {
    if (!that.getDeclarationModel().hasConstructors()) {
        boolean cs = enterCapturingScope();
        super.visit(that);
        exitCapturingScope(cs);
    } else {
        // super special case for unshared members when we have constructors
        if (!declaration.isCaptured() && declaration instanceof FunctionOrValue && declaration.isClassMember()) {
            Map<Constructor, ConstructorPlan> constructorPlans = new HashMap<Constructor, ConstructorPlan>();
            List<Tree.Statement> statements = new ArrayList<>(that.getClassBody().getStatements().size());
            // find every constructor, and build a model of how they delegate
            for (Tree.Statement stmt : that.getClassBody().getStatements()) {
                if (stmt instanceof Tree.Constructor) {
                    Tree.Constructor ctor = (Tree.Constructor) stmt;
                    // build a new plan for it
                    ConstructorPlan plan = new ConstructorPlan();
                    plan.constructor = ctor;
                    constructorPlans.put(ctor.getConstructor(), plan);
                    // find every constructor which delegates to another constructor
                    if (ctor.getDelegatedConstructor() != null && ctor.getDelegatedConstructor().getInvocationExpression() != null) {
                        if (ctor.getDelegatedConstructor().getInvocationExpression().getPrimary() instanceof Tree.ExtendedTypeExpression) {
                            Tree.ExtendedTypeExpression ete = (Tree.ExtendedTypeExpression) ctor.getDelegatedConstructor().getInvocationExpression().getPrimary();
                            // are we delegating to a constructor (not a supertype) of the same class (this class)?
                            if (Decl.isConstructor(ete.getDeclaration()) && ModelUtil.getConstructedClass(ete.getDeclaration()).equals(that.getDeclarationModel())) {
                                // remember the delegation
                                Constructor delegate = ModelUtil.getConstructor(ete.getDeclaration());
                                ConstructorPlan delegatePlan = constructorPlans.get(delegate);
                                plan.delegate = delegatePlan;
                                // mark the delegate as delegated
                                delegatePlan.isDelegate = true;
                                // we have all the statements before us and after our delegate
                                plan.before.addAll(delegatePlan.after);
                            }
                        }
                    }
                    // if we have no delegate, we start with every common statement
                    if (plan.delegate == null)
                        plan.before.addAll(statements);
                    // also add all the constructor's statements
                    if (ctor.getBlock() != null) {
                        plan.before.addAll(ctor.getBlock().getStatements());
                    }
                } else {
                    statements.add(stmt);
                    // make sure all existing constructors get this statement too
                    for (ConstructorPlan constructorPlan : constructorPlans.values()) constructorPlan.after.add(stmt);
                }
            }
            // try every constructor plan and see if it's used in two methods
            for (ConstructorPlan constructorPlan : constructorPlans.values()) {
                visitConstructorPlan(constructorPlan);
                // are we done?
                if (declaration.isCaptured())
                    break;
            }
        }
        // do regular capturing after that (for members), if required
        if (!declaration.isCaptured()) {
            boolean cs = enterCapturingScope();
            super.visit(that);
            exitCapturingScope(cs);
        }
    }
}
Also used : HashMap(java.util.HashMap) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) Statement(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement) SpecifierStatement(org.eclipse.ceylon.compiler.typechecker.tree.Tree.SpecifierStatement) ArrayList(java.util.ArrayList) Statement(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Aggregations

FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)65 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)28 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)27 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)26 Type (org.eclipse.ceylon.model.typechecker.model.Type)25 Value (org.eclipse.ceylon.model.typechecker.model.Value)24 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)22 Function (org.eclipse.ceylon.model.typechecker.model.Function)22 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)21 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)19 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)13 ArrayList (java.util.ArrayList)12 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)11 TypedReference (org.eclipse.ceylon.model.typechecker.model.TypedReference)10 AnalyzerUtil.getTupleType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType)9 AnalyzerUtil.spreadType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType)9 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)9 ModelUtil.genericFunctionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.genericFunctionType)9 ModelUtil.intersectionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType)9 ModelUtil.unionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.unionType)9