com.google.devtools.build.lib.syntax.FunctionDefStatement.java Source code

Java tutorial

Introduction

Here is the source code for com.google.devtools.build.lib.syntax.FunctionDefStatement.java

Source

// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.syntax;

import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;

/**
 * Syntax node for a function definition.
 */
public class FunctionDefStatement extends Statement {

    private final Identifier ident;
    private final FunctionSignature.WithValues<Expression, Expression> signature;
    private final ImmutableList<Statement> statements;
    private final ImmutableList<Parameter<Expression, Expression>> parameters;

    public FunctionDefStatement(Identifier ident, Iterable<Parameter<Expression, Expression>> parameters,
            FunctionSignature.WithValues<Expression, Expression> signature, Iterable<Statement> statements) {
        this.ident = ident;
        this.signature = signature;
        this.statements = ImmutableList.copyOf(statements);
        this.parameters = ImmutableList.copyOf(parameters);
    }

    @Override
    void doExec(Environment env) throws EvalException, InterruptedException {
        List<Expression> defaultExpressions = signature.getDefaultValues();
        ArrayList<Object> defaultValues = null;
        ArrayList<SkylarkType> types = null;

        if (defaultExpressions != null) {
            defaultValues = new ArrayList<>(defaultExpressions.size());
            for (Expression expr : defaultExpressions) {
                defaultValues.add(expr.eval(env));
            }
        }
        env.update(ident.getName(),
                new UserDefinedFunction(ident, FunctionSignature.WithValues.<Object, SkylarkType>create(
                        signature.getSignature(), defaultValues, types), statements, env.getGlobals()));
    }

    @Override
    public String toString() {
        return "def " + ident + "(" + signature + "):\n";
    }

    public Identifier getIdent() {
        return ident;
    }

    public ImmutableList<Statement> getStatements() {
        return statements;
    }

    public ImmutableList<Parameter<Expression, Expression>> getParameters() {
        return parameters;
    }

    public FunctionSignature.WithValues<Expression, Expression> getSignature() {
        return signature;
    }

    @Override
    public void accept(SyntaxTreeVisitor visitor) {
        visitor.visit(this);
    }

    @Override
    void validate(final ValidationEnvironment env) throws EvalException {
        ValidationEnvironment localEnv = new ValidationEnvironment(env);
        FunctionSignature sig = signature.getSignature();
        FunctionSignature.Shape shape = sig.getShape();
        ImmutableList<String> names = sig.getNames();
        List<Expression> defaultExpressions = signature.getDefaultValues();

        int positionals = shape.getPositionals();
        int mandatoryPositionals = shape.getMandatoryPositionals();
        int namedOnly = shape.getNamedOnly();
        int mandatoryNamedOnly = shape.getMandatoryNamedOnly();
        boolean starArg = shape.hasStarArg();
        boolean kwArg = shape.hasKwArg();
        int named = positionals + namedOnly;
        int args = named + (starArg ? 1 : 0) + (kwArg ? 1 : 0);
        int startOptionals = mandatoryPositionals;
        int endOptionals = named - mandatoryNamedOnly;

        int j = 0; // index for the defaultExpressions
        for (int i = 0; i < args; i++) {
            String name = names.get(i);
            if (startOptionals <= i && i < endOptionals) {
                defaultExpressions.get(j++).validate(env);
            }
            localEnv.declare(name, getLocation());
        }
        for (Statement stmts : statements) {
            stmts.validate(localEnv);
        }
    }
}