You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nlpcraft.apache.org by se...@apache.org on 2022/08/25 10:28:41 UTC

[incubator-nlpcraft] branch NLPCRAFT-500 updated (5490d1bf -> 4c7be2b1)

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

sergeykamov pushed a change to branch NLPCRAFT-500
in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git


    from 5490d1bf WIP.
     new 9bac8d03 IDL fragments related fixes.
     new ce166aa7 IDL fragments related fixes.
     new 4cc1f0e3 IDL fragments related fixes.
     new 0b2855bd IDL fragments related fixes.
     new 167461bd IDL fragments related fixes.
     new 43eb7bfe IDL fragments related fixes.
     new 1b1e7315 IDL fragments related fixes.
     new 9fa4af8b IDL fragments related fixes.
     new b661edeb IDL fragments related fixes.
     new 47ef27dd IDL fragments related fixes.
     new 4c7be2b1 IDL fragments related fixes.

The 11 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../examples/lightswitch/LightSwitchFrModel.scala  |   5 +-
 .../examples/lightswitch/LightSwitchRuModel.scala  |   5 +-
 .../lightswitch/LightSwitchScalaModel.scala        |   5 +-
 .../apache/nlpcraft/examples/time/TimeModel.scala  |   2 +-
 .../main/scala/org/apache/nlpcraft/NCResult.scala  |   6 +
 .../nlpcraft/internal/impl/NCModelScanner.scala    |  10 +-
 .../internal/intent/compiler/NCIDLCompiler.scala   | 134 +++++++++------------
 .../conversation/NCConversationTimeoutSpec.scala   |   2 +-
 .../internal/impl/NCModelCallbacksSpec.scala       |  10 +-
 .../nlpcraft/internal/impl/NCModelClientSpec.scala |   4 +-
 .../internal/impl/NCModelClientSpec3.scala         |   2 +-
 .../impl/scan/NCModelIntentsInvalidArgsSpec.scala  |   2 +-
 .../compiler/NCIDLFragmentsOverridingSpec.scala    |  50 ++++++++
 .../compiler/NCIDLFragmentsOverridingSpec2.scala   |  55 +++++++++
 .../intent/compiler/NCIDLFragmentsSpec.scala       |  50 ++++----
 .../internal/intent/compiler/impl_level1.idl}      |   9 +-
 .../internal/intent/compiler/impl_level2.idl}      |  10 +-
 .../apache/nlpcraft/nlp/NCEntityEnricherSpec.scala |   2 +-
 .../apache/nlpcraft/nlp/NCEntityMapperSpec.scala   |   2 +-
 .../nlpcraft/nlp/NCEntityValidatorSpec.scala       |   2 +-
 .../apache/nlpcraft/nlp/NCTokenEnricherSpec.scala  |   2 +-
 .../apache/nlpcraft/nlp/NCTokenValidatorSpec.scala |   2 +-
 .../apache/nlpcraft/nlp/NCVariantFilterSpec.scala  |   2 +-
 .../apache/nlpcraft/nlp/util/NCTestResult.scala    |   7 +-
 24 files changed, 236 insertions(+), 144 deletions(-)
 create mode 100644 nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec.scala
 create mode 100644 nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec2.scala
 copy nlpcraft/src/test/{resources/scan/idl.idl => scala/org/apache/nlpcraft/internal/intent/compiler/impl_level1.idl} (85%)
 copy nlpcraft/src/test/{resources/scan/idl.idl => scala/org/apache/nlpcraft/internal/intent/compiler/impl_level2.idl} (79%)


[incubator-nlpcraft] 05/11: IDL fragments related fixes.

Posted by se...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 167461bdc596f3fa79044379f06d0e9e4af0fb6d
Author: Sergey Kamov <sk...@gmail.com>
AuthorDate: Thu Aug 25 12:07:23 2022 +0300

    IDL fragments related fixes.
---
 .../examples/lightswitch/LightSwitchFrModel.scala  |  5 +--
 .../examples/lightswitch/LightSwitchRuModel.scala  |  5 +--
 .../lightswitch/LightSwitchScalaModel.scala        |  5 +--
 .../apache/nlpcraft/examples/time/TimeModel.scala  |  2 +-
 .../main/scala/org/apache/nlpcraft/NCResult.scala  |  6 +++
 .../internal/intent/compiler/NCIDLCompiler.scala   | 13 ++++--
 .../conversation/NCConversationTimeoutSpec.scala   |  2 +-
 .../internal/impl/NCModelCallbacksSpec.scala       | 10 ++---
 .../nlpcraft/internal/impl/NCModelClientSpec.scala |  4 +-
 .../internal/impl/NCModelClientSpec3.scala         |  2 +-
 .../impl/scan/NCModelIntentsInvalidArgsSpec.scala  |  2 +-
 .../compiler/NCIDLFragmentsOverridingSpec.scala    | 50 ++++++++++++++++++++++
 .../apache/nlpcraft/nlp/NCEntityEnricherSpec.scala |  2 +-
 .../apache/nlpcraft/nlp/NCEntityMapperSpec.scala   |  2 +-
 .../nlpcraft/nlp/NCEntityValidatorSpec.scala       |  2 +-
 .../apache/nlpcraft/nlp/NCTokenEnricherSpec.scala  |  2 +-
 .../apache/nlpcraft/nlp/NCTokenValidatorSpec.scala |  2 +-
 .../apache/nlpcraft/nlp/NCVariantFilterSpec.scala  |  2 +-
 .../apache/nlpcraft/nlp/util/NCTestResult.scala    |  7 ++-
 19 files changed, 89 insertions(+), 36 deletions(-)

