This is an automated email from the ASF dual-hosted git repository. aradzinski pushed a commit to branch NLPCRAFT-278 in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git
commit e83b473a816869417277e55b600f1f4b220e1abd Author: Aaron Radzinski <[email protected]> AuthorDate: Wed Mar 24 15:13:07 2021 -0700 WIP. --- .../model/intent/compiler/NCIdlCompilerBase.scala | 18 +++++- .../model/intent/solver/NCIntentSolverEngine.scala | 60 +++++++++--------- .../idl/compiler/functions/NCIdlFunctions.scala | 5 +- .../compiler/functions/NCIdlFunctionsMath.scala | 8 +-- .../compiler/functions/NCIdlFunctionsStat.scala | 8 +-- .../compiler/functions/NCIdlFunctionsStrings.scala | 73 +++++++++++----------- 6 files changed, 94 insertions(+), 78 deletions(-) diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompilerBase.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompilerBase.scala index 9d5f282..66cb2c1 100644 --- a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompilerBase.scala +++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompilerBase.scala @@ -154,8 +154,12 @@ trait NCIdlCompilerBase { newRuntimeError(s"Too many parameters for IDL function (only $argNum is required): $fun()") def rtParamTypeError(fun: String, invalid: Object, expectType: String)(implicit ctx: PRC): NCE = newRuntimeError(s"Expected '$expectType' type of parameter for IDL function '$fun()', found: $invalid") + def rtParamNullError(fun: String)(implicit ctx: PRC): NCE = + newRuntimeError(s"Unexpected 'null' parameter for IDL function: $fun()") def rtListTypeError(fun: String, cause: Exception)(implicit ctx: PRC): NCE = newRuntimeError(s"Expected uniform list type for IDL function '$fun()', found polymorphic list.", cause) + def rtFunError(fun: String, cause: Exception)(implicit ctx: PRC): NCE = + newRuntimeError(s"Runtime error in IDL function: $fun()", cause) /** * @@ -551,8 +555,11 @@ trait NCIdlCompilerBase { } else arg1() + def toX[T](typ: String, v: Object, is: Object ⇒ Boolean, as: Object ⇒ T): T = { - if (!is(v)) + if (v == null) + throw rtParamNullError(fun) + else if (!is(v)) throw rtParamTypeError(fun, v, typ) as(v) @@ -584,7 +591,7 @@ trait NCIdlCompilerBase { () ⇒ { val (v1, v2, n) = extract2(x1, x2) - Z(util.Arrays.asList(toStr(v1).split(toStr(v2)).toList.map(_.strip)), n) + Z(util.Arrays.asList(toStr(v1).split(toStr(v2)).toList.map(_.strip):_*), n) } ) } @@ -991,7 +998,8 @@ trait NCIdlCompilerBase { def z[Y](args: () ⇒ Y, body: Y ⇒ Z): Unit = { val x = args(); stack.push(() ⇒ body(x)) } def z0(body: () ⇒ Z): Unit = { popMarker(0); stack.push(() ⇒ body()) } - fun match { + try + fun match { // Metadata access. case "meta_part" ⇒ doPartMeta() case "meta_token" ⇒ z[ST](arg1, { x ⇒ val Z(v, _) = x(); Z(box(tok.meta[Object](toStr(v))), 1) }) @@ -1164,5 +1172,9 @@ trait NCIdlCompilerBase { case _ ⇒ throw rtUnknownFunError(fun) // Assertion. } + catch { + case e: NCE ⇒ throw e // Rethrow. + case e: Exception ⇒ throw rtFunError(fun, e) + } } } 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 b9d0de5..9cba0d7 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 @@ -608,36 +608,40 @@ object NCIntentSolverEngine extends LazyLogging with NCOpenCensusTrace { senToks: Seq[UsedToken], convToks: Seq[UsedToken] ): Option[TermMatch] = { - solvePredicate(term.pred, ctx, term.min, term.max, senToks, convToks) match { - case Some((usedToks, predWeight)) ⇒ Some( - TermMatch( - term.id, - usedToks, - if (usedToks.nonEmpty) { - // If term match is non-empty we add the following weights: - // - min - // - delta between specified max and normalized max (how close the actual quantity was to the specified one). - // - normalized max - predWeight - .append(term.min) - .append(-(term.max - usedToks.size)) - // Normalize max quantifier in case of unbound max. - .append(if (term.max == Integer.MAX_VALUE) usedToks.size else term.max) - } else { - // Term is optional (found but empty). - require(term.min == 0) - - predWeight - .append(0) - .append(-term.max) - // Normalize max quantifier in case of unbound max. - .append(if (term.max == Integer.MAX_VALUE) 0 else term.max) - } + try + solvePredicate(term.pred, ctx, term.min, term.max, senToks, convToks) match { + case Some((usedToks, predWeight)) ⇒ Some( + TermMatch( + term.id, + usedToks, + if (usedToks.nonEmpty) { + // If term match is non-empty we add the following weights: + // - min + // - delta between specified max and normalized max (how close the actual quantity was to the specified one). + // - normalized max + predWeight + .append(term.min) + .append(-(term.max - usedToks.size)) + // Normalize max quantifier in case of unbound max. + .append(if (term.max == Integer.MAX_VALUE) usedToks.size else term.max) + } else { + // Term is optional (found but empty). + require(term.min == 0) + + predWeight + .append(0) + .append(-term.max) + // Normalize max quantifier in case of unbound max. + .append(if (term.max == Integer.MAX_VALUE) 0 else term.max) + } + ) ) - ) - // Term not found at all. - case None ⇒ None + // Term not found at all. + case None ⇒ None + } + catch { + case e: Exception ⇒ throw new NCE(s"Runtime error processing IDL term: ${term.toAnsiString}", e) } } diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctions.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctions.scala index e28b91e..4c8840d 100644 --- a/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctions.scala +++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctions.scala @@ -175,15 +175,14 @@ private[functions] trait NCIdlFunctions { } } - protected def expectNceError(f: String): Unit = + protected def expectError(f: String): Unit = try { test(f) require(false) } catch { - case e: NCE ⇒ println(s"Expected error: ${e.getLocalizedMessage}") - case e: Exception ⇒ throw e + case e: Exception ⇒ println(s"Expected error: ${e.getLocalizedMessage}") } protected implicit def convert(pred: String): TestDesc = TestDesc(truth = pred) diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctionsMath.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctionsMath.scala index 3ef44fa..9b317b7 100644 --- a/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctionsMath.scala +++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctionsMath.scala @@ -27,12 +27,12 @@ class NCIdlFunctionsMath extends NCIdlFunctions { @Test def testError(): Unit = { // Invalid name. - expectNceError("xxx(1, 1)") - expectNceError("xxx()") + expectError("xxx(1, 1)") + expectError("xxx()") // Invalid arguments count. - expectNceError("atan(1, 1) == 1") - expectNceError("pi(1)") + expectError("atan(1, 1) == 1") + expectError("pi(1)") } @Test diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctionsStat.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctionsStat.scala index 4bbd7b3..4e99c1b 100644 --- a/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctionsStat.scala +++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctionsStat.scala @@ -25,10 +25,10 @@ import org.junit.jupiter.api.Test class NCIdlFunctionsStat extends NCIdlFunctions { @Test def testError(): Unit = { - expectNceError("avg(list()) == 2") - expectNceError("avg(list('A')) == 2") - expectNceError("stdev(list()) == 2") - expectNceError("stdev(list('A')) == 2") + expectError("avg(list()) == 2") + expectError("avg(list('A')) == 2") + expectError("stdev(list()) == 2") + expectError("stdev(list('A')) == 2") } @Test diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctionsStrings.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctionsStrings.scala index 88658d8..f913e91 100644 --- a/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctionsStrings.scala +++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/model/intent/idl/compiler/functions/NCIdlFunctionsStrings.scala @@ -26,48 +26,49 @@ class NCIdlFunctionsStrings extends NCIdlFunctions { @Test def test(): Unit = test( -// "trim(' a b ') == 'a b'", -// "strip(' a b ') == 'a b'", -// "uppercase('aB') == 'AB'", -// "lowercase('aB') == 'ab'", -// "is_alpha('aB') == true", -// "is_alpha('aB1') == false", -// "is_alphanum('aB1') == true", -// "is_whitespace('A') == false", -// "is_num('a') == false", -// "is_num('1') == true", -// "is_numspace('A') == false", -// "is_alphaspace('A') == true", -// "is_alphanumspace('A') == true", -// "is_alphanumspace('1 A') == true", -// "start_with('ab', 'a') == true", -// "start_with('ab', 'b') == false", -// "end_with('ab', 'a') == false", -// "end_with('ab', 'b') == true", -// "contains('ab', 'a') == true", -// "contains('ab', 'bc') == false", -// "index_of('ab', 'b') == 1", -// "index_of('ab', 'bc') == -1", -// "substr('abc', 0, 1) == 'a'", -// "substr('abc', 0, 2) == 'ab'", -// "replace('abc', 'a', 'X') == 'Xbc'", -// "replace('abc', '0', '0') == 'abc'", + "trim(' a b ') == 'a b'", + "strip(' a b ') == 'a b'", + "uppercase('aB') == 'AB'", + "lowercase('aB') == 'ab'", + "is_alpha('aB') == true", + "is_alpha('aB1') == false", + "is_alphanum('aB1') == true", + "is_whitespace('A') == false", + "is_num('a') == false", + "is_num('1') == true", + "is_numspace('A') == false", + "is_alphaspace('A') == true", + "is_alphanumspace('A') == true", + "is_alphanumspace('1 A') == true", + "start_with('ab', 'a') == true", + "start_with('ab', 'b') == false", + "end_with('ab', 'a') == false", + "end_with('ab', 'b') == true", + "contains('ab', 'a') == true", + "contains('ab', 'bc') == false", + "index_of('ab', 'b') == 1", + "index_of('ab', 'bc') == -1", + "substr('abc', 0, 1) == 'a'", + "substr('abc', 0, 2) == 'ab'", + "replace('abc', 'a', 'X') == 'Xbc'", + "replace('abc', '0', '0') == 'abc'", "split('1 A', ' ') == list('1', 'A')", -// "split_trim('1 A ', ' ') == list('1', 'A')", + "split_trim('1 A ', ' ') == list('1', 'A')", // Whitespaces. -// "replace('abc', 'ab', '') == 'c'", -// "substr('abc', 20, 30) == ''", -// "is_alphanumspace(' ') == true", -// "is_alphanumspace(' ') == true", -// "is_alphanumspace(' ') == true", -// "is_whitespace(' ') == true", -// "trim(' ') == ''" + "replace('abc', 'ab', '') == 'c'", + "substr('abc', 1, 3) == 'bc'", + "is_alphanumspace(' ') == true", + "is_alphanumspace(' ') == true", + "is_alphanumspace(' ') == true", + "is_whitespace(' ') == true", + "trim(' ') == ''" ) @Test def testError(): Unit = { - expectNceError("split('1 A') == true") - expectNceError("split_trim('1 A') == true") + expectError("substr('abc', 10, 30) == 'bc'") + expectError("split('1 A') == true") + expectError("split_trim('1 A') == true") } }
