millfork/src/main/scala/millfork/node/Node.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)
}