package scotch.compiler; import static java.util.Arrays.asList; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static scotch.compiler.syntax.type.Types.sum; import static scotch.compiler.syntax.type.Types.toType; import static scotch.symbol.MethodSignature.methodSignature; import static scotch.symbol.Operator.operator; import static scotch.symbol.Symbol.qualified; import static scotch.symbol.Symbol.symbol; import static scotch.symbol.Value.Fixity.LEFT_INFIX; import static scotch.symbol.descriptor.DataFieldDescriptor.field; import static scotch.symbol.type.TypeDescriptors.fn; import static scotch.symbol.type.TypeDescriptors.var; import static scotch.util.TestUtil.constructor; import static scotch.util.TestUtil.dataType; import static scotch.util.TestUtil.intType; import static scotch.util.TestUtil.typeClass; import static scotch.util.TestUtil.typeInstance; import java.util.Optional; import java.util.Set; import org.junit.Before; import org.junit.Test; import scotch.symbol.MethodSignature; import scotch.symbol.SymbolEntry; import scotch.symbol.descriptor.TypeInstanceDescriptor; import scotch.data.num.NumInt; import scotch.symbol.type.TypeDescriptor; public class ClassLoaderResolverTest { private ClassLoaderResolver resolver; @Before public void setUp() { resolver = new ClassLoaderResolver(Optional.empty(), getClass().getClassLoader()); } @Test public void shouldResolveJavaSymbol() { TypeDescriptor a = var("a", asList("scotch.data.num.Num")); SymbolEntry entry = resolver.getEntry(symbol("scotch.data.num.(+)")).get(); assertThat(entry.getValue(), is(Optional.of(fn(a, fn(a, a))))); assertThat(entry.getOperator(), is(Optional.of(operator(LEFT_INFIX, 6)))); assertThat(entry.getValueMethod(), is(Optional.of(methodSignature("scotch/data/num/Num:add:()Lscotch/runtime/Applicable;")))); assertThat(entry.getMemberOf(), is(Optional.of((symbol("scotch.data.num.Num"))))); } @Test public void shouldResolveJavaTypeClass() { SymbolEntry entry = resolver.getEntry(symbol("scotch.data.num.Num")).get(); assertThat(entry.getTypeClass(), is(Optional.of(typeClass("scotch.data.num.Num", asList(toType(var("a"))), asList( "scotch.data.num.(+)", "scotch.data.num.(-)", "scotch.data.num.(*)", "scotch.data.num.fromInteger", "scotch.data.num.signum", "scotch.data.num.negate", "scotch.data.num.abs" ))))); } @Test public void shouldResolveJavaTypeInstanceByClassAndType() { assertThat(resolver.getTypeInstances(symbol("scotch.data.num.Num"), asList(intType().toDescriptor())), hasItem(typeInstance( "scotch.data.num", "scotch.data.num.Num", asList(intType()), MethodSignature.fromMethod(NumInt.class, "instance") ))); } @Test public void shouldResolveJavaTypeInstanceByModuleName() { assertThat(resolver.getTypeInstancesByModule("scotch.data.num"), hasItem(typeInstance( "scotch.data.num", "scotch.data.num.Num", asList(intType()), MethodSignature.fromMethod(NumInt.class, "instance") ))); } @Test public void shouldResolveDataType() { assertThat(resolver.getEntry(symbol("scotch.data.maybe.Maybe")).get().getDataType(), is(Optional.of(dataType( "scotch.data.maybe.Maybe", asList(toType(var("a"))), asList( constructor( 0, "scotch.data.maybe.Maybe", "scotch.data.maybe.Nothing", "scotch/data/maybe/Maybe$Nothing" ), constructor( 1, "scotch.data.maybe.Maybe", "scotch.data.maybe.Just", "scotch/data/maybe/Maybe$Just", asList(field(0, "value", "getValue", var("a"))) ) ) )))); } @Test public void shouldResolveEqForListOfInt() { Set<TypeInstanceDescriptor> typeInstances = resolver.getTypeInstances( symbol("scotch.data.eq.Eq"), asList(sum("scotch.data.list.[]", asList(intType())).toDescriptor()) ); assertThat(typeInstances, hasSize(1)); } @Test public void shouldGetIntThroughScotchLang() { Optional<SymbolEntry> maybeEntry = resolver.getEntry(qualified("scotch.lang", "Int")); assertThat(maybeEntry.map(SymbolEntry::getSymbol), is(Optional.of(qualified("scotch.data.int", "Int")))); } }