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

com.jtransc.ast.dependency.analyzer.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.dependency

import com.jtransc.ast.*
import com.jtransc.error.noImpl

object AstDependencyAnalyzer {
	@JvmStatic fun analyze(program: AstProgram, body: AstBody?): AstReferences {
		val types = hashSetOf()
		val fields = hashSetOf()
		val methods = hashSetOf()

		fun ana(type: AstType) = types.addAll(type.getRefTypesFqName())
		fun ana(types: List) = types.map { ana(it) }

		fun ana(expr: AstExpr?) {
			if (expr == null) return
			when (expr) {
				is AstExpr.CAST -> {
					ana(expr.from)
					ana(expr.to)
					ana(expr.expr)
				}
				is AstExpr.NEW -> {
					ana(expr.target)
				}
				is AstExpr.NEW_ARRAY -> {
					for (c in expr.counts) ana(c)
					ana(expr.element)
				}
				is AstExpr.ARRAY_ACCESS -> {
					ana(expr.type)
					ana(expr.array)
					ana(expr.index)
				}
				is AstExpr.ARRAY_LENGTH -> {
					ana(expr.array)
				}
				is AstExpr.BINOP -> {
					ana(expr.left)
					ana(expr.right)
				}
				is AstExpr.CALL_BASE -> {
					ana(expr.method.type)
					for (arg in expr.args) ana(arg)
					methods.add(expr.method)
					if (expr is AstExpr.CALL_INSTANCE) ana(expr.obj)
				}
				is AstExpr.CAUGHT_EXCEPTION -> {
					ana(expr.type)
				}
				is AstExpr.CLASS_CONSTANT -> {
					types.addAll(expr.type.getRefTypesFqName())
				}
				is AstExpr.INSTANCE_FIELD_ACCESS -> {
					ana(expr.expr)
					fields.add(expr.field)
				}
				is AstExpr.STATIC_FIELD_ACCESS -> {
					fields.add(expr.field)
				}
				is AstExpr.INSTANCE_OF -> {
					ana(expr.checkType)
				}
				is AstExpr.UNOP -> ana(expr.right)
				is AstExpr.THIS -> {
					ana(expr.type)
				}
				is AstExpr.LITERAL -> {
				}
				is AstExpr.LOCAL -> {
				}
				is AstExpr.PARAM -> {
					ana(expr.type)
				}
				is AstExpr.METHOD_CLASS -> {
					ana(expr.type)
					ana(expr.methodToConvertRef.allClassRefs.map { it.type })
				}
				else -> noImpl("Not implemented $expr")
			}
		}

		fun ana(stm: AstStm?) {
			if (stm == null) return
			when (stm) {
				is AstStm.STMS -> for (s in stm.stms) ana(s)
				is AstStm.STM_EXPR -> ana(stm.expr)
				is AstStm.GOTO -> {
				}
				is AstStm.CONTINUE -> {
				}
				is AstStm.BREAK -> {
				}
				is AstStm.STM_LABEL -> {
				}
				is AstStm.IF_GOTO -> ana(stm.cond)
				is AstStm.MONITOR_ENTER -> ana(stm.expr)
				is AstStm.MONITOR_EXIT -> ana(stm.expr)
				is AstStm.SET -> ana(stm.expr)
				is AstStm.SET_ARRAY -> {
					ana(stm.expr); ana(stm.index)
				}
				is AstStm.SET_FIELD_INSTANCE -> {
					fields.add(stm.field); ana(stm.left); ana(stm.expr)
				}
				is AstStm.SET_FIELD_STATIC -> {
					fields.add(stm.field);  ana(stm.expr)
				}
				is AstStm.RETURN -> ana(stm.retval)
				is AstStm.IF -> {
					ana(stm.cond); ana(stm.strue); ana(stm.sfalse)
				}
				is AstStm.THROW -> ana(stm.value)
				is AstStm.WHILE -> {
					ana(stm.cond); ana(stm.iter)
				}
				is AstStm.TRY_CATCH -> {
					ana(stm.trystm);
					ana(stm.catch)
					/*
					for (catch in stm.catches) {
						ana(catch.first)
						ana(catch.second)
					}
					*/
				}
				is AstStm.SWITCH_GOTO -> {
					ana(stm.subject)
				}
				is AstStm.SWITCH -> {
					ana(stm.subject); ana(stm.default)
					for (catch in stm.cases) ana(catch.second)
				}
				is AstStm.SET_NEW_WITH_CONSTRUCTOR -> {
					ana(stm.target)
					ana(stm.method.type)
					for (arg in stm.args) {
						ana(arg)
					}
				}
				else -> throw NotImplementedError("Not implemented STM $stm")
			}
		}

		if (body != null) {
			for (local in body.locals) ana(local.type)

			ana(body.stm)
		}

		return AstReferences(
			program = program,
			classes = types.map { AstClassRef(it) }.toSet(),
			fields = fields.toSet(),
			methods = methods.toSet()
		)
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy