All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jtransc.ast.ast_body.kt Maven / Gradle / Ivy

There is a newer version: 0.6.8
Show newest version
package com.jtransc.ast

data class AstBody(
	val stm: AstStm,
	val locals: List,
	val traps: List
)

enum class AstBinop(val symbol: String, val str: String) {
	ADD("+", "add"), SUB("-", "sub"), MUL("*", "mul"), DIV("/", "div"), REM("%", "rem"),
	AND("&", "and"), OR("|", "or"), XOR("^", "xor"),
	SHL("<<", "shl"), SHR(">>", "shr"), USHR(">>>", "ushr"),
	BAND("&&", "band"), BOR("||", "bor"),
	EQ("==", "eq"), NE("!=", "ne"), GE(">=", "ge"), LE("<=", "le"), LT("<", "lt"), GT(">", "gt"),
	LCMP("lcmp", "lcmp"), CMP("cmp", "cmp"), CMPL("cmpl", "cml"), CMPG("cmpg", "cmpg");

	companion object {
		//val operators = values.flatMap { listOf(Pair(it.symbol, it), Pair(it.str, it)) }.toMap()
	}
}

enum class AstUnop(val symbol: String, val str: String) {
	NEG("-", "neg"),
	NOT("!", "not"),
	INV("~", "inv");

	companion object {
		//val operators = values.flatMap { listOf(Pair(it.symbol, it), Pair(it.str, it)) }.toMap()
	}
}

data class AstLocal(val index: Int, val name: String, val type: AstType) {
	override fun toString() = "AstLocal:$name:$type"
}

data class AstTrap(val start: AstLabel, val end: AstLabel, val handler: AstLabel, val exception: AstType.REF)

data class AstLabel(val name: String)

interface AstElement

interface AstStm : AstElement {
	data class STMS(val stms: List) : AstStm {
		constructor(vararg stms: AstStm) : this(stms.toList())
	}

	data class NOP(val dummy: Any? = null) : AstStm
	data class STM_EXPR(val expr: AstExpr) : AstStm
	data class SET(val local: AstLocal, val expr: AstExpr) : AstStm
	data class SET_ARRAY(val local: AstLocal, val index: AstExpr, val expr: AstExpr) : AstStm
	data class SET_FIELD_STATIC(val clazz: AstType.REF, val field: AstFieldRef, val expr: AstExpr, val isInterface: Boolean) : AstStm
	data class SET_FIELD_INSTANCE(val left: AstExpr, val field: AstFieldRef, val expr: AstExpr) : AstStm
	data class SET_NEW_WITH_CONSTRUCTOR(val local: AstLocal, val target: AstType.REF, val method: AstMethodRef, val args: List) : AstStm

	data class IF(val cond: AstExpr, val strue: AstStm, val sfalse: AstStm? = null) : AstStm
	data class WHILE(val cond: AstExpr, val iter: AstStm) : AstStm
	data class RETURN(val retval: AstExpr?) : AstStm
	data class THROW(val value: AstExpr) : AstStm

	object RETHROW : AstStm

	//data class TRY_CATCH(val trystm: AstStm, val catches: List>) : AstStm
	data class TRY_CATCH(val trystm: AstStm, val catch: AstStm) : AstStm

	class BREAK() : AstStm
	class CONTINUE() : AstStm

	// SwitchFeature
	data class SWITCH(val subject: AstExpr, val default: AstStm, val cases: List>) : AstStm

	// GotoFeature

	data class STM_LABEL(val label: AstLabel) : AstStm
	data class IF_GOTO(val cond: AstExpr, val label: AstLabel) : AstStm
	data class SWITCH_GOTO(val subject: AstExpr, val default: AstLabel, val cases: List>) : AstStm
	data class GOTO(val label: AstLabel) : AstStm

	data class MONITOR_ENTER(val expr: AstExpr) : AstStm
	data class MONITOR_EXIT(val expr: AstExpr) : AstStm
}

interface AstExpr : AstElement {
	open val type: AstType

	interface ImmutableRef : AstExpr
	interface LValueExpr : AstExpr

	data class THIS(val ref: FqName) : LValueExpr {
		override val type: AstType = AstType.REF(ref)
	}

	data class CLASS_CONSTANT(val classType: AstType) : AstExpr {
		override val type: AstType = AstType.GENERIC(AstType.REF("java.lang.Class"), listOf(classType))
	}

	data class LITERAL(val value: Any?) : AstExpr {
		override val type: AstType = when (value) {
			null -> AstType.NULL
			is Boolean -> AstType.BOOL
			is Byte -> AstType.BYTE
			is Char -> AstType.CHAR
			is Short -> AstType.SHORT
			is Int -> AstType.INT
			is Long -> AstType.LONG
			is Float -> AstType.FLOAT
			is Double -> AstType.DOUBLE
			is String -> AstType.STRING
			else -> throw NotImplementedError("Literal type: $value")
		}
	}

