1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-12-22 16:31:02 +00:00

Officially deprecate old decimal operators

This commit is contained in:
Karol Stasiak 2021-05-23 22:31:11 +02:00
parent ca35367974
commit 4f6eefab79
6 changed files with 74 additions and 52 deletions

View File

@ -18,9 +18,9 @@ Millfork has different operator precedence compared to most other languages. Fro
* `->` and `[]`
* `*`, `*'`, `/`, `%%`
* `*`, `$*`, `/`, `%%`
* `+`, `+'`, `-`, `-'`, `|`, `&`, `^`, `>>`, `>>'`, `<<`, `<<'`, `>>>>`
* `+`, `$+`, `-`, `$-`, `|`, `&`, `^`, `>>`, `$>>`, `<<`, `$<<`, `>>>>`
* `:`
@ -34,16 +34,16 @@ Millfork has different operator precedence compared to most other languages. Fro
You cannot use two different operators at the same precedence levels without using parentheses to disambiguate.
It is to prevent confusion about whether `a + b & c << d` means `(a + b) & (c << d)` `((a + b) & c) << d` or something else.
The only exceptions are `+` and `-`, and `+'` and `-'`.
They are interpreted as expected: `5 - 3 + 2 == 4` and `5 -' 3 +' 2 == 4`.
Note that you cannot mix `+'` and `-'` with `+` and `-`.
The only exceptions are `+` and `-`, and `$+` and `$-`.
They are interpreted as expected: `5 - 3 + 2 == 4` and `5 $- 3 $+ 2 == 4`.
Note that you cannot mix `$+` and `$-` with `+` and `-`.
Certain operators (`/`, `%%`, `<<`, `>>`, `<<'`, `>>'`, `>>>>`, `:`, `!=`) cannot have more than 2 parameters,
Certain operators (`/`, `%%`, `<<`, `>>`, `$<<`, `$>>`, `>>>>`, `:`, `!=`) cannot have more than 2 parameters,
i.e. `x / y / z` will not compile.
The decimal operators have two different forms:
* apostrophe form (e.g. `+'`) the original one, to be deprecated in the future, may be removed in Millfork 0.4
* apostrophe form (e.g. `+'`) the original one, deprecated, will be removed in Millfork 0.4
* dollar form (e.g. `$+`) available since Millfork 0.3.22
@ -135,20 +135,20 @@ These operators work using the decimal arithmetic (packed BCD).
On Ricoh-based targets (e.g. Famicom) they require the zeropage register to have size at least 4
* `+'`, `-'`: decimal addition/subtraction
`$+`, `$-`: (since Millfork 0.3.22)
`byte +' byte`
`constant word +' constant word`
`constant long +' constant long`
`word +' word` (zpreg)
* `$+`, `$-`: decimal addition/subtraction
`+'`, `-'`: (deprecated form)
`byte $+ byte`
`constant word $+ constant word`
`constant long $+ constant long`
`word $+ word` (zpreg)
* `*'`: decimal multiplication
`$*`: (since Millfork 0.3.22)
`constant *' constant`
* `$*`: decimal multiplication
`*'`: (deprecated form)
`constant $* constant`
* `<<'`, `>>'`: decimal multiplication/division by power of two
`$<<`, `$>>`: (since Millfork 0.3.22)
`byte <<' constant byte`
* `$<<`, `$>>`: decimal multiplication/division by power of two
`<<'`, `>>'`: (deprecated form)
`byte $<< constant byte`
## Comparison operators
@ -201,8 +201,8 @@ An expression of form `a[f()] += b` may call `f` an undefined number of times.
`mutable word = word`
`mutable long = long`
* `+=`, `+'=`, `|=`, `^=`, `&=`: modification in place
`$+=` (since Millfork 0.3.22)
* `+=`, `$+=`, `|=`, `^=`, `&=`: modification in place
`+'=` (deprecated form)
`mutable byte += byte`
`mutable word += word`
`mutable trivial long += long`
@ -212,14 +212,14 @@ An expression of form `a[f()] += b` may call `f` an undefined number of times.
`mutable word <<= byte`
`mutable trivial long <<= byte`
* `<<'=`, `>>'=`: decimal shift in place
`$<<=`, `$>>=` (since Millfork 0.3.22)
`mutable byte <<'= constant byte`
`mutable word <<'= constant byte`
`mutable trivial long <<'= constant byte`
* `$<<=`, `$>>=`: decimal shift in place
`<<'=`, `>>'=` (deprecated form)
`mutable byte $<<= constant byte`
`mutable word $<<= constant byte`
`mutable trivial long $<<= constant byte`
* `-=`, `-'=`: subtraction in place
`$-=` (since Millfork 0.3.22)
* `-=`, `$-=`: subtraction in place
`-'=` (deprecated form)
`mutable byte -= byte`
`mutable word -= simple word`
`mutable trivial long -= simple long`
@ -230,9 +230,9 @@ An expression of form `a[f()] += b` may call `f` an undefined number of times.
`mutable word *= unsigned byte` (zpreg)
`mutable word *= word` (zpreg)
* `*'=`: decimal multiplication in place
`$*=` (since Millfork 0.3.22)
`mutable byte *'= constant byte`
* `$*=`: decimal multiplication in place
`*'=` (deprecated form)
`mutable byte $*= constant byte`
* `/=`, `%%=`: unsigned division and modulo in place
`mutable unsigned byte /= unsigned byte` (zpreg)
@ -291,9 +291,9 @@ but you can access its fields or take its pointer:
* `nonet`: expansion of an 8-bit operation to a 9-bit operation
`nonet(byte + byte)`
`nonet(byte +' byte)`
`nonet(byte $+ byte)`
`nonet(byte << constant byte)`
`nonet(byte <<' constant byte)`
`nonet(byte $<< constant byte)`
Other kinds of expressions than the above (even `nonet(byte + byte + byte)`) will not work as expected.
* `hi`, `lo`: most/least significant byte of a word

