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

com.jtransc.ast.transform.combinenewinit.kt Maven / Gradle / Ivy

There is a newer version: 0.6.8
Show newest version
/*
 * Copyright 2016 Carlos Ballesteros Velasco
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.jtransc.ast.transform

import com.jtransc.ast.*
import java.util.*

object CombineNewInitTransform : AstTransform() {
	private fun transform(stms: ArrayList) {
		var newToLocal = hashMapOf>()

		for (n in 0 until stms.size) {
			val stm = stms[n]

			// empty NEW
			if (stm is AstStm.SET && stm.expr is AstExpr.NEW) {
				val setLocal = stm.local
				val newExpr = stm.expr
				newToLocal[setLocal] = Pair(n, newExpr.type)
			}

			// CALL  constructor method
			if (stm is AstStm.STM_EXPR && stm.expr is AstExpr.CALL_INSTANCE) {
				val callExpr = stm.expr as AstExpr.CALL_INSTANCE

				val callLocal = if (callExpr.obj is AstExpr.LOCAL) {
					callExpr.obj.local
				} else if (callExpr.obj is AstExpr.CAST && callExpr.obj.expr is AstExpr.LOCAL) {
					callExpr.obj.expr.local
				} else {
					null
				}

				if (callLocal != null) {
					if (callExpr.isSpecial && callExpr.method.name == "") {
						if (callLocal in newToLocal) {
							val (instantiateIndex, instantiateType) = newToLocal[callLocal]!!
							if (callExpr.method.containingClass != instantiateType.name) {
								throw AssertionError("Unexpected new +  call!")
							}
							stms[instantiateIndex] = AstStm.NOP()
							stms[n] = AstStm.SET_NEW_WITH_CONSTRUCTOR(callLocal, instantiateType, callExpr.method, callExpr.args)
							newToLocal.remove(callLocal)
						}
					}
				}
			}
		}

		// All new must have their  counterpart!, so we assert that!
        // TODO Commented, but important for kotlin classes that must be initializated!!
		//assert(newToLocal.isEmpty())
		if (newToLocal.isNotEmpty()) {
			println("WARNING (combining new+): $newToLocal couldn't combine. This would make native instantiations to fail, otherwise this will work just fine.")
			//println(stms.joinToString("\n"))
		}
	}

	override fun invoke(body: AstBody): AstBody {
		if (body.stm is AstStm.STMS) {
			val stms = (body.stm as AstStm.STMS).stms.toCollection(arrayListOf())
			transform(stms)
			return AstBody(AstStm.STMS(stms.filter { it !is AstStm.NOP }), body.locals, body.traps)
		}

		return body
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy