mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-03 19:31:02 +00:00
Allow casting to wider types
This commit is contained in:
parent
9581891d66
commit
34b7107d27
@ -225,8 +225,17 @@ Other kinds of expressions than the above (even `nonet(byte + byte + byte)`) wil
|
||||
* `hi`, `lo`: most/least significant byte of a word
|
||||
`hi(word)`
|
||||
|
||||
Furthermore, any type that can be assigned to a variable
|
||||
can be used to convert from one type to another of the same size.
|
||||
Furthermore, any type that can be assigned to a variable can be used to convert
|
||||
either from one type either to another type of the same size,
|
||||
or from a 1-byte integer type to a compatible 2-byte integer type.
|
||||
|
||||
`byte` → `word`
|
||||
`word` → `pointer`
|
||||
some enum → `byte`
|
||||
`byte` → some enum
|
||||
but not
|
||||
`word` → `byte`
|
||||
some enum → `word`
|
||||
|
||||
|
||||
|
||||
|
@ -130,6 +130,24 @@ class AbstractExpressionCompiler[T <: AbstractCode] {
|
||||
}
|
||||
count <= 1
|
||||
}
|
||||
|
||||
def validateTypeCastAndGetSourceExpressionType(ctx: CompilationContext, typ: Type, params: List[Expression]): Type = {
|
||||
var failed = false
|
||||
if (typ.name == "pointer") {
|
||||
ctx.log.error("Cannot cast into pointer")
|
||||
failed = true
|
||||
}
|
||||
if (params.length != 1) {
|
||||
ctx.log.error("Type casting should have exactly one argument")
|
||||
failed = true
|
||||
}
|
||||
val sourceType = getExpressionType(ctx, params.head)
|
||||
if (typ.size != sourceType.size && !sourceType.isAssignableTo(typ)) {
|
||||
ctx.log.error("Cannot cast a type to an incompatible type of different size")
|
||||
failed = true
|
||||
}
|
||||
sourceType
|
||||
}
|
||||
}
|
||||
|
||||
object AbstractExpressionCompiler {
|
||||
|
@ -1066,22 +1066,9 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
case _ =>
|
||||
env.maybeGet[Type](f.functionName) match {
|
||||
case Some(typ) =>
|
||||
var failed = false
|
||||
if (typ.name == "pointer") {
|
||||
ctx.log.error("Cannot cast into pointer")
|
||||
failed = true
|
||||
}
|
||||
if (params.length != 1) {
|
||||
ctx.log.error("Type casting should have exactly one argument")
|
||||
failed = true
|
||||
}
|
||||
val sourceType = getExpressionType(ctx, params.head)
|
||||
if (typ.size != sourceType.size){
|
||||
ctx.log.error("Cannot cast a type to a type of different size")
|
||||
failed = true
|
||||
}
|
||||
val sourceType = validateTypeCastAndGetSourceExpressionType(ctx, typ, params)
|
||||
val newExprTypeAndVariable = exprTypeAndVariable.map(i => sourceType -> i._2)
|
||||
return if (failed) Nil else compile(ctx, params.head, newExprTypeAndVariable, branches)
|
||||
return compile(ctx, params.head, newExprTypeAndVariable, branches)
|
||||
case None =>
|
||||
// fallthrough to the lookup below
|
||||
}
|
||||
|
@ -782,20 +782,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
case _ =>
|
||||
env.maybeGet[Type](f.functionName) match {
|
||||
case Some(typ) =>
|
||||
var failed = false
|
||||
if (typ.name == "pointer") {
|
||||
ctx.log.error("Cannot cast into pointer")
|
||||
failed = true
|
||||
}
|
||||
if (params.length != 1) {
|
||||
ctx.log.error("Type casting should have exactly one argument")
|
||||
failed = true
|
||||
}
|
||||
val sourceType = getExpressionType(ctx, params.head)
|
||||
if (typ.size != sourceType.size) {
|
||||
ctx.log.error("Cannot cast a type to a type of different size")
|
||||
failed = true
|
||||
}
|
||||
val sourceType = validateTypeCastAndGetSourceExpressionType(ctx, typ, params)
|
||||
return sourceType.size match {
|
||||
case 1 => targetifyA(ctx, target, compileToA(ctx, params.head), isSigned = sourceType.isSigned)
|
||||
case 2 => targetifyHL(ctx, target, compileToHL(ctx, params.head))
|
||||
|
@ -20,6 +20,19 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
""".stripMargin)(_.readWord(0xc000) should equal(1280))
|
||||
}
|
||||
|
||||
test("Cast word addition") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)("""
|
||||
| byte output @$c000
|
||||
| word a
|
||||
| void main () {
|
||||
| output = add(155, 166)
|
||||
| }
|
||||
| byte add(byte a, byte b) {
|
||||
| return hi(word(a) + word(b))
|
||||
| }
|
||||
""".stripMargin)(_.readByte(0xc000) should equal(1))
|
||||
}
|
||||
|
||||
test("Word subtraction") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)("""
|
||||
| word output @$c000
|
||||
@ -132,7 +145,7 @@ class WordMathSuite extends FunSuite with Matchers {
|
||||
| output = get(5, 6)
|
||||
| }
|
||||
| byte get(byte mx, byte my) {
|
||||
| return map[((mx + 00000) << 5) + my]
|
||||
| return map[(word(mx) << 5) + my]
|
||||
| }
|
||||
""".stripMargin){ m =>
|
||||
m.readByte(0xc3a6) should equal(77)
|
||||
|
Loading…
Reference in New Issue
Block a user