millfork/src/main/scala/millfork/env/Thing.scala

264 lines
7.2 KiB
Scala

package millfork.env
import millfork.assembly.Opcode
import millfork.error.ErrorReporting
import millfork.node._
sealed trait Thing {
def name: String
}
sealed trait Type extends Thing {
def size: Int
def isSigned: Boolean
def isSubtypeOf(other: Type): Boolean = this == other
def isCompatible(other: Type): Boolean = this == other
override def toString(): String = name
def isAssignableTo(targetType: Type): Boolean = isCompatible(targetType)
}
case object VoidType extends Type {
def size = 0
def isSigned = false
override def name = "void"
}
sealed trait PlainType extends Type {
override def isCompatible(other: Type): Boolean = this == other || this.isSubtypeOf(other) || other.isSubtypeOf(this)
override def isAssignableTo(targetType: Type): Boolean = isCompatible(targetType) || (targetType match {
case BasicPlainType(_, size) => size > this.size // TODO
case _ => false
})
}
case class BasicPlainType(name: String, size: Int) extends PlainType {
def isSigned = false
override def isSubtypeOf(other: Type): Boolean = this == other
}
case class DerivedPlainType(name: String, parent: PlainType, isSigned: Boolean) extends PlainType {
def size: Int = parent.size
override def isSubtypeOf(other: Type): Boolean = parent == other || parent.isSubtypeOf(other)
}
sealed trait BooleanType extends Type {
def size = 0
def isSigned = false
}
case class ConstantBooleanType(name: String, value: Boolean) extends BooleanType
case class FlagBooleanType(name: String, jumpIfTrue: Opcode.Value, jumpIfFalse: Opcode.Value) extends BooleanType
case object BuiltInBooleanType extends BooleanType {
override def name = "bool$"
}
sealed trait TypedThing extends Thing {
def typ: Type
}
sealed trait ThingInMemory extends Thing {
def toAddress: Constant
}
sealed trait PrellocableThing extends ThingInMemory {
def shouldGenerate: Boolean
def address: Option[Constant]
def toAddress: Constant = address.getOrElse(MemoryAddressConstant(this))
}
case class Label(name: String) extends ThingInMemory {
override def toAddress: MemoryAddressConstant = MemoryAddressConstant(this)
}
sealed trait Variable extends TypedThing
case class BlackHole(typ: Type) extends Variable {
override def name = "<black hole>"
}
sealed trait VariableInMemory extends Variable with ThingInMemory {
def zeropage: Boolean
}
case class RegisterVariable(register: Register.Value, typ: Type) extends Variable {
def name: String = register.toString
}
case class Placeholder(name: String, typ: Type) extends Variable
sealed trait UninitializedMemory extends ThingInMemory {
def sizeInBytes: Int
def alloc: VariableAllocationMethod.Value
}
object VariableAllocationMethod extends Enumeration {
val Auto, Static, Zeropage, None = Value
}
case class StackVariable(name: String, typ: Type, baseOffset: Int) extends Variable {
def sizeInBytes: Int = typ.size
}
case class MemoryVariable(name: String, typ: Type, alloc: VariableAllocationMethod.Value) extends VariableInMemory with UninitializedMemory {
override def sizeInBytes: Int = typ.size
override def zeropage: Boolean = alloc == VariableAllocationMethod.Zeropage
override def toAddress: MemoryAddressConstant = MemoryAddressConstant(this)
}
trait MlArray extends ThingInMemory
case class UninitializedArray(name: String, sizeInBytes: Int) extends MlArray with UninitializedMemory {
override def toAddress: MemoryAddressConstant = MemoryAddressConstant(this)
override def alloc = VariableAllocationMethod.Static
}
case class RelativeArray(name: String, address: Constant, sizeInBytes: Int) extends MlArray {
override def toAddress: Constant = address
}
case class InitializedArray(name: String, address: Option[Constant], contents: List[Constant]) extends MlArray with PrellocableThing {
override def shouldGenerate = true
}
case class RelativeVariable(name: String, address: Constant, typ: Type, zeropage: Boolean) extends VariableInMemory {
override def toAddress: Constant = address
}
sealed trait MangledFunction extends Thing {
def name: String
def returnType: Type
def params: ParamSignature
def interrupt: Boolean
}
case class EmptyFunction(name: String,
returnType: Type,
paramType: Type) extends MangledFunction {
override def params = EmptyFunctionParamSignature(paramType)
override def interrupt = false
}
case class InlinedFunction(name: String,
returnType: Type,
params: ParamSignature,
environment: Environment,
code: List[ExecutableStatement]) extends MangledFunction {
override def interrupt = false
}
sealed trait FunctionInMemory extends MangledFunction with ThingInMemory {
def environment: Environment
}
case class ExternFunction(name: String,
returnType: Type,
params: ParamSignature,
address: Constant,
environment: Environment) extends FunctionInMemory {
override def toAddress: Constant = address
override def interrupt = false
}
case class NormalFunction(name: String,
returnType: Type,
params: ParamSignature,
environment: Environment,
stackVariablesSize: Int,
address: Option[Constant],
code: List[ExecutableStatement],
interrupt: Boolean,
reentrant: Boolean,
position: Option[Position]) extends FunctionInMemory with PrellocableThing {
override def shouldGenerate = true
}
case class ConstantThing(name: String, value: Constant, typ: Type) extends TypedThing
trait ParamSignature {
def types: List[Type]
def length: Int
}
case class NormalParamSignature(params: List[MemoryVariable]) extends ParamSignature {
override def length: Int = params.length
override def types: List[Type] = params.map(_.typ)
}
sealed trait ParamPassingConvention {
def inInlinedOnly: Boolean
def inNonInlinedOnly: Boolean
}
case class ByRegister(register: Register.Value) extends ParamPassingConvention {
override def inInlinedOnly = false
override def inNonInlinedOnly = false
}
case class ByVariable(name: String) extends ParamPassingConvention {
override def inInlinedOnly = false
override def inNonInlinedOnly = true
}
case class ByConstant(name: String) extends ParamPassingConvention {
override def inInlinedOnly = true
override def inNonInlinedOnly = false
}
case class ByReference(name: String) extends ParamPassingConvention {
override def inInlinedOnly = true
override def inNonInlinedOnly = false
}
object AssemblyParameterPassingBehaviour extends Enumeration {
val Copy, ByReference, ByConstant = Value
}
case class AssemblyParam(typ: Type, variable: TypedThing, behaviour: AssemblyParameterPassingBehaviour.Value)
case class AssemblyParamSignature(params: List[AssemblyParam]) extends ParamSignature {
override def length: Int = params.length
override def types: List[Type] = params.map(_.typ)
}
case class EmptyFunctionParamSignature(paramType: Type) extends ParamSignature {
override def length: Int = 1
override def types: List[Type] = List(paramType)
}