implement (most) intrinsics without reference to standard library
This commit is contained in:
@@ -77,6 +77,7 @@ public class IntrinsicMethods {
|
|||||||
private final Map<CallableMemberDescriptor, IntrinsicMethod> myMethods = new HashMap<CallableMemberDescriptor, IntrinsicMethod>();
|
private final Map<CallableMemberDescriptor, IntrinsicMethod> myMethods = new HashMap<CallableMemberDescriptor, IntrinsicMethod>();
|
||||||
private final Map<String, IntrinsicMethod> namedMethods = new HashMap<String, IntrinsicMethod>();
|
private final Map<String, IntrinsicMethod> namedMethods = new HashMap<String, IntrinsicMethod>();
|
||||||
private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator();
|
private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator();
|
||||||
|
private final IntrinsicsMap intrinsicsMap = new IntrinsicsMap();
|
||||||
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -97,21 +98,21 @@ public class IntrinsicMethods {
|
|||||||
|
|
||||||
ImmutableList<Name> primitiveCastMethods = OperatorConventions.NUMBER_CONVERSIONS.asList();
|
ImmutableList<Name> primitiveCastMethods = OperatorConventions.NUMBER_CONVERSIONS.asList();
|
||||||
for (Name method : primitiveCastMethods) {
|
for (Name method : primitiveCastMethods) {
|
||||||
declareIntrinsicFunction(Name.identifier("Number"), method, 0, NUMBER_CAST, true);
|
declareIntrinsicFunction(Name.identifier("Number"), method, 0, NUMBER_CAST);
|
||||||
for (Name type : PRIMITIVE_NUMBER_TYPES) {
|
for (Name type : PRIMITIVE_NUMBER_TYPES) {
|
||||||
declareIntrinsicFunction(type, method, 0, NUMBER_CAST, true);
|
declareIntrinsicFunction(type, method, 0, NUMBER_CAST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Name type : PRIMITIVE_NUMBER_TYPES) {
|
for (Name type : PRIMITIVE_NUMBER_TYPES) {
|
||||||
declareIntrinsicFunction(type, Name.identifier("plus"), 0, UNARY_PLUS, false);
|
declareIntrinsicFunction(type, Name.identifier("plus"), 0, UNARY_PLUS);
|
||||||
declareIntrinsicFunction(type, Name.identifier("minus"), 0, UNARY_MINUS, false);
|
declareIntrinsicFunction(type, Name.identifier("minus"), 0, UNARY_MINUS);
|
||||||
declareIntrinsicFunction(type, Name.identifier("inv"), 0, INV, false);
|
declareIntrinsicFunction(type, Name.identifier("inv"), 0, INV);
|
||||||
declareIntrinsicFunction(type, Name.identifier("rangeTo"), 1, UP_TO, false);
|
declareIntrinsicFunction(type, Name.identifier("rangeTo"), 1, UP_TO);
|
||||||
declareIntrinsicFunction(type, Name.identifier("upto"), 1, UP_TO, false);
|
declareIntrinsicFunction(type, Name.identifier("upto"), 1, UP_TO);
|
||||||
declareIntrinsicFunction(type, Name.identifier("downto"), 1, DOWN_TO, false);
|
declareIntrinsicFunction(type, Name.identifier("downto"), 1, DOWN_TO);
|
||||||
declareIntrinsicFunction(type, Name.identifier("inc"), 0, INC, false);
|
declareIntrinsicFunction(type, Name.identifier("inc"), 0, INC);
|
||||||
declareIntrinsicFunction(type, Name.identifier("dec"), 0, DEC, false);
|
declareIntrinsicFunction(type, Name.identifier("dec"), 0, DEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
declareBinaryOp(Name.identifier("plus"), Opcodes.IADD);
|
declareBinaryOp(Name.identifier("plus"), Opcodes.IADD);
|
||||||
@@ -126,32 +127,33 @@ public class IntrinsicMethods {
|
|||||||
declareBinaryOp(Name.identifier("or"), Opcodes.IOR);
|
declareBinaryOp(Name.identifier("or"), Opcodes.IOR);
|
||||||
declareBinaryOp(Name.identifier("xor"), Opcodes.IXOR);
|
declareBinaryOp(Name.identifier("xor"), Opcodes.IXOR);
|
||||||
|
|
||||||
declareIntrinsicFunction(Name.identifier("Boolean"), Name.identifier("not"), 0, new Not(), true);
|
declareIntrinsicFunction(Name.identifier("Boolean"), Name.identifier("not"), 0, new Not());
|
||||||
|
|
||||||
declareIntrinsicFunction(Name.identifier("String"), Name.identifier("plus"), 1, new Concat(), true);
|
declareIntrinsicFunction(Name.identifier("String"), Name.identifier("plus"), 1, new Concat());
|
||||||
declareIntrinsicFunction(Name.identifier("CharSequence"), Name.identifier("get"), 1, new StringGetChar(), true);
|
declareIntrinsicFunction(Name.identifier("CharSequence"), Name.identifier("get"), 1, new StringGetChar());
|
||||||
declareIntrinsicFunction(Name.identifier("String"), Name.identifier("get"), 1, new StringGetChar(), true);
|
declareIntrinsicFunction(Name.identifier("String"), Name.identifier("get"), 1, new StringGetChar());
|
||||||
|
|
||||||
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("toString")), 0, new ToString());
|
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("toString"), 0, new ToString());
|
||||||
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("equals")), 1, EQUALS);
|
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("equals"), 1, EQUALS);
|
||||||
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("identityEquals")), 1, IDENTITY_EQUALS);
|
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("identityEquals"), 1, IDENTITY_EQUALS);
|
||||||
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("plus")), 1, STRING_PLUS);
|
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("plus"), 1, STRING_PLUS);
|
||||||
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("arrayOfNulls")), 1, new NewArray());
|
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("arrayOfNulls"), 1, new NewArray());
|
||||||
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("sure")), 0, new Sure());
|
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("sure"), 0, new Sure());
|
||||||
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("synchronized")), 2, new StupidSync());
|
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("synchronized"), 2, new StupidSync());
|
||||||
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("iterator")), 0, new IteratorIterator());
|
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("iterator"), 0, new IteratorIterator());
|
||||||
|
|
||||||
declareIntrinsicFunction(Name.identifier("ByteIterator"), Name.identifier("next"), 0, ITERATOR_NEXT, false);
|
|
||||||
declareIntrinsicFunction(Name.identifier("ShortIterator"), Name.identifier("next"), 0, ITERATOR_NEXT, false);
|
declareIntrinsicFunction(Name.identifier("ByteIterator"), Name.identifier("next"), 0, ITERATOR_NEXT);
|
||||||
declareIntrinsicFunction(Name.identifier("IntIterator"), Name.identifier("next"), 0, ITERATOR_NEXT, false);
|
declareIntrinsicFunction(Name.identifier("ShortIterator"), Name.identifier("next"), 0, ITERATOR_NEXT);
|
||||||
declareIntrinsicFunction(Name.identifier("LongIterator"), Name.identifier("next"), 0, ITERATOR_NEXT, false);
|
declareIntrinsicFunction(Name.identifier("IntIterator"), Name.identifier("next"), 0, ITERATOR_NEXT);
|
||||||
declareIntrinsicFunction(Name.identifier("CharIterator"), Name.identifier("next"), 0, ITERATOR_NEXT, false);
|
declareIntrinsicFunction(Name.identifier("LongIterator"), Name.identifier("next"), 0, ITERATOR_NEXT);
|
||||||
declareIntrinsicFunction(Name.identifier("BooleanIterator"), Name.identifier("next"), 0, ITERATOR_NEXT, false);
|
declareIntrinsicFunction(Name.identifier("CharIterator"), Name.identifier("next"), 0, ITERATOR_NEXT);
|
||||||
declareIntrinsicFunction(Name.identifier("FloatIterator"), Name.identifier("next"), 0, ITERATOR_NEXT, false);
|
declareIntrinsicFunction(Name.identifier("BooleanIterator"), Name.identifier("next"), 0, ITERATOR_NEXT);
|
||||||
declareIntrinsicFunction(Name.identifier("DoubleIterator"), Name.identifier("next"), 0, ITERATOR_NEXT, false);
|
declareIntrinsicFunction(Name.identifier("FloatIterator"), Name.identifier("next"), 0, ITERATOR_NEXT);
|
||||||
|
declareIntrinsicFunction(Name.identifier("DoubleIterator"), Name.identifier("next"), 0, ITERATOR_NEXT);
|
||||||
|
|
||||||
for (Name type : PRIMITIVE_TYPES) {
|
for (Name type : PRIMITIVE_TYPES) {
|
||||||
declareIntrinsicFunction(type, Name.identifier("compareTo"), 1, new CompareTo(), false);
|
declareIntrinsicFunction(type, Name.identifier("compareTo"), 1, new CompareTo());
|
||||||
}
|
}
|
||||||
// declareIntrinsicFunction("Any", "equals", 1, new Equals());
|
// declareIntrinsicFunction("Any", "equals", 1, new Equals());
|
||||||
//
|
//
|
||||||
@@ -170,22 +172,22 @@ public class IntrinsicMethods {
|
|||||||
|
|
||||||
declareIntrinsicProperty(Name.identifier("Array"), Name.identifier("size"), ARRAY_SIZE);
|
declareIntrinsicProperty(Name.identifier("Array"), Name.identifier("size"), ARRAY_SIZE);
|
||||||
declareIntrinsicProperty(Name.identifier("Array"), Name.identifier("indices"), ARRAY_INDICES);
|
declareIntrinsicProperty(Name.identifier("Array"), Name.identifier("indices"), ARRAY_INDICES);
|
||||||
declareIntrinsicFunction(Name.identifier("Array"), Name.identifier("set"), 2, ARRAY_SET, true);
|
declareIntrinsicFunction(Name.identifier("Array"), Name.identifier("set"), 2, ARRAY_SET);
|
||||||
declareIntrinsicFunction(Name.identifier("Array"), Name.identifier("get"), 1, ARRAY_GET, true);
|
declareIntrinsicFunction(Name.identifier("Array"), Name.identifier("get"), 1, ARRAY_GET);
|
||||||
declareIterator(myStdLib.getArray());
|
declareIterator(Name.identifier("Array"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void declareArrayMethodsForPrimitive(JvmPrimitiveType jvmPrimitiveType) {
|
private void declareArrayMethodsForPrimitive(JvmPrimitiveType jvmPrimitiveType) {
|
||||||
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
|
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
|
||||||
declareIntrinsicProperty(primitiveType.getArrayTypeName(), Name.identifier("size"), ARRAY_SIZE);
|
declareIntrinsicProperty(primitiveType.getArrayTypeName(), Name.identifier("size"), ARRAY_SIZE);
|
||||||
declareIntrinsicProperty(primitiveType.getArrayTypeName(), Name.identifier("indices"), ARRAY_INDICES);
|
declareIntrinsicProperty(primitiveType.getArrayTypeName(), Name.identifier("indices"), ARRAY_INDICES);
|
||||||
declareIntrinsicFunction(primitiveType.getArrayTypeName(), Name.identifier("set"), 2, ARRAY_SET, true);
|
declareIntrinsicFunction(primitiveType.getArrayTypeName(), Name.identifier("set"), 2, ARRAY_SET);
|
||||||
declareIntrinsicFunction(primitiveType.getArrayTypeName(), Name.identifier("get"), 1, ARRAY_GET, true);
|
declareIntrinsicFunction(primitiveType.getArrayTypeName(), Name.identifier("get"), 1, ARRAY_GET);
|
||||||
declareIterator(myStdLib.getPrimitiveArrayClassDescriptor(primitiveType));
|
declareIterator(primitiveType.getArrayTypeName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void declareIterator(ClassDescriptor classDescriptor) {
|
private void declareIterator(@NotNull Name arrayClassName) {
|
||||||
declareOverload(classDescriptor.getDefaultType().getMemberScope().getFunctions(Name.identifier("iterator")), 0, ARRAY_ITERATOR);
|
declareIntrinsicFunction(arrayClassName, Name.identifier("iterator"), 0, ARRAY_ITERATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void declareIntrinsicStringMethods() {
|
private void declareIntrinsicStringMethods() {
|
||||||
@@ -217,26 +219,16 @@ public class IntrinsicMethods {
|
|||||||
private void declareBinaryOp(Name methodName, int opcode) {
|
private void declareBinaryOp(Name methodName, int opcode) {
|
||||||
BinaryOp op = new BinaryOp(opcode);
|
BinaryOp op = new BinaryOp(opcode);
|
||||||
for (Name type : PRIMITIVE_TYPES) {
|
for (Name type : PRIMITIVE_TYPES) {
|
||||||
declareIntrinsicFunction(type, methodName, 1, op, false);
|
declareIntrinsicFunction(type, methodName, 1, op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void declareIntrinsicProperty(Name className, Name methodName, IntrinsicMethod implementation) {
|
private void declareIntrinsicProperty(Name className, Name methodName, IntrinsicMethod implementation) {
|
||||||
final JetScope numberScope = getClassMemberScope(className);
|
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME.child(className), methodName, -1, implementation);
|
||||||
Collection<VariableDescriptor> properties = numberScope.getProperties(methodName);
|
|
||||||
assert properties.size() == 1;
|
|
||||||
final PropertyDescriptor property = (PropertyDescriptor) properties.iterator().next();
|
|
||||||
myMethods.put(property.getOriginal(), implementation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void declareIntrinsicFunction(Name className, Name functionName, int arity, IntrinsicMethod implementation, boolean original) {
|
private void declareIntrinsicFunction(Name className, Name functionName, int arity, IntrinsicMethod implementation) {
|
||||||
JetScope memberScope = getClassMemberScope(className);
|
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME.child(className), functionName, arity, implementation);
|
||||||
final Collection<FunctionDescriptor> group = memberScope.getFunctions(functionName);
|
|
||||||
for (FunctionDescriptor descriptor : group) {
|
|
||||||
if (className.equals(descriptor.getContainingDeclaration().getName()) && descriptor.getValueParameters().size() == arity) {
|
|
||||||
myMethods.put(original ? descriptor.getOriginal() : descriptor, implementation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void declareOverload(Collection<FunctionDescriptor> group, int arity, IntrinsicMethod implementation) {
|
private void declareOverload(Collection<FunctionDescriptor> group, int arity, IntrinsicMethod implementation) {
|
||||||
@@ -274,15 +266,22 @@ public class IntrinsicMethods {
|
|||||||
@Nullable
|
@Nullable
|
||||||
public IntrinsicMethod getIntrinsic(@NotNull CallableMemberDescriptor descriptor) {
|
public IntrinsicMethod getIntrinsic(@NotNull CallableMemberDescriptor descriptor) {
|
||||||
IntrinsicMethod intrinsicMethod = myMethods.get(descriptor.getOriginal());
|
IntrinsicMethod intrinsicMethod = myMethods.get(descriptor.getOriginal());
|
||||||
if (intrinsicMethod == null) {
|
if (intrinsicMethod != null) {
|
||||||
List<AnnotationDescriptor> annotations = descriptor.getAnnotations();
|
return intrinsicMethod;
|
||||||
if (annotations != null) {
|
}
|
||||||
for (AnnotationDescriptor annotation : annotations) {
|
|
||||||
if("Intrinsic".equals(annotation.getType().getConstructor().getDeclarationDescriptor().getName().getName())) {
|
intrinsicMethod = intrinsicsMap.getIntrinsic(descriptor);
|
||||||
String value = (String) annotation.getValueArguments().get(0).getValue();
|
if (intrinsicMethod != null) {
|
||||||
intrinsicMethod = namedMethods.get(value);
|
return intrinsicMethod;
|
||||||
if (intrinsicMethod != null) { break; }
|
}
|
||||||
}
|
|
||||||
|
List<AnnotationDescriptor> annotations = descriptor.getAnnotations();
|
||||||
|
if (annotations != null) {
|
||||||
|
for (AnnotationDescriptor annotation : annotations) {
|
||||||
|
if("Intrinsic".equals(annotation.getType().getConstructor().getDeclarationDescriptor().getName().getName())) {
|
||||||
|
String value = (String) annotation.getValueArguments().get(0).getValue();
|
||||||
|
intrinsicMethod = namedMethods.get(value);
|
||||||
|
if (intrinsicMethod != null) { break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2012 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* 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 org.jetbrains.jet.codegen.intrinsics;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.sun.javaws.jnl.PropertyDesc;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Stepan Koltsov
|
||||||
|
*/
|
||||||
|
class IntrinsicsMap {
|
||||||
|
|
||||||
|
|
||||||
|
private static final class Key {
|
||||||
|
@NotNull
|
||||||
|
private final FqNameUnsafe owner;
|
||||||
|
@NotNull
|
||||||
|
private final Name name;
|
||||||
|
private final int valueParameterCount;
|
||||||
|
|
||||||
|
private Key(@NotNull FqNameUnsafe owner, @NotNull Name name, int valueParameterCount) {
|
||||||
|
this.owner = owner;
|
||||||
|
this.name = name;
|
||||||
|
this.valueParameterCount = valueParameterCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
Key key = (Key) o;
|
||||||
|
|
||||||
|
if (valueParameterCount != key.valueParameterCount) return false;
|
||||||
|
if (!name.equals(key.name)) return false;
|
||||||
|
if (!owner.equals(key.owner)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = owner.hashCode();
|
||||||
|
result = 31 * result + name.hashCode();
|
||||||
|
result = 31 * result + valueParameterCount;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int valueParameterCountForKey(@NotNull CallableMemberDescriptor member) {
|
||||||
|
if (member instanceof PropertyDescriptor) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return member.getValueParameters().size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Key, IntrinsicMethod> intrinsicsMap = Maps.newHashMap();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param valueParameterCount -1 for property
|
||||||
|
*/
|
||||||
|
public void registerIntrinsic(@NotNull FqName owner, @NotNull Name name, int valueParameterCount, @NotNull IntrinsicMethod impl) {
|
||||||
|
intrinsicsMap.put(new Key(owner.toUnsafe(), name, valueParameterCount), impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public IntrinsicMethod getIntrinsic(@NotNull CallableMemberDescriptor descriptor) {
|
||||||
|
Key key = new Key(
|
||||||
|
DescriptorUtils.getFQName(descriptor.getContainingDeclaration()),
|
||||||
|
descriptor.getName(),
|
||||||
|
valueParameterCountForKey(descriptor));
|
||||||
|
return intrinsicsMap.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user