1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-06-12 06:29:34 +00:00

Added #define directive

This commit is contained in:
Karol Stasiak 2019-06-26 13:43:15 +02:00
parent b85e175292
commit c9a65d5971
5 changed files with 53 additions and 2 deletions

View File

@ -60,6 +60,8 @@
* Preprocessor: Added `if` function
* Preprocessor: Added `#define` directive.
* Fixed volatile-related bugs.
* Fixed optimizations removing jumps to jumps.

View File

@ -148,6 +148,15 @@ Emits a diagnostic message.
Evaluates an expression and emits the result as a diagnostic message.
### `#define`
#define <ident> = <expr>
Defines a new feature value or redefines a previous feature value.
The feature value is visible only to the preprocessor, only when processing the current file,
and only in lines preprocessed after this one.
### `#use`
#use <ident> = <expr>

View File

@ -10,6 +10,8 @@ import c64_basic
import c264_basic
#endif
#define READKEY = CBM_64 | CBM_VIC | CBM_264 | CBM_128 | ZX_SPECTRUM | NEC_PC_88 | ATARI_8
void main () {
init_rand_seed()
ensure_mixedcase()
@ -60,5 +62,10 @@ void play_round() {
putword(guess_count)
putstrz(" attempts!"z)
new_line()
#if READKEY
putstrz("Press any key to play again."z)
readkey()
new_line()
#endif
new_line()
}

View File

@ -37,11 +37,12 @@ object Preprocessor {
var enabled = true
val ifStack = mutable.Stack[IfContext]()
var lineNo = 0
var currentFeatures = options.features
def evalParam(param: String, pos: Some[Position]): Long = {
new PreprocessorParser(options).expression.parse(param) match {
case Success(q, _) =>
val value = q.apply(options.features).getOrElse(0L)
val value = q.apply(currentFeatures).getOrElse(0L)
// log.trace(param + " ===> " + value)
value
case Failure(_, _, _) =>
@ -50,6 +51,17 @@ object Preprocessor {
}
}
def assertIdentifier(ident: String, pos: Option[Position]) : String = {
ident.foreach{
case ' ' => log.error("Unexpected space in a preprocessor identifier", pos)
case '_' => // ok
case c if c < 128 && Character.isDigit(c) => // ok
case c if c < 128 && Character.isLetter(c) => // ok
case _ => log.error("Invalid character in a preprocessor identifier", pos)
}
ident
}
for (line <- lines) {
lineNo += 1
var resulting = ""
@ -65,7 +77,13 @@ object Preprocessor {
log.warn(s"Undefined parameter $param, assuming 0", pos)
0L
})
case Array(p0,p1) => featureConstants += p0.trim() -> evalParam(p1, pos)
case Array(p0,p1) => featureConstants += assertIdentifier(p0.trim(), pos) -> evalParam(p1, pos)
}
}
case "define" => if (enabled) {
param.split("=", 2) match {
case Array(p0,p1) => currentFeatures += assertIdentifier(p0.trim(), pos) -> evalParam(p1, pos)
case _ => log.error("#define should have a parameter", pos)
}
}
case "fatal" => if (enabled) log.fatal(param, pos)

View File

@ -214,6 +214,21 @@ class BasicSymonTest extends FunSuite with Matchers {
| }
| #endif
|
| #if 1
| #define A=4
| #endif
| #if 0
| #define B=1
| #endif
|
| #if B
| #error B should not be defined
| #endif
|
| #if A != 4
| #error A should be defined
| #endif
|
| #if 1 + 1 == 2
| #info 1
| #if 1 == 3