diff --git a/nlpcraft-examples/lightswitch-fr/src/main/scala/org/apache/nlpcraft/examples/lightswitch/LightSwitchFrModel.scala b/nlpcraft-examples/lightswitch-fr/src/main/scala/org/apache/nlpcraft/examples/lightswitch/LightSwitchFrModel.scala
index 7989fe05..494d098d 100644
--- a/nlpcraft-examples/lightswitch-fr/src/main/scala/org/apache/nlpcraft/examples/lightswitch/LightSwitchFrModel.scala
+++ b/nlpcraft-examples/lightswitch-fr/src/main/scala/org/apache/nlpcraft/examples/lightswitch/LightSwitchFrModel.scala
@@ -68,7 +68,4 @@ class LightSwitchFrModel extends NCModelAdapter(
 
         // Add HomeKit, Arduino or other integration here.
         // By default - just return a descriptive action string.
-        NCResult(
-            new Gson().toJson(Map("locations" -> locations, "action" -> action).asJava),
-            NCResultType.ASK_RESULT
-        )
\ No newline at end of file
+        NCResult(new Gson().toJson(Map("locations" -> locations, "action" -> action).asJava))
\ No newline at end of file
diff --git a/nlpcraft-examples/lightswitch-ru/src/main/scala/org/apache/nlpcraft/examples/lightswitch/LightSwitchRuModel.scala b/nlpcraft-examples/lightswitch-ru/src/main/scala/org/apache/nlpcraft/examples/lightswitch/LightSwitchRuModel.scala
index ef6063ab..81021e4e 100644
--- a/nlpcraft-examples/lightswitch-ru/src/main/scala/org/apache/nlpcraft/examples/lightswitch/LightSwitchRuModel.scala
+++ b/nlpcraft-examples/lightswitch-ru/src/main/scala/org/apache/nlpcraft/examples/lightswitch/LightSwitchRuModel.scala
@@ -60,7 +60,4 @@ class LightSwitchRuModel extends NCModelAdapter(
 
         // Add HomeKit, Arduino or other integration here.
         // By default - just return a descriptive action string.
-        NCResult(
-           new Gson().toJson(Map("locations" -> locations, "action" -> action).asJava),
-           NCResultType.ASK_RESULT
-        )
\ No newline at end of file
+        NCResult(new Gson().toJson(Map("locations" -> locations, "action" -> action).asJava))
\ No newline at end of file
diff --git a/nlpcraft-examples/lightswitch/src/main/scala/org/apache/nlpcraft/examples/lightswitch/LightSwitchScalaModel.scala b/nlpcraft-examples/lightswitch/src/main/scala/org/apache/nlpcraft/examples/lightswitch/LightSwitchScalaModel.scala
index 42b43495..df159909 100644
--- a/nlpcraft-examples/lightswitch/src/main/scala/org/apache/nlpcraft/examples/lightswitch/LightSwitchScalaModel.scala
+++ b/nlpcraft-examples/lightswitch/src/main/scala/org/apache/nlpcraft/examples/lightswitch/LightSwitchScalaModel.scala
@@ -59,7 +59,4 @@ class LightSwitchScalaModel extends NCModelAdapter(
 
         // Add HomeKit, Arduino or other integration here.=
         // By default - just return a descriptive action string.
-        NCResult(
-            s"Lights are [$status] in [${locations.toLowerCase}].",
-            NCResultType.ASK_RESULT
-        )
\ No newline at end of file
+        NCResult(s"Lights are [$status] in [${locations.toLowerCase}].")
\ No newline at end of file
diff --git a/nlpcraft-examples/time/src/main/scala/org/apache/nlpcraft/examples/time/TimeModel.scala b/nlpcraft-examples/time/src/main/scala/org/apache/nlpcraft/examples/time/TimeModel.scala
index 89c8fadb..4524a817 100644
--- a/nlpcraft-examples/time/src/main/scala/org/apache/nlpcraft/examples/time/TimeModel.scala
+++ b/nlpcraft-examples/time/src/main/scala/org/apache/nlpcraft/examples/time/TimeModel.scala
@@ -66,7 +66,7 @@ class TimeModel extends NCModelAdapter(
             )
 
         try
-            NCResult(new ObjectMapper(new YAMLFactory).writeValueAsString(m), NCResultType.ASK_RESULT)
+            NCResult(new ObjectMapper(new YAMLFactory).writeValueAsString(m))
         catch
             case e: JsonProcessingException => throw new RuntimeException("YAML conversion error.", e)
 
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/NCResult.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/NCResult.scala
index 67bd4789..0dfaca5c 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/NCResult.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/NCResult.scala
@@ -33,6 +33,12 @@ object NCResult:
             def getType: NCResultType = resultType
             def getIntentId: Option[String] = None
 
+    def apply(body: Any): NCResult =
+        new NCResult() :
+            def getBody: Any = body
+            def getType: NCResultType = NCResultType.ASK_RESULT
+            def getIntentId: Option[String] = None
+
 trait NCResult:
     def getBody: Any
     def getType: NCResultType
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
index bb93bd9d..d54028d5 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
@@ -182,7 +182,6 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with mutable.Cloneab
 
         override def exitFragId(ctx: IDP.FragIdContext): Unit =
             fragId = ctx.id().getText
-            if fragCache.contains(fragId) then SE(s"Duplicate fragment ID: $fragId")(ctx.id())
 
         override def exitFragRef(ctx: IDP.FragRefContext): Unit =
             val id = ctx.id().getText
@@ -258,7 +257,15 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with mutable.Cloneab
 
         override def exitFrag(ctx: IDP.FragContext): Unit =
             val frag = NCIDLFragment(fragId, terms.toList)
+
+            fragCache.get(frag.id) match
+                case Some(exFrag) =>
+                    if frag.terms != exFrag.terms then logger.warn(s"Fragment '${frag.id}' was override for origin: '${this.origin}'.")
+                case None => // No-op.
+
             fragCache += frag.id -> frag
+
+
             terms.clear()
             fragId = null
 
@@ -279,7 +286,7 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with mutable.Cloneab
                     idl,
                     intentId,
                     intentOpts,
-                    if (intentMeta == null) Map.empty else intentMeta,
+                    if intentMeta == null then Map.empty else intentMeta,
                     flowRegex,
                     terms.toList
                 )
@@ -307,7 +314,7 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with mutable.Cloneab
                     // Second, try as a classloader resource.
                     if imports == null then
                         val in = cfg.getClass.getClassLoader.getResourceAsStream(x)
-                        if (in != null)
+                        if in != null then
                             val idl = NCUtils.readStream(in).mkString("\n")
                             imports = compile(idl, x)
 
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/conversation/NCConversationTimeoutSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/conversation/NCConversationTimeoutSpec.scala
index 3417b93b..726f966c 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/conversation/NCConversationTimeoutSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/conversation/NCConversationTimeoutSpec.scala
@@ -55,7 +55,7 @@ class NCConversationTimeoutSpec:
                 @NCIntent("intent=i term(e)~{# == 'test'}")
                 def onMatch(ctx: NCContext, im: NCIntentMatch, @NCIntentTerm("e") e: NCEntity): NCResult =
                     val conv = ctx.getConversation
-                    val res = NCResult(conv.getData.getOpt("key").getOrElse(EMPTY), NCResultType.ASK_RESULT)
+                    val res = NCResult(conv.getData.getOpt("key").getOrElse(EMPTY))
 
                     // For next calls.
                     conv.getData.put("key", VALUE)
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelCallbacksSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelCallbacksSpec.scala
index b5af15f5..5c07dbb5 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelCallbacksSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelCallbacksSpec.scala
@@ -41,11 +41,11 @@ class NCModelCallbacksSpec:
 
     private val states = collection.mutable.HashSet.empty[State]
 
-    private val RESULT_INTENT = NCResult("result-intent", NCResultType.ASK_RESULT)
-    private val RESULT_CONTEXT = NCResult("result-context", NCResultType.ASK_RESULT)
-    private val RESULT_RESULT = NCResult("result-result", NCResultType.ASK_RESULT)
-    private val RESULT_REJECTION = NCResult("result-rejection", NCResultType.ASK_RESULT)
-    private val RESULT_ERROR = NCResult("result-error", NCResultType.ASK_RESULT)
+    private val RESULT_INTENT = NCResult("result-intent")
+    private val RESULT_CONTEXT = NCResult("result-context")
+    private val RESULT_RESULT = NCResult("result-result")
+    private val RESULT_REJECTION = NCResult("result-rejection")
+    private val RESULT_ERROR = NCResult("result-error")
 
     private val MDL: NCTestModelAdapter =
         new NCTestModelAdapter():
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec.scala
index 9b2140ef..ccfbd2cb 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec.scala
@@ -64,7 +64,7 @@ class NCModelClientSpec:
         test0(
             new NCTestModelAdapter():
                 @NCIntent("intent=ls term(act)={# == 'ls:on'} term(loc)={# == 'ls:loc'}*")
-                def onMatch(ctx: NCContext, im: NCIntentMatch, @NCIntentTerm("act") act: NCEntity, @NCIntentTerm("loc") locs: List[NCEntity]): NCResult = NCResult("test", NCResultType.ASK_RESULT)
+                def onMatch(ctx: NCContext, im: NCIntentMatch, @NCIntentTerm("act") act: NCEntity, @NCIntentTerm("loc") locs: List[NCEntity]): NCResult = TEST_RESULT
         )
     /**
       * 
@@ -74,6 +74,6 @@ class NCModelClientSpec:
         test0(
             new NCTestModelAdapter():
                 @NCIntent("intent=ls term(act)={has(ent_groups, 'act')} term(loc)={# == 'ls:loc'}*")
-                def onMatch(ctx: NCContext, im: NCIntentMatch, @NCIntentTerm("act") act: NCEntity, @NCIntentTerm("loc") locs: List[NCEntity]): NCResult = NCResult("test", NCResultType.ASK_RESULT)
+                def onMatch(ctx: NCContext, im: NCIntentMatch, @NCIntentTerm("act") act: NCEntity, @NCIntentTerm("loc") locs: List[NCEntity]): NCResult = TEST_RESULT
         )
 
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec3.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec3.scala
index 9850b4fe..a18a2885 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec3.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec3.scala
@@ -43,7 +43,7 @@ class NCModelClientSpec3:
                 pl
 
             @NCIntent("intent=i1 term(t1)={# == 'e1'}")
-            def onMatch(ctx: NCContext, im: NCIntentMatch, @NCIntentTerm("t1") t1: NCEntity): NCResult = NCResult("Data", NCResultType.ASK_RESULT)
+            def onMatch(ctx: NCContext, im: NCIntentMatch, @NCIntentTerm("t1") t1: NCEntity): NCResult = TEST_RESULT
 
         Using.resource(new NCModelClient(mdl)) { client =>
             def ask(): NCFiredIntent = client.debugAsk("e1", "userId", true)
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/scan/NCModelIntentsInvalidArgsSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/scan/NCModelIntentsInvalidArgsSpec.scala
index 5043c0d1..eae13ea3 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/scan/NCModelIntentsInvalidArgsSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/scan/NCModelIntentsInvalidArgsSpec.scala
@@ -97,7 +97,7 @@ class NCModelIntentsInvalidArgsSpec:
 
     private def mkResult0(obj: Any): NCResult =
         println(s"Result body: $obj, class=${obj.getClass}")
-        NCResult(obj, NCResultType.ASK_RESULT)
+        NCResult(obj)
 
     private def processOptInt(opt: Option[Int]): NCResult =
         // Access and cast.
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec.scala
new file mode 100644
index 00000000..23f228a2
--- /dev/null
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec.scala
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.nlpcraft.internal.intent.compiler
+
+import org.apache.nlpcraft.*
+import org.apache.nlpcraft.annotations.NCIntent
+import org.apache.nlpcraft.internal.impl.NCModelScanner
+import org.apache.nlpcraft.nlp.parsers.NCSemanticTestElement as TE
+import org.apache.nlpcraft.nlp.util.*
+import org.junit.jupiter.api.Test
+
+import scala.util.Using
+
+class NCIDLFragmentsOverridingSpec:
+    @NCIntent("fragment=f term(x)~{# == 'x'}")
+    class M extends NCTestModelAdapter:
+        override val getPipeline: NCPipeline =
+            val pl = mkEnPipeline
+            pl.entParsers += NCTestUtils.mkEnSemanticParser(TE("x"), TE("y"))
+            pl
+
+        // Uses fragment defined on class level.
+        @NCIntent("intent=i2 fragment(f)")
+        private def onX(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult("onX")
+
+        // Overrides fragment defined on class level.
+        @NCIntent("fragment=f term(y)~{# == 'y'} intent=i1 fragment(f)")
+        private def onY(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult("onY")
+    
+    @Test
+    def test(): Unit =
+        Using.resource(new NCModelClient(new M())) { client =>
+            require(client.ask("x", "usr").getBody == "onX")
+            require(client.ask("y", "usr").getBody == "onY")
+        }
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCEntityEnricherSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCEntityEnricherSpec.scala
index 1ae0b536..2a031087 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCEntityEnricherSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCEntityEnricherSpec.scala
@@ -33,7 +33,7 @@ class NCEntityEnricherSpec:
     private def test0(pipeline: NCPipeline, ok: Boolean): Unit =
         val mdl: NCModel = new NCModelAdapter(NCModelConfig("test.id", "Test model", "1.0"), pipeline):
             @NCIntent("intent=i term(any)={meta_ent('k1') == 'v1'}")
-            def onMatch(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult("OK", NCResultType.ASK_RESULT)
+            def onMatch(ctx: NCContext, im: NCIntentMatch): NCResult = TEST_RESULT
 
         NCTestUtils.askSomething(mdl, ok)
 
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCEntityMapperSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCEntityMapperSpec.scala
index 76db57d5..ff73f090 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCEntityMapperSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCEntityMapperSpec.scala
@@ -67,7 +67,7 @@ class NCEntityMapperSpec:
             pl
 
         @NCIntent("intent=abcd term(abcd)={# == 'abcd'}")
-        def onMatch(ctx: NCContext, im: NCIntentMatch, @NCIntentTerm("abcd") abcd: NCEntity): NCResult = NCResult("OK", NCResultType.ASK_RESULT)
+        def onMatch(ctx: NCContext, im: NCIntentMatch, @NCIntentTerm("abcd") abcd: NCEntity): NCResult = TEST_RESULT
 
     @Test
     def test(): Unit = Using.resource(new NCModelClient(mdl)) { client =>
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCEntityValidatorSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCEntityValidatorSpec.scala
index 362797e9..51de067b 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCEntityValidatorSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCEntityValidatorSpec.scala
@@ -32,7 +32,7 @@ import scala.util.Using
 class NCEntityValidatorSpec:
     private def test0(pipeline: NCPipeline, ok: Boolean): Unit =
         val mdl: NCModel = new NCModelAdapter(NCModelConfig("test.id", "Test model", "1.0"), pipeline):
-            override def onContext(ctx: NCContext): Option[NCResult] = Option(NCResult("OK", NCResultType.ASK_RESULT))
+            override def onContext(ctx: NCContext): Option[NCResult] = Option(TEST_RESULT)
 
         NCTestUtils.askSomething(mdl, ok)
 
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCTokenEnricherSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCTokenEnricherSpec.scala
index bb80677d..86033532 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCTokenEnricherSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCTokenEnricherSpec.scala
@@ -33,7 +33,7 @@ class NCTokenEnricherSpec:
     private def test0(pipeline: NCPipeline, ok: Boolean): Unit =
         val mdl: NCModel = new NCModelAdapter(NCModelConfig("test.id", "Test model", "1.0"), pipeline):
             @NCIntent("intent=i term(any)={meta_ent('nlp:token:k1') == 'v1'}")
-            def onMatch(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult("OK", NCResultType.ASK_RESULT)
+            def onMatch(ctx: NCContext, im: NCIntentMatch): NCResult = TEST_RESULT
 
         NCTestUtils.askSomething(mdl, ok)
 
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCTokenValidatorSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCTokenValidatorSpec.scala
index b1cf7047..7be9bda7 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCTokenValidatorSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCTokenValidatorSpec.scala
@@ -31,7 +31,7 @@ import scala.util.Using
 class NCTokenValidatorSpec:
     private def test0(pipeline: NCPipeline, ok: Boolean): Unit =
         val mdl: NCModel = new NCModelAdapter(NCModelConfig("test.id", "Test model", "1.0"), pipeline):
-            override def onContext(ctx: NCContext): Option[NCResult] = Option(NCResult("OK", NCResultType.ASK_RESULT))
+            override def onContext(ctx: NCContext): Option[NCResult] = Option(TEST_RESULT)
 
         NCTestUtils.askSomething(mdl, ok)
 
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCVariantFilterSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCVariantFilterSpec.scala
index aed99a34..c0644da4 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCVariantFilterSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/NCVariantFilterSpec.scala
@@ -34,7 +34,7 @@ class NCVariantFilterSpec:
     private def test0(pipeline: NCPipeline, ok: Boolean): Unit =
         val mdl: NCModel = new NCModelAdapter(NCModelConfig("test.id", "Test model", "1.0"), pipeline):
             @NCIntent("intent=i term(any)={true}")
-            def onMatch(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult("OK", NCResultType.ASK_RESULT)
+            def onMatch(ctx: NCContext, im: NCIntentMatch): NCResult = TEST_RESULT
 
         NCTestUtils.askSomething(mdl, ok)
 
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/util/NCTestResult.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/util/NCTestResult.scala
index 14b86626..1936ed70 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/util/NCTestResult.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/nlp/util/NCTestResult.scala
@@ -17,16 +17,15 @@
 
 package org.apache.nlpcraft.nlp.util
 
-import org.apache.nlpcraft.{NCResult, NCResultType}
+import org.apache.nlpcraft.*
 
 /**
   *
   */
-object  NCTestResult {
+object NCTestResult:
     def apply(): NCResult = TEST_RESULT
-}
 
 /**
   *
   */
-val TEST_RESULT = NCResult("test", NCResultType.ASK_RESULT)
+val TEST_RESULT = NCResult("test")


[incubator-nlpcraft] 02/11: IDL fragments related fixes.

Posted by se...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit ce166aa7d8e2abdaa1abfe422bdb0154c0f2e673
Author: Sergey Kamov <sk...@gmail.com>
AuthorDate: Thu Aug 25 11:03:13 2022 +0300

    IDL fragments related fixes.
---
 .../internal/intent/compiler/NCIDLCompiler.scala   | 65 ++++++----------------
 1 file changed, 16 insertions(+), 49 deletions(-)

diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
index 36cbca7b..1385dcf4 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
@@ -32,54 +32,21 @@ import java.io.*
 import java.net.*
 import java.util.Optional
 import java.util.regex.*
-import scala.collection.concurrent.TrieMap
 import scala.collection.mutable
-import scala.jdk.CollectionConverters.*
 
-class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with scala.collection.mutable.Cloneable[NCIDLCompiler]:
+class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with mutable.Cloneable[NCIDLCompiler]:
     private val intents = mutable.HashMap.empty[String, Set[NCIDLIntent]]
 
     // Compiler caches.
     private val fragCache = mutable.HashMap.empty[String, NCIDLFragment]
     private val importCache = mutable.HashSet.empty[String]
 
-    /**
-      *
-      * @param fragId
-      * @return
-      */
-    private def getFragment(fragId: String): Option[NCIDLFragment] = fragCache.get(fragId)
-
-    /**
-      *
-      * @param fragId
-      * @return
-      */
-    private def hasFragment(fragId: String): Boolean = fragCache.contains(fragId)
-
-    /**
-      *
-      * @param mdlId
-      * @param frag
-      */
-    private def addFragment(mdlId: String, frag: NCIDLFragment): Unit = fragCache += frag.id -> frag
-
-    private def addImport(imp: String): Unit = importCache += imp
-
-    /**
-      *
-      * @param imp
-      * @return
-      */
-    private def hasImport(imp: String): Boolean = importCache.contains(imp)
-
     /**
       *
       * @param origin
       * @param idl
-      * @param mdlCfg
       */
-    class FiniteStateMachine(origin: String, idl: String, mdlCfg: NCModelConfig) extends NCIDLBaseListener with NCIDLCodeGenerator:
+    class FiniteStateMachine(origin: String, idl: String) extends NCIDLBaseListener with NCIDLCodeGenerator:
         // Actual value for '*' as in min/max shortcut.
         final private val MINMAX_MAX = 100
 
@@ -215,12 +182,12 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with scala.collectio
 
         override def exitFragId(ctx: IDP.FragIdContext): Unit =
             fragId = ctx.id().getText
-            if hasFragment(fragId) then SE(s"Duplicate fragment ID: $fragId")(ctx.id())
+            if fragCache.contains(fragId) then SE(s"Duplicate fragment ID: $fragId")(ctx.id())
 
         override def exitFragRef(ctx: IDP.FragRefContext): Unit =
             val id = ctx.id().getText
 
-            getFragment(id) match
+            fragCache.get(id) match
                 case Some(frag) =>
                     val meta = if fragMeta == null then Map.empty[String, Any] else fragMeta
                     for (fragTerm <- frag.terms)
@@ -290,7 +257,8 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with scala.collectio
             }
 
         override def exitFrag(ctx: IDP.FragContext): Unit =
-            addFragment(mdlCfg.getId, NCIDLFragment(fragId, terms.toList))
+            val frag = NCIDLFragment(fragId, terms.toList)
+            fragCache += frag.id -> frag
             terms.clear()
             fragId = null
 
@@ -324,9 +292,9 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with scala.collectio
         override def exitImprt(ctx: IDP.ImprtContext): Unit =
                 val x = NCUtils.trimQuotes(ctx.qstring().getText)
 
-                if hasImport(x) then logger.warn(s"Ignoring already processed IDL import '$x' in: $origin")
+                if importCache.contains(x) then logger.warn(s"Ignoring already processed IDL import '$x' in: $origin")
                 else
-                   addImport(x)
+                   importCache += x
 
                     var imports: Set[NCIDLIntent] = null
                     val file = new File(x)
@@ -338,7 +306,7 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with scala.collectio
 
                     // Second, try as a classloader resource.
                     if imports == null then
-                        val in = mdlCfg.getClass.getClassLoader.getResourceAsStream(x)
+                        val in = cfg.getClass.getClassLoader.getResourceAsStream(x)
                         if (in != null)
                             val idl = NCUtils.readStream(in).mkString("\n")
                             imports = compile(idl, x)
@@ -354,10 +322,10 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with scala.collectio
                     imports.foreach(addIntent(_)(ctx.qstring()))
 
         override def syntaxError(errMsg: String, srcName: String, line: Int, pos: Int): NCException =
-            throw new NCException(mkSyntaxError(errMsg, srcName, line, pos, idl, origin, mdlCfg))
+            throw new NCException(mkSyntaxError(errMsg, srcName, line, pos, idl, origin, cfg))
 
         override def runtimeError(errMsg: String, srcName: String, line: Int, pos: Int, cause: Exception = null): NCException =
-            throw new NCException(mkRuntimeError(errMsg, srcName, line, pos, idl, origin, mdlCfg), cause)
+            throw new NCException(mkRuntimeError(errMsg, srcName, line, pos, idl, origin, cfg), cause)
 
     /**
       *
@@ -480,7 +448,7 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with scala.collectio
 
         val idlNorm = idl.strip()
         intents.getOrElseUpdate(idlNorm, {
-            val (fsm, parser) = antlr4Armature(idlNorm, cfg, srcName)
+            val (fsm, parser) = antlr4Armature(idlNorm, srcName)
 
             // Parse the input IDL and walk built AST.
             (new ParseTreeWalker).walk(fsm, parser.idl())
@@ -492,22 +460,21 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with scala.collectio
     /**
       *
       * @param idl
-      * @param mdlCfg
       * @param origin
       * @return
       */
-    private def antlr4Armature(idl: String, mdlCfg: NCModelConfig, origin: String): (FiniteStateMachine, IDP) =
+    private def antlr4Armature(idl: String, origin: String): (FiniteStateMachine, IDP) =
         val lexer = new NCIDLLexer(CharStreams.fromString(idl, origin))
         val parser = new IDP(new CommonTokenStream(lexer))
 
         // Set custom error handlers.
         lexer.removeErrorListeners()
         parser.removeErrorListeners()
-        lexer.addErrorListener(new CompilerErrorListener(idl, mdlCfg, origin))
-        parser.addErrorListener(new CompilerErrorListener(idl, mdlCfg, origin))
+        lexer.addErrorListener(new CompilerErrorListener(idl, cfg, origin))
+        parser.addErrorListener(new CompilerErrorListener(idl, cfg, origin))
 
         // State automata + it's parser.
-        new FiniteStateMachine(origin, idl, mdlCfg) -> parser
+        new FiniteStateMachine(origin, idl) -> parser
 
     /**
       * Compiles inline (supplied) fragments and/or intents. Note that fragments are accumulated in a static


[incubator-nlpcraft] 07/11: IDL fragments related fixes.

Posted by se...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 1b1e731590a5b04df45a423e6b5e75e6fe8d1467
Author: Sergey Kamov <sk...@gmail.com>
AuthorDate: Thu Aug 25 12:31:15 2022 +0300

    IDL fragments related fixes.
---
 .../nlpcraft/internal/impl/NCModelScanner.scala    |  2 +-
 .../internal/intent/compiler/NCIDLCompiler.scala   | 56 +++++++++++-----------
 2 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelScanner.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelScanner.scala
index cdb61d2e..19bc019a 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelScanner.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelScanner.scala
@@ -489,7 +489,7 @@ object NCModelScanner extends LazyLogging:
             for (mtd <- methods)
                 callNoCache(
                     () =>
-                        for (ann <- mtd.getAnnotationsByType(CLS_INTENT); intent <- compiler.compile(ann.value, method2Str(mtd)))
+                        for (ann <- mtd.getAnnotationsByType(CLS_INTENT); intent <- compiler.compile(ann.value, method2Str(mtd), isMethodLevel = true))
                             addDecl(intent)
                             addIntent(intent, mtd, obj)
                 )
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
index dbf93735..b403545d 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
@@ -45,8 +45,9 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with mutable.Cloneab
       *
       * @param origin
       * @param idl
+      * @param isMethodLevel
       */
-    class FiniteStateMachine(origin: String, idl: String) extends NCIDLBaseListener with NCIDLCodeGenerator:
+    class FiniteStateMachine(origin: String, idl: String, isMethodLevel: Boolean) extends NCIDLBaseListener with NCIDLCodeGenerator:
         // Actual value for '*' as in min/max shortcut.
         final private val MINMAX_MAX = 100
 
@@ -260,7 +261,12 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with mutable.Cloneab
 
             fragCache.get(frag.id) match
                 case Some(exFrag) =>
-                    if frag.terms != exFrag.terms then logger.warn(s"Fragment '${frag.id}' was overriden for origin: '${this.origin}'.")
+                    if frag.terms != exFrag.terms then
+                        // TODO: text
+                        if isMethodLevel then
+                            logger.warn(s"Fragment '${frag.id}' was overriden just for for origin: '${this.origin}'.")
+                        else
+                            logger.warn(s"Fragment '${frag.id}' was overriden in origin: '${this.origin}' permanently.")
                 case None => // No-op.
 
             fragCache += frag.id -> frag
@@ -441,35 +447,14 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with mutable.Cloneab
 
             throw new NCException(mkSyntaxError(aMsg, recog.getInputStream.getSourceName, line, charPos - 1, dsl, origin, mdlCfg))
 
-    /**
-      *
-      * @param idl
-      * @param srcName
-      * @return
-      */
-    private def parseIntents(idl: String, srcName: String): Set[NCIDLIntent] =
-        require(idl != null)
-        require(cfg != null)
-        require(srcName != null)
-
-        val idlNorm = idl.strip()
-        intents.getOrElseUpdate(idlNorm, {
-            val (fsm, parser) = antlr4Armature(idlNorm, srcName)
-
-            // Parse the input IDL and walk built AST.
-            (new ParseTreeWalker).walk(fsm, parser.idl())
-
-            // Return the compiled intents.
-            fsm.getCompiledIntents
-        })
-
     /**
       *
       * @param idl
       * @param origin
+      * @param isMethodLevel
       * @return
       */
-    private def antlr4Armature(idl: String, origin: String): (FiniteStateMachine, IDP) =
+    private def antlr4Armature(idl: String, origin: String, isMethodLevel: Boolean): (FiniteStateMachine, IDP) =
         val lexer = new NCIDLLexer(CharStreams.fromString(idl, origin))
         val parser = new IDP(new CommonTokenStream(lexer))
 
@@ -480,7 +465,7 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with mutable.Cloneab
         parser.addErrorListener(new CompilerErrorListener(idl, cfg, origin))
 
         // State automata + it's parser.
-        new FiniteStateMachine(origin, idl) -> parser
+        new FiniteStateMachine(origin, idl, isMethodLevel) -> parser
 
     /**
       * Compiles inline (supplied) fragments and/or intents. Note that fragments are accumulated in a static
@@ -488,10 +473,25 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with mutable.Cloneab
       *
       * @param idl Intent IDL to compile.
       * @param origin Optional source name.
+      * @param isMethodLevel Flag.
       * @return
       */
     @throws[NCException]
-    def compile(idl: String, origin: String): Set[NCIDLIntent] = parseIntents(idl,  origin)
+    def compile(idl: String, origin: String, isMethodLevel: Boolean = false): Set[NCIDLIntent] =
+        require(idl != null)
+        require(origin != null)
+
+        val x = idl.strip()
+
+        intents.getOrElseUpdate(x, {
+            val (fsm, parser) = antlr4Armature(x, origin, isMethodLevel)
+
+            // Parse the input IDL and walk built AST.
+            (new ParseTreeWalker).walk(fsm, parser.idl())
+
+            // Return the compiled intents.
+            fsm.getCompiledIntents
+        })
 
     def clone(cp: NCIDLCompiler): NCIDLCompiler =
         val cp = new NCIDLCompiler(cfg)
@@ -503,4 +503,4 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with mutable.Cloneab
 
         cp
 
-    override def clone(): NCIDLCompiler = clone(this)
+    override def clone(): NCIDLCompiler = clone(this)
\ No newline at end of file


[incubator-nlpcraft] 09/11: IDL fragments related fixes.

Posted by se...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit b661edeb74246d09b716ecfd224cdced2271e4e7
Author: Sergey Kamov <sk...@gmail.com>
AuthorDate: Thu Aug 25 13:20:29 2022 +0300

    IDL fragments related fixes.
---
 .../intent/compiler/NCIDLFragmentsOverridingSpec.scala   | 16 ++++++++--------
 ...ingSpec.scala => NCIDLFragmentsOverridingSpec2.scala} | 12 ++++++------
 .../intent/compiler/{imp1.idl => impl_level1.idl}        |  0
 .../intent/compiler/{imp2.idl => impl_level2.idl}        |  2 +-
 4 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec.scala
