001/* 002 * Copyright (c) 2012-2021 Institut National des Sciences Appliquées de Lyon (INSA Lyon) and others 003 * 004 * This program and the accompanying materials are made available under the 005 * terms of the Eclipse Public License 2.0 which is available at 006 * http://www.eclipse.org/legal/epl-2.0. 007 * 008 * SPDX-License-Identifier: EPL-2.0 009 */ 010 011package org.eclipse.golo.compiler; 012 013import java.io.Reader; 014import java.io.File; 015import java.io.IOException; 016import java.util.List; 017 018import gololang.ir.GoloModule; 019 020/** 021 * Provides a facility to dynamically load Golo source code and access the generated code from a dedicated class loader. 022 * <p> 023 * Golo source files can be compiled and the resulting JVM bytecode be injected into the class loader. It is important 024 * to note that this class loader definition is not thread safe. 025 * <p> 026 * This class loader does not support reloading. Attempts to load source files that may produce the same bytecode 027 * definitions will resulting in exceptions. 028 */ 029public final class GoloClassLoader extends ClassLoader { 030 031 private final GoloCompiler compiler; 032 033 /** 034 * Creates a class loader from a parent. 035 * 036 * @param parent the parent classloader. 037 */ 038 public GoloClassLoader(ClassLoader parent) { 039 super(parent); 040 compiler = new GoloCompiler(this); 041 } 042 043 /** 044 * Creates a class loader from the default parent. 045 */ 046 public GoloClassLoader() { 047 super(); 048 compiler = new GoloCompiler(this); 049 } 050 051 public GoloCompiler getCompiler() { 052 return this.compiler; 053 } 054 055 /** 056 * Compiles and loads the resulting JVM bytecode for a Golo source file. 057 * 058 * @param goloSourceFilename the source file name. 059 * @param sourceCode the source reader. 060 * @return the class matching the Golo module defined in the source. 061 * @throws GoloCompilationException if either of the compilation phase failed. 062 */ 063 public synchronized Class<?> load(String goloSourceFilename, Reader sourceCode) throws GoloCompilationException { 064 return load(compiler.compile(goloSourceFilename, sourceCode)); 065 } 066 067 public synchronized Class<?> load(File goloSourceFile) throws GoloCompilationException, IOException { 068 return load(compiler.compile(goloSourceFile)); 069 } 070 071 /** 072 * Compiles and loads the resulting JVM bytecode for a Golo module IR. 073 * 074 * @param module the Golo module IR to load. 075 * @return the class matching the Golo module defined in the IR. 076 * @throws GoloCompilationException if either of the compilation phase failed. 077 */ 078 public synchronized Class<?> load(GoloModule module) { 079 compiler.expand(module); 080 compiler.refine(module); 081 return load(compiler.generate(module)); 082 } 083 084 public synchronized Class<?> load(List<CodeGenerationResult> results) { 085 Class<?> lastClassIsModule = null; 086 for (CodeGenerationResult result : results) { 087 lastClassIsModule = load(result); 088 } 089 return lastClassIsModule; 090 } 091 092 public synchronized Class<?> load(CodeGenerationResult result) { 093 return defineClass(result.getBinaryName(), result.getBytecode(), 0, result.size()); 094 } 095}