implement (most) intrinsics without reference to standard library

This commit is contained in:
Stepan Koltsov
2012-06-17 03:53:11 +04:00
parent 0c73115911
commit f73f5b5074
2 changed files with 164 additions and 62 deletions
@@ -77,6 +77,7 @@ public class IntrinsicMethods {
private final Map<CallableMemberDescriptor, IntrinsicMethod> myMethods = new HashMap<CallableMemberDescriptor, IntrinsicMethod>();
private final Map<String, IntrinsicMethod> namedMethods = new HashMap<String, IntrinsicMethod>();
private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator();
private final IntrinsicsMap intrinsicsMap = new IntrinsicsMap();
@Inject
@@ -97,21 +98,21 @@ public class IntrinsicMethods {
ImmutableList<Name> primitiveCastMethods = OperatorConventions.NUMBER_CONVERSIONS.asList();
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) {
declareIntrinsicFunction(type, method, 0, NUMBER_CAST, true);
declareIntrinsicFunction(type, method, 0, NUMBER_CAST);
}
}
for (Name type : PRIMITIVE_NUMBER_TYPES) {
declareIntrinsicFunction(type, Name.identifier("plus"), 0, UNARY_PLUS, false);
declareIntrinsicFunction(type, Name.identifier("minus"), 0, UNARY_MINUS, false);
declareIntrinsicFunction(type, Name.identifier("inv"), 0, INV, false);
declareIntrinsicFunction(type, Name.identifier("rangeTo"), 1, UP_TO, false);
declareIntrinsicFunction(type, Name.identifier("upto"), 1, UP_TO, false);
declareIntrinsicFunction(type, Name.identifier("downto"), 1, DOWN_TO, false);
declareIntrinsicFunction(type, Name.identifier("inc"), 0, INC, false);
declareIntrinsicFunction(type, Name.identifier("dec"), 0, DEC, false);
declareIntrinsicFunction(type, Name.identifier("plus"), 0, UNARY_PLUS);
declareIntrinsicFunction(type, Name.identifier("minus"), 0, UNARY_MINUS);
declareIntrinsicFunction(type, Name.identifier("inv"), 0, INV);
declareIntrinsicFunction(type, Name.identifier("rangeTo"), 1, UP_TO);
declareIntrinsicFunction(type, Name.identifier("upto"), 1, UP_TO);
declareIntrinsicFunction(type, Name.identifier("downto"), 1, DOWN_TO);
declareIntrinsicFunction(type, Name.identifier("inc"), 0, INC);
declareIntrinsicFunction(type, Name.identifier("dec"), 0, DEC);
}
declareBinaryOp(Name.identifier("plus"), Opcodes.IADD);
@@ -126,32 +127,33 @@ public class IntrinsicMethods {
declareBinaryOp(Name.identifier("or"), Opcodes.IOR);
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("CharSequence"), Name.identifier("get"), 1, new StringGetChar(), true);
declareIntrinsicFunction(Name.identifier("String"), Name.identifier("get"), 1, new StringGetChar(), true);
declareIntrinsicFunction(Name.identifier("String"), Name.identifier("plus"), 1, new Concat());
declareIntrinsicFunction(Name.identifier("CharSequence"), Name.identifier("get"), 1, new StringGetChar());
declareIntrinsicFunction(Name.identifier("String"), Name.identifier("get"), 1, new StringGetChar());
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("toString")), 0, new ToString());
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("equals")), 1, EQUALS);
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("identityEquals")), 1, IDENTITY_EQUALS);
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("plus")), 1, STRING_PLUS);
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("arrayOfNulls")), 1, new NewArray());
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("sure")), 0, new Sure());
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("synchronized")), 2, new StupidSync());
declareOverload(myStdLib.getLibraryScope().getFunctions(Name.identifier("iterator")), 0, new IteratorIterator());
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("toString"), 0, new ToString());
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("equals"), 1, EQUALS);
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("identityEquals"), 1, IDENTITY_EQUALS);
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("plus"), 1, STRING_PLUS);
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("arrayOfNulls"), 1, new NewArray());
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("sure"), 0, new Sure());
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("synchronized"), 2, new StupidSync());
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("IntIterator"), Name.identifier("next"), 0, ITERATOR_NEXT, false);
declareIntrinsicFunction(Name.identifier("LongIterator"), Name.identifier("next"), 0, ITERATOR_NEXT, false);
declareIntrinsicFunction(Name.identifier("CharIterator"), Name.identifier("next"), 0, ITERATOR_NEXT, false);
declareIntrinsicFunction(Name.identifier("BooleanIterator"), Name.identifier("next"), 0, ITERATOR_NEXT, false);
declareIntrinsicFunction(Name.identifier("FloatIterator"), Name.identifier("next"), 0, ITERATOR_NEXT, false);
declareIntrinsicFunction(Name.identifier("DoubleIterator"), Name.identifier("next"), 0, ITERATOR_NEXT, false);
declareIntrinsicFunction(Name.identifier("ByteIterator"), Name.identifier("next"), 0, ITERATOR_NEXT);
declareIntrinsicFunction(Name.identifier("ShortIterator"), Name.identifier("next"), 0, ITERATOR_NEXT);
declareIntrinsicFunction(Name.identifier("IntIterator"), Name.identifier("next"), 0, ITERATOR_NEXT);
declareIntrinsicFunction(Name.identifier("LongIterator"), Name.identifier("next"), 0, ITERATOR_NEXT);
declareIntrinsicFunction(Name.identifier("CharIterator"), Name.identifier("next"), 0, ITERATOR_NEXT);
declareIntrinsicFunction(Name.identifier("BooleanIterator"), Name.identifier("next"), 0, ITERATOR_NEXT);
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) {
declareIntrinsicFunction(type, Name.identifier("compareTo"), 1, new CompareTo(), false);
declareIntrinsicFunction(type, Name.identifier("compareTo"), 1, new CompareTo());
}
// 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("indices"), ARRAY_INDICES);
declareIntrinsicFunction(Name.identifier("Array"), Name.identifier("set"), 2, ARRAY_SET, true);
declareIntrinsicFunction(Name.identifier("Array"), Name.identifier("get"), 1, ARRAY_GET, true);
declareIterator(myStdLib.getArray());
declareIntrinsicFunction(Name.identifier("Array"), Name.identifier("set"), 2, ARRAY_SET);
declareIntrinsicFunction(Name.identifier("Array"), Name.identifier("get"), 1, ARRAY_GET);
declareIterator(Name.identifier("Array"));
}
private void declareArrayMethodsForPrimitive(JvmPrimitiveType jvmPrimitiveType) {
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
declareIntrinsicProperty(primitiveType.getArrayTypeName(), Name.identifier("size"), ARRAY_SIZE);
declareIntrinsicProperty(primitiveType.getArrayTypeName(), Name.identifier("indices"), ARRAY_INDICES);
declareIntrinsicFunction(primitiveType.getArrayTypeName(), Name.identifier("set"), 2, ARRAY_SET, true);
declareIntrinsicFunction(primitiveType.getArrayTypeName(), Name.identifier("get"), 1, ARRAY_GET, true);
declareIterator(myStdLib.getPrimitiveArrayClassDescriptor(primitiveType));
declareIntrinsicFunction(primitiveType.getArrayTypeName(), Name.identifier("set"), 2, ARRAY_SET);
declareIntrinsicFunction(primitiveType.getArrayTypeName(), Name.identifier("get"), 1, ARRAY_GET);
declareIterator(primitiveType.getArrayTypeName());
}
private void declareIterator(ClassDescriptor classDescriptor) {
declareOverload(classDescriptor.getDefaultType().getMemberScope().getFunctions(Name.identifier("iterator")), 0, ARRAY_ITERATOR);
private void declareIterator(@NotNull Name arrayClassName) {
declareIntrinsicFunction(arrayClassName, Name.identifier("iterator"), 0, ARRAY_ITERATOR);
}
private void declareIntrinsicStringMethods() {
@@ -217,26 +219,16 @@ public class IntrinsicMethods {
private void declareBinaryOp(Name methodName, int opcode) {
BinaryOp op = new BinaryOp(opcode);
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) {
final JetScope numberScope = getClassMemberScope(className);
Collection<VariableDescriptor> properties = numberScope.getProperties(methodName);
assert properties.size() == 1;
final PropertyDescriptor property = (PropertyDescriptor) properties.iterator().next();
myMethods.put(property.getOriginal(), implementation);
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME.child(className), methodName, -1, implementation);
}
private void declareIntrinsicFunction(Name className, Name functionName, int arity, IntrinsicMethod implementation, boolean original) {
JetScope memberScope = getClassMemberScope(className);
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 declareIntrinsicFunction(Name className, Name functionName, int arity, IntrinsicMethod implementation) {
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME.child(className), functionName, arity, implementation);
}
private void declareOverload(Collection<FunctionDescriptor> group, int arity, IntrinsicMethod implementation) {
@@ -274,15 +266,22 @@ public class IntrinsicMethods {
@Nullable
public IntrinsicMethod getIntrinsic(@NotNull CallableMemberDescriptor descriptor) {
IntrinsicMethod intrinsicMethod = myMethods.get(descriptor.getOriginal());
if (intrinsicMethod == null) {
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; }
}
if (intrinsicMethod != null) {
return intrinsicMethod;
}
intrinsicMethod = intrinsicsMap.getIntrinsic(descriptor);
if (intrinsicMethod != null) {
return intrinsicMethod;
}
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);
}
}