mirror of
https://github.com/DanilaFe/abacus
synced 2024-12-22 15:30:09 -08:00
Add the contexts and delegates for them.
This commit is contained in:
parent
fd246f935c
commit
f0e38fed87
|
@ -0,0 +1,26 @@
|
||||||
|
package org.nwapw.abacus.context
|
||||||
|
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A delegate to accumulate a collection of elements in a [ReductionContext] hierarchy.
|
||||||
|
*
|
||||||
|
* ChainAccumulateDelegate is similar to the [ChainSearchDelegate], however, it operates only on collections.
|
||||||
|
* Instead of returning the most recent collection, it merges them into a [Set].
|
||||||
|
*
|
||||||
|
* @param T the type of element in the collection.
|
||||||
|
* @property valueGetter the getter used to access the collection from the context.
|
||||||
|
*/
|
||||||
|
class ChainAccumulateDelegate<out T>(private val valueGetter: ReductionContext.() -> Collection<T>) {
|
||||||
|
|
||||||
|
operator fun getValue(selfRef: Any, property: KProperty<*>): Set<T> {
|
||||||
|
val set = mutableSetOf<T>()
|
||||||
|
var currentRef: ReductionContext = selfRef as? ReductionContext ?: return set
|
||||||
|
while(true) {
|
||||||
|
set.addAll(currentRef.valueGetter())
|
||||||
|
currentRef = currentRef.parent ?: break
|
||||||
|
}
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.nwapw.abacus.context
|
||||||
|
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A delegate to search a hierarchy made up of [ReductionContext].
|
||||||
|
*
|
||||||
|
* ChainSearchDelegate is a variable delegate written specifically for use in [ReductionContext], because
|
||||||
|
* of its hierarchical structure. Variables not found in the current context are searched
|
||||||
|
* for in its parent, which continues recursively until the context being examined has no parent.
|
||||||
|
* This class assists that logic, which is commonly re-used with different variable types, by calling
|
||||||
|
* [valueGetter] on the current context, then its parent, etc.
|
||||||
|
*
|
||||||
|
* @param V the type of the property to search recursively.
|
||||||
|
* @property valueGetter the getter lambda to access the value from the context.
|
||||||
|
*/
|
||||||
|
class ChainSearchDelegate<out V>(private val valueGetter: ReductionContext.() -> V?) {
|
||||||
|
|
||||||
|
operator fun getValue(selfRef: Any, property: KProperty<*>): V? {
|
||||||
|
var currentRef = selfRef as? ReductionContext ?: return null
|
||||||
|
var returnedValue = currentRef.valueGetter()
|
||||||
|
while (returnedValue == null) {
|
||||||
|
currentRef = currentRef.parent ?: break
|
||||||
|
returnedValue = currentRef.valueGetter()
|
||||||
|
}
|
||||||
|
return returnedValue
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
package org.nwapw.abacus.context
|
||||||
|
|
||||||
|
import org.nwapw.abacus.number.NumberInterface
|
||||||
|
import org.nwapw.abacus.plugin.NumberImplementation
|
||||||
|
import org.nwapw.abacus.tree.Reducer
|
||||||
|
import org.nwapw.abacus.tree.TreeNode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reduction context that is mutable.
|
||||||
|
* @param parent the parent of this context.
|
||||||
|
* @param numberImplementation the number implementation used in this context.
|
||||||
|
* @param reducer the reducer used in this context
|
||||||
|
*/
|
||||||
|
class MutableReductionContext(parent: ReductionContext? = null,
|
||||||
|
numberImplementation: NumberImplementation? = null,
|
||||||
|
reducer: Reducer<NumberInterface>? = null) :
|
||||||
|
ReductionContext(parent, numberImplementation, reducer) {
|
||||||
|
|
||||||
|
override var numberImplementation: NumberImplementation? = super.numberImplementation
|
||||||
|
override var reducer: Reducer<NumberInterface>? = super.reducer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes data stored in the [other] context over data stored in this one.
|
||||||
|
* @param other the context from which to copy data.
|
||||||
|
*/
|
||||||
|
fun apply(other: ReductionContext) {
|
||||||
|
if(other.numberImplementation != null) numberImplementation = other.numberImplementation
|
||||||
|
if(other.reducer != null) reducer = other.reducer
|
||||||
|
for(name in other.variables) {
|
||||||
|
setVariable(name, other.getVariable(name) ?: continue)
|
||||||
|
}
|
||||||
|
for(name in other.definitions) {
|
||||||
|
setDefinition(name, other.getDefinition(name) ?: continue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a variable to a certain [value].
|
||||||
|
* @param name the name of the variable.
|
||||||
|
* @param value the value of the variable.
|
||||||
|
*/
|
||||||
|
fun setVariable(name: String, value: NumberInterface) {
|
||||||
|
variableMap[name] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a definition to a certain [value].
|
||||||
|
* @param name the name of the definition.
|
||||||
|
* @param value the value of the definition.
|
||||||
|
*/
|
||||||
|
fun setDefinition(name: String, value: TreeNode) {
|
||||||
|
definitionMap[name] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the variables defined in this context.
|
||||||
|
*/
|
||||||
|
fun clearVariables(){
|
||||||
|
variableMap.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the definitions defined in this context.
|
||||||
|
*/
|
||||||
|
fun clearDefinitions(){
|
||||||
|
definitionMap.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
package org.nwapw.abacus.context
|
||||||
|
|
||||||
|
import org.nwapw.abacus.number.NumberInterface
|
||||||
|
import org.nwapw.abacus.plugin.NumberImplementation
|
||||||
|
import org.nwapw.abacus.tree.Reducer
|
||||||
|
import org.nwapw.abacus.tree.TreeNode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A context for the reduction of a [org.nwapw.abacus.tree.TreeNode] into a number.
|
||||||
|
*
|
||||||
|
* The reduction context is used to carry important state information captured at the beginning
|
||||||
|
* of the reduction of an expression, such as the variables and the implementation in use.
|
||||||
|
*
|
||||||
|
* @property parent the parent of this context.
|
||||||
|
* @property numberImplementation the implementation for numbers of this context.
|
||||||
|
* @property reducer the reducer used by this context.
|
||||||
|
*/
|
||||||
|
open class ReductionContext(val parent: ReductionContext? = null,
|
||||||
|
open val numberImplementation: NumberImplementation? = null,
|
||||||
|
open val reducer: Reducer<NumberInterface>? = null) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map of variables in this context.
|
||||||
|
*/
|
||||||
|
protected val variableMap = mutableMapOf<String, NumberInterface>()
|
||||||
|
/**
|
||||||
|
* The map of definitions in this context.
|
||||||
|
*/
|
||||||
|
protected val definitionMap = mutableMapOf<String, TreeNode>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The set of all variable names defined in this context.
|
||||||
|
*/
|
||||||
|
val variables: Set<String>
|
||||||
|
get() = variableMap.keys
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The set of all definition names defined in this context.
|
||||||
|
*/
|
||||||
|
val definitions: Set<String>
|
||||||
|
get() = definitionMap.keys
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The implementation inherited from this context's parent.
|
||||||
|
*/
|
||||||
|
val inheritedNumberImplementation: NumberImplementation?
|
||||||
|
by ChainSearchDelegate { numberImplementation}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The reducer inherited from this context's parent.
|
||||||
|
*/
|
||||||
|
val inheritedReducer: Reducer<NumberInterface>?
|
||||||
|
by ChainSearchDelegate { reducer }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The set of all variables in this context and its parents.
|
||||||
|
*/
|
||||||
|
val inheritedVariables: Set<String> by ChainAccumulateDelegate { variables }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The set of all definition in this context and its parents.
|
||||||
|
*/
|
||||||
|
val inheritedDefinitions: Set<String> by ChainAccumulateDelegate { definitions }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new child instance of this context that is mutable.
|
||||||
|
* @return the new child instance.
|
||||||
|
*/
|
||||||
|
fun mutableSubInstance(): MutableReductionContext = MutableReductionContext(this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a variable stored in this context.
|
||||||
|
*/
|
||||||
|
fun getVariable(name: String): NumberInterface? {
|
||||||
|
return variableMap[name] ?: parent?.getVariable(name)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Gets the definition stored in this context.
|
||||||
|
*/
|
||||||
|
fun getDefinition(name: String): TreeNode? {
|
||||||
|
return definitionMap[name] ?: parent?.getDefinition(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user