mirror of https://github.com/KarolS/millfork.git
181 lines
7.7 KiB
Scala
181 lines
7.7 KiB
Scala
package millfork.node
|
|
|
|
import millfork.assembly.{AddrMode, Opcode}
|
|
import millfork.env.{Label, ParamPassingConvention}
|
|
|
|
case class Position(filename: String, line: Int, column: Int, cursor: Int)
|
|
|
|
sealed trait Node {
|
|
var position: Option[Position] = None
|
|
}
|
|
|
|
object Node {
|
|
implicit class NodeOps[N<:Node](val node: N) extends AnyVal {
|
|
def pos(position: Position): N = {
|
|
node.position = Some(position)
|
|
node
|
|
}
|
|
}
|
|
}
|
|
|
|
sealed trait Expression extends Node {
|
|
def replaceVariable(variable: String, actualParam: Expression): Expression
|
|
}
|
|
|
|
case class LiteralExpression(value: Long, requiredSize: Int) extends Expression {
|
|
override def replaceVariable(variable: String, actualParam: Expression): Expression = this
|
|
}
|
|
|
|
case class BooleanLiteralExpression(value: Boolean) extends Expression {
|
|
override def replaceVariable(variable: String, actualParam: Expression): Expression = this
|
|
}
|
|
|
|
sealed trait LhsExpression extends Expression
|
|
|
|
case object BlackHoleExpression extends LhsExpression {
|
|
override def replaceVariable(variable: String, actualParam: Expression): LhsExpression = this
|
|
}
|
|
|
|
case class SeparateBytesExpression(hi: Expression, lo: Expression) extends LhsExpression {
|
|
def replaceVariable(variable: String, actualParam: Expression): Expression =
|
|
SeparateBytesExpression(
|
|
hi.replaceVariable(variable, actualParam),
|
|
lo.replaceVariable(variable, actualParam))
|
|
}
|
|
|
|
case class SumExpression(expressions: List[(Boolean, Expression)], decimal: Boolean) extends Expression {
|
|
override def replaceVariable(variable: String, actualParam: Expression): Expression =
|
|
SumExpression(expressions.map { case (n, e) => n -> e.replaceVariable(variable, actualParam) }, decimal)
|
|
}
|
|
|
|
case class FunctionCallExpression(functionName: String, expressions: List[Expression]) extends Expression {
|
|
override def replaceVariable(variable: String, actualParam: Expression): Expression =
|
|
FunctionCallExpression(functionName, expressions.map {
|
|
_.replaceVariable(variable, actualParam)
|
|
})
|
|
}
|
|
|
|
case class HalfWordExpression(expression: Expression, hiByte: Boolean) extends Expression {
|
|
override def replaceVariable(variable: String, actualParam: Expression): Expression =
|
|
HalfWordExpression(expression.replaceVariable(variable, actualParam), hiByte)
|
|
}
|
|
|
|
object Register extends Enumeration {
|
|
val A, X, Y, AX, AY, YA, XA, XY, YX = Value
|
|
}
|
|
|
|
//case class Indexing(child: Expression, register: Register.Value) extends Expression
|
|
|
|
case class VariableExpression(name: String) extends LhsExpression {
|
|
override def replaceVariable(variable: String, actualParam: Expression): Expression =
|
|
if (name == variable) actualParam else this
|
|
}
|
|
|
|
case class IndexedExpression(name: String, index: Expression) extends LhsExpression {
|
|
override def replaceVariable(variable: String, actualParam: Expression): Expression =
|
|
if (name == variable) {
|
|
actualParam match {
|
|
case VariableExpression(actualVariable) => IndexedExpression(actualVariable, index.replaceVariable(variable, actualParam))
|
|
case _ => ??? // TODO
|
|
}
|
|
} else IndexedExpression(name, index.replaceVariable(variable, actualParam))
|
|
}
|
|
|
|
sealed trait Statement extends Node {
|
|
def getAllExpressions: List[Expression]
|
|
}
|
|
|
|
sealed trait DeclarationStatement extends Statement
|
|
|
|
case class TypeDefinitionStatement(name: String, parent: String) extends DeclarationStatement {
|
|
override def getAllExpressions: List[Expression] = Nil
|
|
}
|
|
|
|
case class VariableDeclarationStatement(name: String,
|
|
typ: String,
|
|
global: Boolean,
|
|
stack: Boolean,
|
|
constant: Boolean,
|
|
volatile: Boolean,
|
|
initialValue: Option[Expression],
|
|
address: Option[Expression]) extends DeclarationStatement {
|
|
override def getAllExpressions: List[Expression] = List(initialValue, address).flatten
|
|
}
|
|
|
|
case class ArrayDeclarationStatement(name: String,
|
|
length: Option[Expression],
|
|
address: Option[Expression],
|
|
elements: Option[List[Expression]]) extends DeclarationStatement {
|
|
override def getAllExpressions: List[Expression] = List(length, address).flatten ++ elements.getOrElse(Nil)
|
|
}
|
|
|
|
case class ParameterDeclaration(typ: String,
|
|
assemblyParamPassingConvention: ParamPassingConvention) extends Node
|
|
|
|
case class ImportStatement(filename: String) extends DeclarationStatement {
|
|
override def getAllExpressions: List[Expression] = Nil
|
|
}
|
|
|
|
case class FunctionDeclarationStatement(name: String,
|
|
resultType: String,
|
|
params: List[ParameterDeclaration],
|
|
address: Option[Expression],
|
|
statements: Option[List[Statement]],
|
|
inlined: Boolean,
|
|
assembly: Boolean,
|
|
interrupt: Boolean,
|
|
reentrant: Boolean) extends DeclarationStatement {
|
|
override def getAllExpressions: List[Expression] = address.toList ++ statements.getOrElse(Nil).flatMap(_.getAllExpressions)
|
|
}
|
|
|
|
sealed trait ExecutableStatement extends Statement
|
|
|
|
case class ExpressionStatement(expression: Expression) extends ExecutableStatement {
|
|
override def getAllExpressions: List[Expression] = List(expression)
|
|
}
|
|
|
|
case class ReturnStatement(value: Option[Expression]) extends ExecutableStatement {
|
|
override def getAllExpressions: List[Expression] = value.toList
|
|
}
|
|
|
|
case class Assignment(destination: LhsExpression, source: Expression) extends ExecutableStatement {
|
|
override def getAllExpressions: List[Expression] = List(destination, source)
|
|
}
|
|
|
|
case class LabelStatement(label: Label) extends ExecutableStatement {
|
|
override def getAllExpressions: List[Expression] = Nil
|
|
}
|
|
|
|
case class AssemblyStatement(opcode: Opcode.Value, addrMode: AddrMode.Value, expression: Expression, elidable: Boolean) extends ExecutableStatement {
|
|
override def getAllExpressions: List[Expression] = List(expression)
|
|
}
|
|
|
|
case class IfStatement(condition: Expression, thenBranch: List[ExecutableStatement], elseBranch: List[ExecutableStatement]) extends ExecutableStatement {
|
|
override def getAllExpressions: List[Expression] = condition :: (thenBranch ++ elseBranch).flatMap(_.getAllExpressions)
|
|
}
|
|
|
|
case class WhileStatement(condition: Expression, body: List[ExecutableStatement]) extends ExecutableStatement {
|
|
override def getAllExpressions: List[Expression] = condition :: body.flatMap(_.getAllExpressions)
|
|
}
|
|
|
|
object ForDirection extends Enumeration {
|
|
val To, Until, DownTo, ParallelTo, ParallelUntil = Value
|
|
}
|
|
|
|
case class ForStatement(variable: String, start: Expression, end: Expression, direction: ForDirection.Value, body: List[ExecutableStatement]) extends ExecutableStatement {
|
|
override def getAllExpressions: List[Expression] = start :: end :: body.flatMap(_.getAllExpressions)
|
|
}
|
|
|
|
case class DoWhileStatement(body: List[ExecutableStatement], condition: Expression) extends ExecutableStatement {
|
|
override def getAllExpressions: List[Expression] = condition :: body.flatMap(_.getAllExpressions)
|
|
}
|
|
|
|
case class BlockStatement(body: List[ExecutableStatement]) extends ExecutableStatement {
|
|
override def getAllExpressions: List[Expression] = body.flatMap(_.getAllExpressions)
|
|
}
|
|
|
|
object AssemblyStatement {
|
|
def implied(opcode: Opcode.Value, elidable: Boolean) = AssemblyStatement(opcode, AddrMode.Implied, LiteralExpression(0, 1), elidable)
|
|
|
|
def nonexistent(opcode: Opcode.Value) = AssemblyStatement(opcode, AddrMode.DoesNotExist, LiteralExpression(0, 1), elidable = true)
|
|
} |