intrinsics - initial
This commit is contained in:
@@ -11,6 +11,8 @@ import jet.IntRange;
|
||||
import jet.JetObject;
|
||||
import jet.Range;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod;
|
||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -83,6 +85,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
private final BindingContext bindingContext;
|
||||
private final Map<TypeParameterDescriptor, StackValue> typeParameterExpressions = new HashMap<TypeParameterDescriptor, StackValue>();
|
||||
private final ClassContext context;
|
||||
private final IntrinsicMethods intrinsics;
|
||||
|
||||
public ExpressionCodegen(MethodVisitor v,
|
||||
FrameMap myMap,
|
||||
@@ -96,6 +99,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
this.v = new InstructionAdapter(v);
|
||||
this.bindingContext = state.getBindingContext();
|
||||
this.context = context;
|
||||
this.intrinsics = state.getIntrinsics();
|
||||
}
|
||||
|
||||
public void addTypeParameter(TypeParameterDescriptor typeParameter, StackValue expression) {
|
||||
@@ -126,7 +130,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private void putTopOfStack(Type type) {
|
||||
public void putTopOfStack(Type type) {
|
||||
StackValue value = myStack.pop();
|
||||
value.put(type, v);
|
||||
}
|
||||
@@ -642,18 +646,15 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
descriptor = ((VariableAsFunctionDescriptor) descriptor).getVariableDescriptor();
|
||||
}
|
||||
|
||||
final DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||
if (descriptor instanceof VariableDescriptor) {
|
||||
if (isClass(container, "Number")) {
|
||||
Type castType = getCastType(expression.getReferencedName());
|
||||
if (castType != null) {
|
||||
final StackValue value = myStack.pop();
|
||||
value.put(castType, v);
|
||||
myStack.push(StackValue.onStack(castType));
|
||||
return;
|
||||
}
|
||||
}
|
||||
final IntrinsicMethod intrinsic = intrinsics.getIntrinsic(descriptor);
|
||||
if (intrinsic != null) {
|
||||
final Type expectedType = expressionType(expression);
|
||||
myStack.push(intrinsic.generate(this, v, expectedType, expression, Collections.<JetExpression>emptyList()));
|
||||
return;
|
||||
}
|
||||
|
||||
final DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||
|
||||
PsiElement declaration = bindingContext.getDeclarationPsiElement(descriptor);
|
||||
if (declaration instanceof PsiField) {
|
||||
PsiField psiField = (PsiField) declaration;
|
||||
@@ -690,12 +691,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
if (isClass(container, "Array") && propertyDescriptor.getName().equals("size")) {
|
||||
ensureReceiverOnStack(expression, null);
|
||||
v.arraylength();
|
||||
myStack.push(StackValue.onStack(Type.INT_TYPE));
|
||||
}
|
||||
else if (declaration instanceof JetObjectDeclarationName) {
|
||||
if (declaration instanceof JetObjectDeclarationName) {
|
||||
JetObjectDeclaration objectDeclaration = PsiTreeUtil.getParentOfType(declaration, JetObjectDeclaration.class);
|
||||
ClassDescriptor classDescriptor = bindingContext.getClassDescriptor(objectDeclaration);
|
||||
myStack.push(StackValue.field(typeMapper.jvmType(classDescriptor, OwnerKind.IMPLEMENTATION),
|
||||
@@ -779,32 +775,6 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
return StackValue.property(propertyDescriptor.getName(), owner, typeMapper.mapType(outType), isStatic, isInterface, getter, setter);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Type getCastType(String castMethodName) {
|
||||
if ("dbl".equals(castMethodName)) {
|
||||
return Type.DOUBLE_TYPE;
|
||||
}
|
||||
if ("flt".equals(castMethodName)) {
|
||||
return Type.FLOAT_TYPE;
|
||||
}
|
||||
if ("lng".equals(castMethodName)) {
|
||||
return Type.LONG_TYPE;
|
||||
}
|
||||
if ("int".equals(castMethodName)) {
|
||||
return Type.INT_TYPE;
|
||||
}
|
||||
if ("chr".equals(castMethodName)) {
|
||||
return Type.CHAR_TYPE;
|
||||
}
|
||||
if ("sht".equals(castMethodName)) {
|
||||
return Type.SHORT_TYPE;
|
||||
}
|
||||
if ("byt".equals(castMethodName)) {
|
||||
return Type.BYTE_TYPE;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCallExpression(JetCallExpression expression) {
|
||||
final JetExpression callee = expression.getCalleeExpression();
|
||||
@@ -944,7 +914,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void ensureReceiverOnStack(PsiElement expression, @Nullable ClassDescriptor calleeContainingClass) {
|
||||
public void ensureReceiverOnStack(PsiElement expression, @Nullable ClassDescriptor calleeContainingClass) {
|
||||
JetExpression receiver = getReceiverForSelector(expression);
|
||||
if (receiver != null) {
|
||||
if (!resolvesToClassOrPackage(receiver)) {
|
||||
@@ -1402,7 +1372,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
final Type asmType = expressionType(expression);
|
||||
DeclarationDescriptor cls = op.getContainingDeclaration();
|
||||
if (isNumberPrimitive(cls)) {
|
||||
if (generateUnaryOp(op, asmType, expression.getBaseExpression())) return;
|
||||
if (generateUnaryOp(op, asmType, expression)) return;
|
||||
}
|
||||
else if (isClass(cls, "Boolean") && op.getName().equals("not")) {
|
||||
generateNot(expression);
|
||||
@@ -1435,11 +1405,11 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
throw new UnsupportedOperationException("Don't know how to generate this prefix expression");
|
||||
}
|
||||
|
||||
private boolean generateUnaryOp(DeclarationDescriptor op, Type asmType, final JetExpression operand) {
|
||||
if (op.getName().equals("minus")) {
|
||||
gen(operand, asmType);
|
||||
v.neg(asmType);
|
||||
myStack.push(StackValue.onStack(asmType));
|
||||
private boolean generateUnaryOp(DeclarationDescriptor op, Type asmType, final JetUnaryExpression unaryExpression) {
|
||||
final IntrinsicMethod intrinsic = intrinsics.getIntrinsic(op);
|
||||
final JetExpression operand = unaryExpression.getBaseExpression();
|
||||
if (intrinsic != null) {
|
||||
myStack.push(intrinsic.generate(this, v, asmType, unaryExpression, Collections.singletonList(operand)));
|
||||
return true;
|
||||
}
|
||||
else if (op.getName().equals("inc") || op.getName().equals("dec")) {
|
||||
|
||||
@@ -6,6 +6,7 @@ package org.jetbrains.jet.codegen;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
|
||||
import org.jetbrains.jet.lang.ErrorHandler;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
@@ -23,11 +24,13 @@ public class GenerationState {
|
||||
private JetTypeMapper typeMapper;
|
||||
private final Stack<BindingContext> bindingContexts = new Stack<BindingContext>();
|
||||
private final JetStandardLibrary standardLibrary;
|
||||
private final IntrinsicMethods intrinsics;
|
||||
|
||||
public GenerationState(Project project, boolean text) {
|
||||
this.project = project;
|
||||
this.standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
|
||||
this.factory = new ClassFileFactory(project, text, this);
|
||||
this.intrinsics = new IntrinsicMethods(standardLibrary);
|
||||
}
|
||||
|
||||
public ClassFileFactory getFactory() {
|
||||
@@ -50,6 +53,10 @@ public class GenerationState {
|
||||
return standardLibrary;
|
||||
}
|
||||
|
||||
public IntrinsicMethods getIntrinsics() {
|
||||
return intrinsics;
|
||||
}
|
||||
|
||||
public ClassVisitor forClassInterface(ClassDescriptor aClass) {
|
||||
return factory.newVisitor(JetTypeMapper.jvmNameForInterface(aClass) + ".class");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class ArraySize implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments) {
|
||||
codegen.ensureReceiverOnStack(element, null);
|
||||
v.arraylength();
|
||||
return StackValue.onStack(Type.INT_TYPE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public interface IntrinsicMethod {
|
||||
StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.resolve.JetScope;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class IntrinsicMethods {
|
||||
private static final IntrinsicMethod UNARY_MINUS = new UnaryMinus();
|
||||
private static final IntrinsicMethod NUMBER_CAST = new NumberCast();
|
||||
private static final IntrinsicMethod ARRAY_SIZE = new ArraySize();
|
||||
|
||||
private final Map<DeclarationDescriptor, IntrinsicMethod> myMethods = new HashMap<DeclarationDescriptor, IntrinsicMethod>();
|
||||
|
||||
public IntrinsicMethods(JetStandardLibrary stdlib) {
|
||||
List<String> primitiveCastMethods = ImmutableList.of("dbl", "flt", "lng", "int", "chr", "sht", "byt");
|
||||
for (String method : primitiveCastMethods) {
|
||||
declareIntrinsicProperty(stdlib, "Number", method, NUMBER_CAST);
|
||||
}
|
||||
declareIntrinsicProperty(stdlib, "Array", "size", ARRAY_SIZE);
|
||||
|
||||
List<ClassDescriptor> primitiveNumberTypes = ImmutableList.of(
|
||||
stdlib.getBoolean(),
|
||||
stdlib.getByte(),
|
||||
stdlib.getChar(),
|
||||
stdlib.getShort(),
|
||||
stdlib.getInt(),
|
||||
stdlib.getFloat(),
|
||||
stdlib.getLong(),
|
||||
stdlib.getDouble()
|
||||
);
|
||||
|
||||
for (ClassDescriptor primitiveNumberType : primitiveNumberTypes) {
|
||||
final JetScope memberScope = primitiveNumberType.getMemberScope(Collections.<TypeProjection>emptyList());
|
||||
|
||||
final FunctionGroup minus = memberScope.getFunctionGroup("minus");
|
||||
for (FunctionDescriptor descriptor : minus.getFunctionDescriptors()) {
|
||||
if (descriptor.getValueParameters().isEmpty()) {
|
||||
myMethods.put(descriptor, UNARY_MINUS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void declareIntrinsicProperty(JetStandardLibrary stdlib, String className, String methodName, IntrinsicMethod implementation) {
|
||||
final ClassDescriptor descriptor = (ClassDescriptor) stdlib.getLibraryScope().getClassifier(className);
|
||||
final List<TypeParameterDescriptor> typeParameterDescriptors = descriptor.getTypeConstructor().getParameters();
|
||||
List<TypeProjection> typeParameters = new ArrayList<TypeProjection>();
|
||||
for (TypeParameterDescriptor typeParameterDescriptor : typeParameterDescriptors) {
|
||||
typeParameters.add(new TypeProjection(JetStandardClasses.getAnyType()));
|
||||
}
|
||||
final JetScope numberScope = descriptor.getMemberScope(typeParameters);
|
||||
final VariableDescriptor variable = numberScope.getVariable(methodName);
|
||||
myMethods.put(variable.getOriginal(), implementation);
|
||||
}
|
||||
|
||||
public IntrinsicMethod getIntrinsic(DeclarationDescriptor descriptor) {
|
||||
return myMethods.get(descriptor.getOriginal());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class NumberCast implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments) {
|
||||
codegen.putTopOfStack(expectedType);
|
||||
return StackValue.onStack(expectedType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class UnaryMinus implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments) {
|
||||
codegen.gen(arguments.get(0), expectedType);
|
||||
v.neg(expectedType);
|
||||
return StackValue.onStack(expectedType);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user