mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-19 19:30:08 +00:00
Added alias support
This commit is contained in:
parent
af1e6d9c9f
commit
35f3638a4f
@ -8,6 +8,8 @@
|
||||
|
||||
* Unified the syntax of commandline switches.
|
||||
|
||||
* Added aliases.
|
||||
|
||||
* Automatic selection of text encoding based on target platform.
|
||||
|
||||
* **Potentially breaking change!** `scr` now refers to the default screencodes as defined for the platform.
|
||||
|
@ -60,6 +60,28 @@ For every variable `x` larger than a byte, extra subvariables are defined:
|
||||
|
||||
TODO
|
||||
|
||||
### Alias definitions
|
||||
|
||||
`alias <alias> = <name>`
|
||||
|
||||
Sets an alias for a global name.
|
||||
Unless shadowed by a local name, the alias will point to the given global object:
|
||||
|
||||
byte x
|
||||
alias a = x
|
||||
|
||||
void f() {
|
||||
a = 5 // writes to the global variable x
|
||||
}
|
||||
|
||||
void f() {
|
||||
byte a
|
||||
a = 5 // writes to the local variable a
|
||||
}
|
||||
|
||||
Aliases can be used for variables, arrays, constants, functions, and types,
|
||||
but not for text encodings, array formats or keywords.
|
||||
|
||||
### Array declarations
|
||||
|
||||
An array is a continuous sequence of bytes in memory.
|
||||
|
17
src/main/scala/millfork/env/Environment.scala
vendored
17
src/main/scala/millfork/env/Environment.scala
vendored
@ -228,7 +228,10 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
if ((t ne null) && clazz.isInstance(t)) {
|
||||
t.asInstanceOf[T]
|
||||
} else {
|
||||
ErrorReporting.fatal(s"`$name` is not a ${clazz.getSimpleName}", position)
|
||||
t match {
|
||||
case Alias(_, target) => root.get[T](target)
|
||||
case _ => ErrorReporting.fatal(s"`$name` is not a ${clazz.getSimpleName}", position)
|
||||
}
|
||||
}
|
||||
} else parent.fold {
|
||||
ErrorReporting.fatal(s"${clazz.getSimpleName} `$name` is not defined", position)
|
||||
@ -236,6 +239,8 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
_.get[T](name, position)
|
||||
}
|
||||
}
|
||||
|
||||
private def root: Environment = parent.fold(this)(_.root)
|
||||
|
||||
def maybeGet[T <: Thing : Manifest](name: String): Option[T] = {
|
||||
if (things.contains(name)) {
|
||||
@ -244,7 +249,10 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
if ((t ne null) && clazz.isInstance(t)) {
|
||||
Some(t.asInstanceOf[T])
|
||||
} else {
|
||||
None
|
||||
t match {
|
||||
case Alias(_, target) => root.maybeGet[T](target)
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
} else parent.flatMap {
|
||||
_.maybeGet[T](name)
|
||||
@ -568,6 +576,10 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
}
|
||||
}
|
||||
|
||||
def registerAlias(stmt: AliasDefinitionStatement): Unit = {
|
||||
addThing(Alias(stmt.name, stmt.target), stmt.position)
|
||||
}
|
||||
|
||||
def registerFunction(stmt: FunctionDeclarationStatement, options: CompilationOptions): Unit = {
|
||||
val w = get[Type]("word")
|
||||
val name = stmt.name
|
||||
@ -1062,6 +1074,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
case f: FunctionDeclarationStatement => registerFunction(f, options)
|
||||
case v: VariableDeclarationStatement => registerVariable(v, options)
|
||||
case a: ArrayDeclarationStatement => registerArray(a, options)
|
||||
case a: AliasDefinitionStatement => registerAlias(a)
|
||||
case i: ImportStatement => ()
|
||||
}
|
||||
if (options.zpRegisterSize > 0 && !things.contains("__reg")) {
|
||||
|
2
src/main/scala/millfork/env/Thing.scala
vendored
2
src/main/scala/millfork/env/Thing.scala
vendored
@ -9,6 +9,8 @@ sealed trait Thing {
|
||||
def name: String
|
||||
}
|
||||
|
||||
case class Alias(name: String, target: String) extends Thing
|
||||
|
||||
sealed trait CallableThing extends Thing
|
||||
|
||||
sealed trait VariableLikeThing extends Thing
|
||||
|
@ -218,6 +218,10 @@ case class ProcessedContents(processor: String, values: ArrayContents) extends A
|
||||
ProcessedContents(processor, values.replaceVariable(variableToReplace, expression))
|
||||
}
|
||||
|
||||
case class AliasDefinitionStatement(name: String, target: String) extends DeclarationStatement {
|
||||
override def getAllExpressions: List[Expression] = Nil
|
||||
}
|
||||
|
||||
case class ArrayDeclarationStatement(name: String,
|
||||
bank: Option[String],
|
||||
length: Option[Expression],
|
||||
|
@ -163,6 +163,12 @@ abstract class MfParser[T](filename: String, input: String, currentDirectory: St
|
||||
|
||||
def arrayContentsForAsm: P[RawBytesStatement] = (arrayListContents | arrayStringContents).map(RawBytesStatement)
|
||||
|
||||
val aliasDefinition: P[Seq[AliasDefinitionStatement]] = for {
|
||||
p <- position()
|
||||
name <- "alias" ~ !letterOrDigit ~/ SWS ~ identifier ~ HWS
|
||||
target <- "=" ~/ HWS ~/ identifier ~/ HWS
|
||||
} yield Seq(AliasDefinitionStatement(name, target).pos(p))
|
||||
|
||||
val arrayDefinition: P[Seq[ArrayDeclarationStatement]] = for {
|
||||
p <- position()
|
||||
bank <- bankDeclaration
|
||||
@ -366,7 +372,7 @@ abstract class MfParser[T](filename: String, input: String, currentDirectory: St
|
||||
|
||||
val program: Parser[Program] = for {
|
||||
_ <- Start ~/ AWS ~/ Pass
|
||||
definitions <- (importStatement | arrayDefinition | functionDefinition | globalVariableDefinition).rep(sep = EOL)
|
||||
definitions <- (importStatement | arrayDefinition | aliasDefinition | functionDefinition | globalVariableDefinition).rep(sep = EOL)
|
||||
_ <- AWS ~ End
|
||||
} yield Program(definitions.flatten.toList)
|
||||
|
||||
|
@ -74,7 +74,7 @@ public class CPURAM {
|
||||
public final void write(int addr, int data) {
|
||||
addr &= 0xffff;
|
||||
if (!mem.writeable()[addr]) {
|
||||
throw new RuntimeException("Can't write to $" + Integer.toHexString(addr));
|
||||
throw new RuntimeException("Can't write $" + Integer.toHexString(data & 0xff) + "to $" + Integer.toHexString(addr));
|
||||
}
|
||||
mem.output()[addr] = (byte) data;
|
||||
}
|
||||
|
@ -149,4 +149,23 @@ class BasicSymonTest extends FunSuite with Matchers {
|
||||
| }
|
||||
""".stripMargin){ m => () }
|
||||
}
|
||||
|
||||
test("Alias test") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos)(
|
||||
"""
|
||||
| alias small = byte
|
||||
| alias big = word
|
||||
| byte crash @$bfff
|
||||
| void main () {
|
||||
| big w
|
||||
| small b
|
||||
| b = 1
|
||||
| w = 1
|
||||
| b <<= 8
|
||||
| w <<= 8
|
||||
| if b != 0 { crash = 1 }
|
||||
| if w == 0 { crash = 2 }
|
||||
| }
|
||||
""".stripMargin){ m => () }
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user