package me.tomassetti.turin.compiler;
import com.google.common.collect.ImmutableList;
import me.tomassetti.turin.classloading.TurinClassLoader;
import me.tomassetti.turin.classloading.ClassFileDefinition;
import me.tomassetti.turin.parser.Parser;
import me.tomassetti.turin.resolvers.*;
import me.tomassetti.turin.resolvers.jdk.JdkTypeResolver;
import me.tomassetti.turin.parser.ast.TurinFile;
import org.junit.Test;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import static org.junit.Assert.assertEquals;
public class FunctionsCompilationTest {
private SymbolResolver getResolverFor(TurinFile turinFile) {
return new ComposedSymbolResolver(ImmutableList.of(new InFileSymbolResolver(JdkTypeResolver.getInstance()), new SrcSymbolResolver(ImmutableList.of(turinFile))));
}
@Test
public void compileFunctionWithBlockBody() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException {
TurinFile turinFile = new Parser().parse(this.getClass().getResourceAsStream("/function_with_block_body.to"));
// generate bytecode
Compiler instance = new Compiler(getResolverFor(turinFile), new Compiler.Options());
List<ClassFileDefinition> classFileDefinitions = instance.compile(turinFile, new AbstractCompilerTest.MyErrorCollector());
assertEquals(1, classFileDefinitions.size());
TurinClassLoader turinClassLoader = new TurinClassLoader();
Class functionClass = turinClassLoader.addClass(classFileDefinitions.get(0).getName(),
classFileDefinitions.get(0).getBytecode());
assertEquals(0, functionClass.getConstructors().length);
Method invoke = functionClass.getMethod("invoke", int.class, int.class);
assertEquals(10, invoke.invoke(null, 7, 3));
}
@Test
public void compileFunctionWithExpressionBody() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException {
TurinFile turinFile = new Parser().parse(this.getClass().getResourceAsStream("/function_with_expression_body.to"));
// generate bytecode
Compiler instance = new Compiler(getResolverFor(turinFile), new Compiler.Options());
List<ClassFileDefinition> classFileDefinitions = instance.compile(turinFile, new AbstractCompilerTest.MyErrorCollector());
assertEquals(1, classFileDefinitions.size());
TurinClassLoader turinClassLoader = new TurinClassLoader();
Class functionClass = turinClassLoader.addClass(classFileDefinitions.get(0).getName(),
classFileDefinitions.get(0).getBytecode());
assertEquals(0, functionClass.getConstructors().length);
Method invoke = functionClass.getMethod("invoke");
assertEquals("foo", invoke.invoke(null));
}
@Test
public void compileFunctionReturningVoid() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException {
TurinFile turinFile = new Parser().parse(this.getClass().getResourceAsStream("/call_void_function.to"));
// generate bytecode
Compiler instance = new Compiler(getResolverFor(turinFile), new Compiler.Options());
List<ClassFileDefinition> classFileDefinitions = instance.compile(turinFile, new AbstractCompilerTest.MyErrorCollector());
assertEquals(2, classFileDefinitions.size());
TurinClassLoader turinClassLoader = new TurinClassLoader();
Class functionClass = turinClassLoader.addClass(classFileDefinitions.get(0).getName(),
classFileDefinitions.get(0).getBytecode());
Class programClass = turinClassLoader.addClass(classFileDefinitions.get(1).getName(),
classFileDefinitions.get(1).getBytecode());
Method main = programClass.getMethod("main", String[].class);
main.invoke(null, (Object)new String[]{});
}
}