1 /*
  2  * Copyright (c) 2024, 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 package jdk.incubator.code.dialect.java;
 27 
 28 import jdk.incubator.code.dialect.java.impl.JavaTypeUtils;
 29 import jdk.incubator.code.extern.ExternalizedTypeElement;
 30 
 31 import java.lang.constant.ClassDesc;
 32 import java.lang.invoke.MethodHandles.Lookup;
 33 import java.lang.reflect.Type;
 34 import java.util.Map;
 35 import java.util.Optional;
 36 
 37 /**
 38  * A primitive type
 39  */
 40 public final class PrimitiveType implements JavaType {
 41     // Fully qualified name
 42     private final ClassDesc type;
 43 
 44     PrimitiveType(ClassDesc type) {
 45         this.type = type;
 46     }
 47 
 48     @Override
 49     public Type resolve(Lookup lookup) throws ReflectiveOperationException {
 50         return type.resolveConstantDesc(lookup);
 51     }
 52 
 53     @Override
 54     public ExternalizedTypeElement externalize() {
 55         return JavaTypeUtils.primitiveType(type.displayName());
 56     }
 57 
 58     @Override
 59     public String toString() {
 60         return JavaTypeUtils.toExternalTypeString(externalize());
 61     }
 62 
 63     @Override
 64     public boolean equals(Object o) {
 65         if (this == o) return true;
 66         if (o == null || getClass() != o.getClass()) return false;
 67 
 68         PrimitiveType typeDesc = (PrimitiveType) o;
 69 
 70         return type.equals(typeDesc.type);
 71     }
 72 
 73     @Override
 74     public int hashCode() {
 75         return type.hashCode();
 76     }
 77 
 78     @Override
 79     public JavaType erasure() {
 80         return this;
 81     }
 82 
 83     @Override
 84     public JavaType toBasicType() {
 85         return switch (type.descriptorString().charAt(0)) {
 86             case 'V' -> JavaType.VOID;
 87             case 'J' -> JavaType.LONG;
 88             case 'F' -> JavaType.FLOAT;
 89             case 'D' -> JavaType.DOUBLE;
 90             default -> JavaType.INT;
 91         };
 92     }
 93 
 94     /**
 95      * {@return the boxed class type associated with this primitive type (if any)}
 96      */
 97     public Optional<ClassType> box() {
 98         class LazyHolder {
 99             static final Map<PrimitiveType, ClassType> primitiveToWrapper = Map.of(
100                     BYTE, J_L_BYTE,
101                     SHORT, J_L_SHORT,
102                     INT, J_L_INTEGER,
103                     LONG, J_L_LONG,
104                     FLOAT, J_L_FLOAT,
105                     DOUBLE, J_L_DOUBLE,
106                     CHAR, J_L_CHARACTER,
107                     BOOLEAN, J_L_BOOLEAN
108             );
109         }
110         return Optional.ofNullable(LazyHolder.primitiveToWrapper.get(this));
111     };
112 
113     @Override
114     public ClassDesc toNominalDescriptor() {
115         return type;
116     }
117 
118     /**
119      * {@return {@code true} if this type is {@link JavaType#VOID}}
120      */
121     public boolean isVoid() {
122         return toBasicType() == JavaType.VOID;
123     }
124 }