View File

@ -151,11 +151,18 @@ The `if` function returns its second parameter if the first parameter is defined
// prints 500:
#infoeval if(0, 400, 500)
TODO
`not`, `lo`, `hi`, `min`, `max` `+`, `-`, `*`, `|`, `&`, `^`, `||`, `&&`, `<<`, `>>`,`==`, `!=`, `>`, `>=`, `<`, `<=`
The `min` and `max` functions return the smallest or largest parameter respectively. They support any number of arguments:
// prints 400:
#infoeval min(400, 500, 600)
// prints 500:
#infoeval max(400, 500)
The following Millfork operators and functions are also available in the preprocessor:
`not`, `lo`, `hi`, `+`, `-`, `*`, `|`, `&`, `^`, `||`, `&&`, `<<`, `>>`,`==`, `!=`, `>`, `>=`, `<`, `<=`
The following Millfork operators and functions are not available in the preprocessor:
`+'`, `-'`, `*'`, `<<'`, `>>'`, `:`, `>>>>`, `nonet`, all the assignment operators
`$+`, `$-`, `$*`, `$<<`, `$>>`, `:`, `>>>>`, `nonet`, all the assignment operators
### Character literals

View File

@ -456,11 +456,26 @@ abstract class MfParser[T](fileId: String, input: String, currentDirectory: Stri
mfParenExpr(allowIntelHex) | derefExpression | a
}
def normalizeOperator(op: String, pos: Position): String = {
if (mfOperatorNormalizations.contains(op)) return mfOperatorNormalizations(op)
if (op.contains('\'')) {
if (options.flag(CompilationFlag.DeprecationWarning)) {
mfOperatorNormalizations.find(_._2.==(op)).map(_._1) match {
case None =>
log.warn(s"Operator $op is deprecated and will be removed in 0.4", Some(pos))
case Some(newOp) =>
log.warn(s"Operator $op is deprecated and will be removed in 0.4, since 0.3.22 you should use $newOp as a replacement", Some(pos))
}
}
}
op
}
def mfExpression(level: Int, allowIntelHex: Boolean, allowTopLevelIndexing: Boolean = true): P[Expression] = {
val allowedOperators = mfOperatorsDropFlatten(level)
def innerNowOperatorOrNothing: P[List[(String, (Boolean, Expression))]] = {
((StringIn(allowedOperators: _*).! ~ !CharIn(Seq('/', '=', '-', '+', ':', '>', '<', '\''))).map(op => if (mfOperatorNormalizations.contains(op)) mfOperatorNormalizations(op) else op) ~/
((position() ~ StringIn(allowedOperators: _*).! ~ !CharIn(Seq('/', '=', '-', '+', ':', '>', '<', '\''))).map{ case (pos, op) => normalizeOperator(op, pos) } ~/
(AWS ~/ P(innerNowTerm) ~/ HWS)).?.map{
case None => Nil
case Some((op, rhs)) => rhs.toPairList(op)

View File

@ -54,7 +54,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
| run()
| }
| void init() { output = $#i }
| void run () { output +'= $#j }
| void run () { output $+= $#j }
""".stripMargin.replace("#i", i.toString).replace("#j", j.toString)) { m =>
toDecimal(m.readByte(0xc000)) should equal((i + j) % 100)
}
@ -68,7 +68,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
| byte a
| void main () {
| a = $50
| output = a -' $35
| output = a $- $35
| }
""".stripMargin)(_.readByte(0xc000) should equal(0x15))
}
@ -81,8 +81,8 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
| void main () {
| a = 1
| output[1] = 5
| output[a] +'= 1
| output[a] +'= $36
| output[a] $+= 1
| output[a] $+= $36
| }
""".stripMargin)(_.readByte(0xc001) should equal(0x42))
}
@ -101,7 +101,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
| x = tmpx
| y = tmpy
| output[y] = $39
| output[x] +'= 1
| output[x] $+= 1
| }
| byte one() { return 1 }
""".stripMargin)(_.readByte(0xc001) should equal(0x40))
@ -124,7 +124,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
"""
| word output @$c000
| void main () {
| output = f() +' g()
| output = f() $+ g()
| }
| word f() {
| return $253
@ -187,7 +187,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
| void main () {
| output = addDecimal(9, 9) + addDecimal(9, 9)
| }
| byte addDecimal(byte a, byte b) { return a +' b }
| byte addDecimal(byte a, byte b) { return a $+ b }
""".stripMargin)(_.readByte(0xc000) should equal(0x30))
}
@ -198,7 +198,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
| void main () {
| output = addDecimalTwice(9, 9)
| }
| byte addDecimalTwice(byte a, byte b) { return (a +' b) + (a +' b) }
| byte addDecimalTwice(byte a, byte b) { return (a $+ b) + (a $+ b) }
""".stripMargin)(_.readByte(0xc000) should equal(0x30))
}
@ -209,7 +209,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
| void main () {
| output = addDecimalTwice($c, $c)
| }
| byte addDecimalTwice(byte a, byte b) { return (a + b) +' (a + b) }
| byte addDecimalTwice(byte a, byte b) { return (a + b) $+ (a + b) }
""".stripMargin)(_.readByte(0xc000) should equal(0x36))
}
@ -398,10 +398,10 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
| byte output @$c000
| void main () {
| init()
| if output +' 1 == 0 {
| if output $+ 1 == 0 {
| output = $22
| }
| output +'= 1
| output $+= 1
| }
| void init() { output = $99 }
""".stripMargin

View File

@ -448,7 +448,7 @@ class ForLoopSuite extends FunSuite with Matchers {
| p = a.addr
| sum = 0
| for i,0,paralleluntil,100 { sum += a[i] }
| for i,0,paralleluntil,100 { sum +'= a[i] }
| for i,0,paralleluntil,100 { sum $+= a[i] }
| for i,0,paralleluntil,100 { sum &= a[i] }
| for i,0,until,100 { sum &= a[i] }
| for i,0,until,50 { sum &= a[i+1] }

View File

@ -376,11 +376,11 @@ class PointerSuite extends FunSuite with Matchers with AppendedClues {
| output2 = 0
| pointer.word value_pointer
| value_pointer = output2.pointer
| value_pointer[0] +'= constant
| value_pointer[0] $+= constant
| tmp[0] = output2
| value_pointer[0] +'= constant
| value_pointer[0] $+= constant
| tmp[1] = output2
| value_pointer[0] -'= constant
| value_pointer[0] $-= constant
| tmp[2] = output2
| value_pointer[0] <<= f(1)
| tmp[3] = output2