This is an automated email from the ASF dual-hosted git repository.

aradzinski pushed a commit to branch NLPCRAFT-206
in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git


The following commit(s) were added to refs/heads/NLPCRAFT-206 by this push:
     new 2133789  WIP.
2133789 is described below

commit 21337890749148610222233366cb0245b1f12eaf
Author: Aaron Radzinski <[email protected]>
AuthorDate: Wed Mar 17 11:20:16 2021 -0700

    WIP.
---
 .../nlpcraft/model/NCTokenPredicateResult.java     |  25 +-
 .../model/intent/NCDslTokenPredicate.scala         |   2 +-
 .../model/intent/compiler/NCDslCompiler.scala      |   4 +-
 .../model/intent/compiler/NCDslCompilerBase.scala  | 300 +++++++++++----------
 .../model/intent/compiler/NCDslStack.scala         |  10 +-
 .../model/intent/solver/NCIntentSolverEngine.scala |  19 +-
 6 files changed, 185 insertions(+), 175 deletions(-)

diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/NCTokenPredicateResult.java 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/NCTokenPredicateResult.java
index 04a7bbf..5b2fbb7 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/NCTokenPredicateResult.java
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/NCTokenPredicateResult.java
@@ -26,18 +26,19 @@ package org.apache.nlpcraft.model;
  * @see NCTokenPredicateContext
  */
 public class NCTokenPredicateResult {
-    private final boolean result;
-    private final boolean wasTokenUsed;
+    private final boolean res;
+    private final int tokUses;
 
     /**
      * Creates token predicate result.
      *
-     * @param result Token predicate result.
-     * @param wasTokenUsed Whether or not a token was used by this predicate 
(if {@link #getResult() result} is {@code true}).
+     * @param res Token predicate result.
+     * @param tokUses How many times a token was used to match this predicate 
(if {@link #getResult() result} is {@code true}).
+     *      The more times a token was used the "stronger" the this match will 
be when used by intent solver.
      */
-    public NCTokenPredicateResult(boolean result, boolean wasTokenUsed) {
-        this.result = result;
-        this.wasTokenUsed = wasTokenUsed;
+    public NCTokenPredicateResult(boolean res, int tokUses) {
+        this.res = res;
+        this.tokUses = tokUses;
     }
 
     /**
@@ -46,15 +47,15 @@ public class NCTokenPredicateResult {
      * @return Predicate result.
      */
     public boolean getResult() {
-        return result;
+        return res;
     }
 
     /**
-     * Whether or not a token was used by this predicate (if {@link 
#getResult() result} is {@code true}).
+     * Gets how many times a token was used to match this predicate (if {@link 
#getResult() result} is {@code true}).
      *
-     * @return {@code true} if token was used by this predicate, {@code false} 
otherwise.
+     * @return Number of times a token was used to match this term.
      */
-    public boolean wasTokenUsed() {
-        return wasTokenUsed;
+    public int getTokenUses() {
+        return tokUses;
     }
 }
diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCDslTokenPredicate.scala
 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCDslTokenPredicate.scala
index a9191de..d70b463 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCDslTokenPredicate.scala
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/NCDslTokenPredicate.scala
@@ -22,4 +22,4 @@ import org.apache.nlpcraft.model.NCToken
 /**
  *
  */
-trait NCDslTokenPredicate extends ((NCToken, NCDslContext) ⇒ (Boolean /* 
Predicate. */ , Boolean /* Whether or not token was used. */ ))
+trait NCDslTokenPredicate extends ((NCToken, NCDslContext) ⇒ (Boolean /* 
Predicate. */ , Int /* How many times a token was used. */ ))
diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslCompiler.scala
 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslCompiler.scala
index 43de203..1898bdc 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslCompiler.scala
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslCompiler.scala
@@ -245,7 +245,7 @@ object NCDslCompiler extends LazyLogging {
                             javaCtx
                         )
 
-                        (res.getResult, res.wasTokenUsed())
+                        (res.getResult, res.getTokenUses)
                     }
                     catch {
                         case e: Exception ⇒
@@ -297,7 +297,7 @@ object NCDslCompiler extends LazyLogging {
                 if (!isBool(v))
                     throw newRuntimeError(s"$subj did not return boolean 
value: ${ctx.getText}")
 
-                (asBool(v), x.usedTok)
+                (asBool(v), x.tokUse)
             }
         }
 
diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslCompilerBase.scala
 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslCompilerBase.scala
index a76f9af..55a7dac 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslCompilerBase.scala
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslCompilerBase.scala
@@ -154,8 +154,8 @@ trait NCDslCompilerBase {
 
         if (lt != null)
             stack.push(() ⇒ {
-                val Z(v1, f1) = x1()
-                val Z(v2, f2) = x2()
+                val Z(v1, n1) = x1()
+                val Z(v2, n2) = x2()
 
                 val f =
                     if (isJLong(v1) && isJLong(v2)) asJLong(v1) < asJLong(v2)
@@ -165,12 +165,12 @@ trait NCDslCompilerBase {
                     else
                         throw rtBinaryOpError("<", v1, v2)
 
-                Z(f, f1 || f2)
+                Z(f, n1 + n2)
             })
         else if (gt != null)
             stack.push(() ⇒ {
-                val Z(v1, f1) = x1()
-                val Z(v2, f2) = x2()
+                val Z(v1, n1) = x1()
+                val Z(v2, n2) = x2()
 
                 val f =
                     if (isJLong(v1) && isJLong(v2)) asJLong(v1) > asJLong(v2)
@@ -180,12 +180,12 @@ trait NCDslCompilerBase {
                     else
                         throw rtBinaryOpError(">", v1, v2)
 
-                Z(f, f1 || f2)
+                Z(f, n1 + n2)
             })
         else if (lteq != null)
             stack.push(() ⇒ {
-                val Z(v1, f1) = x1()
-                val Z(v2, f2) = x2()
+                val Z(v1, n1) = x1()
+                val Z(v2, n2) = x2()
 
                 val f =
                     if (isJLong(v1) && isJLong(v2)) asJLong(v1) <= asJLong(v2)
@@ -195,14 +195,14 @@ trait NCDslCompilerBase {
                     else
                         throw rtBinaryOpError("<=", v1, v2)
 
-                Z(f, f1 || f2)
+                Z(f, n1 + n2)
             })
         else {
             require(gteq != null)
 
             stack.push(() ⇒ {
-                val Z(v1, f1) = x1()
-                val Z(v2, f2) = x2()
+                val Z(v1, n1) = x1()
+                val Z(v2, n2) = x2()
 
                 val f =
                     if (isJLong(v1) && isJLong(v2)) asJLong(v1) >= asJLong(v2)
@@ -212,7 +212,7 @@ trait NCDslCompilerBase {
                     else
                         throw rtBinaryOpError(">=", v1, v2)
 
-                Z(f, f1 || f2)
+                Z(f, n1 + n2)
             })
         }
     }
@@ -228,8 +228,8 @@ trait NCDslCompilerBase {
 
         if (mult != null)
             stack.push(() ⇒ {
-                val Z(v1, f1) = x1()
-                val Z(v2, f2) = x2()
+                val Z(v1, n1) = x1()
+                val Z(v2, n2) = x2()
 
                 val f =
                     if (isJLong(v1) && isJLong(v2)) asJLong(v1) * asJLong(v2)
@@ -239,26 +239,26 @@ trait NCDslCompilerBase {
                     else
                         throw rtBinaryOpError("*", v1, v2)
 
-                Z(f, f1 || f2)
+                Z(f, n1 + n2)
             })
         else if (mod != null)
             stack.push(() ⇒ {
-                val Z(v1, f1) = x1()
-                val Z(v2, f2) = x2()
+                val Z(v1, n1) = x1()
+                val Z(v2, n2) = x2()
 
                 val f =
                     if (isJLong(v1) && isJLong(v2)) asJLong(v1) % asJLong(v2)
                     else
                         throw rtBinaryOpError("%", v1, v2)
 
-                Z(f, f1 || f2)
+                Z(f, n1 + n2)
             })
         else {
             assert(div != null)
 
             stack.push(() ⇒ {
-                val Z(v1, f1) = x1()
-                val Z(v2, f2) = x2()
+                val Z(v1, n1) = x1()
+                val Z(v2, n2) = x2()
 
                 val f =
                     if (isJLong(v1) && isJLong(v2)) asJLong(v1) / asJLong(v2)
@@ -268,7 +268,7 @@ trait NCDslCompilerBase {
                     else
                         throw rtBinaryOpError("/", v1, v2)
 
-                Z(f, f1 || f2)
+                Z(f, n1 + n2)
             })
         }
     }
@@ -285,21 +285,21 @@ trait NCDslCompilerBase {
         stack.push(() ⇒ {
             val (op, flag) = if (and != null) ("&&", false) else ("||", true)
 
-            val Z(v1, f1) = x1()
+            val Z(v1, n1) = x1()
 
             if (!isBool(v1))
                 throw rtBinaryOpError(op, v1, x2().value)
 
             // NOTE: check v1 first and only if it is {true|false} check the 
v2.
             if (asBool(v1) == flag)
-                Z(flag, f1)
+                Z(flag, n1)
             else {
-                val Z(v2, f2) = x2()
+                val Z(v2, n2) = x2()
 
                 if (!isBool(v2))
                     throw rtBinaryOpError(op, v2, v1)
 
-                Z(asBool(v2), if (and != null) f1 || f2 else f1 && f2)
+                Z(asBool(v2), n1 + n2)
             }
         })
     }
@@ -326,8 +326,8 @@ trait NCDslCompilerBase {
             }}
 
         stack.push(() ⇒ {
-            val Z(v1, f1) = x1()
-            val Z(v2, f2) = x2()
+            val Z(v1, n1) = x1()
+            val Z(v2, n2) = x2()
 
             val f =
                 if (eq != null)
@@ -338,7 +338,7 @@ trait NCDslCompilerBase {
                     !doEq("!='", v1, v2)
                 }
 
-            Z(f, f1 || f2)
+            Z(f, n1 + n2)
         })
     }
 
@@ -350,17 +350,22 @@ trait NCDslCompilerBase {
     def parsePlusMinusExpr(plus: TN, minus: TN)(implicit ctx: PRC): I = (_, 
stack: S, _) ⇒ {
         val (x1, x2) = pop2()(stack, ctx)
 
+        def extract(): (Object, Object, Int) = {
+            val Z(v1, n1) = x1()
+            val Z(v2, n2) = x2()
+
+            (v1, v2, n1 + n2)
+        }
+
         if (plus != null)
             stack.push(() ⇒ {
-                val Z(v1, f1) = x1()
-                val Z(v2, f2) = x2()
-                val f = f1 || f2
-
-                if (isStr(v1) && isStr(v2)) Z(asStr(v1) + asStr(v2), f)
-                else if (isJLong(v1) && isJLong(v2))  Z(asJLong(v1) + 
asJLong(v2), f)
-                else if (isJLong(v1) && isJDouble(v2))  Z(asJLong(v1) + 
asJDouble(v2), f)
-                else if (isJDouble(v1) && isJLong(v2))  Z(asJDouble(v1) + 
asJLong(v2), f)
-                else if (isJDouble(v1) && isJDouble(v2))  Z(asJDouble(v1) + 
asJDouble(v2), f)
+                val (v1, v2, n) = extract()
+
+                if (isStr(v1) && isStr(v2)) Z(asStr(v1) + asStr(v2), n)
+                else if (isJLong(v1) && isJLong(v2))  Z(asJLong(v1) + 
asJLong(v2), n)
+                else if (isJLong(v1) && isJDouble(v2))  Z(asJLong(v1) + 
asJDouble(v2), n)
+                else if (isJDouble(v1) && isJLong(v2))  Z(asJDouble(v1) + 
asJLong(v2), n)
+                else if (isJDouble(v1) && isJDouble(v2))  Z(asJDouble(v1) + 
asJDouble(v2), n)
                 else
                     throw rtBinaryOpError("+", v1, v2)
             })
@@ -368,10 +373,9 @@ trait NCDslCompilerBase {
             assert(minus != null)
 
             stack.push(() ⇒ {
-                val v1 = x1()
-                val v2 = x2()
+                val (v1, v2, n) = extract()
 
-                val f =
+                val v =
                     if (isJLong(v1) && isJLong(v2)) asJLong(v1) - asJLong(v2)
                     else if (isJLong(v1) && isJDouble(v2)) asJLong(v1) - 
asJDouble(v2)
                     else if (isJDouble(v1) && isJLong(v2)) asJDouble(v1) - 
asJLong(v2)
@@ -379,7 +383,7 @@ trait NCDslCompilerBase {
                     else
                         throw rtBinaryOpError("-", v1, v2)
 
-                Z(f, v1.usedTok || v2.usedTok)
+                Z(v, n)
             })
         }
     }
@@ -394,7 +398,7 @@ trait NCDslCompilerBase {
 
         if (minus != null)
             stack.push(() ⇒ {
-                val Z(v, f) = x()
+                val Z(v, n) = x()
 
                 val z =
                     if (isJDouble(v)) -asJDouble(v)
@@ -402,15 +406,15 @@ trait NCDslCompilerBase {
                     else
                         throw rtUnaryOpError("-", v)
 
-                Z(z, f)
+                Z(z, n)
             })
         else {
             assert(not != null)
 
             stack.push(() ⇒ {
-                val Z(v, f) = x()
+                val Z(v, n) = x()
 
-                if (isBool(v)) Z(!asBool(v), f)
+                if (isBool(v)) Z(!asBool(v), n)
                 else
                     throw rtUnaryOpError("!", v)
             })
@@ -444,7 +448,7 @@ trait NCDslCompilerBase {
                 }
             }
 
-        (_, stack, _) ⇒ stack.push(() ⇒ Z(atom, false))
+        (_, stack, _) ⇒ stack.push(() ⇒ Z(atom, 0))
     }
 
     /**
@@ -476,7 +480,7 @@ trait NCDslCompilerBase {
             if (stack.nonEmpty && stack.top == stack.PLIST_MARKER) {
                 delMarker()
             
-                () ⇒ Z(tok, true)
+                () ⇒ Z(tok, 1)
             }
             else
                 arg1()
@@ -498,10 +502,10 @@ trait NCDslCompilerBase {
 
             stack.push(
                 () ⇒ {
-                    val Z(v1, f1) = x1()
-                    val Z(v2, f2) = x2()
+                    val Z(v1, n1) = x1()
+                    val Z(v2, n2) = x2()
 
-                   Z(util.Arrays.asList(toStr(v1).split(toStr(v2))), f1 || f2)
+                   Z(util.Arrays.asList(toStr(v1).split(toStr(v2))), n1 + n2)
                 }
             )
         }
@@ -511,10 +515,10 @@ trait NCDslCompilerBase {
 
             stack.push(
                 () ⇒ {
-                    val Z(v1, f1) = x1()
-                    val Z(v2, f2) = x2()
+                    val Z(v1, n1) = x1()
+                    val Z(v2, n2) = x2()
 
-                    
Z(util.Arrays.asList(toStr(v1).split(toStr(v2)).toList.map(_.strip)), f1 || f2)
+                    
Z(util.Arrays.asList(toStr(v1).split(toStr(v2)).toList.map(_.strip)), n1 + n2)
                 }
             )
         }
@@ -529,17 +533,17 @@ trait NCDslCompilerBase {
 
             stack.push(() ⇒ {
                 val jl = new util.ArrayList[Object]()
-                var f: Boolean = true
+                var z = 0
 
                 dump.reverse.foreach { x ⇒
-                    val v = x()
+                    val Z(v, n) = x()
 
-                    f = f || v.usedTok
+                    z += n
 
-                    jl.add(v.value)
+                    jl.add(v)
                 }
 
-                Z(jl, f)
+                Z(jl, z)
             })
         }
         
@@ -547,13 +551,13 @@ trait NCDslCompilerBase {
             val x = arg1()
             
             stack.push(() ⇒ {
-                val Z(v, f) = x()
+                val Z(v, n) = x()
         
                 val jl = toJList(v)
         
                 Collections.reverse(jl)
         
-                Z(jl, f)
+                Z(jl, n)
             })
         }
         
@@ -561,15 +565,15 @@ trait NCDslCompilerBase {
             val x = arg1()
     
             stack.push(() ⇒ {
-                val Z(v, f) = x()
+                val Z(v, n) = x()
                 
                 val lst = toJList(v).asInstanceOf[util.List[Object]]
                 
                 try
                     if (lst.isEmpty)
-                        Z(0, f)
+                        Z(0, n)
                     else
-                        Z(Collections.min(lst, null), f)
+                        Z(Collections.min(lst, null), n)
                 catch {
                     case e: Exception ⇒ throw rtListTypeError(fun, e)
                 }
@@ -580,15 +584,15 @@ trait NCDslCompilerBase {
             val x = arg1()
         
             stack.push(() ⇒ {
-                val Z(v, f) = x()
+                val Z(v, n) = x()
             
                 val lst = toJList(v).asInstanceOf[util.List[Object]]
             
                 try
                     if (lst.isEmpty)
-                        Z(0, f)
+                        Z(0, n)
                     else
-                        Z(Collections.max(lst, null), f)
+                        Z(Collections.max(lst, null), n)
                 catch {
                     case e: Exception ⇒ throw rtListTypeError(fun, e)
                 }
@@ -599,13 +603,13 @@ trait NCDslCompilerBase {
             val x = arg1()
         
             stack.push(() ⇒ {
-                val Z(v, f) = x()
+                val Z(v, n) = x()
             
                 val jl = toJList(v)
                 
                 jl.sort(null) // Use natural order.
             
-                Z(jl, f)
+                Z(jl, n)
             })
         }
 
@@ -613,10 +617,10 @@ trait NCDslCompilerBase {
             val (x1, x2) = arg2()
 
             stack.push(() ⇒ {
-                val Z(v1, f1) = x1()
-                val Z(v2, f2) = x2()
+                val Z(v1, n1) = x1()
+                val Z(v2, n2) = x2()
 
-                Z(toJList(v1).contains(v2), f1 || f2)
+                Z(toJList(v1).contains(v2), n1 + n2)
             })
         }
 
@@ -624,18 +628,18 @@ trait NCDslCompilerBase {
             val (x1, x2) = arg2()
 
             stack.push(() ⇒ {
-                val Z(col, f1) = x1()
-                val Z(key, f2) = x2()
-                val f = f1 || f2
+                val Z(col, n1) = x1()
+                val Z(key, n2) = x2()
+                val n = n1 + n2
 
                 if (isJList(col)) {
                     if (isJLong(key))
-                        
Z(asJList(col).get(asJLong(key).intValue()).asInstanceOf[Object], f)
+                        
Z(asJList(col).get(asJLong(key).intValue()).asInstanceOf[Object], n)
                     else
                         throw rtParamTypeError(fun, key, "numeric")
                 }
                 else if (isJMap(col))
-                    Z(asJMap(col).get(key).asInstanceOf[Object], f)
+                    Z(asJMap(col).get(key).asInstanceOf[Object], n)
                 else
                     throw rtParamTypeError(fun, col, "list or map")
             })
@@ -643,11 +647,11 @@ trait NCDslCompilerBase {
 
         def doAbs(): Unit = arg1() match {
             case x ⇒ stack.push(() ⇒ {
-                val Z(v, f) = x()
+                val Z(v, n) = x()
 
                 v match {
-                    case a: JLong ⇒ Z(Math.abs(a), f)
-                    case a: JDouble ⇒ Z(Math.abs(a), f)
+                    case a: JLong ⇒ Z(Math.abs(a), n)
+                    case a: JDouble ⇒ Z(Math.abs(a), n)
                     case _ ⇒ throw rtParamTypeError(fun, v, "numeric")
                 }
             })
@@ -655,11 +659,11 @@ trait NCDslCompilerBase {
 
         def doSquare(): Unit = arg1() match {
             case x ⇒ stack.push(() ⇒ {
-                val Z(v, f) = x()
+                val Z(v, n) = x()
 
                 v match {
-                    case a: JLong ⇒ Z(a * a, f)
-                    case a: JDouble ⇒ Z(a * a, f)
+                    case a: JLong ⇒ Z(a * a, n)
+                    case a: JDouble ⇒ Z(a * a, n)
                     case _ ⇒ throw rtParamTypeError(fun, v, "numeric")
                 }
             })
@@ -669,17 +673,17 @@ trait NCDslCompilerBase {
             val (x1, x2, x3) = arg3()
 
             stack.push(() ⇒ {
-                val Z(v1, f1) = x1()
+                val Z(v1, n1) = x1()
 
                 if (toBool(v1)) {
-                    val Z(v2, f2) = x2()
+                    val Z(v2, n2) = x2()
 
-                    Z(v2, f1 || f2)
+                    Z(v2, n1 + n2)
                 }
                 else {
-                    val Z(v3, f3) = x3()
+                    val Z(v3, n3) = x3()
 
-                    Z(v3, f1 || f3)
+                    Z(v3, n1 + n3)
                 }
             })
         }
@@ -689,8 +693,8 @@ trait NCDslCompilerBase {
             val (x1, x2) = arg2()
 
             stack.push(() ⇒ {
-                val Z(t, f1) = x1()
-                val Z(a, f2) = x2()
+                val Z(t, n1) = x1()
+                val Z(a, n2) = x2()
 
                 val tok = toToken(t)
                 val aliasId = toStr(a)
@@ -708,7 +712,7 @@ trait NCDslCompilerBase {
                         s"partId=$aliasId" +
                     s"]")
 
-                Z(parts.get(0), f1 || f2)
+                Z(parts.get(0), n1 + n2)
             })
         }
 
@@ -717,13 +721,13 @@ trait NCDslCompilerBase {
             val (x1, x2) = arg2()
 
             stack.push(() ⇒ {
-                val Z(t, f1) = x1()
-                val Z(a, f2) = x2()
+                val Z(t, n1) = x1()
+                val Z(a, n2) = x2()
 
                 val tok = toToken(t)
                 val aliasId = toStr(a)
 
-                Z(tok.findPartTokens(aliasId), f1 || f2)
+                Z(tok.findPartTokens(aliasId), n1 + n2)
             })
         }
 
@@ -732,15 +736,15 @@ trait NCDslCompilerBase {
 
         fun match {
             // Metadata access.
-            case "meta_part" ⇒ z[(T, T)](arg2, { x ⇒ val Z(v1, f1) = x._1(); 
val Z(v2, f2) = x._2(); Z(toToken(v1).meta[Object](toStr(v2)), f1 || f2) })
-            case "meta_token" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(tok.meta[Object](toStr(v)), true) })
-            case "meta_model" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(tok.getModel.meta[Object](toStr(v)), false) })
-            case "meta_intent" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(termCtx.intentMeta.get(toStr(v)).orNull, false) })
-            case "meta_req" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(termCtx.req.getRequestData.get(toStr(v)), false) })
-            case "meta_user" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(termCtx.req.getUser.getMetadata.get(toStr(v)), false) })
-            case "meta_company" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(termCtx.req.getCompany.getMetadata.get(v), false) })
-            case "meta_sys" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(U.sysEnv(toStr(v)).orNull, false) })
-            case "meta_conv" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(termCtx.convMeta.get(toStr(v)).orNull, false) })
+            case "meta_part" ⇒ z[(T, T)](arg2, { x ⇒ val Z(v1, n1) = x._1(); 
val Z(v2, n2) = x._2(); Z(toToken(v1).meta[Object](toStr(v2)), n1 + n2) })
+            case "meta_token" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(tok.meta[Object](toStr(v)), 1) })
+            case "meta_model" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(tok.getModel.meta[Object](toStr(v)), 0) })
+            case "meta_intent" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(termCtx.intentMeta.get(toStr(v)).orNull, 0) })
+            case "meta_req" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(termCtx.req.getRequestData.get(toStr(v)), 0) })
+            case "meta_user" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(termCtx.req.getUser.getMetadata.get(toStr(v)), 0) })
+            case "meta_company" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(termCtx.req.getCompany.getMetadata.get(v), 0) })
+            case "meta_sys" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(U.sysEnv(toStr(v)).orNull, 0) })
+            case "meta_conv" ⇒ z[T](arg1, { x ⇒ val Z(v, _) = x(); 
Z(termCtx.convMeta.get(toStr(v)).orNull, 0) })
             case "meta_frag" ⇒ z[T](arg1, { x ⇒ val Z(v, f) = x(); 
Z(termCtx.fragMeta.get(toStr(v)).orNull, f) })
 
             // Converts JSON to map.
@@ -750,42 +754,42 @@ trait NCDslCompilerBase {
             case "if" ⇒ doIf()
 
             // Token functions.
-            case "id" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getId, true) }) }
-            case "ancestors" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getAncestors, true) }) }
-            case "parent" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getParentId, true) }) }
-            case "groups" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getGroups, true) }) }
-            case "value" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getValue, true) }) }
-            case "aliases" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getAliases, true) }) }
-            case "start_idx" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getStartCharIndex, true) }) }
-            case "end_idx" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getEndCharIndex, true) }) }
-            case "this" ⇒ z0(() ⇒ Z(tok, true))
+            case "id" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getId, 1) }) }
+            case "ancestors" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getAncestors, 1) }) }
+            case "parent" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getParentId, 1) }) }
+            case "groups" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getGroups, 1) }) }
+            case "value" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getValue, 1) }) }
+            case "aliases" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getAliases, 1) }) }
+            case "start_idx" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getStartCharIndex, 1) }) }
+            case "end_idx" ⇒ arg1Tok() match { case x ⇒ stack.push(() ⇒ { 
Z(toToken(x().value).getEndCharIndex, 1) }) }
+            case "this" ⇒ z0(() ⇒ Z(tok, 1))
             case "part" ⇒ doPart()
             case "parts" ⇒ doParts()
 
             // Request data.
-            case "req_id" ⇒ z0(() ⇒ Z(termCtx.req.getServerRequestId, false))
-            case "req_normtext" ⇒ z0(() ⇒ Z(termCtx.req.getNormalizedText, 
false))
-            case "req_tstamp" ⇒ z0(() ⇒ Z(termCtx.req.getReceiveTimestamp, 
false))
-            case "req_addr" ⇒ z0(() ⇒ 
Z(termCtx.req.getRemoteAddress.orElse(null), false))
-            case "req_agent" ⇒ z0(() ⇒ 
Z(termCtx.req.getClientAgent.orElse(null), false))
+            case "req_id" ⇒ z0(() ⇒ Z(termCtx.req.getServerRequestId, 0))
+            case "req_normtext" ⇒ z0(() ⇒ Z(termCtx.req.getNormalizedText, 0))
+            case "req_tstamp" ⇒ z0(() ⇒ Z(termCtx.req.getReceiveTimestamp, 0))
+            case "req_addr" ⇒ z0(() ⇒ 
Z(termCtx.req.getRemoteAddress.orElse(null), 0))
+            case "req_agent" ⇒ z0(() ⇒ 
Z(termCtx.req.getClientAgent.orElse(null), 0))
 
             // User data.
-            case "user_id" ⇒ z0(() ⇒ Z(termCtx.req.getUser.getId, false))
-            case "user_fname" ⇒ z0(() ⇒ Z(termCtx.req.getUser.getFirstName, 
false))
-            case "user_lname" ⇒ z0(() ⇒ Z(termCtx.req.getUser.getLastName, 
false))
-            case "user_email" ⇒ z0(() ⇒ Z(termCtx.req.getUser.getEmail, false))
-            case "user_admin" ⇒ z0(() ⇒ Z(termCtx.req.getUser.isAdmin, false))
-            case "user_signup_tstamp" ⇒ z0(() ⇒ 
Z(termCtx.req.getUser.getSignupTimestamp, false))
+            case "user_id" ⇒ z0(() ⇒ Z(termCtx.req.getUser.getId, 0))
+            case "user_fname" ⇒ z0(() ⇒ Z(termCtx.req.getUser.getFirstName, 0))
+            case "user_lname" ⇒ z0(() ⇒ Z(termCtx.req.getUser.getLastName, 0))
+            case "user_email" ⇒ z0(() ⇒ Z(termCtx.req.getUser.getEmail, 0))
+            case "user_admin" ⇒ z0(() ⇒ Z(termCtx.req.getUser.isAdmin, 0))
+            case "user_signup_tstamp" ⇒ z0(() ⇒ 
Z(termCtx.req.getUser.getSignupTimestamp, 0))
 
             // Company data.
-            case "comp_id" ⇒ z0(() ⇒ Z(termCtx.req.getCompany.getId, false))
-            case "comp_name" ⇒ z0(() ⇒ Z(termCtx.req.getCompany.getName, 
false))
-            case "comp_website" ⇒ z0(() ⇒ Z(termCtx.req.getCompany.getWebsite, 
false))
-            case "comp_country" ⇒ z0(() ⇒ Z(termCtx.req.getCompany.getCountry, 
false))
-            case "comp_region" ⇒ z0(() ⇒ Z(termCtx.req.getCompany.getRegion, 
false))
-            case "comp_city" ⇒ z0(() ⇒ Z(termCtx.req.getCompany.getCity, 
false))
-            case "comp_addr" ⇒ z0(() ⇒ Z(termCtx.req.getCompany.getAddress, 
false))
-            case "comp_postcode" ⇒ z0(() ⇒ 
Z(termCtx.req.getCompany.getPostalCode, false))
+            case "comp_id" ⇒ z0(() ⇒ Z(termCtx.req.getCompany.getId, 0))
+            case "comp_name" ⇒ z0(() ⇒ Z(termCtx.req.getCompany.getName, 0))
+            case "comp_website" ⇒ z0(() ⇒ Z(termCtx.req.getCompany.getWebsite, 
0))
+            case "comp_country" ⇒ z0(() ⇒ Z(termCtx.req.getCompany.getCountry, 
0))
+            case "comp_region" ⇒ z0(() ⇒ Z(termCtx.req.getCompany.getRegion, 
0))
+            case "comp_city" ⇒ z0(() ⇒ Z(termCtx.req.getCompany.getCity, 0))
+            case "comp_addr" ⇒ z0(() ⇒ Z(termCtx.req.getCompany.getAddress, 0))
+            case "comp_postcode" ⇒ z0(() ⇒ 
Z(termCtx.req.getCompany.getPostalCode, 0))
 
             // String functions.
             case "trim" | "strip" ⇒ z[T](arg1, { x ⇒ val Z(v, f) = x(); 
Z(toStr(v).trim, f) })
@@ -828,20 +832,20 @@ trait NCDslCompilerBase {
             case "cosh" ⇒ z[T](arg1, { x ⇒ val Z(v, f) = x(); 
Z(Math.cosh(toJDouble(v)), f) }) 
             case "sinh" ⇒ z[T](arg1, { x ⇒ val Z(v, f) = x(); 
Z(Math.sinh(toJDouble(v)), f) }) 
             case "tanh" ⇒ z[T](arg1, { x ⇒ val Z(v, f) = x(); 
Z(Math.tanh(toJDouble(v)), f) }) 
-            case "atn2" ⇒ z[(T, T)](arg2, { x ⇒ val Z(v1, f1) = x._1(); val 
Z(v2, f2) = x._2(); Z(Math.atan2(toJDouble(v1), toJDouble(v2)), f1 || f2) }) 
+            case "atn2" ⇒ z[(T, T)](arg2, { x ⇒ val Z(v1, n1) = x._1(); val 
Z(v2, n2) = x._2(); Z(Math.atan2(toJDouble(v1), toJDouble(v2)), n1 + n2) })
             case "degrees" ⇒ z[T](arg1, { x ⇒ val Z(v, f) = x(); 
Z(Math.toDegrees(toJDouble(v)), f) }) 
             case "radians" ⇒ z[T](arg1, { x ⇒ val Z(v, f) = x(); Z( 
Math.toRadians(toJDouble(v)), f) }) 
             case "exp" ⇒ z[T](arg1, { x ⇒ val Z(v, f) = x(); 
Z(Math.exp(toJDouble(v)), f) }) 
             case "expm1" ⇒ z[T](arg1, { x ⇒ val Z(v, f) = x(); 
Z(Math.expm1(toJDouble(v)), f) }) 
-            case "hypot" ⇒ z[(T, T)](arg2, { x ⇒ val Z(v1, f1) = x._1(); val 
Z(v2, f2) = x._2(); Z(Math.hypot(toJDouble(v1), toJDouble(v2)), f1 || f2) }) 
+            case "hypot" ⇒ z[(T, T)](arg2, { x ⇒ val Z(v1, n1) = x._1(); val 
Z(v2, n2) = x._2(); Z(Math.hypot(toJDouble(v1), toJDouble(v2)), n1 + n2) })
             case "log" ⇒ z[T](arg1, { x ⇒ val Z(v, f) = x(); 
Z(Math.log(toJDouble(v)), f) }) 
             case "log10" ⇒ z[T](arg1, { x ⇒ val Z(v, f) = x(); 
Z(Math.log10(toJDouble(v)), f) }) 
             case "log1p" ⇒ z[T](arg1, { x ⇒ val Z(v, f) = x(); 
Z(Math.log1p(toJDouble(v)), f) }) 
-            case "pow" ⇒ z[(T, T)](arg2, { x ⇒ val Z(v1, f1) = x._1(); val 
Z(v2, f2) = x._2(); Z(Math.pow(toJDouble(v1), toJDouble(v2)), f1 || f2) }) 
+            case "pow" ⇒ z[(T, T)](arg2, { x ⇒ val Z(v1, f1) = x._1(); val 
Z(v2, f2) = x._2(); Z(Math.pow(toJDouble(v1), toJDouble(v2)), f1 + f2 + 1) })
             case "square" ⇒ doSquare()
-            case "pi" ⇒ z0(() ⇒ Z(Math.PI, false))
-            case "euler" ⇒ z0(() ⇒ Z(Math.E, false))
-            case "rand" ⇒ z0(() ⇒ Z(Math.random, false))
+            case "pi" ⇒ z0(() ⇒ Z(Math.PI, 0))
+            case "euler" ⇒ z0(() ⇒ Z(Math.E, 0))
+            case "rand" ⇒ z0(() ⇒ Z(Math.random, 0))
 
             // Collection functions.
             case "list" ⇒ doList()
@@ -866,18 +870,18 @@ trait NCDslCompilerBase {
             case "sum" ⇒
 
             // Date-time functions.
-            case "year" ⇒ z0(() ⇒ Z(LocalDate.now.getYear, false)) // 2021.
-            case "month" ⇒ z0(() ⇒ Z(LocalDate.now.getMonthValue, false)) // 1 
... 12.
-            case "day_of_month" ⇒ z0(() ⇒ Z(LocalDate.now.getDayOfMonth, 
false)) // 1 ... 31.
-            case "day_of_week" ⇒ z0(() ⇒ 
Z(LocalDate.now.getDayOfWeek.getValue, false))
-            case "day_of_year" ⇒ z0(() ⇒ Z(LocalDate.now.getDayOfYear, false))
-            case "hour" ⇒ z0(() ⇒ Z(LocalTime.now.getHour, false))
-            case "minute" ⇒ z0(() ⇒ Z(LocalTime.now.getMinute, false))
-            case "second" ⇒ z0(() ⇒ Z(LocalTime.now.getSecond, false))
-            case "week_of_month" ⇒ z0(() ⇒ 
Z(Calendar.getInstance().get(Calendar.WEEK_OF_MONTH), false))
-            case "week_of_year" ⇒ z0(() ⇒ 
Z(Calendar.getInstance().get(Calendar.WEEK_OF_YEAR), false))
-            case "quarter" ⇒ z0(() ⇒ 
Z(LocalDate.now().get(IsoFields.QUARTER_OF_YEAR), false))
-            case "now" ⇒ z0(() ⇒ Z(System.currentTimeMillis(), false)) // Epoc 
time.
+            case "year" ⇒ z0(() ⇒ Z(LocalDate.now.getYear, 0)) // 2021.
+            case "month" ⇒ z0(() ⇒ Z(LocalDate.now.getMonthValue, 0)) // 1 ... 
12.
+            case "day_of_month" ⇒ z0(() ⇒ Z(LocalDate.now.getDayOfMonth, 0)) 
// 1 ... 31.
+            case "day_of_week" ⇒ z0(() ⇒ 
Z(LocalDate.now.getDayOfWeek.getValue, 0))
+            case "day_of_year" ⇒ z0(() ⇒ Z(LocalDate.now.getDayOfYear, 0))
+            case "hour" ⇒ z0(() ⇒ Z(LocalTime.now.getHour, 0))
+            case "minute" ⇒ z0(() ⇒ Z(LocalTime.now.getMinute, 0))
+            case "second" ⇒ z0(() ⇒ Z(LocalTime.now.getSecond, 0))
+            case "week_of_month" ⇒ z0(() ⇒ 
Z(Calendar.getInstance().get(Calendar.WEEK_OF_MONTH), 0))
+            case "week_of_year" ⇒ z0(() ⇒ 
Z(Calendar.getInstance().get(Calendar.WEEK_OF_YEAR), 0))
+            case "quarter" ⇒ z0(() ⇒ 
Z(LocalDate.now().get(IsoFields.QUARTER_OF_YEAR), 0))
+            case "now" ⇒ z0(() ⇒ Z(System.currentTimeMillis(), 0)) // Epoc 
time.
 
             case _ ⇒ throw rtUnknownFunError(fun) // Assertion.
         }
diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslStack.scala
 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslStack.scala
index 7efbb4c..f16f7d7 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslStack.scala
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslStack.scala
@@ -24,13 +24,13 @@ import scala.collection.mutable
   */
 case class NCDslStackItem (
     value: Object,
-    usedTok: Boolean
+    tokUse: Int
 )
 
 object NCDslStackItem {
-    def apply(v: Boolean, f: Boolean): NCDslStackItem = new 
NCDslStackItem(Boolean.box(v), f)
-    def apply(v: Long, f: Boolean): NCDslStackItem = new 
NCDslStackItem(Long.box(v), f)
-    def apply(v: Double, f: Boolean): NCDslStackItem = new 
NCDslStackItem(Double.box(v), f)
+    def apply(v: Boolean, f: Int): NCDslStackItem = new 
NCDslStackItem(Boolean.box(v), f)
+    def apply(v: Long, f: Int): NCDslStackItem = new 
NCDslStackItem(Long.box(v), f)
+    def apply(v: Double, f: Int): NCDslStackItem = new 
NCDslStackItem(Double.box(v), f)
 }
 
 /**
@@ -45,5 +45,5 @@ class NCDslStack extends mutable.ArrayStack[NCDslStackType] {
     /**
       * Special marker for stack frames.
       */
-    final val PLIST_MARKER: NCDslStackType = () ⇒ { NCDslStackItem(null, 
false) }
+    final val PLIST_MARKER: NCDslStackType = () ⇒ { NCDslStackItem(null, 0) }
 }
diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolverEngine.scala
 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolverEngine.scala
index fcb7ef1..0f4aa94 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolverEngine.scala
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolverEngine.scala
@@ -558,9 +558,10 @@ object NCIntentSolverEngine extends LazyLogging with 
NCOpenCensusTrace {
                                 Seq(
                                     s"${y("SEN_TOK: ")}${w.head}",
                                     s"${y("CNV_TOK: ")}${w(1)}",
-                                    s"${y("SPC_MIN: ")}${w(2)}",
-                                    s"${y("DLT_MAX: ")}${w(3)}",
-                                    s"${y("NRM_MAX: ")}${w(4)}"
+                                    s"${y("TOK_USN: ")}${w(2)}",
+                                    s"${y("SPC_MIN: ")}${w(3)}",
+                                    s"${y("DLT_MAX: ")}${w(4)}",
+                                    s"${y("NRM_MAX: ")}${w(5)}"
                                 )
                             )
 
@@ -681,7 +682,7 @@ object NCIntentSolverEngine extends LazyLogging with 
NCOpenCensusTrace {
      */
     @throws[NCE]
     private def solvePredicate(
-        pred: (NCToken, NCDslContext) ⇒ (Boolean /*Predicate.*/ , Boolean 
/*Whether or not token was used.*/ ),
+        pred: (NCToken, NCDslContext) ⇒ (Boolean /*Predicate.*/ , Int /*How 
many times a token was used.*/ ),
         ctx: NCDslContext,
         min: Int,
         max: Int,
@@ -695,16 +696,19 @@ object NCIntentSolverEngine extends LazyLogging with 
NCOpenCensusTrace {
         var usedToks = List.empty[UsedToken]
 
         var matches = 0
+        var tokUses = 0
 
         // Collect to the 'max' from sentence & conversation, if possible.
         for (col ← Seq(senToks, convToks); tok ← col.filter(!_.used) if 
usedToks.lengthCompare(max) < 0) {
-            val (res, used) = pred.apply(tok.token, ctx)
+            val (res, uses) = pred.apply(tok.token, ctx)
 
             if (res) {
                 matches += 1
 
-                if (used)
+                if (uses > 0) {
+                    tokUses += uses
                     usedToks :+= tok
+                }
             }
         }
 
@@ -736,7 +740,8 @@ object NCIntentSolverEngine extends LazyLogging with 
NCOpenCensusTrace {
 
             Some(usedToks → new Weight(
                 senTokNum,
-                convDepthsSum
+                convDepthsSum,
+                tokUses
             ))
         }
     }

Reply via email to