Skip to content

Commit

Permalink
Make optimization phase optional
Browse files Browse the repository at this point in the history
  • Loading branch information
ChAoSUnItY committed Feb 6, 2023
1 parent e3e6703 commit 1289477
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 52 deletions.
116 changes: 72 additions & 44 deletions src/main/kotlin/org/yakou/lang/compilation/CompilationSession.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import org.yakou.lang.util.Constants
class CompilationSession(val preference: AbstractPreference) {
val table: Table = Table()
private val sourceFile: File? = preference.sourceFile
private val unitProcessResult: MutableMap<String, Pair<Boolean, Long>> = mutableMapOf()
private val unitProcessResult: MutableMap<String, Pair<UnitProcessResult, Long>> = mutableMapOf()

fun compile() {
if (sourceFile == null || !sourceFile.exists()) {
Expand All @@ -32,10 +32,7 @@ class CompilationSession(val preference: AbstractPreference) {
val statusPadding = if (preference.enableColor) 10 else 1

for ((unitName, result) in unitProcessResult) {
val status = when (result.first) {
true -> if (preference.useAscii) "V" else ""
false -> if (preference.useAscii) "X" else ""
}
val status = result.first.stateLiteral

println(
"%-${unitNamePadding}s %s status: %-${statusPadding}s | elapsed time: %d ms".format(
Expand All @@ -44,14 +41,18 @@ class CompilationSession(val preference: AbstractPreference) {
if (preference.enableColor) {
Ansi.colorize(
status,
if (result.first) Attribute.GREEN_BACK() else Attribute.RED_BACK(),
Attribute.BLACK_TEXT()
when (result.first) {
UnitProcessResult.PASSED -> Attribute.GREEN_BACK()
UnitProcessResult.FAILED -> Attribute.RED_BACK()
UnitProcessResult.SKIPPED -> Attribute.BRIGHT_BLACK_BACK()
},
Attribute.BLACK_TEXT(),
)
} else {
status
},
result.second
)
result.second,
),
)
}
}
Expand All @@ -65,52 +66,63 @@ class CompilationSession(val preference: AbstractPreference) {

// PHASE I: LEXICAL ANALYSIS
unitProcessResult["lexical analysis"] = measureTime {
compilationUnits.all(CompilationUnit::lex)
compilationUnits.processAll(CompilationUnit::lex)
}

if (!unitProcessResult["lexical analysis"]!!.first) {
if (!unitProcessResult["lexical analysis"]!!.first.ok()) {
return
}

// PHASE II: SYNTACTIC ANALYSIS
unitProcessResult["syntactic analysis"] = measureTime {
compilationUnits.all(CompilationUnit::parse)
compilationUnits.processAll(CompilationUnit::parse)
}

if (!unitProcessResult["syntactic analysis"]!!.first) {
if (!unitProcessResult["syntactic analysis"]!!.first.ok()) {
return
}

// PHASE III: TYPE BINDING
unitProcessResult["type binding"] = measureTime {
val declarationBinding = compilationUnits.all(CompilationUnit::bind)

declarationBinding && compilationUnits.all(CompilationUnit::postBind)
// PHASE III: DECLARATION BINDING
unitProcessResult["declaration binding"] = measureTime {
compilationUnits.processAll(CompilationUnit::bind)
}

if (!unitProcessResult["type binding"]!!.first) {
if (!unitProcessResult["declaration binding"]!!.first.ok()) {
return
}

// PHASE III: SEMANTIC CHECKING
unitProcessResult["semantic checking"] = measureTime {
compilationUnits.all(CompilationUnit::check)
// PHASE IV: TYPE BINDING
unitProcessResult["type binding"] = measureTime {
compilationUnits.processAll(CompilationUnit::postBind)
}

if (!unitProcessResult["semantic checking"]!!.first) {
if (!unitProcessResult["type binding"]!!.first.ok()) {
return
}

// PHASE IV: CODE OPTIMIZATION
unitProcessResult["code optimization"] = measureTime {
compilationUnits.all(CompilationUnit::optimize)
// PHASE V: SEMANTIC CHECKING
unitProcessResult["semantic checking"] = measureTime {
compilationUnits.processAll(CompilationUnit::check)
}

if (!unitProcessResult["code optimization"]!!.first) {
if (!unitProcessResult["semantic checking"]!!.first.ok()) {
return
}

// PHASE V: CODE GENERATION
// PHASE VI: CODE OPTIMIZATION
if (!preference.noOpt) {
unitProcessResult["code optimization"] = measureTime {
compilationUnits.processAll(CompilationUnit::optimize)
}

if (!unitProcessResult["code optimization"]!!.first.ok()) {
return
}
} else {
unitProcessResult["code optimization"] = UnitProcessResult.SKIPPED to 0
}

// PHASE VII: CODE GENERATION
unitProcessResult["code generation"] = measureTime {
val generator = JvmBytecodeGenerator(this)

Expand All @@ -119,7 +131,7 @@ class CompilationSession(val preference: AbstractPreference) {

generator.finalize()

true
UnitProcessResult.PASSED
}
}

Expand All @@ -129,54 +141,70 @@ class CompilationSession(val preference: AbstractPreference) {
// PHASE I: LEXICAL ANALYZE
unitProcessResult["lexical analysis"] = measureTime(compilationUnit::lex)

if (!unitProcessResult["lexical analysis"]!!.first) {
if (!unitProcessResult["lexical analysis"]!!.first.ok()) {
return
}

// PHASE II: SYNTACTIC ANALYSIS
unitProcessResult["syntactic analysis"] = measureTime(compilationUnit::parse)

if (!unitProcessResult["syntactic analysis"]!!.first) {
if (!unitProcessResult["syntactic analysis"]!!.first.ok()) {
return
}

// PHASE III: TYPE BINDING
unitProcessResult["type binding"] = measureTime {
compilationUnit.bind() && compilationUnit.postBind()
// PHASE III: DECLARATION BINDING
unitProcessResult["declaration binding"] = measureTime(compilationUnit::bind)

if (!unitProcessResult["declaration binding"]!!.first.ok()) {
return
}

if (!unitProcessResult["type binding"]!!.first) {
// PHASE IV: TYPE BINDING
unitProcessResult["type binding"] = measureTime(compilationUnit::postBind)

if (!unitProcessResult["type binding"]!!.first.ok()) {
return
}

// PHASE III: SEMANTIC CHECKING
// PHASE V: SEMANTIC CHECKING
unitProcessResult["semantic checking"] = measureTime(compilationUnit::check)

if (!unitProcessResult["semantic checking"]!!.first) {
if (!unitProcessResult["semantic checking"]!!.first.ok()) {
return
}

// PHASE IV: SEMANTIC CHECKING
unitProcessResult["code optimization"] = measureTime(compilationUnit::optimize)
// PHASE VI: CODE OPTIMIZATION
if (!preference.noOpt) {
unitProcessResult["code optimization"] = measureTime(compilationUnit::optimize)

if (!unitProcessResult["code optimization"]!!.first) {
return
if (!unitProcessResult["code optimization"]!!.first.ok()) {
return
}
} else {
unitProcessResult["code optimization"] = UnitProcessResult.SKIPPED to 0
}

// PHASE V: CODE GENERATION
// PHASE VII: CODE GENERATION
unitProcessResult["code generation"] = measureTime {
val generator = JvmBytecodeGenerator(this)
generator.gen(compilationUnit)
generator.finalize()

true
UnitProcessResult.PASSED
}
}

private inline fun measureTime(crossinline process: () -> Boolean): Pair<Boolean, Long> {
private inline fun measureTime(crossinline process: () -> UnitProcessResult): Pair<UnitProcessResult, Long> {
val before = Instant.now()
val result = process()
val after = Instant.now()
return result to Duration.between(before, after).toMillis()
}

private inline fun List<CompilationUnit>.processAll(crossinline process: CompilationUnit.() -> UnitProcessResult): UnitProcessResult =
if (map(process).any { it == UnitProcessResult.FAILED }) {
UnitProcessResult.FAILED
} else {
UnitProcessResult.PASSED
}
}
16 changes: 8 additions & 8 deletions src/main/kotlin/org/yakou/lang/compilation/CompilationUnit.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,40 +31,40 @@ class CompilationUnit(val sourceFile: File, val session: CompilationSession) : U
override fun maxLineCount(): Int =
SourceCache.INSTANCE.getOrAdd(sourceFile).size

fun lex(): Boolean {
fun lex(): UnitProcessResult {
tokens = Lexer(this).lex()
return dumpReportStatus()
}

fun parse(): Boolean {
fun parse(): UnitProcessResult {
ykFile = Parser(this).parse()
return dumpReportStatus()
}

fun bind(): Boolean {
fun bind(): UnitProcessResult {
binder = Binder(this)
binder.bind()
return dumpReportStatus()
}

fun postBind(): Boolean {
fun postBind(): UnitProcessResult {
binder.bindSecondary()
return dumpReportStatus()
}

fun check(): Boolean {
fun check(): UnitProcessResult {
Checker(this).check()
return dumpReportStatus()
}

fun optimize(): Boolean {
fun optimize(): UnitProcessResult {
Optimizer(this).optimize()
return dumpReportStatus()
}

private fun dumpReportStatus(): Boolean {
private fun dumpReportStatus(): UnitProcessResult {
val hasError = reportBuilder.containsError()
reportBuilder.dump(preference().outputStream)
return !hasError
return if (!hasError) UnitProcessResult.PASSED else UnitProcessResult.FAILED
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.yakou.lang.compilation

enum class UnitProcessResult(val stateLiteral: String) {
PASSED("passed"),
FAILED("failed"),
SKIPPED("skipped");

fun ok(): Boolean = this != FAILED
}

0 comments on commit 1289477

Please sign in to comment.