aionnetwork / AVM

Enabling Java code to run in a blockchain environment
https://theoan.com/
MIT License
49 stars 25 forks source link

Extract TypeAwareClassWriter logic into separate classes #391

Closed aionick closed 5 years ago

aionick commented 5 years ago

The TypeAwareclassWriter has been loaded with a lot of logic to handle various situations. Better to pull this logic out, where we can, to separate classes that the writer can call when it needs to. This will also greatly improve our ability to unit test these separate pieces of functionality.

This is all related to the getCommonSuper() method. Essentially, the portions of logic that can be extracted are already in separate methods, it's mostly just a means of moving those methods out to another class and adding some unit test coverage to them.

aionick commented 5 years ago

The logic of the TypeAwareClassWriter will be pulled out into 3 classes: ArraySuperResolver, ExceptionWrapperSuperResolver and PlainTypeSuperResolver. Each of these 3 classes has a single method, to get the common super class of the two input types.

The array resolver will return null if neither of the two types are arrays, and will produce a super class if at least one of them is an array. This pattern holds for the other two resolvers; that is, they will produce an answer if at least one of the two types is a type they handle, otherwise null.

A 'plain type' is anything that is not an array or an exception wrapper, and so the 3 resolvers handle mutually exclusive types that, when combined, account for all types in the system.

So it is guaranteed that if all 3 resolvers are queried, a non-null super class will be produced. The class writer now simply calls into these 3 resolvers one by one, and returning once it first gets an answer.

The old logic of the TypeAwareClassWriter was doing something similar to this but because it asked these questions in a specific order it had logic at each stage that was able to take advantage of what it knew about the two input types from previous attempts to resolve them. Trying to extract this dependency across the classes would be awkward, fragile and bulky. So they were developed each as standalone entities such that the 3 resolvers can be queried in any order to produce the same answer.