2018-09-15 14:21:05 +00:00
package prog8.compiler
2018-08-16 16:32:05 +00:00
2022-02-05 02:50:54 +00:00
import com.github.michaelbull.result.onFailure
2021-10-28 23:06:01 +00:00
import prog8.ast.AstToSourceTextConverter
2021-07-13 07:51:34 +00:00
import prog8.ast.IBuiltinFunctions
2022-02-10 22:20:19 +00:00
import prog8.ast.IStatementContainer
2021-07-13 07:51:34 +00:00
import prog8.ast.Program
2021-02-09 00:13:38 +00:00
import prog8.ast.base.AstException
import prog8.ast.expressions.Expression
2022-02-10 23:21:40 +00:00
import prog8.ast.expressions.NumericLiteral
2021-02-09 00:13:38 +00:00
import prog8.ast.statements.Directive
2022-02-10 22:20:19 +00:00
import prog8.ast.statements.VarDecl
import prog8.ast.walk.IAstVisitor
2022-03-10 22:08:41 +00:00
import prog8.code.SymbolTable
import prog8.code.core.*
2022-03-11 19:35:25 +00:00
import prog8.code.target.AtariTarget
import prog8.code.target.C128Target
import prog8.code.target.C64Target
import prog8.code.target.Cx16Target
2022-02-05 02:50:54 +00:00
import prog8.compiler.astprocessing.*
2021-02-09 00:13:38 +00:00
import prog8.optimizer.*
2021-10-13 19:55:51 +00:00
import prog8.parser.ParseError
2019-01-23 23:35:30 +00:00
import java.nio.file.Path
2021-10-10 22:22:04 +00:00
import kotlin.io.path.Path
import kotlin.io.path.nameWithoutExtension
2022-02-06 21:56:17 +00:00
import kotlin.math.round
2021-02-09 00:13:38 +00:00
import kotlin.system.measureTimeMillis
2018-08-16 16:32:05 +00:00
2022-03-07 20:41:12 +00:00
class CompilationResult ( val program : Program ,
2022-02-22 21:43:14 +00:00
val compilationOptions : CompilationOptions ,
2021-02-09 00:13:38 +00:00
val importedFiles : List < Path > )
2021-11-30 00:40:21 +00:00
class CompilerArguments ( val filepath : Path ,
val optimize : Boolean ,
val optimizeFloatExpressions : Boolean ,
2022-01-01 15:35:36 +00:00
val dontReinitGlobals : Boolean ,
2021-11-30 00:40:21 +00:00
val writeAssembly : Boolean ,
val slowCodegenWarnings : Boolean ,
val quietAssembler : Boolean ,
2021-12-30 13:38:40 +00:00
val asmListfile : Boolean ,
2022-02-05 20:25:19 +00:00
val experimentalCodegen : Boolean ,
2021-11-30 00:40:21 +00:00
val compilationTarget : String ,
val sourceDirs : List < String > = emptyList ( ) ,
val outputDir : Path = Path ( " " ) ,
val errors : IErrorReporter = ErrorReporter ( ) )
2021-02-09 00:13:38 +00:00
2021-11-30 00:40:21 +00:00
2022-03-07 20:41:12 +00:00
fun compileProgram ( args : CompilerArguments ) : CompilationResult ? {
2021-10-29 22:25:34 +00:00
lateinit var program : Program
2021-02-09 00:13:38 +00:00
lateinit var importedFiles : List < Path >
2021-11-30 00:40:21 +00:00
val optimizeFloatExpr = if ( args . optimize ) args . optimizeFloatExpressions else false
2021-11-09 02:45:07 +00:00
2021-02-19 17:27:31 +00:00
val compTarget =
2021-11-30 00:40:21 +00:00
when ( args . compilationTarget ) {
2022-02-06 20:29:06 +00:00
C64Target . NAME -> C64Target ( )
C128Target . NAME -> C128Target ( )
Cx16Target . NAME -> Cx16Target ( )
2022-02-21 22:38:53 +00:00
AtariTarget . NAME -> AtariTarget ( )
2021-07-01 22:11:21 +00:00
else -> throw IllegalArgumentException ( " invalid compilation target " )
2021-02-09 00:13:38 +00:00
}
2022-02-22 21:43:14 +00:00
var compilationOptions : CompilationOptions
2021-02-09 00:13:38 +00:00
try {
val totalTime = measureTimeMillis {
// import main module and everything it needs
2022-02-22 21:43:14 +00:00
val ( programresult , options , imported ) = parseImports ( args . filepath , args . errors , compTarget , args . sourceDirs )
compilationOptions = options
2022-02-05 13:02:24 +00:00
print ( " Parsed ${args.filepath} " )
ModuleImporter . ansiEraseRestOfLine ( true )
2021-11-03 21:52:08 +00:00
with ( compilationOptions ) {
2021-12-30 13:38:40 +00:00
slowCodegenWarnings = args . slowCodegenWarnings
optimize = args . optimize
optimizeFloatExpressions = optimizeFloatExpr
2022-01-01 15:35:36 +00:00
dontReinitGlobals = args . dontReinitGlobals
2021-12-30 13:38:40 +00:00
asmQuiet = args . quietAssembler
asmListfile = args . asmListfile
2022-02-05 20:25:19 +00:00
experimentalCodegen = args . experimentalCodegen
2022-02-06 16:07:03 +00:00
outputDir = args . outputDir . normalize ( )
2021-11-03 21:52:08 +00:00
}
2021-10-29 22:25:34 +00:00
program = programresult
2021-02-09 00:13:38 +00:00
importedFiles = imported
2021-11-30 00:40:21 +00:00
processAst ( program , args . errors , compilationOptions )
2021-12-30 01:00:36 +00:00
if ( compilationOptions . optimize ) {
// println("*********** AST RIGHT BEFORE OPTIMIZING *************")
// printProgram(program)
2021-10-13 19:55:51 +00:00
optimizeAst (
2021-10-29 22:25:34 +00:00
program ,
2021-11-03 21:52:08 +00:00
compilationOptions ,
2021-11-30 00:40:21 +00:00
args . errors ,
2021-10-13 19:55:51 +00:00
BuiltinFunctionsFacade ( BuiltinFunctions ) ,
2021-10-29 14:20:53 +00:00
compTarget
2021-10-13 19:55:51 +00:00
)
2021-12-30 01:00:36 +00:00
}
2021-11-30 00:40:21 +00:00
postprocessAst ( program , args . errors , compilationOptions )
2021-02-09 00:13:38 +00:00
2021-10-25 21:01:07 +00:00
// println("*********** AST BEFORE ASSEMBLYGEN *************")
2021-11-20 21:43:08 +00:00
// printProgram(program)
2021-02-09 00:13:38 +00:00
2021-11-30 00:40:21 +00:00
if ( args . writeAssembly ) {
2022-03-08 17:51:07 +00:00
if ( ! createAssemblyAndAssemble ( program , args . errors , compilationOptions ) ) {
System . err . println ( " Error in codegeneration or assembler " )
return null
2021-07-01 22:11:21 +00:00
}
}
2021-02-09 00:13:38 +00:00
}
System . out . flush ( )
System . err . flush ( )
2022-02-06 21:56:17 +00:00
val seconds = totalTime / 1000.0
println ( " \n Total compilation+assemble time: ${round(seconds*100.0)/100.0} sec. " )
2022-03-07 20:41:12 +00:00
return CompilationResult ( program , compilationOptions , importedFiles )
2021-10-13 19:55:51 +00:00
} catch ( px : ParseError ) {
2022-02-10 20:36:28 +00:00
System . err . print ( " \n \u001b [91m " ) // bright red
2021-10-13 19:55:51 +00:00
System . err . println ( " ${px.position.toClickableStr()} parse error: ${px.message} " . trim ( ) )
System . err . print ( " \u001b [0m " ) // reset
2022-03-10 22:08:41 +00:00
} catch ( ac : ErrorsReportedException ) {
2021-10-30 15:05:23 +00:00
if ( ! ac . message . isNullOrEmpty ( ) ) {
2022-02-10 20:36:28 +00:00
System . err . print ( " \n \u001b [91m " ) // bright red
2021-10-30 15:05:23 +00:00
System . err . println ( ac . message )
System . err . print ( " \u001b [0m " ) // reset
}
2021-10-26 22:23:54 +00:00
} catch ( nsf : NoSuchFileException ) {
2022-02-10 20:36:28 +00:00
System . err . print ( " \n \u001b [91m " ) // bright red
2021-10-26 22:23:54 +00:00
System . err . println ( " File not found: ${nsf.message} " )
System . err . print ( " \u001b [0m " ) // reset
2021-02-09 00:13:38 +00:00
} catch ( ax : AstException ) {
2022-02-10 20:36:28 +00:00
System . err . print ( " \n \u001b [91m " ) // bright red
2021-02-09 00:13:38 +00:00
System . err . println ( ax . toString ( ) )
System . err . print ( " \u001b [0m " ) // reset
} catch ( x : Exception ) {
2022-02-10 20:36:28 +00:00
print ( " \n \u001b [91m " ) // bright red
2021-02-09 00:13:38 +00:00
println ( " \n * internal error * " )
print ( " \u001b [0m " ) // reset
System . out . flush ( )
throw x
} catch ( x : NotImplementedError ) {
2022-02-10 20:36:28 +00:00
print ( " \n \u001b [91m " ) // bright red
2021-02-09 00:13:38 +00:00
println ( " \n * internal error: missing feature/code * " )
print ( " \u001b [0m " ) // reset
System . out . flush ( )
throw x
}
2022-03-07 20:41:12 +00:00
return null
2021-02-09 00:13:38 +00:00
}
private class BuiltinFunctionsFacade ( functions : Map < String , FSignature > ) : IBuiltinFunctions {
lateinit var program : Program
override val names = functions . keys
2021-02-09 00:47:05 +00:00
override val purefunctionNames = functions . filter { it . value . pure } . map { it . key } . toSet ( )
2022-02-10 23:21:40 +00:00
override fun constValue ( name : String , args : List < Expression > , position : Position ) : NumericLiteral ? {
2021-02-09 00:13:38 +00:00
val func = BuiltinFunctions [ name ]
if ( func != null ) {
val exprfunc = func . constExpressionFunc
if ( exprfunc != null ) {
return try {
2021-10-29 21:25:18 +00:00
exprfunc ( args , position , program )
2021-02-09 00:13:38 +00:00
} catch ( x : NotConstArgumentException ) {
// const-evaluating the builtin function call failed.
null
} catch ( x : CannotEvaluateException ) {
// const-evaluating the builtin function call failed.
null
}
}
}
return null
}
override fun returnType ( name : String , args : MutableList < Expression > ) =
builtinFunctionReturnType ( name , args , program )
}
2021-09-12 16:16:24 +00:00
fun parseImports ( filepath : Path ,
2021-10-13 16:16:51 +00:00
errors : IErrorReporter ,
compTarget : ICompilationTarget ,
sourceDirs : List < String > ) : Triple < Program , CompilationOptions , List < Path > > {
2022-02-15 00:39:12 +00:00
println ( " Compilation target: ${compTarget.name} " )
2021-02-09 00:13:38 +00:00
val bf = BuiltinFunctionsFacade ( BuiltinFunctions )
2021-10-29 22:25:34 +00:00
val program = Program ( filepath . nameWithoutExtension , bf , compTarget , compTarget )
bf . program = program
2021-04-28 18:04:23 +00:00
2021-10-29 22:25:34 +00:00
val importer = ModuleImporter ( program , compTarget . name , errors , sourceDirs )
2021-10-12 21:54:48 +00:00
val importedModuleResult = importer . importModule ( filepath )
importedModuleResult . onFailure { throw it }
2021-02-20 16:19:54 +00:00
errors . report ( )
2021-02-09 00:13:38 +00:00
2021-10-29 22:25:34 +00:00
val importedFiles = program . modules . map { it . source }
2021-10-16 15:15:22 +00:00
. filter { it . isFromFilesystem }
. map { Path ( it . origin ) }
2021-10-29 22:25:34 +00:00
val compilerOptions = determineCompilationOptions ( program , compTarget )
2021-02-09 00:13:38 +00:00
// depending on the machine and compiler options we may have to include some libraries
2021-07-13 07:51:34 +00:00
for ( lib in compTarget . machine . importLibs ( compilerOptions , compTarget . name ) )
2021-04-28 18:04:23 +00:00
importer . importLibraryModule ( lib )
2021-02-09 00:13:38 +00:00
// always import prog8_lib and math
2021-04-28 18:04:23 +00:00
importer . importLibraryModule ( " math " )
importer . importLibraryModule ( " prog8_lib " )
2021-10-30 15:05:23 +00:00
2022-02-26 14:36:22 +00:00
if ( compilerOptions . launcher == CbmPrgLauncherType . BASIC && compilerOptions . output != OutputType . PRG )
2021-10-30 15:05:23 +00:00
errors . err ( " BASIC launcher requires output type PRG " , program . toplevelModule . position )
2022-03-11 19:35:25 +00:00
if ( compilerOptions . launcher == CbmPrgLauncherType . BASIC && compTarget . name == AtariTarget . NAME )
2022-02-21 22:38:53 +00:00
errors . err ( " atari target cannot use CBM BASIC launcher, use NONE " , program . toplevelModule . position )
2021-02-20 16:19:54 +00:00
errors . report ( )
2021-10-30 15:05:23 +00:00
2021-10-29 22:25:34 +00:00
return Triple ( program , compilerOptions , importedFiles )
2021-02-09 00:13:38 +00:00
}
2021-09-12 16:16:24 +00:00
fun determineCompilationOptions ( program : Program , compTarget : ICompilationTarget ) : CompilationOptions {
2021-10-19 19:49:05 +00:00
val toplevelModule = program . toplevelModule
val outputDirective = ( toplevelModule . statements . singleOrNull { it is Directive && it . directive == " %output " } as ? Directive )
val launcherDirective = ( toplevelModule . statements . singleOrNull { it is Directive && it . directive == " %launcher " } as ? Directive )
2021-07-01 22:11:21 +00:00
val outputTypeStr = outputDirective ?. args ?. single ( ) ?. name ?. uppercase ( )
val launcherTypeStr = launcherDirective ?. args ?. single ( ) ?. name ?. uppercase ( )
2021-10-19 19:49:05 +00:00
val zpoption : String ? = ( toplevelModule . statements . singleOrNull { it is Directive && it . directive == " %zeropage " }
2021-05-05 21:01:04 +00:00
as ? Directive ) ?. args ?. single ( ) ?. name ?. uppercase ( )
val allOptions = program . modules . flatMap { it . statements } . filter { it is Directive && it . directive == " %option " }
. flatMap { ( it as Directive ) . args } . toSet ( )
2021-02-09 00:13:38 +00:00
val floatsEnabled = allOptions . any { it . name == " enable_floats " }
val noSysInit = allOptions . any { it . name == " no_sysinit " }
var zpType : ZeropageType =
2021-05-05 21:01:04 +00:00
if ( zpoption == null )
if ( floatsEnabled ) ZeropageType . FLOATSAFE else ZeropageType . KERNALSAFE
else
try {
ZeropageType . valueOf ( zpoption )
} catch ( x : IllegalArgumentException ) {
ZeropageType . KERNALSAFE
// error will be printed by the astchecker
}
2021-02-09 00:13:38 +00:00
2022-02-06 20:29:06 +00:00
if ( zpType == ZeropageType . FLOATSAFE && compTarget . name == Cx16Target . NAME ) {
2021-04-05 22:15:43 +00:00
System . err . println ( " Warning: zp option floatsafe changed to basicsafe for cx16 target " )
2021-02-09 00:13:38 +00:00
zpType = ZeropageType . BASICSAFE
}
2021-10-19 19:49:05 +00:00
val zpReserved = toplevelModule . statements
2021-05-05 21:01:04 +00:00
. asSequence ( )
. filter { it is Directive && it . directive == " %zpreserved " }
. map { ( it as Directive ) . args }
2022-01-15 12:03:55 +00:00
. filter { it . size == 2 && it [ 0 ] . int != null && it [ 1 ] . int != null }
2021-05-05 21:01:04 +00:00
. map { it [ 0 ] . int !! .. it [ 1 ] . int !! }
. toList ( )
2021-02-09 00:13:38 +00:00
2022-02-26 14:36:22 +00:00
val outputType = if ( outputTypeStr == null ) {
if ( compTarget is AtariTarget )
OutputType . XEX
else
OutputType . PRG
} else {
2021-07-01 22:11:21 +00:00
try {
OutputType . valueOf ( outputTypeStr )
} catch ( x : IllegalArgumentException ) {
// set default value; actual check and error handling of invalid option is handled in the AstChecker later
OutputType . PRG
}
2021-02-09 00:13:38 +00:00
}
2022-02-26 14:36:22 +00:00
val launcherType = if ( launcherTypeStr == null ) {
when ( compTarget ) {
is AtariTarget -> CbmPrgLauncherType . NONE
else -> CbmPrgLauncherType . BASIC
}
} else {
2021-07-01 22:11:21 +00:00
try {
2022-02-26 14:36:22 +00:00
CbmPrgLauncherType . valueOf ( launcherTypeStr )
2021-07-01 22:11:21 +00:00
} catch ( x : IllegalArgumentException ) {
// set default value; actual check and error handling of invalid option is handled in the AstChecker later
2022-02-26 14:36:22 +00:00
CbmPrgLauncherType . BASIC
2021-07-01 22:11:21 +00:00
}
2021-02-09 00:13:38 +00:00
}
return CompilationOptions (
2021-07-01 22:11:21 +00:00
outputType ,
launcherType ,
2021-05-18 21:52:43 +00:00
zpType , zpReserved , floatsEnabled , noSysInit ,
2021-05-05 21:01:04 +00:00
compTarget
2021-02-09 00:13:38 +00:00
)
}
2021-10-29 22:25:34 +00:00
private fun processAst ( program : Program , errors : IErrorReporter , compilerOptions : CompilationOptions ) {
2022-02-05 03:25:34 +00:00
println ( " Analyzing code... " )
2022-02-21 22:38:53 +00:00
program . preprocessAst ( errors , compilerOptions . compTarget )
2022-01-21 22:33:54 +00:00
program . checkIdentifiers ( errors , compilerOptions )
2021-02-20 16:19:54 +00:00
errors . report ( )
2022-02-15 00:39:12 +00:00
program . charLiteralsToUByteLiterals ( compilerOptions . compTarget , errors )
errors . report ( )
2021-10-29 22:25:34 +00:00
program . constantFold ( errors , compilerOptions . compTarget )
2021-02-20 16:19:54 +00:00
errors . report ( )
2021-12-25 20:42:50 +00:00
program . desugaring ( errors )
errors . report ( )
2021-11-27 22:52:47 +00:00
program . reorderStatements ( errors , compilerOptions )
2021-02-20 16:19:54 +00:00
errors . report ( )
2021-12-15 00:52:28 +00:00
program . addTypecasts ( errors , compilerOptions )
2021-02-20 16:19:54 +00:00
errors . report ( )
2022-01-21 22:33:54 +00:00
program . variousCleanups ( errors , compilerOptions )
2021-04-01 21:04:13 +00:00
errors . report ( )
2021-11-03 21:52:08 +00:00
program . checkValid ( errors , compilerOptions )
2021-02-20 16:19:54 +00:00
errors . report ( )
2022-01-21 22:33:54 +00:00
program . checkIdentifiers ( errors , compilerOptions )
2021-02-20 16:19:54 +00:00
errors . report ( )
2021-02-09 00:13:38 +00:00
}
2021-11-03 21:52:08 +00:00
private fun optimizeAst ( program : Program , compilerOptions : CompilationOptions , errors : IErrorReporter , functions : IBuiltinFunctions , compTarget : ICompilationTarget ) {
2021-02-09 00:13:38 +00:00
println ( " Optimizing... " )
2021-10-29 22:25:34 +00:00
val remover = UnusedCodeRemover ( program , errors , compTarget )
remover . visit ( program )
2021-04-04 13:52:10 +00:00
remover . applyModifications ( )
2021-02-09 00:13:38 +00:00
while ( true ) {
// keep optimizing expressions and statements until no more steps remain
2022-01-06 21:45:36 +00:00
val optsDone1 = program . simplifyExpressions ( errors )
2022-03-11 18:54:30 +00:00
val optsDone2 = program . splitBinaryExpressions ( compilerOptions )
2021-10-29 22:25:34 +00:00
val optsDone3 = program . optimizeStatements ( errors , functions , compTarget )
program . constantFold ( errors , compTarget ) // because simplified statements and expressions can result in more constants that can be folded away
2021-02-20 16:19:54 +00:00
errors . report ( )
2021-02-09 00:13:38 +00:00
if ( optsDone1 + optsDone2 + optsDone3 == 0 )
break
}
2021-02-20 16:19:54 +00:00
errors . report ( )
2021-02-09 00:13:38 +00:00
}
2021-10-29 22:25:34 +00:00
private fun postprocessAst ( program : Program , errors : IErrorReporter , compilerOptions : CompilationOptions ) {
2021-12-25 20:42:50 +00:00
program . desugaring ( errors )
2021-12-15 00:52:28 +00:00
program . addTypecasts ( errors , compilerOptions )
2021-02-20 16:19:54 +00:00
errors . report ( )
2022-01-21 22:33:54 +00:00
program . variousCleanups ( errors , compilerOptions )
2021-10-29 22:25:34 +00:00
val callGraph = CallGraph ( program )
2021-02-09 00:13:38 +00:00
callGraph . checkRecursiveCalls ( errors )
2022-02-27 15:27:02 +00:00
program . verifyFunctionArgTypes ( errors )
2021-02-20 16:19:54 +00:00
errors . report ( )
2021-10-29 22:25:34 +00:00
program . moveMainAndStartToFirst ( )
2021-12-27 01:04:28 +00:00
program . checkValid ( errors , compilerOptions ) // check if final tree is still valid
errors . report ( )
2021-02-09 00:13:38 +00:00
}
2022-03-08 17:51:07 +00:00
private fun createAssemblyAndAssemble ( program : Program ,
errors : IErrorReporter ,
compilerOptions : CompilationOptions
) : Boolean {
2022-02-06 17:57:23 +00:00
compilerOptions . compTarget . machine . initializeZeropage ( compilerOptions )
2022-03-04 22:08:05 +00:00
program . processAstBeforeAsmGeneration ( compilerOptions , errors )
2021-02-20 16:19:54 +00:00
errors . report ( )
2022-03-04 22:25:26 +00:00
val symbolTable = SymbolTableMaker ( ) . makeFrom ( program )
2021-02-09 00:13:38 +00:00
2022-02-10 22:20:19 +00:00
// TODO make removing all VarDecls work, but this needs inferType to be able to get its information from somewhere else as the VarDecl nodes in the Ast,
// or don't use inferType at all anymore and "bake the type information" into the Ast somehow.
// Note: we don't actually *need* to remove the VarDecl nodes, but it is nice as a temporary measure
// to help clean up the code that still depends on them.
// removeAllVardeclsFromAst(program)
2021-11-28 02:05:46 +00:00
// println("*********** AST RIGHT BEFORE ASM GENERATION *************")
// printProgram(program)
2021-02-09 00:13:38 +00:00
2022-03-05 13:26:33 +00:00
val assembly = asmGeneratorFor ( program , errors , symbolTable , compilerOptions ) . compileToAssembly ( )
2021-10-31 01:34:17 +00:00
errors . report ( )
2021-10-11 23:45:32 +00:00
2022-02-05 20:25:19 +00:00
return if ( assembly != null && errors . noErrors ( ) ) {
2022-03-11 18:54:30 +00:00
assembly . assemble ( compilerOptions )
2021-10-11 23:45:32 +00:00
} else {
2022-03-08 17:51:07 +00:00
false
2021-07-01 22:11:21 +00:00
}
2021-02-09 00:13:38 +00:00
}
2022-02-10 22:20:19 +00:00
private fun removeAllVardeclsFromAst ( program : Program ) {
// remove all VarDecl nodes from the AST.
// code generation doesn't require them anymore, it operates only on the 'variables' collection.
class SearchAndRemove : IAstVisitor {
private val allVars = mutableListOf < VarDecl > ( )
init {
visit ( program )
for ( it in allVars ) {
require ( ( it . parent as IStatementContainer ) . statements . remove ( it ) )
}
}
override fun visit ( decl : VarDecl ) {
allVars . add ( decl )
}
}
SearchAndRemove ( )
}
2021-11-20 16:33:02 +00:00
fun printProgram ( program : Program ) {
2021-02-09 00:13:38 +00:00
println ( )
2021-10-29 22:25:34 +00:00
val printer = AstToSourceTextConverter ( :: print , program )
printer . visit ( program )
2021-02-09 00:13:38 +00:00
println ( )
}
2022-03-04 22:25:26 +00:00
internal fun asmGeneratorFor ( program : Program ,
errors : IErrorReporter ,
symbolTable : SymbolTable ,
options : CompilationOptions ) : IAssemblyGenerator
2021-10-29 00:42:10 +00:00
{
2022-02-05 20:25:19 +00:00
if ( options . experimentalCodegen ) {
2022-03-10 20:28:35 +00:00
if ( options . compTarget . machine . cpu in arrayOf ( CpuType . CPU6502 , CpuType . CPU65c02 ) ) {
// TODO for now, only use the new Intermediary Ast for this experimental codegen:
2022-03-12 22:28:17 +00:00
val intermediateAst = IntermediateAstMaker ( program , options ) . transform ( )
2022-03-11 20:22:16 +00:00
return prog8 . codegen . experimental . AsmGen ( intermediateAst , errors , symbolTable , options )
2022-03-10 20:28:35 +00:00
}
2022-02-05 20:25:19 +00:00
} else {
if ( options . compTarget . machine . cpu in arrayOf ( CpuType . CPU6502 , CpuType . CPU65c02 ) )
2022-03-05 13:26:33 +00:00
return prog8 . codegen . cpu6502 . AsmGen ( program , errors , symbolTable , options )
2022-02-05 20:25:19 +00:00
}
throw NotImplementedError ( " no asm generator for cpu ${options.compTarget.machine.cpu} " )
2021-10-29 00:42:10 +00:00
}