blob: 70c4c95943bf7f003b76957ba548011e1b50656e [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.syntax;
15
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010016import com.google.common.collect.ImmutableList;
Francois-Rene Rideau5dcdbf92015-02-19 18:36:17 +000017import java.util.ArrayList;
Francois-Rene Rideau5dcdbf92015-02-19 18:36:17 +000018import java.util.List;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010019
20/**
21 * Syntax node for a function definition.
22 */
23public class FunctionDefStatement extends Statement {
24
Florian Weikert6f864c32015-07-23 11:26:39 +000025 private final Identifier ident;
Laurent Le Brun4baefdc2015-09-04 11:27:46 +000026 private final FunctionSignature.WithValues<Expression, Expression> signature;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010027 private final ImmutableList<Statement> statements;
Laurent Le Brun4baefdc2015-09-04 11:27:46 +000028 private final ImmutableList<Parameter<Expression, Expression>> parameters;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010029
Florian Weikert6f864c32015-07-23 11:26:39 +000030 public FunctionDefStatement(Identifier ident,
Laurent Le Brun4baefdc2015-09-04 11:27:46 +000031 Iterable<Parameter<Expression, Expression>> parameters,
32 FunctionSignature.WithValues<Expression, Expression> signature,
33 Iterable<Statement> statements) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010034 this.ident = ident;
Laurent Le Brun4baefdc2015-09-04 11:27:46 +000035 this.signature = signature;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010036 this.statements = ImmutableList.copyOf(statements);
Laurent Le Brun4baefdc2015-09-04 11:27:46 +000037 this.parameters = ImmutableList.copyOf(parameters);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010038 }
39
40 @Override
Florian Weikert90a15962015-09-11 13:43:10 +000041 void doExec(Environment env) throws EvalException, InterruptedException {
Laurent Le Brun4baefdc2015-09-04 11:27:46 +000042 List<Expression> defaultExpressions = signature.getDefaultValues();
Francois-Rene Rideau5dcdbf92015-02-19 18:36:17 +000043 ArrayList<Object> defaultValues = null;
44 ArrayList<SkylarkType> types = null;
45
46 if (defaultExpressions != null) {
Ulf Adams07dba942015-03-05 14:47:37 +000047 defaultValues = new ArrayList<>(defaultExpressions.size());
Francois-Rene Rideau5dcdbf92015-02-19 18:36:17 +000048 for (Expression expr : defaultExpressions) {
49 defaultValues.add(expr.eval(env));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010050 }
51 }
Francois-Rene Rideau89312fb2015-09-10 18:53:03 +000052 env.update(
53 ident.getName(),
54 new UserDefinedFunction(
55 ident,
56 FunctionSignature.WithValues.<Object, SkylarkType>create(
57 signature.getSignature(), defaultValues, types),
58 statements,
59 env.getGlobals()));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010060 }
61
62 @Override
63 public String toString() {
Laurent Le Brun4baefdc2015-09-04 11:27:46 +000064 return "def " + ident + "(" + signature + "):\n";
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010065 }
66
Florian Weikert6f864c32015-07-23 11:26:39 +000067 public Identifier getIdent() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010068 return ident;
69 }
70
71 public ImmutableList<Statement> getStatements() {
72 return statements;
73 }
74
Laurent Le Brun4baefdc2015-09-04 11:27:46 +000075 public ImmutableList<Parameter<Expression, Expression>> getParameters() {
76 return parameters;
77 }
78
79 public FunctionSignature.WithValues<Expression, Expression> getSignature() {
80 return signature;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010081 }
82
83 @Override
84 public void accept(SyntaxTreeVisitor visitor) {
85 visitor.visit(this);
86 }
87
88 @Override
Francois-Rene Rideau5dcdbf92015-02-19 18:36:17 +000089 void validate(final ValidationEnvironment env) throws EvalException {
Laurent Le Brun8d966f72015-04-15 18:47:34 +000090 ValidationEnvironment localEnv = new ValidationEnvironment(env);
Laurent Le Brun4baefdc2015-09-04 11:27:46 +000091 FunctionSignature sig = signature.getSignature();
Francois-Rene Rideau5dcdbf92015-02-19 18:36:17 +000092 FunctionSignature.Shape shape = sig.getShape();
93 ImmutableList<String> names = sig.getNames();
Laurent Le Brun4baefdc2015-09-04 11:27:46 +000094 List<Expression> defaultExpressions = signature.getDefaultValues();
Francois-Rene Rideau5dcdbf92015-02-19 18:36:17 +000095
96 int positionals = shape.getPositionals();
97 int mandatoryPositionals = shape.getMandatoryPositionals();
98 int namedOnly = shape.getNamedOnly();
99 int mandatoryNamedOnly = shape.getMandatoryNamedOnly();
100 boolean starArg = shape.hasStarArg();
Francois-Rene Rideau5dcdbf92015-02-19 18:36:17 +0000101 boolean kwArg = shape.hasKwArg();
102 int named = positionals + namedOnly;
103 int args = named + (starArg ? 1 : 0) + (kwArg ? 1 : 0);
104 int startOptionals = mandatoryPositionals;
105 int endOptionals = named - mandatoryNamedOnly;
Francois-Rene Rideau5dcdbf92015-02-19 18:36:17 +0000106
107 int j = 0; // index for the defaultExpressions
108 for (int i = 0; i < args; i++) {
109 String name = names.get(i);
Laurent Le Brun2e78d612015-04-15 09:06:46 +0000110 if (startOptionals <= i && i < endOptionals) {
111 defaultExpressions.get(j++).validate(env);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100112 }
Laurent Le Brun964d8d52015-04-13 12:15:04 +0000113 localEnv.declare(name, getLocation());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100114 }
115 for (Statement stmts : statements) {
116 stmts.validate(localEnv);
117 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100118 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100119}