-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
211 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package technology.idlab.compiler | ||
|
||
import technology.idlab.logging.createLogger | ||
import technology.idlab.logging.fatal | ||
import java.io.File | ||
|
||
abstract class CodeHandler { | ||
protected val outputDirectory = "out" | ||
protected open val logger = createLogger() | ||
private val classLoader: ClassLoader = FileClassLoader(outputDirectory) | ||
|
||
/** | ||
* Compile a single file using the language's compiler and write it to the | ||
* output directory. | ||
*/ | ||
abstract fun compile(file: File) | ||
|
||
/** | ||
* Load a class with specific name as a variable. | ||
*/ | ||
fun load(name: String): Class<*> { | ||
return classLoader.loadClass(name) | ||
} | ||
|
||
/** | ||
* Initialize a class using its default constructor. | ||
*/ | ||
fun createInstance(clazz: Class<*>): Any { | ||
val constructor = try { | ||
clazz.getConstructor() | ||
} catch (e: NoSuchMethodException) { | ||
logger.fatal("Could not find constructor for ${clazz.name}") | ||
} | ||
|
||
return try { | ||
constructor.newInstance() | ||
} catch (e: Exception) { | ||
logger.fatal("Could not instantiate ${clazz.name}") | ||
} | ||
} | ||
|
||
/** | ||
* Given a list of strings, map them to their respective classes. | ||
*/ | ||
fun mapToType(input: List<String>): Array<Class<*>> { | ||
return input.map { | ||
Class.forName(it) | ||
}.toTypedArray() | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package technology.idlab.compiler | ||
|
||
import technology.idlab.logging.createLogger | ||
import technology.idlab.logging.fatal | ||
import java.io.File | ||
|
||
class FileClassLoader(private val directory: String) : ClassLoader() { | ||
private val logger = createLogger() | ||
|
||
override fun findClass(name: String): Class<*> { | ||
// Define the path to the class file. | ||
val path = "$directory/${name.replace('.', File.separatorChar)}.class" | ||
|
||
// Open file pointer. | ||
val file = File(path) | ||
if (!file.exists()) { | ||
logger.fatal("Failed to read file $name") | ||
} | ||
|
||
// Read the file into a byte array. | ||
logger.info("Reading $path") | ||
val bytes = file.readBytes() | ||
|
||
// Define and return the class. | ||
return try { | ||
defineClass(name, bytes, 0, bytes.size) | ||
} catch (e: ClassFormatError) { | ||
logger.fatal("Failed to load class $name") | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package technology.idlab.compiler | ||
|
||
import technology.idlab.logging.createLogger | ||
import technology.idlab.logging.fatal | ||
import java.io.File | ||
import javax.tools.JavaCompiler | ||
import javax.tools.ToolProvider | ||
|
||
class JavaCodeHandler : CodeHandler() { | ||
override val logger = createLogger() | ||
private val compiler: JavaCompiler = ToolProvider.getSystemJavaCompiler() ?: logger.fatal("No Java compiler found.") | ||
private val fileManager = compiler.getStandardFileManager(null, null, null) | ||
|
||
override fun compile(file: File) { | ||
val compilationUnits = fileManager.getJavaFileObjectsFromFiles(listOf(file)) | ||
val options = listOf("-d", outputDirectory) | ||
val task = compiler.getTask(null, fileManager, null, options, null, compilationUnits) | ||
|
||
// Execute compilation. | ||
logger.info("Compiling $file") | ||
val success = task.call() | ||
if (!success) { | ||
logger.fatal("Compilation of $file failed") | ||
} | ||
logger.info("Compilation of $file succeeded") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import java.util.* | ||
import java.util.logging.Formatter | ||
|
||
class BasicFormatter(): Formatter() { | ||
override fun format(record: java.util.logging.LogRecord): String { | ||
// Parse date and time. | ||
val instant = Date(record.millis).toInstant() | ||
val instantTimezone = instant.atZone(TimeZone.getDefault().toZoneId()) | ||
val isoString = instantTimezone.format(java.time.format.DateTimeFormatter.ISO_LOCAL_TIME) | ||
val time = isoString.padEnd(12, '0'); | ||
|
||
// Parse thread. | ||
val thread = "[${record.longThreadID}]".padEnd(6, ' '); | ||
// Parse level. | ||
val level = record.level.toString().padEnd(7, ' '); | ||
|
||
// Parse class and method. | ||
val className = record.sourceClassName.split(".").last(); | ||
val location = "${className}::${record.sourceMethodName}" | ||
.padEnd(30, ' '); | ||
|
||
// Output the result as a single string. | ||
return "$time $thread $level $location ${record.message}\n" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package technology.idlab.logging | ||
|
||
import java.util.logging.Level | ||
import java.util.logging.Logger | ||
import kotlin.system.exitProcess | ||
|
||
fun createLogger(): Logger { | ||
val caller = Throwable().stackTrace[1] | ||
val logger = Logger.getLogger(caller.className) | ||
logger.addHandler(StandardOutput()) | ||
logger.level = Level.ALL | ||
return logger | ||
} | ||
|
||
/** | ||
* Log a message and exit the program with a status code of -1. This function | ||
* is intended to use in a try-catch block. Since it returns Nothing, it can be | ||
* the only expression in the catch block of an assignment. | ||
* | ||
* Example: | ||
* ``` | ||
* const x = try { | ||
* 10 / 0 | ||
* } catch (e: Exception) { | ||
* logger.fatal("An error occurred: ${e.message}") | ||
* } | ||
* ``` | ||
*/ | ||
fun Logger.fatal(message: String): Nothing { | ||
val caller = Throwable().stackTrace[1] | ||
logp(Level.SEVERE, caller.className, caller.methodName, message) | ||
exitProcess(-1) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package technology.idlab.logging | ||
|
||
import BasicFormatter | ||
import java.util.logging.ConsoleHandler | ||
|
||
class StandardOutput(): ConsoleHandler() { | ||
init { | ||
this.formatter = BasicFormatter() | ||
this.setOutputStream(System.out) | ||
} | ||
} |