Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add missing features #473

Merged
merged 14 commits into from
Feb 2, 2024
2 changes: 1 addition & 1 deletion silver
Submodule silver updated 22 files
+2 −2 src/test/resources/all/heap-dependent_triggers/triggerFoldPackage.vpr
+4 −4 src/test/resources/all/heap-dependent_triggers/triggerWand.vpr
+1 −1 src/test/resources/all/impure_assume/assume10QPwand.vpr
+0 −1 src/test/resources/all/issues/silicon/0388.vpr
+0 −2 src/test/resources/all/issues/silicon/0493c.vpr
+0 −1 src/test/resources/all/issues/silicon/0496.vpr
+0 −3 src/test/resources/all/issues/silicon/0678b.vpr
+4 −4 src/test/resources/all/permission_introspection/forpermPredicatesAdvanced.vpr
+1 −1 src/test/resources/all/permission_introspection/forpermQP.vpr
+4 −4 src/test/resources/all/permission_introspection/forpermWands.vpr
+3 −4 src/test/resources/all/permission_introspection/permWandAlias.vpr
+3 −4 src/test/resources/all/permission_introspection/permWandApply.vpr
+3 −4 src/test/resources/all/permission_introspection/permWandInhale.vpr
+3 −4 src/test/resources/all/permission_introspection/permWandQP.vpr
+0 −1 src/test/resources/quantifiedcombinations/independence.vpr
+0 −1 src/test/resources/quantifiedpredicates/basic/independence.vpr
+0 −1 src/test/resources/quantifiedpredicates/basic/partial_permissions.vpr
+0 −1 src/test/resources/wands/new_syntax/ApplyingBranching.vpr
+0 −1 src/test/resources/wands/new_syntax/ApplyingExpression.vpr
+0 −1 src/test/resources/wands/new_syntax/SnapshotsWithPredicates.vpr
+0 −2 src/test/resources/wands/regression/snapshots.vpr
+0 −1 src/test/resources/wands/regression/wand_shapes_simple_exhale.vpr
23 changes: 7 additions & 16 deletions src/main/scala/viper/carbon/modules/HeapModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -92,23 +92,15 @@ trait HeapModule extends Module with CarbonStateComponent {
def predicateGhostFieldDecl(f: sil.Predicate): Seq[Decl]

/**
* Translation of a resource access (field read/write, predicate or wand instance)
* Translation of a field read, predicate instance, or wand instance.
*/
def translateResourceAccess(r: sil.ResourceAccess): Exp = r match {
case la: LocationAccess => translateLocationAccess(la)
case mw: MagicWand => sys.error(s"Unexpectedly found magic wand $mw")
}

/**
* Translation of a field read or predicate instance
*/
def translateLocationAccess(f: sil.LocationAccess): Exp
def translateResourceAccess(f: sil.ResourceAccess): Exp
/**
* Translation of a field read.
*/
def translateLocationAccess(rcv: Exp, loc:Exp):Exp

def translateLocation(f: sil.LocationAccess): Exp
def translateResource(f: sil.ResourceAccess): Exp
def translateLocation(pred: sil.Predicate, args: Seq[Exp]): Exp

/**
Expand Down Expand Up @@ -147,15 +139,14 @@ trait HeapModule extends Module with CarbonStateComponent {
def isPredicateField(f: Exp): Exp

/**
* get Predicate Id (unique for each Predicate)
* get Predicate or wand Id (unique for each Predicate or wand)
*/
def getPredicateId(f:Exp): Exp
def getPredicateOrWandId(f:Exp): Exp

/**
* Predicate name mapping to Id
* Predicate or (internal) wand name mapping to Id
*/

def getPredicateId(s:String):BigInt
def getPredicateOrWandId(s:String):BigInt
/**
* Is the given field a wand field?
*/
Expand Down
7 changes: 2 additions & 5 deletions src/main/scala/viper/carbon/modules/PermModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,12 @@ trait PermModule extends Module with CarbonStateComponent {

def zeroPMask: Exp

def hasDirectPerm(la: sil.LocationAccess): Exp

def permissionLookup(la: sil.LocationAccess) : Exp
/** FIXME: duplicate method, here */
def hasDirectPerm(ra: sil.ResourceAccess): Exp

/**
* The expression for the current permission at a location.
*/
def currentPermission(loc: sil.LocationAccess): Exp
def currentPermission(loc: sil.ResourceAccess): Exp

def currentPermission(rcv:Exp, loc:Exp):Exp

Expand Down
6 changes: 5 additions & 1 deletion src/main/scala/viper/carbon/modules/WandModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ package viper.carbon.modules
import viper.carbon.modules.components.{ComponentRegistry, TransferComponent}
import viper.silver.verifier.PartialVerificationError
import viper.silver.{ast => sil}
import viper.carbon.boogie.{Exp, LocalVar, Stmt, TrueLit}
import viper.carbon.boogie.{Exp, Identifier, LocalVar, Stmt, TrueLit}
marcoeilers marked this conversation as resolved.
Show resolved Hide resolved


trait WandModule extends Module with ComponentRegistry[TransferComponent] {
Expand Down Expand Up @@ -61,6 +61,10 @@ trait WandModule extends Module with ComponentRegistry[TransferComponent] {

def getWandRepresentation(w: sil.MagicWand):Exp

def getWandRepresentationWithArgs(w: sil.MagicWand, args: Seq[sil.Exp]):Exp

def getWandName(w: sil.MagicWand): String

/**
* Translates the 'apply' statements to the corresponding Boogie statements
* the 'statesStackForPackageStmt', 'allStateAssms' and 'insidePackageStmt' parameters are used when being called inside a package statement
Expand Down
62 changes: 27 additions & 35 deletions src/main/scala/viper/carbon/modules/impls/DefaultExpModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,13 @@ class DefaultExpModule(val verifier: Verifier) extends ExpModule with Definednes
case [email protected](_) =>
translateResult(r)
case [email protected](_, _) =>
translateLocationAccess(f)
translateResourceAccess(f)
case sil.InhaleExhaleExp(_, _) =>
sys.error("should not occur here (either, we inhale or exhale this expression, in which case whenInhaling/whenExhaling should be used, or the expression is not allowed to occur.")
case [email protected](_, _) =>
translateLocationAccess(p)
translateResourceAccess(p)
case w: sil.MagicWand =>
translateResourceAccess(w)
case sil.Unfolding(_, exp) =>
translateExp(exp)
case sil.Applying(_, exp) => translateExp(exp)
Expand Down Expand Up @@ -144,41 +146,39 @@ class DefaultExpModule(val verifier: Verifier) extends ExpModule with Definednes
}
case sil.ForPerm(variables, accessRes, body) => {

val variable = variables.head

if (variables.length != 1) sys.error("Carbon only supports a single quantified variable in forperm, see Carbon issue #243")
if (variable.typ != Ref) sys.error("Carbon only supports Ref type in forperm, see Carbon issue #243")
accessRes match {
case _: MagicWand => sys.error("Carbon does not support magic wands in forperm, see Carbon issue #243")
case p: PredicateAccess => if (p.loc(program).formalArgs.length != 1) sys.error("Carbon only supports predicates with a single argument in forperm, see Carbon issue #243")
case _ =>
}

val locations = Seq(accessRes.asInstanceOf[LocationAccess].loc(program))
val locations = Seq(accessRes)

// alpha renaming, to avoid clashes in context
val renamedVar: sil.LocalVarDecl = {
val renamedVars: Seq[sil.LocalVarDecl] = variables.map(variable => {
val v1 = env.makeUniquelyNamed(variable); env.define(v1.localVar); v1
}
val renaming = (e: sil.Exp) => Expressions.instantiateVariables(e, Seq(variable.localVar), Seq(renamedVar.localVar))
// val ts = triggers map (t => Trigger(t.exps map {e => verifier.funcPredModule.toTriggers(translateExp(renaming(e)))} // no triggers yet?
val perLocFilter: sil.Location => (Exp, Trigger) = loc => {
val locAccess: LocationAccess = loc match {
case f: sil.Field => sil.FieldAccess(renamedVar.localVar, f)(loc.pos, loc.info)
case p: sil.Predicate => sil.PredicateAccess(Seq(renamedVar.localVar), p)(loc.pos, loc.info, loc.errT)
})
val renaming = (e: sil.Exp) => Expressions.instantiateVariables(e, variables.map(_.localVar), renamedVars.map(_.localVar))
val perResFilter: sil.ResourceAccess => (Exp, Seq[Trigger]) = resAcc => {
val zipped = variables.map(_.localVar) zip renamedVars.map(_.localVar)
val replacements = zipped.toMap

val substitutedResAccess: sil.ResourceAccess = resAcc match {
case fa: sil.FieldAccess =>
sil.FieldAccess(renamedVars.head.localVar, fa.field)(fa.pos, fa.info)
marcoeilers marked this conversation as resolved.
Show resolved Hide resolved
case pp: sil.PredicateAccess =>
pp.replace(replacements)
case w: sil.MagicWand =>
w.replace(replacements)
}
(hasDirectPerm(locAccess), Trigger(permissionLookup(locAccess)))
val maskRead = currentPermission(substitutedResAccess)
val heapRead = translateResourceAccess(substitutedResAccess)
(hasDirectPerm(substitutedResAccess), Seq(Trigger(maskRead), Trigger(heapRead)))
}
val filter = locations.foldLeft[(Exp, Seq[Trigger])](BoolLit(false), Seq())((soFar, loc) => soFar match {
case (exp, triggers) =>
perLocFilter(loc) match {
case (newExp, newTrigger) => (BinExp(exp, Or, newExp), triggers ++ Seq(newTrigger))
perResFilter(loc) match {
case (newExp, newTriggers) => (BinExp(exp, Or, newExp), triggers ++ newTriggers)
}
})

val res = Forall(translateLocalVarDecl(renamedVar), filter._2, // no triggers yet :(
val res = Forall(renamedVars.map(renamedVar => translateLocalVarDecl(renamedVar)), filter._2, // no triggers yet :(
BinExp(filter._1, Implies, translateExp(renaming(body))))
env.undefine(renamedVar.localVar)
renamedVars.foreach(renamedVar => env.undefine(renamedVar.localVar))
res
}
case sil.WildcardPerm() =>
Expand Down Expand Up @@ -430,15 +430,7 @@ class DefaultExpModule(val verifier: Verifier) extends ExpModule with Definednes
val res = if (e.isInstanceOf[sil.ForPerm]) {
val eAsForallRef = Expressions.renameVariables(e, orig_vars.map(_.localVar), bound_vars.map(_.localVar)).asInstanceOf[sil.ForPerm]

if (eAsForallRef.variables.length != 1) sys.error("Carbon only supports a single quantified variable in forperm, see Carbon issue #243")
if (eAsForallRef.variables.head.typ != Ref) sys.error("Carbon only supports Ref type in forperm, see Carbon issue #243")
eAsForallRef.resource match {
case _: MagicWand => sys.error("Carbon does not support magic wands in forperm, see Carbon issue #243")
case p: PredicateAccess => if (p.loc(program).formalArgs.length != 1) sys.error("Carbon only supports predicates with a single argument in forperm, see Carbon issue #243")
case _ =>
}

val filter: Exp = hasDirectPerm(eAsForallRef.resource.asInstanceOf[LocationAccess])
val filter: Exp = hasDirectPerm(eAsForallRef.resource)

handleQuantifiedLocals(bound_vars, If(filter, translate(eAsForallRef, definednessStateOpt), Nil))
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ with DefinednessComponent with ExhaleComponent with InhaleComponent {
}
assertion match {
case [email protected](la, perm) =>
val fragmentBody = translateLocationAccess(renaming(la).asInstanceOf[sil.LocationAccess])
val fragmentBody = translateResourceAccess(renaming(la).asInstanceOf[sil.LocationAccess])
val fragment = if (s.isInstanceOf[PredicateAccessPredicate]) fragmentBody else frameFragment(fragmentBody)
if (permModule.conservativeIsPositivePerm(perm)) fragment else
FuncApp(condFrameName, Seq(translatePerm(renaming(perm)),fragment),frameType)
Expand Down Expand Up @@ -962,7 +962,7 @@ with DefinednessComponent with ExhaleComponent with InhaleComponent {
val location = acc.loc
val predicate = verifier.program.findPredicate(location.predicateName)
val translatedArgs = location.args map (x => translateExpInWand(x))
Assume(translateLocationAccess(location) === getPredicateFrame(predicate,translatedArgs)._1)
Assume(translateResourceAccess(location) === getPredicateFrame(predicate,translatedArgs)._1)
}

foldInfo = null
Expand Down Expand Up @@ -999,7 +999,7 @@ with DefinednessComponent with ExhaleComponent with InhaleComponent {
val location = acc.loc
val predicate = verifier.program.findPredicate(location.predicateName)
val translatedArgs = location.args map translateExp
Assume(translateLocationAccess(location) === getPredicateFrame(predicate,translatedArgs)._1)
Assume(translateResourceAccess(location) === getPredicateFrame(predicate,translatedArgs)._1)
} ++
(if(exhaleUnfoldedPredicate)
exhaleSingleWithoutDefinedness(acc, error, havocHeap = false, statesStackForPackageStmt = statesStackForPackageStmt, insidePackageStmt = insidePackageStmt)
Expand Down
35 changes: 19 additions & 16 deletions src/main/scala/viper/carbon/modules/impls/DefaultHeapModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class DefaultHeapModule(val verifier: Verifier)
private var PredIdMap:Map[String, BigInt] = Map()
private var NextPredicateId:BigInt = 0
private val isWandFieldName = Identifier("IsWandField")
private val getPredicateIdName = Identifier("getPredicateId")
private val getPredicateOrWandIdName = Identifier("getPredWandId")
private val sumHeapName = Identifier("SumHeap")
private val readHeapName = Identifier("readHeap")
private val updateHeapName = Identifier("updHeap")
Expand Down Expand Up @@ -167,7 +167,7 @@ class DefaultHeapModule(val verifier: Verifier)
Func(isWandFieldName,
Seq(LocalVarDecl(Identifier("f"), fieldType)),
Bool) ++
Func(getPredicateIdName,
Func(getPredicateOrWandIdName,
Seq(LocalVarDecl(Identifier("f"), fieldType)),
Int) ++
{
Expand Down Expand Up @@ -413,11 +413,11 @@ class DefaultHeapModule(val verifier: Verifier)
}

// returns predicate Id
override def getPredicateId(f:Exp): Exp = {
FuncApp(getPredicateIdName,Seq(f), Int)
override def getPredicateOrWandId(f:Exp): Exp = {
FuncApp(getPredicateOrWandIdName,Seq(f), Int)
}

override def getPredicateId(s:String): BigInt = {
override def getPredicateOrWandId(s:String): BigInt = {
if (!PredIdMap.contains(s)) {
val predId:BigInt = getNewPredId;
PredIdMap += (s -> predId)
Expand Down Expand Up @@ -447,7 +447,7 @@ class DefaultHeapModule(val verifier: Verifier)
val pmT = predicateMaskFieldTypeOf(p)
val varDecls = p.formalArgs map mainModule.translateLocalVarDecl
val vars = varDecls map (_.l)
val predId:BigInt = getPredicateId(p.name)
val predId:BigInt = getPredicateOrWandId(p.name)
val f0 = FuncApp(predicate, vars, t)
val f1 = predicateMaskField(f0)
val f2 = FuncApp(pmField, vars, pmT)
Expand All @@ -456,7 +456,7 @@ class DefaultHeapModule(val verifier: Verifier)
Func(pmField, varDecls, pmT) ++
Axiom(MaybeForall(varDecls, Trigger(f1), f1 === f2)) ++
Axiom(MaybeForall(varDecls, Trigger(f0), isPredicateField(f0))) ++
Axiom(MaybeForall(varDecls, Trigger(f0), getPredicateId(f0) === IntLit(predId))) ++
Axiom(MaybeForall(varDecls, Trigger(f0), getPredicateOrWandId(f0) === IntLit(predId))) ++
Func(predicateTriggerIdentifier(p), Seq(LocalVarDecl(heapName, heapTyp), LocalVarDecl(Identifier("pred"), predicateVersionFieldType())), Bool) ++
Func(predicateTriggerAnyStateIdentifier(p), Seq(LocalVarDecl(Identifier("pred"), predicateVersionFieldType())), Bool) ++
{
Expand Down Expand Up @@ -537,7 +537,7 @@ class DefaultHeapModule(val verifier: Verifier)
}
override def predicateTrigger(extras : Seq[Exp], pred: sil.PredicateAccess, anyState : Boolean = false): Exp = {
val predicate = verifier.program.findPredicate(pred.predicateName)
val location = translateLocation(pred)
val location = translateResource(pred)
if (anyState) predicateTriggerAnyState(predicate, location) else predicateTrigger(extras, predicate, location)
}

Expand All @@ -562,10 +562,11 @@ class DefaultHeapModule(val verifier: Verifier)
}
}

def rcvAndFieldExp(f: sil.LocationAccess) : (Exp, Exp) =
def rcvAndFieldExp(f: sil.ResourceAccess) : (Exp, Exp) =
f match {
case sil.FieldAccess(rcv, _) => (translateExp(rcv), translateLocation(f))
case sil.PredicateAccess(_, _) => (nullLit, translateLocation(f))
case sil.FieldAccess(rcv, _) => (translateExp(rcv), translateResource(f))
case sil.PredicateAccess(_, _) => (nullLit, translateResource(f))
case w: sil.MagicWand => (nullLit, translateResource(f))
}

override def currentHeapAssignUpdate(f: sil.LocationAccess, newVal: Exp): Stmt = {
Expand All @@ -589,10 +590,10 @@ class DefaultHeapModule(val verifier: Verifier)
FuncApp(if(isPMask) { permModule.pmaskTypeDesugared.storeId } else { updateHeapName }, Seq(heap, rcv, field, newVal), Bool)
}

override def translateLocationAccess(f: sil.LocationAccess): Exp = {
translateLocationAccess(f, heapExp)
override def translateResourceAccess(f: sil.ResourceAccess): Exp = {
translateResourceAccess(f, heapExp)
}
private def translateLocationAccess(f: sil.LocationAccess, heap: Exp, isPMask: Boolean = false): Exp = {
private def translateResourceAccess(f: sil.ResourceAccess, heap: Exp, isPMask: Boolean = false): Exp = {
val (rcvExp, fieldExp) = rcvAndFieldExp(f)
lookup(heap, rcvExp, fieldExp, isPMask)
}
Expand All @@ -602,14 +603,16 @@ class DefaultHeapModule(val verifier: Verifier)
lookup(heap, rcv, loc)
}

override def translateLocation(l: sil.LocationAccess): Exp = {
override def translateResource(l: sil.ResourceAccess): Exp = {
l match {
case sil.PredicateAccess(args, predName) =>
val pred = verifier.program.findPredicate(predName)
val t = predicateMetaTypeOf(pred)
FuncApp(locationIdentifier(pred), args map translateExp, t)
case sil.FieldAccess(rcv, field) =>
Const(locationIdentifier(field))
case w: sil.MagicWand =>
wandModule.getWandRepresentation(w)
}
}

Expand Down Expand Up @@ -726,7 +729,7 @@ class DefaultHeapModule(val verifier: Verifier)
MaybeComment("register all known folded permissions guarded by predicate " + loc.predicateName,
Havoc(newPMask) ++
Assume(Forall(Seq(obj, field), Seq(Trigger(pm2)), (pm1 ==> pm2))) ++
Assume(Forall(vsFresh.map(vFresh => translateLocalVarDecl(vFresh)),Seq(),translatedCond ==> (translateLocationAccess(renamingFieldAccess, newPMask, true) === TrueLit()) ))) ++
Assume(Forall(vsFresh.map(vFresh => translateLocalVarDecl(vFresh)),Seq(),translatedCond ==> (translateResourceAccess(renamingFieldAccess, newPMask, true) === TrueLit()) ))) ++
curHeapAssignUpdatePredWandMask(pmask.maskField, newPMask)
vsFresh.foreach(vFresh => env.undefine(vFresh.localVar))
res
Expand Down
37 changes: 34 additions & 3 deletions src/main/scala/viper/carbon/modules/impls/DefaultWandModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,18 @@ DefaultWandModule(val verifier: Verifier) extends WandModule with StmtComponent
override def preamble = wandToShapes.values.collect({
case fun@Func(name,args,typ,_) =>
val vars = args.map(decl => decl.l)
val f0 = FuncApp(name,vars,typ)
val args2 = args map (
v => LocalVarDecl(Identifier(v.name.name + "_2")(v.name.namespace), v.typ))
val vars2 = args2 map (_.l)
val varsEqual = All((vars zip vars2) map {
case (v1, v2) => v1 === v2
})
val f0 = FuncApp(name, vars, typ)
val f0_2 = FuncApp(name, vars2, typ)
val f1 = FuncApp(heapModule.wandMaskIdentifier(name), vars, heapModule.predicateMaskFieldTypeOfWand(name.name)) // w#sm (wands secondary mask)
val f2 = FuncApp(heapModule.wandFtIdentifier(name), vars, heapModule.predicateVersionFieldTypeOfWand(name.name)) // w#ft (permission to w#fm is added when at the begining of a package statement)
val f3 = wandMaskField(f2) // wandMaskField (wandMaskField(w) == w#sm)
val wandId = heapModule.getPredicateOrWandId(name.name)
val typeDecl: Seq[TypeDecl] = heapModule.wandBasicType(name.preferredName) match {
case named: NamedType => TypeDecl(named)
case _ => Nil
Expand All @@ -127,7 +135,10 @@ DefaultWandModule(val verifier: Verifier) extends WandModule with StmtComponent
Axiom(MaybeForall(args, Trigger(f2),heapModule.isWandField(f2))) ++
Axiom(MaybeForall(args, Trigger(f0),heapModule.isPredicateField(f0).not)) ++
Axiom(MaybeForall(args, Trigger(f2),heapModule.isPredicateField(f2).not)) ++
Axiom(MaybeForall(args, Trigger(f3), f1 === f3))
Axiom(MaybeForall(args, Trigger(f3), f1 === f3)) ++
Axiom(MaybeForall(args, Trigger(f0), heapModule.getPredicateOrWandId(f0) === IntLit(wandId))) ++
Axiom(Forall(args ++ args2, Trigger(Seq(f0, f0_2)),
(f0 === f0_2) ==> varsEqual))
}).flatten[Decl].toSeq

/*
Expand All @@ -149,6 +160,26 @@ DefaultWandModule(val verifier: Verifier) extends WandModule with StmtComponent
}
}

def getWandRepresentationWithArgs(wand: sil.MagicWand, args: Seq[sil.Exp]): Exp = {

//need to compute shape of wand
val ghostFreeWand = wand
marcoeilers marked this conversation as resolved.
Show resolved Hide resolved

//get all the expressions which form the "holes" of the shape,
val shape: WandShape = wandToShapes(wand.structure(mainModule.verifier.program))

shape match {
case Func(name, _, typ, _) => FuncApp(name, args.map(arg => expModule.translateExp(arg)), typ)
}
marcoeilers marked this conversation as resolved.
Show resolved Hide resolved
}

override def getWandName(w: MagicWand): String = {
val shape = wandToShapes(w.structure(mainModule.verifier.program))
shape match {
case Func(name, _, _, _) => name.name
}
}

// returns the corresponding mask (wand#ft or wand#sm) depending on the value of 'ftsm'.
override def getWandFtSmRepresentation(wand: sil.MagicWand, ftsm: Int): Exp = {
//need to compute shape of wand
Expand Down Expand Up @@ -559,7 +590,7 @@ private def setupTransferableEntity(e: sil.Exp, permTransfer: Exp):(Transferable
e match {
case [email protected](loc, _) =>
val assignStmt = rcvLocal := expModule.translateExpInWand(loc.rcv)
val evalLoc = heapModule.translateLocation(loc)
val evalLoc = heapModule.translateResource(loc)
(TransferableFieldAccessPred(rcvLocal, evalLoc, permTransfer,fa), assignStmt)

case [email protected](loc, _) =>
Expand Down
Loading
Loading