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:
parent
ca35367974
commit
4f6eefab79
@ -18,9 +18,9 @@ Millfork has different operator precedence compared to most other languages. Fro
|
|||||||
|
|
||||||
* `->` and `[]`
|
* `->` 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.
|
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.
|
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 `-'`.
|
The only exceptions are `+` and `-`, and `$+` and `$-`.
|
||||||
They are interpreted as expected: `5 - 3 + 2 == 4` and `5 -' 3 +' 2 == 4`.
|
They are interpreted as expected: `5 - 3 + 2 == 4` and `5 $- 3 $+ 2 == 4`.
|
||||||
Note that you cannot mix `+'` and `-'` with `+` and `-`.
|
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.
|
i.e. `x / y / z` will not compile.
|
||||||
|
|
||||||
The decimal operators have two different forms:
|
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
|
* 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
|
On Ricoh-based targets (e.g. Famicom) they require the zeropage register to have size at least 4
|
||||||
|
|
||||||
* `+'`, `-'`: decimal addition/subtraction
|
* `$+`, `$-`: decimal addition/subtraction
|
||||||
`$+`, `$-`: (since Millfork 0.3.22)
|
`+'`, `-'`: (deprecated form)
|
||||||
`byte +' byte`
|
`byte $+ byte`
|
||||||
`constant word +' constant word`
|
`constant word $+ constant word`
|
||||||
`constant long +' constant long`
|
`constant long $+ constant long`
|
||||||
`word +' word` (zpreg)
|
`word $+ word` (zpreg)
|
||||||
|
|
||||||
* `*'`: decimal multiplication
|
* `$*`: decimal multiplication
|
||||||
`$*`: (since Millfork 0.3.22)
|
`*'`: (deprecated form)
|
||||||
`constant *' constant`
|
`constant $* constant`
|
||||||
|
|
||||||
* `<<'`, `>>'`: decimal multiplication/division by power of two
|
* `$<<`, `$>>`: decimal multiplication/division by power of two
|
||||||
`$<<`, `$>>`: (since Millfork 0.3.22)
|
`<<'`, `>>'`: (deprecated form)
|
||||||
`byte <<' constant byte`
|
`byte $<< constant byte`
|
||||||
|
|
||||||
## Comparison operators
|
## 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 word = word`
|
||||||
`mutable long = long`
|
`mutable long = long`
|
||||||
|
|
||||||
* `+=`, `+'=`, `|=`, `^=`, `&=`: modification in place
|
* `+=`, `$+=`, `|=`, `^=`, `&=`: modification in place
|
||||||
`$+=` (since Millfork 0.3.22)
|
`+'=` (deprecated form)
|
||||||
`mutable byte += byte`
|
`mutable byte += byte`
|
||||||
`mutable word += word`
|
`mutable word += word`
|
||||||
`mutable trivial long += long`
|
`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 word <<= byte`
|
||||||
`mutable trivial long <<= byte`
|
`mutable trivial long <<= byte`
|
||||||
|
|
||||||
* `<<'=`, `>>'=`: decimal shift in place
|
* `$<<=`, `$>>=`: decimal shift in place
|
||||||
`$<<=`, `$>>=` (since Millfork 0.3.22)
|
`<<'=`, `>>'=` (deprecated form)
|
||||||
`mutable byte <<'= constant byte`
|
`mutable byte $<<= constant byte`
|
||||||
`mutable word <<'= constant byte`
|
`mutable word $<<= constant byte`
|
||||||
`mutable trivial long <<'= constant byte`
|
`mutable trivial long $<<= constant byte`
|
||||||
|
|
||||||
* `-=`, `-'=`: subtraction in place
|
* `-=`, `$-=`: subtraction in place
|
||||||
`$-=` (since Millfork 0.3.22)
|
`-'=` (deprecated form)
|
||||||
`mutable byte -= byte`
|
`mutable byte -= byte`
|
||||||
`mutable word -= simple word`
|
`mutable word -= simple word`
|
||||||
`mutable trivial long -= simple long`
|
`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 *= unsigned byte` (zpreg)
|
||||||
`mutable word *= word` (zpreg)
|
`mutable word *= word` (zpreg)
|
||||||
|
|
||||||
* `*'=`: decimal multiplication in place
|
* `$*=`: decimal multiplication in place
|
||||||
`$*=` (since Millfork 0.3.22)
|
`*'=` (deprecated form)
|
||||||
`mutable byte *'= constant byte`
|
`mutable byte $*= constant byte`
|
||||||
|
|
||||||
* `/=`, `%%=`: unsigned division and modulo in place
|
* `/=`, `%%=`: unsigned division and modulo in place
|
||||||
`mutable unsigned byte /= unsigned byte` (zpreg)
|
`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`: expansion of an 8-bit operation to a 9-bit operation
|
||||||
`nonet(byte + byte)`
|
`nonet(byte + byte)`
|
||||||
`nonet(byte +' byte)`
|
`nonet(byte $+ byte)`
|
||||||
`nonet(byte << constant 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.
|
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
|
* `hi`, `lo`: most/least significant byte of a word
|
||||||
|
@ -151,11 +151,18 @@ The `if` function returns its second parameter if the first parameter is defined
|
|||||||
// prints 500:
|
// prints 500:
|
||||||
#infoeval if(0, 400, 500)
|
#infoeval if(0, 400, 500)
|
||||||
|
|
||||||
TODO
|
The `min` and `max` functions return the smallest or largest parameter respectively. They support any number of arguments:
|
||||||
`not`, `lo`, `hi`, `min`, `max` `+`, `-`, `*`, `|`, `&`, `^`, `||`, `&&`, `<<`, `>>`,`==`, `!=`, `>`, `>=`, `<`, `<=`
|
|
||||||
|
// 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:
|
The following Millfork operators and functions are not available in the preprocessor:
|
||||||
`+'`, `-'`, `*'`, `<<'`, `>>'`, `:`, `>>>>`, `nonet`, all the assignment operators
|
`$+`, `$-`, `$*`, `$<<`, `$>>`, `:`, `>>>>`, `nonet`, all the assignment operators
|
||||||
|
|
||||||
|
|
||||||
### Character literals
|
### Character literals
|
||||||
|
@ -456,11 +456,26 @@ abstract class MfParser[T](fileId: String, input: String, currentDirectory: Stri
|
|||||||
mfParenExpr(allowIntelHex) | derefExpression | a
|
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] = {
|
def mfExpression(level: Int, allowIntelHex: Boolean, allowTopLevelIndexing: Boolean = true): P[Expression] = {
|
||||||
val allowedOperators = mfOperatorsDropFlatten(level)
|
val allowedOperators = mfOperatorsDropFlatten(level)
|
||||||
|
|
||||||
def innerNowOperatorOrNothing: P[List[(String, (Boolean, Expression))]] = {
|
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{
|
(AWS ~/ P(innerNowTerm) ~/ HWS)).?.map{
|
||||||
case None => Nil
|
case None => Nil
|
||||||
case Some((op, rhs)) => rhs.toPairList(op)
|
case Some((op, rhs)) => rhs.toPairList(op)
|
||||||
|
@ -54,7 +54,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
|
|||||||
| run()
|
| run()
|
||||||
| }
|
| }
|
||||||
| void init() { output = $#i }
|
| void init() { output = $#i }
|
||||||
| void run () { output +'= $#j }
|
| void run () { output $+= $#j }
|
||||||
""".stripMargin.replace("#i", i.toString).replace("#j", j.toString)) { m =>
|
""".stripMargin.replace("#i", i.toString).replace("#j", j.toString)) { m =>
|
||||||
toDecimal(m.readByte(0xc000)) should equal((i + j) % 100)
|
toDecimal(m.readByte(0xc000)) should equal((i + j) % 100)
|
||||||
}
|
}
|
||||||
@ -68,7 +68,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
|
|||||||
| byte a
|
| byte a
|
||||||
| void main () {
|
| void main () {
|
||||||
| a = $50
|
| a = $50
|
||||||
| output = a -' $35
|
| output = a $- $35
|
||||||
| }
|
| }
|
||||||
""".stripMargin)(_.readByte(0xc000) should equal(0x15))
|
""".stripMargin)(_.readByte(0xc000) should equal(0x15))
|
||||||
}
|
}
|
||||||
@ -81,8 +81,8 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
|
|||||||
| void main () {
|
| void main () {
|
||||||
| a = 1
|
| a = 1
|
||||||
| output[1] = 5
|
| output[1] = 5
|
||||||
| output[a] +'= 1
|
| output[a] $+= 1
|
||||||
| output[a] +'= $36
|
| output[a] $+= $36
|
||||||
| }
|
| }
|
||||||
""".stripMargin)(_.readByte(0xc001) should equal(0x42))
|
""".stripMargin)(_.readByte(0xc001) should equal(0x42))
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
|
|||||||
| x = tmpx
|
| x = tmpx
|
||||||
| y = tmpy
|
| y = tmpy
|
||||||
| output[y] = $39
|
| output[y] = $39
|
||||||
| output[x] +'= 1
|
| output[x] $+= 1
|
||||||
| }
|
| }
|
||||||
| byte one() { return 1 }
|
| byte one() { return 1 }
|
||||||
""".stripMargin)(_.readByte(0xc001) should equal(0x40))
|
""".stripMargin)(_.readByte(0xc001) should equal(0x40))
|
||||||
@ -124,7 +124,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
|
|||||||
"""
|
"""
|
||||||
| word output @$c000
|
| word output @$c000
|
||||||
| void main () {
|
| void main () {
|
||||||
| output = f() +' g()
|
| output = f() $+ g()
|
||||||
| }
|
| }
|
||||||
| word f() {
|
| word f() {
|
||||||
| return $253
|
| return $253
|
||||||
@ -187,7 +187,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
|
|||||||
| void main () {
|
| void main () {
|
||||||
| output = addDecimal(9, 9) + addDecimal(9, 9)
|
| 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))
|
""".stripMargin)(_.readByte(0xc000) should equal(0x30))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +198,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
|
|||||||
| void main () {
|
| void main () {
|
||||||
| output = addDecimalTwice(9, 9)
|
| 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))
|
""".stripMargin)(_.readByte(0xc000) should equal(0x30))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
|
|||||||
| void main () {
|
| void main () {
|
||||||
| output = addDecimalTwice($c, $c)
|
| 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))
|
""".stripMargin)(_.readByte(0xc000) should equal(0x36))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,10 +398,10 @@ class ByteDecimalMathSuite extends FunSuite with Matchers with AppendedClues {
|
|||||||
| byte output @$c000
|
| byte output @$c000
|
||||||
| void main () {
|
| void main () {
|
||||||
| init()
|
| init()
|
||||||
| if output +' 1 == 0 {
|
| if output $+ 1 == 0 {
|
||||||
| output = $22
|
| output = $22
|
||||||
| }
|
| }
|
||||||
| output +'= 1
|
| output $+= 1
|
||||||
| }
|
| }
|
||||||
| void init() { output = $99 }
|
| void init() { output = $99 }
|
||||||
""".stripMargin
|
""".stripMargin
|
||||||
|
@ -448,7 +448,7 @@ class ForLoopSuite extends FunSuite with Matchers {
|
|||||||
| p = a.addr
|
| p = a.addr
|
||||||
| sum = 0
|
| 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,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,100 { sum &= a[i] }
|
||||||
| for i,0,until,50 { sum &= a[i+1] }
|
| for i,0,until,50 { sum &= a[i+1] }
|
||||||
|
@ -376,11 +376,11 @@ class PointerSuite extends FunSuite with Matchers with AppendedClues {
|
|||||||
| output2 = 0
|
| output2 = 0
|
||||||
| pointer.word value_pointer
|
| pointer.word value_pointer
|
||||||
| value_pointer = output2.pointer
|
| value_pointer = output2.pointer
|
||||||
| value_pointer[0] +'= constant
|
| value_pointer[0] $+= constant
|
||||||
| tmp[0] = output2
|
| tmp[0] = output2
|
||||||
| value_pointer[0] +'= constant
|
| value_pointer[0] $+= constant
|
||||||
| tmp[1] = output2
|
| tmp[1] = output2
|
||||||
| value_pointer[0] -'= constant
|
| value_pointer[0] $-= constant
|
||||||
| tmp[2] = output2
|
| tmp[2] = output2
|
||||||
| value_pointer[0] <<= f(1)
|
| value_pointer[0] <<= f(1)
|
||||||
| tmp[3] = output2
|
| tmp[3] = output2
|
||||||
|
Loading…
Reference in New Issue
Block a user