index 1940c2f6..dfe77b57 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec.scala
@@ -27,24 +27,24 @@ import org.junit.jupiter.api.Test
 import scala.util.Using
 
 class NCIDLFragmentsOverridingSpec:
-    @NCIntent("fragment=f term(x)~{# == 'x'}")
+    @NCIntent("fragment=f term(x)~{# == 'x1'}")
     class M extends NCTestModelAdapter:
         // Uses fragment defined on class level.
         @NCIntent("intent=i2 fragment(f)")
-        private def onX(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult("onX")
+        private def onX(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult(1)
 
-        // Overrides fragment defined on class level.
-        @NCIntent("fragment=f term(y)~{# == 'y'} intent=i1 fragment(f)")
-        private def onY(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult("onY")
+        // Overrides fragment defined on class level by its own.
+        @NCIntent("fragment=f term(y)~{# == 'x2'} intent=i1 fragment(f)")
+        private def onY(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult(2)
 
         override val getPipeline: NCPipeline =
             val pl = mkEnPipeline
-            pl.entParsers += NCTestUtils.mkEnSemanticParser(TE("x"), TE("y"))
+            pl.entParsers += NCTestUtils.mkEnSemanticParser(TE("x1"), TE("x2"))
             pl
 
     @Test
     def test(): Unit =
         Using.resource(new NCModelClient(new M())) { client =>
-            require(client.ask("x", "usr").getBody == "onX")
-            require(client.ask("y", "usr").getBody == "onY")
+            require(client.ask("x1", "usr").getBody == 1)
+            require(client.ask("x2", "usr").getBody == 2)
         }
\ No newline at end of file
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLImportsOverridingSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec2.scala
similarity index 87%
rename from nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLImportsOverridingSpec.scala
rename to nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec2.scala
index 0d58e858..41d5adfa 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLImportsOverridingSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec2.scala
@@ -26,19 +26,19 @@ import org.junit.jupiter.api.Test
 
 import scala.util.Using
 
-class NCIDLImportsOverridingSpec:
-    @NCIntent("import('org/apache/nlpcraft/internal/intent/compiler/imp2.idl')")
+class NCIDLFragmentsOverridingSpec2:
+    @NCIntent("import('org/apache/nlpcraft/internal/intent/compiler/impl_level2.idl')")
     class M extends NCTestModelAdapter:
-        // Uses fragment defined on imp2.idl, which overrides imp1.idl.
+        // Uses fragment, defined on impl_level2.idl, which overrides impl_level1.idl.
         @NCIntent("intent=i2 fragment(f)")
         private def on2(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult(2)
 
-        // Uses own fragment, which which overrides all.
+        // Uses own fragment, which overrides all.
         @NCIntent("fragment=f term(z)~{# == 'x3'} intent=i3 fragment(f)")
         private def on3(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult(3)
 
-        // Uses initial fragment version, defined in imp1.idl.
-        @NCIntent("import('org/apache/nlpcraft/internal/intent/compiler/imp1.idl')")
+        // Uses initial fragment version (with intent), defined in impl_level1.idl.
+        @NCIntent("import('org/apache/nlpcraft/internal/intent/compiler/impl_level1.idl')")
         @NCIntentRef("i1")
         private def on1(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult(1)
 
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/imp1.idl b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/impl_level1.idl
similarity index 100%
rename from nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/imp1.idl
rename to nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/impl_level1.idl
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/imp2.idl b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/impl_level2.idl
similarity index 92%
rename from nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/imp2.idl
rename to nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/impl_level2.idl
index f92ba03f..fe5a0139 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/imp2.idl
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/impl_level2.idl
@@ -19,6 +19,6 @@
 // Test content.
 // ============================
 
-import('org/apache/nlpcraft/internal/intent/compiler/imp1.idl')
+import('org/apache/nlpcraft/internal/intent/compiler/impl_level1.idl')
 // Overrides fragment.
 fragment=f term={# == 'x2'}


[incubator-nlpcraft] 03/11: IDL fragments related fixes.

Posted by se...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 4cc1f0e326b1be72e37be69a740bcacc46a86ca4
Author: Sergey Kamov <sk...@gmail.com>
AuthorDate: Thu Aug 25 11:19:32 2022 +0300

    IDL fragments related fixes.
---
 .../scala/org/apache/nlpcraft/internal/impl/NCModelScanner.scala    | 2 ++
 .../nlpcraft/internal/intent/compiler/NCIDLFragmentsSpec.scala      | 6 ++++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelScanner.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelScanner.scala
index b799136e..cdb61d2e 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelScanner.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelScanner.scala
@@ -414,11 +414,13 @@ object NCModelScanner extends LazyLogging:
 
         var compiler = new NCIDLCompiler(mdl.getConfig)
 
+        // Overrides current compiler with new intents but without any cache (imports ang fragments)
         def callNoCache[T](f: () => T): T =
             val cp = compiler.clone()
             try f()
             finally compiler = cp.clone(compiler)
 
+        // Recovers initial compiler state if any error occur, clears all intermediate results.
         def callClear[T](f: () => T): T =
             val cp = compiler.clone()
             try f()
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsSpec.scala
index 164fa271..fbce3af0 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsSpec.scala
@@ -48,17 +48,18 @@ class NCIDLFragmentsSpec:
         @NCIntent("intent=intent2 term~{# == 'x:time'} fragment(f)")
         private def m(ctx: NCContext, im: NCIntentMatch): NCResult = null
 
-    // Fragment. Reference from method (inside a).
+    // Fragment. Reference from method (inside).
     class M4 extends NCModelAdapter(mkCfg("m4"), PL) :
         @NCIntent("fragment=f term(city)~{# == 'opennlp:location'} intent=intent2 term~{# == 'x:time'} fragment(f)")
         private def m(ctx: NCContext, im: NCIntentMatch): NCResult = null
 
     // Bad models.
 
-    // Invalid fragment.
+    // Missed fragment definition.
     @NCIntent("intent=intent2 term~{# == 'x:time'} fragment(f)")
     class E1 extends NCModelAdapter(mkCfg("e1"), PL)
 
+    // Attempt to reference on fragment defined in method.
     class E2 extends NCModelAdapter(mkCfg("e2"), PL):
         @NCIntent("fragment=f term(city)~{# == 'opennlp:location'} intent=intent1 term~{# == 'x:time'} fragment(f)")
         private def m1(ctx: NCContext, im: NCIntentMatch): NCResult = null
@@ -66,6 +67,7 @@ class NCIDLFragmentsSpec:
         @NCIntent("intent=intent2 term~{# == 'x:time'} fragment(f)")
         private def m2(ctx: NCContext, im: NCIntentMatch): NCResult = null
 
+    // Attempt to reference on fragment defined in method.
     class E3 extends NCModelAdapter(mkCfg("e3"), PL):
         @NCIntent("fragment=f term(city)~{# == 'opennlp:location'} intent=intent1 term~{# == 'x:time'} fragment(f)")
         private def m2(ctx: NCContext, im: NCIntentMatch): NCResult = null


[incubator-nlpcraft] 10/11: IDL fragments related fixes.

Posted by se...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 47ef27ddcf27393aa34595c73bea1c7add72b671
Author: Sergey Kamov <sk...@gmail.com>
AuthorDate: Thu Aug 25 13:21:50 2022 +0300

    IDL fragments related fixes.
---
 .../internal/intent/compiler/NCIDLFragmentsOverridingSpec2.scala | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec2.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec2.scala
index 41d5adfa..8583b3de 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec2.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec2.scala
@@ -29,6 +29,10 @@ import scala.util.Using
 class NCIDLFragmentsOverridingSpec2:
     @NCIntent("import('org/apache/nlpcraft/internal/intent/compiler/impl_level2.idl')")
     class M extends NCTestModelAdapter:
+        // Uses initial fragment version (with intent), defined in impl_level1.idl.
+        @NCIntent("import('org/apache/nlpcraft/internal/intent/compiler/impl_level1.idl')")
+        @NCIntentRef("i1") private def on1(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult(1)
+
         // Uses fragment, defined on impl_level2.idl, which overrides impl_level1.idl.
         @NCIntent("intent=i2 fragment(f)")
         private def on2(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult(2)
@@ -37,11 +41,6 @@ class NCIDLFragmentsOverridingSpec2:
         @NCIntent("fragment=f term(z)~{# == 'x3'} intent=i3 fragment(f)")
         private def on3(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult(3)
 
-        // Uses initial fragment version (with intent), defined in impl_level1.idl.
-        @NCIntent("import('org/apache/nlpcraft/internal/intent/compiler/impl_level1.idl')")
-        @NCIntentRef("i1")
-        private def on1(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult(1)
-
         override val getPipeline: NCPipeline =
             val pl = mkEnPipeline
             pl.entParsers += NCTestUtils.mkEnSemanticParser(TE("x1"), TE("x2"), TE("x3"))


[incubator-nlpcraft] 04/11: IDL fragments related fixes.

Posted by se...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 0b2855bda936fe4f0ff2bb7b256ca2ba72bd6936
Author: Sergey Kamov <sk...@gmail.com>
AuthorDate: Thu Aug 25 11:20:08 2022 +0300

    IDL fragments related fixes.
---
 .../apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala   | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
index 1385dcf4..bb93bd9d 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
@@ -489,9 +489,12 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with mutable.Cloneab
 
     def clone(cp: NCIDLCompiler): NCIDLCompiler =
         val cp = new NCIDLCompiler(cfg)
+
         cp.intents ++= cp.intents.clone()
-        cp.importCache ++= importCache.clone()
-        cp.fragCache ++= fragCache.clone()
+
+        cp.importCache ++= this.importCache.clone()
+        cp.fragCache ++= this.fragCache.clone()
+
         cp
 
     override def clone(): NCIDLCompiler = clone(this)


[incubator-nlpcraft] 11/11: IDL fragments related fixes.

Posted by se...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 4c7be2b1b06914b400df03990b7192a942a2ab65
Author: Sergey Kamov <sk...@gmail.com>
AuthorDate: Thu Aug 25 13:25:37 2022 +0300

    IDL fragments related fixes.
---
 .../intent/compiler/NCIDLFragmentsSpec.scala       | 44 ++++++++++------------
 1 file changed, 20 insertions(+), 24 deletions(-)

diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsSpec.scala
index fbce3af0..8c33c50b 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsSpec.scala
@@ -17,8 +17,8 @@
 
 package org.apache.nlpcraft.internal.intent.compiler
 
-import org.apache.nlpcraft.annotations.NCIntent
 import org.apache.nlpcraft.*
+import org.apache.nlpcraft.annotations.NCIntent
 import org.apache.nlpcraft.internal.impl.NCModelScanner
 import org.apache.nlpcraft.nlp.util.*
 import org.junit.jupiter.api.Test
@@ -26,53 +26,49 @@ import org.junit.jupiter.api.Test
 import scala.util.Using
 
 class NCIDLFragmentsSpec:
-    private val PL = mkEnPipeline
-
-    private def mkCfg(id: String): NCModelConfig = NCModelConfig(id, "test", "1.0", desc = "Test", orig = "Test")
-
     // Normal models.
 
     // Fragment. One annotations order.
-    @NCIntent("fragment=f term(city)~{# == 'opennlp:location'}")
-    @NCIntent("intent=intent2 term~{# == 'x:time'} fragment(f)")
-    class M1 extends NCModelAdapter(mkCfg("m1"), PL)
+    @NCIntent("fragment=f term(x)~{# == 'x1'}")
+    @NCIntent("intent=i1 term~{# == 'x2'} fragment(f)")
+    class M1 extends NCModelAdapter(CFG, mkEnPipeline)
 
     // Fragment. Another annotations order.
-    @NCIntent("intent=intent2 term~{# == 'x:time'} fragment(f)")
-    @NCIntent("fragment=f term(city)~{# == 'opennlp:location'}")
-    class M2 extends NCModelAdapter(mkCfg("m2"), PL)
+    @NCIntent("intent=i1 term~{# == 'x2'} fragment(f)")
+    @NCIntent("fragment=f term(x)~{# == 'x1'}")
+    class M2 extends NCModelAdapter(CFG, mkEnPipeline)
 
     // Fragment. Reference from method to class.
-    @NCIntent("fragment=f term(city)~{# == 'opennlp:location'}")
-    class M3 extends NCModelAdapter(mkCfg("m3"), PL):
-        @NCIntent("intent=intent2 term~{# == 'x:time'} fragment(f)")
+    @NCIntent("fragment=f term(x)~{# == 'x1'}")
+    class M3 extends NCModelAdapter(CFG, mkEnPipeline):
+        @NCIntent("intent=i1 term~{# == 'x2'} fragment(f)")
         private def m(ctx: NCContext, im: NCIntentMatch): NCResult = null
 
     // Fragment. Reference from method (inside).
-    class M4 extends NCModelAdapter(mkCfg("m4"), PL) :
-        @NCIntent("fragment=f term(city)~{# == 'opennlp:location'} intent=intent2 term~{# == 'x:time'} fragment(f)")
+    class M4 extends NCModelAdapter(CFG, mkEnPipeline) :
+        @NCIntent("fragment=f term(x)~{# == 'x1'} intent=i1 term~{# == 'x2'} fragment(f)")
         private def m(ctx: NCContext, im: NCIntentMatch): NCResult = null
 
     // Bad models.
 
     // Missed fragment definition.
-    @NCIntent("intent=intent2 term~{# == 'x:time'} fragment(f)")
-    class E1 extends NCModelAdapter(mkCfg("e1"), PL)
+    @NCIntent("intent=i2 term~{# == 'x2'} fragment(f)")
+    class E1 extends NCModelAdapter(CFG, mkEnPipeline)
 
     // Attempt to reference on fragment defined in method.
-    class E2 extends NCModelAdapter(mkCfg("e2"), PL):
-        @NCIntent("fragment=f term(city)~{# == 'opennlp:location'} intent=intent1 term~{# == 'x:time'} fragment(f)")
+    class E2 extends NCModelAdapter(CFG, mkEnPipeline):
+        @NCIntent("fragment=f term(x)~{# == 'x1'} intent=i1 term~{# == 'x2'} fragment(f)")
         private def m1(ctx: NCContext, im: NCIntentMatch): NCResult = null
 
-        @NCIntent("intent=intent2 term~{# == 'x:time'} fragment(f)")
+        @NCIntent("intent=i2 term~{# == 'x2'} fragment(f)")
         private def m2(ctx: NCContext, im: NCIntentMatch): NCResult = null
 
     // Attempt to reference on fragment defined in method.
-    class E3 extends NCModelAdapter(mkCfg("e3"), PL):
-        @NCIntent("fragment=f term(city)~{# == 'opennlp:location'} intent=intent1 term~{# == 'x:time'} fragment(f)")
+    class E3 extends NCModelAdapter(CFG, mkEnPipeline):
+        @NCIntent("fragment=f term(x)~{# == 'x1'} intent=i1 term~{# == 'x2'} fragment(f)")
         private def m2(ctx: NCContext, im: NCIntentMatch): NCResult = null
 
-        @NCIntent("intent=intent2 term~{# == 'x:time'} fragment(f)")
+        @NCIntent("intent=i2 term~{# == 'x2'} fragment(f)")
         private def m1(ctx: NCContext, im: NCIntentMatch): NCResult = null
 
     private def testOk(mdls: NCModel*): Unit =


[incubator-nlpcraft] 06/11: IDL fragments related fixes.

Posted by se...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 43eb7bfe57586fed96e8382e7d8e62a080e44091
Author: Sergey Kamov <sk...@gmail.com>
AuthorDate: Thu Aug 25 12:19:41 2022 +0300

    IDL fragments related fixes.
---
 .../nlpcraft/internal/intent/compiler/NCIDLCompiler.scala  |  3 +--
 .../intent/compiler/NCIDLFragmentsOverridingSpec.scala     | 14 +++++++-------
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
index d54028d5..dbf93735 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
@@ -260,12 +260,11 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with mutable.Cloneab
 
             fragCache.get(frag.id) match
                 case Some(exFrag) =>
-                    if frag.terms != exFrag.terms then logger.warn(s"Fragment '${frag.id}' was override for origin: '${this.origin}'.")
+                    if frag.terms != exFrag.terms then logger.warn(s"Fragment '${frag.id}' was overriden for origin: '${this.origin}'.")
                 case None => // No-op.
 
             fragCache += frag.id -> frag
 
-
             terms.clear()
             fragId = null
 
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec.scala
index 23f228a2..1940c2f6 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLFragmentsOverridingSpec.scala
@@ -29,11 +29,6 @@ import scala.util.Using
 class NCIDLFragmentsOverridingSpec:
     @NCIntent("fragment=f term(x)~{# == 'x'}")
     class M extends NCTestModelAdapter:
-        override val getPipeline: NCPipeline =
-            val pl = mkEnPipeline
-            pl.entParsers += NCTestUtils.mkEnSemanticParser(TE("x"), TE("y"))
-            pl
-
         // Uses fragment defined on class level.
         @NCIntent("intent=i2 fragment(f)")
         private def onX(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult("onX")
@@ -41,10 +36,15 @@ class NCIDLFragmentsOverridingSpec:
         // Overrides fragment defined on class level.
         @NCIntent("fragment=f term(y)~{# == 'y'} intent=i1 fragment(f)")
         private def onY(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult("onY")
-    
+
+        override val getPipeline: NCPipeline =
+            val pl = mkEnPipeline
+            pl.entParsers += NCTestUtils.mkEnSemanticParser(TE("x"), TE("y"))
+            pl
+
     @Test
     def test(): Unit =
         Using.resource(new NCModelClient(new M())) { client =>
             require(client.ask("x", "usr").getBody == "onX")
             require(client.ask("y", "usr").getBody == "onY")
-        }
+        }
\ No newline at end of file


[incubator-nlpcraft] 08/11: IDL fragments related fixes.

Posted by se...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 9fa4af8b6d0a3304cb3516179b7f7ac3eee819fe
Author: Sergey Kamov <sk...@gmail.com>
AuthorDate: Thu Aug 25 13:14:50 2022 +0300

    IDL fragments related fixes.
---
 .../internal/intent/compiler/NCIDLCompiler.scala   | 11 ++---
 .../compiler/NCIDLImportsOverridingSpec.scala      | 56 ++++++++++++++++++++++
 .../nlpcraft/internal/intent/compiler/imp1.idl     | 23 +++++++++
 .../nlpcraft/internal/intent/compiler/imp2.idl     | 24 ++++++++++
 4 files changed, 108 insertions(+), 6 deletions(-)

diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
index b403545d..e0c48480 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
@@ -261,12 +261,11 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with mutable.Cloneab
 
             fragCache.get(frag.id) match
                 case Some(exFrag) =>
-                    if frag.terms != exFrag.terms then
-                        // TODO: text
-                        if isMethodLevel then
-                            logger.warn(s"Fragment '${frag.id}' was overriden just for for origin: '${this.origin}'.")
-                        else
-                            logger.warn(s"Fragment '${frag.id}' was overriden in origin: '${this.origin}' permanently.")
+                    // TODO: text
+                    if isMethodLevel then
+                        logger.warn(s"Fragment '${frag.id}' was overriden just for for origin: '${this.origin}'.")
+                    else
+                        logger.warn(s"Fragment '${frag.id}' was overriden in origin: '${this.origin}' permanently.")
                 case None => // No-op.
 
             fragCache += frag.id -> frag
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLImportsOverridingSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLImportsOverridingSpec.scala
new file mode 100644
index 00000000..0d58e858
--- /dev/null
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLImportsOverridingSpec.scala
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.nlpcraft.internal.intent.compiler
+
+import org.apache.nlpcraft.*
+import org.apache.nlpcraft.annotations.{NCIntent, NCIntentRef}
+import org.apache.nlpcraft.internal.impl.NCModelScanner
+import org.apache.nlpcraft.nlp.parsers.NCSemanticTestElement as TE
+import org.apache.nlpcraft.nlp.util.*
+import org.junit.jupiter.api.Test
+
+import scala.util.Using
+
+class NCIDLImportsOverridingSpec:
+    @NCIntent("import('org/apache/nlpcraft/internal/intent/compiler/imp2.idl')")
+    class M extends NCTestModelAdapter:
+        // Uses fragment defined on imp2.idl, which overrides imp1.idl.
+        @NCIntent("intent=i2 fragment(f)")
+        private def on2(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult(2)
+
+        // Uses own fragment, which which overrides all.
+        @NCIntent("fragment=f term(z)~{# == 'x3'} intent=i3 fragment(f)")
+        private def on3(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult(3)
+
+        // Uses initial fragment version, defined in imp1.idl.
+        @NCIntent("import('org/apache/nlpcraft/internal/intent/compiler/imp1.idl')")
+        @NCIntentRef("i1")
+        private def on1(ctx: NCContext, im: NCIntentMatch): NCResult = NCResult(1)
+
+        override val getPipeline: NCPipeline =
+            val pl = mkEnPipeline
+            pl.entParsers += NCTestUtils.mkEnSemanticParser(TE("x1"), TE("x2"), TE("x3"))
+            pl
+
+    @Test
+    def test(): Unit =
+        Using.resource(new NCModelClient(new M())) { client =>
+            require(client.ask("x1", "usr").getBody == 1)
+            require(client.ask("x2", "usr").getBody == 2)
+            require(client.ask("x3", "usr").getBody == 3)
+        }
\ No newline at end of file
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/imp1.idl b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/imp1.idl
new file mode 100644
index 00000000..e428c36c
--- /dev/null
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/imp1.idl
@@ -0,0 +1,23 @@
+ /*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ============================
+// Test content.
+// ============================
+
+fragment=f term={# == 'x1'}
+intent=i1 fragment(f)
\ No newline at end of file
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/imp2.idl b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/imp2.idl
new file mode 100644
index 00000000..f92ba03f
--- /dev/null
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/intent/compiler/imp2.idl
@@ -0,0 +1,24 @@
+ /*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ============================
+// Test content.
+// ============================
+
+import('org/apache/nlpcraft/internal/intent/compiler/imp1.idl')
+// Overrides fragment.
+fragment=f term={# == 'x2'}


[incubator-nlpcraft] 01/11: IDL fragments related fixes.

Posted by se...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 9bac8d033d6555e0ad667890110c5d4ea574c30a
Author: Sergey Kamov <sk...@gmail.com>
AuthorDate: Thu Aug 25 10:53:32 2022 +0300

    IDL fragments related fixes.
---
 .../nlpcraft/internal/impl/NCModelScanner.scala    |  6 +-
 .../internal/intent/compiler/NCIDLCompiler.scala   | 65 ++++++++++++----------
 2 files changed, 38 insertions(+), 33 deletions(-)

diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelScanner.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelScanner.scala
index 58f6347d..b799136e 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelScanner.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelScanner.scala
@@ -417,9 +417,9 @@ object NCModelScanner extends LazyLogging:
         def callNoCache[T](f: () => T): T =
             val cp = compiler.clone()
             try f()
-            finally compiler = cp
+            finally compiler = cp.clone(compiler)
 
-        def callNoCacheOnError[T](f: () => T): T =
+        def callClear[T](f: () => T): T =
             val cp = compiler.clone()
             try f()
             catch case e: Throwable => { compiler = cp; throw e }
@@ -453,7 +453,7 @@ object NCModelScanner extends LazyLogging:
 
             // 1. First pass.
             for (ann <- anns)
-                try callNoCacheOnError(() => addIntents(ann))
+                try callClear(() => addIntents(ann))
                 catch case _: NCException => errAnns += ann
 
             // 2. Second pass.
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
index fb82548e..36cbca7b 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/compiler/NCIDLCompiler.scala
@@ -37,34 +37,41 @@ import scala.collection.mutable
 import scala.jdk.CollectionConverters.*
 
 class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with scala.collection.mutable.Cloneable[NCIDLCompiler]:
+    private val intents = mutable.HashMap.empty[String, Set[NCIDLIntent]]
+
     // Compiler caches.
-    private val cacheIntents = new mutable.HashMap[String, Set[NCIDLIntent]]
-    private val fragCache = TrieMap.empty[String /* Model ID. */ , mutable.Map[String, NCIDLFragment]]
+    private val fragCache = mutable.HashMap.empty[String, NCIDLFragment]
     private val importCache = mutable.HashSet.empty[String]
 
-    private def getFragment(mdlId: String, fragId: String): Option[NCIDLFragment] = fragCache.get(mdlId).flatMap(_.get(fragId))
-
-    private def addFragment(mdlId: String, frag: NCIDLFragment): Unit =
-        fragCache.getOrElse(mdlId, {
-            val m = mutable.HashMap.empty[String, NCIDLFragment]
+    /**
+      *
+      * @param fragId
+      * @return
+      */
+    private def getFragment(fragId: String): Option[NCIDLFragment] = fragCache.get(fragId)
 
-            fragCache += mdlId -> m
+    /**
+      *
+      * @param fragId
+      * @return
+      */
+    private def hasFragment(fragId: String): Boolean = fragCache.contains(fragId)
 
-            m
-        }) += (frag.id -> frag)
+    /**
+      *
+      * @param mdlId
+      * @param frag
+      */
+    private def addFragment(mdlId: String, frag: NCIDLFragment): Unit = fragCache += frag.id -> frag
 
-    private def addImport(imp: String): Unit = importCache.synchronized {
-        importCache += imp
-    }
+    private def addImport(imp: String): Unit = importCache += imp
 
     /**
       *
       * @param imp
       * @return
       */
-    private def hasImport(imp: String): Boolean = importCache.synchronized {
-        importCache.contains(imp)
-    }
+    private def hasImport(imp: String): Boolean = importCache.contains(imp)
 
     /**
       *
@@ -208,12 +215,12 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with scala.collectio
 
         override def exitFragId(ctx: IDP.FragIdContext): Unit =
             fragId = ctx.id().getText
-            if getFragment(mdlCfg.getId, fragId).isDefined then SE(s"Duplicate fragment ID: $fragId")(ctx.id())
+            if hasFragment(fragId) then SE(s"Duplicate fragment ID: $fragId")(ctx.id())
 
         override def exitFragRef(ctx: IDP.FragRefContext): Unit =
             val id = ctx.id().getText
 
-            getFragment(mdlCfg.getId, id) match
+            getFragment(id) match
                 case Some(frag) =>
                     val meta = if fragMeta == null then Map.empty[String, Any] else fragMeta
                     for (fragTerm <- frag.terms)
@@ -471,9 +478,9 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with scala.collectio
         require(cfg != null)
         require(srcName != null)
 
-        val x = idl.strip()
-        val intents: Set[NCIDLIntent] = cacheIntents.getOrElseUpdate(x, {
-            val (fsm, parser) = antlr4Armature(x, cfg, srcName)
+        val idlNorm = idl.strip()
+        intents.getOrElseUpdate(idlNorm, {
+            val (fsm, parser) = antlr4Armature(idlNorm, cfg, srcName)
 
             // Parse the input IDL and walk built AST.
             (new ParseTreeWalker).walk(fsm, parser.idl())
@@ -482,8 +489,6 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with scala.collectio
             fsm.getCompiledIntents
         })
 
-        intents
-
     /**
       *
       * @param idl
@@ -515,11 +520,11 @@ class NCIDLCompiler(cfg: NCModelConfig) extends LazyLogging with scala.collectio
     @throws[NCException]
     def compile(idl: String, origin: String): Set[NCIDLIntent] = parseIntents(idl,  origin)
 
-    override def clone(): NCIDLCompiler =
-        val copy = new NCIDLCompiler(cfg)
-        this.cacheIntents ++= cacheIntents.clone()
-        this.importCache ++= importCache.clone()
-        this.fragCache ++= fragCache.clone()
-        copy
-
+    def clone(cp: NCIDLCompiler): NCIDLCompiler =
+        val cp = new NCIDLCompiler(cfg)
+        cp.intents ++= cp.intents.clone()
+        cp.importCache ++= importCache.clone()
+        cp.fragCache ++= fragCache.clone()
+        cp
 
+    override def clone(): NCIDLCompiler = clone(this)