	data class LOCAL(val local: AstLocal) : LValueExpr {
		override val type = local.type
	}

	data class PARAM(val argument: AstArgument) : LValueExpr {
		override val type = argument.type
	}

	data class CAUGHT_EXCEPTION(override val type: AstType = AstType.OBJECT) : AstExpr
	data class BINOP(override val type: AstType, val left: AstExpr, val op: AstBinop, val right: AstExpr) : AstExpr

	data class UNOP(val op: AstUnop, val right: AstExpr) : AstExpr {
		override val type = right.type
	}

	interface CALL_BASE : AstExpr {
		//override val type = method.type.ret
		val method: AstMethodRef
		val args: List
		val isSpecial: Boolean
	}

	data class CALL_INSTANCE(val obj: AstExpr, override val method: AstMethodRef, override val args: List, override val isSpecial: Boolean = false) : CALL_BASE {
		override val type = method.type.ret
	}

	data class CALL_SUPER(val obj: AstExpr, val target: FqName, override val method: AstMethodRef, override val args: List, override val isSpecial: Boolean = false) : CALL_BASE {
		override val type = method.type.ret
	}

	data class CALL_STATIC(val clazz: AstType.REF, override val method: AstMethodRef, override val args: List, override val isSpecial: Boolean = false) : CALL_BASE {
		//val clazz: AstType.REF = method.classRef.type
		override val type = method.type.ret
	}

	data class ARRAY_LENGTH(val array: AstExpr) : AstExpr {
		override val type = AstType.INT
	}

	data class ARRAY_ACCESS(val array: AstExpr, val index: AstExpr) : LValueExpr {
		override val type = array.type.elementType
	}

	data class INSTANCE_FIELD_ACCESS(val expr: AstExpr, val field: AstFieldRef, override val type: AstType) : LValueExpr
	data class STATIC_FIELD_ACCESS(val clazzName: AstType.REF, val field: AstFieldRef, override val type: AstType, val isInterface: Boolean) : LValueExpr

	data class INSTANCE_OF(val expr: AstExpr, val checkType: AstType) : AstExpr {
		override val type = AstType.BOOL
	}

	data class CAST(val expr: AstExpr, val to: AstType) : AstExpr {
		val from: AstType get() = expr.type

		override val type = to
	}

	data class NEW(val target: AstType.REF) : AstExpr {
		override val type = target
	}

	data class NEW_WITH_CONSTRUCTOR(val target: AstType.REF, val method: AstMethodRef, val args: List) : AstExpr {
		override val type = target
	}

	data class NEW_ARRAY(val element: AstType, val counts: List) : AstExpr {
		override val type = AstType.ARRAY(element, counts.size)
	}

	data class METHOD_CLASS(
		val methodInInterfaceRef: AstMethodRef,
		val methodToConvertRef: AstMethodRef
	) : AstExpr {
		override val type = AstType.REF(methodInInterfaceRef.containingClass)
	}

	infix fun ge(that: AstExpr) = AstExpr.BINOP(AstType.BOOL, this, AstBinop.GE, that)
	infix fun le(that: AstExpr) = AstExpr.BINOP(AstType.BOOL, this, AstBinop.LE, that)
	infix fun band(that: AstExpr) = AstExpr.BINOP(AstType.BOOL, this, AstBinop.BAND, that)
	infix fun and(that: AstExpr) = AstExpr.BINOP(this.type, this, AstBinop.AND, that)
	infix fun instanceof(that: AstType) = AstExpr.INSTANCE_OF(this, that)
}

open class AstTransformer {
	open fun visit(type: AstType) {
	}

	open fun transform(body: AstBody): AstBody {
		for (local in body.locals) visit(local.type)
		return AstBody(
			stm = transform(body.stm),
			locals = body.locals,
			traps = body.traps
		)
	}

	open fun transform(stm: AstStm): AstStm = when (stm) {
		is AstStm.STMS -> transform(stm)
		else -> throw NotImplementedError("Unhandled statement $stm")
	}

	open fun transform(stm: AstStm.STMS): AstStm = AstStm.STMS(stm.stms.map { transform(stm) })

	open fun transform(expr: AstExpr): AstExpr = when (expr) {
	//else -> expr
		else -> throw NotImplementedError("Unhandled expression $expr")
	}
}

val AstLocal.expr: AstExpr.LOCAL get() = AstExpr.LOCAL(this)
val Iterable.stms: AstStm get() = AstStm.STMS(this.toList())
val Any?.lit: AstExpr get() = AstExpr.LITERAL(this)




© 2015 - 2025 Weber Informatics LLC | Privacy Policy