1 /*
  2  *  Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
  3  *  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  *  This code is free software; you can redistribute it and/or modify it
  6  *  under the terms of the GNU General Public License version 2 only, as
  7  *  published by the Free Software Foundation.  Oracle designates this
  8  *  particular file as subject to the "Classpath" exception as provided
  9  *  by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  *  This code is distributed in the hope that it will be useful, but WITHOUT
 12  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  *  version 2 for more details (a copy is included in the LICENSE file that
 15  *  accompanied this code).
 16  *
 17  *  You should have received a copy of the GNU General Public License version
 18  *  2 along with this work; if not, write to the Free Software Foundation,
 19  *  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  *   Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  *  or visit www.oracle.com if you need additional information or have any
 23  *  questions.
 24  *
 25  */
 26 
 27 package jdk.internal.jextract.impl;
 28 
 29 import java.lang.constant.Constable;
 30 import java.util.Collections;
 31 import java.util.HashMap;
 32 import java.util.List;
 33 import java.util.Map;
 34 import java.util.Objects;
 35 import java.util.Optional;
 36 import java.util.Set;
 37 import jdk.incubator.foreign.MemoryLayout;
 38 import jdk.incubator.jextract.Declaration;
 39 import jdk.incubator.jextract.Position;
 40 import jdk.incubator.jextract.Type;
 41 
 42 public abstract class DeclarationImpl implements Declaration {
 43 
 44     private final String name;
 45     private final Position pos;
 46     private final Optional<Map<String, List<Constable>>> attributes;
 47 
 48     public DeclarationImpl(String name, Position pos, Map<String, List<Constable>> attrs) {
 49         this.name = name;
 50         this.pos = pos;
 51         this.attributes = Optional.ofNullable(attrs);
 52     }
 53 
 54     public String toString() {
 55         return new PrettyPrinter().print(this);
 56     }
 57 
 58     public String name() {
 59         return name;
 60     }
 61 
 62     @Override
 63     public Position pos() {
 64         return pos;
 65     }
 66 
 67     @Override
 68     public Optional<List<Constable>> getAttribute(String name) {
 69         return attributes.map(attrs -> attrs.get(name));
 70     }
 71 
 72     @Override
 73     public Set<String> attributeNames() { return Collections.unmodifiableSet(
 74             attributes.map(Map::keySet).orElse(Collections.emptySet()));
 75     }
 76 
 77     @Override
 78     public Declaration withAttribute(String name, Constable... values) {
 79         if (values == null || values.length == 0) {
 80             return withAttributes(null);
 81         }
 82         var attrs = attributes.map(HashMap::new).orElseGet(HashMap::new);
 83         attrs.put(name, List.of(values));
 84         return withAttributes(attrs);
 85     }
 86 
 87     abstract protected Declaration withAttributes(Map<String, List<Constable>> attrs);
 88 
 89     @Override
 90     public boolean equals(Object o) {
 91         if (this == o) return true;
 92         if (!(o instanceof Declaration)) return false;
 93         Declaration decl = (Declaration) o;
 94         return name().equals(decl.name());
 95     }
 96 
 97     @Override
 98     public int hashCode() {
 99         return Objects.hash(name);
100     }
101 
102     public static final class TypedefImpl extends DeclarationImpl implements Declaration.Typedef {
103         final Type type;
104 
105         public TypedefImpl(Type type, String name, Position pos, Map<String, List<Constable>> attrs) {
106             super(name, pos, attrs);
107             this.type = Objects.requireNonNull(type);
108         }
109 
110         @Override
111         public <R, D> R accept(Visitor<R, D> visitor, D data) {
112             return visitor.visitTypedef(this, data);
113         }
114 
115         @Override
116         public Type type() {
117             return type;
118         }
119 
120         @Override
121         public Typedef withAttributes(Map<String, List<Constable>> attrs) {
122             return new TypedefImpl(type, name(), pos(), attrs);
123         }
124 
125         @Override
126         public Typedef stripAttributes() {
127             return new TypedefImpl(type, name(), pos(), null);
128         }
129 
130         @Override
131         public boolean equals(Object o) {
132             if (this == o) return true;
133             if (!(o instanceof Declaration.Typedef)) return false;
134 
135             Declaration.Typedef other = (Declaration.Typedef) o;
136             return name().equals(other.name()) &&
137                     type.equals(other.type());
138         }
139 
140         @Override
141         public int hashCode() {
142             return Objects.hash(super.hashCode(), type);
143         }
144     }
145 
146     public static final class VariableImpl extends DeclarationImpl implements Declaration.Variable {
147 
148         final Variable.Kind kind;
149         final Type type;
150         final Optional<MemoryLayout> layout;
151 
152         private VariableImpl(Type type, Optional<MemoryLayout> layout, Variable.Kind kind, String name, Position pos, Map<String, List<Constable>> attrs) {
153             super(name, pos, attrs);
154             this.kind = Objects.requireNonNull(kind);
155             this.type = Objects.requireNonNull(type);
156             this.layout = Objects.requireNonNull(layout);
157         }
158 
159         public VariableImpl(Type type, Variable.Kind kind, String name, Position pos) {
160             this(type, TypeImpl.getLayout(type), kind, name, pos, null);
161         }
162 
163         public VariableImpl(Type type, MemoryLayout layout, Variable.Kind kind, String name, Position pos) {
164             this(type, Optional.of(layout), kind, name, pos, null);
165         }
166 
167         @Override
168         public Kind kind() {
169             return kind;
170         }
171 
172         @Override
173         public <R, D> R accept(Visitor<R, D> visitor, D data) {
174             return visitor.visitVariable(this, data);
175         }
176 
177         @Override
178         public Type type() {
179             return type;
180         }
181 
182         @Override
183         public Optional<MemoryLayout> layout() {
184             return layout;
185         }
186 
187         @Override
188         public Variable withAttributes(Map<String, List<Constable>> attrs) {
189             return new VariableImpl(type, layout, kind, name(), pos(), attrs);
190         }
191 
192         @Override
193         public Variable stripAttributes() {
194             return new VariableImpl(type, layout, kind, name(), pos(), null);
195         }
196 
197         @Override
198         public boolean equals(Object o) {
199             if (this == o) return true;
200             if (!(o instanceof Declaration.Variable)) return false;
201 
202             Declaration.Variable variable = (Declaration.Variable) o;
203             if (!super.equals(o)) return false;
204             return kind == variable.kind() &&
205                     type.equals(variable.type());
206         }
207 
208         @Override
209         public int hashCode() {
210             return Objects.hash(super.hashCode(), kind, type);
211         }
212     }
213 
214     public static final class FunctionImpl extends DeclarationImpl implements Declaration.Function {
215 
216         final List<Variable> params;
217         final Type.Function type;
218 
219         public FunctionImpl(Type.Function type, List<Variable> params, String name, Position pos) {
220             this(type, params, name, pos, null);
221         }
222 
223         public FunctionImpl(Type.Function type, List<Variable> params, String name, Position pos, Map<String, List<Constable>> attrs) {
224             super(name, pos, attrs);
225             this.params = Objects.requireNonNull(params);
226             this.type = Objects.requireNonNull(type);
227         }
228 
229         @Override
230         public <R, D> R accept(Visitor<R, D> visitor, D data) {
231             return visitor.visitFunction(this, data);
232         }
233 
234         @Override
235         public List<Variable> parameters() {
236             return params;
237         }
238 
239         @Override
240         public Type.Function type() {
241             return type;
242         }
243 
244         @Override
245         public Function withAttributes(Map<String, List<Constable>> attrs) {
246             return new FunctionImpl(type, params, name(), pos(), attrs);
247         }
248 
249         @Override
250         public Function stripAttributes() {
251             return new FunctionImpl(type, params, name(), pos(), null);
252         }
253 
254         @Override
255         public boolean equals(Object o) {
256             if (this == o) return true;
257             if (!(o instanceof Declaration.Function)) return false;
258             if (!super.equals(o)) return false;
259 
260             Declaration.Function function = (Declaration.Function) o;
261             return type.equals(function.type());
262         }
263 
264         @Override
265         public int hashCode() {
266             return Objects.hash(super.hashCode(), type);
267         }
268     }
269 
270     public static class ScopedImpl extends DeclarationImpl implements Declaration.Scoped {
271 
272         private final Scoped.Kind kind;
273         private final List<Declaration> declarations;
274         private final Optional<MemoryLayout> optLayout;
275 
276         public ScopedImpl(Kind kind, MemoryLayout layout, List<Declaration> declarations, String name, Position pos) {
277             this(kind, Optional.of(layout), declarations, name, pos, null);
278         }
279 
280         public ScopedImpl(Kind kind, List<Declaration> declarations, String name, Position pos) {
281             this(kind, Optional.empty(), declarations, name, pos, null);
282         }
283 
284         ScopedImpl(Kind kind, Optional<MemoryLayout> optLayout, List<Declaration> declarations,
285                 String name, Position pos, Map<String, List<Constable>> attrs) {
286             super(name, pos, attrs);
287             this.kind = Objects.requireNonNull(kind);
288             this.declarations = Objects.requireNonNull(declarations);
289             this.optLayout = Objects.requireNonNull(optLayout);
290         }
291 
292         @Override
293         public <R, D> R accept(Visitor<R, D> visitor, D data) {
294             return visitor.visitScoped(this, data);
295         }
296 
297         @Override
298         public List<Declaration> members() {
299             return declarations;
300         }
301 
302         @Override
303         public Optional<MemoryLayout> layout() {
304             return optLayout;
305         }
306 
307         @Override
308         public Kind kind() {
309             return kind;
310         }
311 
312         @Override
313         public Scoped withAttributes(Map<String, List<Constable>> attrs) {
314             return new ScopedImpl(kind, optLayout, declarations, name(), pos(), attrs);
315         }
316 
317         @Override
318         public Scoped stripAttributes() {
319             return new ScopedImpl(kind, optLayout, declarations, name(), pos(), null);
320         }
321 
322         @Override
323         public boolean equals(Object o) {
324             if (this == o) return true;
325             if (!(o instanceof Declaration.Scoped)) return false;
326             if (!super.equals(o)) return false;
327             Declaration.Scoped scoped = (Declaration.Scoped) o;
328             return kind == scoped.kind() &&
329                     declarations.equals(scoped.members());
330         }
331 
332         @Override
333         public int hashCode() {
334             return Objects.hash(super.hashCode(), kind, declarations);
335         }
336     }
337 
338     public static final class ConstantImpl extends DeclarationImpl implements Declaration.Constant {
339 
340         final Object value;
341         final Type type;
342 
343         public ConstantImpl(Type type, Object value, String name, Position pos) {
344             this(type, value, name, pos, null);
345         }
346 
347         public ConstantImpl(Type type, Object value, String name, Position pos, Map<String, List<Constable>> attrs) {
348             super(name, pos, attrs);
349             this.value = Objects.requireNonNull(value);
350             this.type = Objects.requireNonNull(type);
351         }
352 
353         @Override
354         public <R, D> R accept(Visitor<R, D> visitor, D data) {
355             return visitor.visitConstant(this, data);
356         }
357 
358         @Override
359         public Object value() {
360             return value;
361         }
362 
363         @Override
364         public Type type() {
365             return type;
366         }
367 
368         @Override
369         public Constant withAttributes(Map<String, List<Constable>> attrs) {
370             return new ConstantImpl(type, value, name(), pos(), attrs);
371         }
372 
373         @Override
374         public Constant stripAttributes() {
375             return new ConstantImpl(type, value, name(), pos(), null);
376         }
377 
378         @Override
379         public boolean equals(Object o) {
380             if (this == o) return true;
381             if (!(o instanceof Declaration.Constant)) return false;
382             if (!super.equals(o)) return false;
383             Declaration.Constant constant = (Declaration.Constant) o;
384             return value.equals(constant.value()) &&
385                     type.equals(constant.type());
386         }
387 
388         @Override
389         public int hashCode() {
390             return Objects.hash(super.hashCode(), value, type);
391         }
392     }
393 }