package org.simantics.scl.compiler.elaboration.modules; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.common.names.Name; import org.simantics.scl.compiler.constants.Constant; import org.simantics.scl.compiler.constants.JavaTypeClassMethod; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import org.simantics.scl.compiler.types.util.MultiFunction; public class TypeClassMethod { TypeClass typeClass; String name; String javaName; Type baseType; int arity; Name defaultImplementation; public long location; public TypeClassMethod(TypeClass typeClass, String name, String javaName, Type baseType, int arity, long location) { if(typeClass == null) throw new NullPointerException(); if(name == null) throw new NullPointerException(); if(javaName == null) throw new NullPointerException(); if(baseType == null) throw new NullPointerException(); this.typeClass = typeClass; this.name = name; this.javaName = javaName; this.baseType = baseType; this.arity = arity; this.location = location; } public void setDefaultImplementation(Name defaultImplementation) { if(this.defaultImplementation != null) throw new InternalCompilerError("Default method implementation already defined"); this.defaultImplementation = defaultImplementation; } public Name getDefaultImplementation() { return defaultImplementation; } public String getName() { return name; } public String getJavaName() { return javaName; } public Type getBaseType() { return baseType; } public int getArity() { return arity; } public Type getType() { return Types.closure(Types.constrained( typeClass.class_, baseType)); } public TypeClass getTypeClass() { return typeClass; } public SCLValue createValue() { String moduleName = typeClass.name.module; SCLValue value = new SCLValue(Name.create(moduleName, name)); MultiFunction mfun = Types.matchFunction(baseType); Type[] parameterTypes = new Type[mfun.parameterTypes.length + 1]; System.arraycopy(mfun.parameterTypes, 0, parameterTypes, 1, mfun.parameterTypes.length); parameterTypes[0] = typeClass.class_; // FIXME totally incorrect type for the method Constant constant = new JavaTypeClassMethod( this, typeClass.javaName, javaName, mfun.effect, mfun.returnType, parameterTypes); value.setValue(constant); value.setType(getType()); return value; } }