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 b7bf65b WIP.
b7bf65b is described below
commit b7bf65b71d7a98c8f68970ef1b110681689df801
Author: Aaron Radzinski <[email protected]>
AuthorDate: Sat Mar 13 22:30:26 2021 -0800
WIP.
---
.../model/intent/compiler/NCDslCompiler.scala | 39 +-
.../model/intent/compiler/NCDslCompilerBase.scala | 523 +++++++++------------
.../model/intent/compiler/NCDslStackItem.scala | 6 +-
3 files changed, 235 insertions(+), 333 deletions(-)
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 f3b09a5..2411c86 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
@@ -104,6 +104,12 @@ object NCDslCompiler extends LazyLogging {
override def exitEqNeqExpr(ctx: IDP.EqNeqExprContext): Unit = instrs
+= parseEqNeqExpr(ctx.EQ, ctx.NEQ())(ctx)
override def exitCallExpr(ctx: IDP.CallExprContext): Unit = instrs +=
parseCallExpr(ctx.FUN_NAME())(ctx)
override def exitAtom(ctx: IDP.AtomContext): Unit = instrs +=
parseAtom(ctx.getText)(ctx)
+ override def exitTermEq(ctx: IDP.TermEqContext): Unit = termConv =
ctx.TILDA() != null
+ override def exitFragMeta(ctx: IDP.FragMetaContext): Unit = fragMeta =
U.jsonToScalaMap(ctx.jsonObj().getText)
+ override def exitMetaDecl(ctx: IDP.MetaDeclContext): Unit = intentMeta
= U.jsonToScalaMap(ctx.jsonObj().getText)
+ override def exitOrderedDecl(ctx: IDP.OrderedDeclContext): Unit =
ordered = ctx.BOOL().getText == "true"
+ override def exitIntentId(ctx: IDP.IntentIdContext): Unit = intentId
= ctx.id().getText
+ override def exitAlias(ctx: IDP.AliasContext): Unit = alias =
ctx.id().getText
/**
*
@@ -152,14 +158,6 @@ object NCDslCompiler extends LazyLogging {
throw newSyntaxError(s"Duplicate intent term ID:
$termId")(ctx.id())
}
- override def exitIntentId(ctx: IDP.IntentIdContext): Unit = {
- intentId = ctx.id().getText
- }
-
- override def exitAlias(ctx: IDP.AliasContext): Unit = {
- alias = ctx.id().getText
- }
-
override def exitSynonym(ctx: IDP.SynonymContext): Unit = {
implicit val evidence: PRC = ctx
@@ -173,11 +171,6 @@ object NCDslCompiler extends LazyLogging {
throw newSyntaxError(s"Duplicate fragment ID:
$fragId")(ctx.id())
}
- override def exitTermEq(ctx: IDP.TermEqContext): Unit = termConv =
ctx.TILDA() != null
- override def exitFragMeta(ctx: IDP.FragMetaContext): Unit = fragMeta =
U.jsonToScalaMap(ctx.jsonObj().getText)
- override def exitMetaDecl(ctx: IDP.MetaDeclContext): Unit = intentMeta
= U.jsonToScalaMap(ctx.jsonObj().getText)
- override def exitOrderedDecl(ctx: IDP.OrderedDeclContext): Unit =
ordered = ctx.BOOL().getText == "true"
-
override def exitFragRef(ctx: IDP.FragRefContext): Unit = {
val id = ctx.id().getText
@@ -271,7 +264,7 @@ object NCDslCompiler extends LazyLogging {
}
catch {
case e: Exception ⇒
- throw newRuntimeError(s"Failed to invoke custom
intent term: $mdlCls.$mtdName", e, ctx.mtdDecl())
+ throw newRuntimeError(s"Failed to invoke custom
intent term: $mdlCls.$mtdName", e)(ctx.mtdDecl())
}
}
}
@@ -306,18 +299,19 @@ object NCDslCompiler extends LazyLogging {
code ++= instrs
(tok: NCToken, termCtx: NCDslContext) ⇒ {
- val stack = new mutable.ArrayStack[NCDslStackItem]()
+ val stack = new mutable.ArrayStack[() ⇒ NCDslStackItem]()
// Execute all instructions.
code.foreach(_ (tok, stack, termCtx))
// Pop final result from stack.
- val x = stack.pop()
+ val x = stack.pop()()
+ val v = x.value
- if (!isBool(x.valFun))
- throw newRuntimeError(s"$subj did not return boolean
value: ${ctx.getText}", ctx = ctx)
+ if (!isBool(v))
+ throw newRuntimeError(s"$subj did not return boolean
value: ${ctx.getText}")
- (asBool(x.valFun), x.usedTok)
+ (asBool(v), x.usedTok)
}
}
@@ -325,6 +319,7 @@ object NCDslCompiler extends LazyLogging {
Global.addFragment(mdl.getId, NCDslFragment(fragId, terms.toList))
terms.clear()
+ fragId = null
}
/**
@@ -353,6 +348,7 @@ object NCDslCompiler extends LazyLogging {
val file = new File(x)
+ // First, try absolute path.
if (file.exists())
imports = NCDslCompiler.compileIntents(
U.readFile(file).mkString("\n"),
@@ -360,6 +356,7 @@ object NCDslCompiler extends LazyLogging {
x
)
+ // Second, try as a classloader resource.
if (imports == null) {
val in = mdl.getClass.getClassLoader.getResourceAsStream(x)
@@ -371,6 +368,7 @@ object NCDslCompiler extends LazyLogging {
)
}
+ // Finally, try as URL resource.
if (imports == null) {
try
imports = NCDslCompiler.compileIntents(
@@ -597,8 +595,7 @@ object NCDslCompiler extends LazyLogging {
origin: String
): (FiniteStateMachine, IDP) = {
val lexer = new NCIntentDslLexer(CharStreams.fromString(dsl, origin))
- val tokens = new CommonTokenStream(lexer)
- val parser = new IDP(tokens)
+ val parser = new IDP(new CommonTokenStream(lexer))
// Set custom error handlers.
lexer.removeErrorListeners()
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 d92ed6f..e0a10ca 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
@@ -22,17 +22,22 @@ import org.apache.nlpcraft.common.{NCE, U}
import org.apache.nlpcraft.model.NCToken
import org.antlr.v4.runtime.{ParserRuleContext ⇒ PRC}
import org.antlr.v4.runtime.tree.{TerminalNode ⇒ TN}
+
import org.apache.nlpcraft.model.intent.NCDslContext
-import org.apache.nlpcraft.model.intent.compiler.NCDslStackItem.StackValue
+import org.apache.nlpcraft.model.intent.compiler.{NCDslStackItem ⇒ Z}
import java.lang.{Double ⇒ JDouble, Long ⇒ JLong}
import java.time.LocalDate
import java.util
import java.util.{Collections, List ⇒ JList, Map ⇒ JMap}
-//import scala.collection.JavaConverters._
+
+import scala.collection.JavaConverters._
import scala.collection.mutable
trait NCDslCompilerBase {
+ type Stack = mutable.ArrayStack[() ⇒ Z]
+ type Instr = (NCToken, Stack, NCDslContext) ⇒ Unit
+
def syntaxError(errMsg: String, srcName: String, line: Int, pos: Int): NCE
def runtimeError(errMsg: String, srcName: String, line: Int, pos: Int,
cause: Exception = null): NCE
@@ -61,9 +66,6 @@ trait NCDslCompilerBase {
runtimeError(errMsg, tok.getTokenSource.getSourceName, tok.getLine,
tok.getCharPositionInLine, cause)
}
- type StackType = mutable.ArrayStack[NCDslStackItem]
- type Instr = (NCToken, StackType, NCDslContext) ⇒ Unit
-
//noinspection ComparingUnrelatedTypes
def isJLong(v: Object): Boolean = v.isInstanceOf[JLong]
//noinspection ComparingUnrelatedTypes
@@ -82,9 +84,6 @@ trait NCDslCompilerBase {
def asToken(v: Object): NCToken = v.asInstanceOf[NCToken]
def asBool(v: Object): Boolean = v.asInstanceOf[Boolean]
- def push(v: StackValue, usedTok: Boolean)(implicit stack: StackType): Unit
=
- stack.push(NCDslStackItem(v, usedTok))
-
// Runtime errors.
def rtUnaryOpError(op: String, v: Object)(implicit ctx: PRC): NCE =
newRuntimeError(s"Unexpected '$op' DSL operation for value: $v")
@@ -104,12 +103,10 @@ trait NCDslCompilerBase {
* @param stack
* @return
*/
- def pop1()(implicit stack: StackType): (() ⇒ Object, Boolean) = {
+ def pop1()(implicit stack: Stack): () ⇒ Z = {
require(stack.nonEmpty)
- val NCDslStackItem(v, f) = stack.pop()
-
- (v, f)
+ stack.pop()
}
/**
@@ -117,14 +114,14 @@ trait NCDslCompilerBase {
* @param stack
* @return
*/
- def pop2()(implicit stack: StackType): (() ⇒ Object, () ⇒ Object, Boolean,
Boolean) = {
+ def pop2()(implicit stack: Stack): (() ⇒ Z, () ⇒ Z) = {
require(stack.size >= 2)
// Stack pops in reverse order of push...
- val NCDslStackItem(v2, f2) = stack.pop()
- val NCDslStackItem(v1, f1) = stack.pop()
+ val v2 = stack.pop()
+ val v1 = stack.pop()
- (v1, v2, f1, f2)
+ (v1, v2)
}
/**
@@ -132,15 +129,15 @@ trait NCDslCompilerBase {
* @param stack
* @return
*/
- def pop3()(implicit stack: StackType): (() ⇒ Object, () ⇒ Object, () ⇒
Object, Boolean, Boolean, Boolean) = {
+ def pop3()(implicit stack: Stack): (() ⇒ Z, () ⇒ Z, () ⇒ Z) = {
require(stack.size >= 3)
// Stack pops in reverse order of push...
- val NCDslStackItem(v3, f3) = stack.pop()
- val NCDslStackItem(v2, f2) = stack.pop()
- val NCDslStackItem(v1, f1) = stack.pop()
+ val v3 = stack.pop()
+ val v2 = stack.pop()
+ val v1 = stack.pop()
- (v1, v2, v3, f1, f2, f3)
+ (v1, v2, v3)
}
/**
@@ -150,72 +147,72 @@ trait NCDslCompilerBase {
* @param lteq
* @param gteq
*/
- def parseCompExpr(lt: TN, gt: TN, lteq: TN, gteq: TN)(implicit ctx: PRC):
Instr = (_, stack: StackType, _) ⇒ {
- implicit val s: StackType = stack
-
- val (v1f, v2f, f1, f2) = pop2()
- val usedTok = f1 || f2
+ def parseCompExpr(lt: TN, gt: TN, lteq: TN, gteq: TN)(implicit ctx: PRC):
Instr = (_, stack: Stack, _) ⇒ {
+ val (item1, item2) = pop2()(stack)
if (lt != null)
- push(
- () ⇒ {
- val v1 = v1f()
- val v2 = v2f()
+ stack.push(() ⇒ {
+ val Z(v1, f1) = item1()
+ val Z(v2, f2) = item2()
+ val f =
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)
else if (isJDouble(v1) && isJDouble(v2)) asJDouble(v1) <
asJDouble(v2)
else
throw rtBinaryOpError("<", v1, v2)
- },
- usedTok
- )
+
+ Z(f, f1 || f2)
+ })
else if (gt != null)
- push(
- () ⇒ {
- val v1 = v1f()
- val v2 = v2f()
+ stack.push(() ⇒ {
+ val Z(v1, f1) = item1()
+ val Z(v2, f2) = item2()
+ val f =
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)
else if (isJDouble(v1) && isJDouble(v2)) asJDouble(v1) >
asJDouble(v2)
else
throw rtBinaryOpError(">", v1, v2)
- },
- usedTok
- )
+
+ Z(f, f1 || f2)
+ })
else if (lteq != null)
- push(
- () ⇒ {
- val v1 = v1f()
- val v2 = v2f()
+ stack.push(() ⇒ {
+ val Z(v1, f1) = item1()
+ val Z(v2, f2) = item2()
+ val f =
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)
else if (isJDouble(v1) && isJDouble(v2)) asJDouble(v1) <=
asJDouble(v2)
else
throw rtBinaryOpError("<=", v1, v2)
- },
- usedTok
- )
- else
- push(
- () ⇒ {
- val v1 = v1f()
- val v2 = v2f()
+ Z(f, f1 || f2)
+ })
+ else {
+ require(gteq != null)
+
+ stack.push(() ⇒ {
+ val Z(v1, f1) = item1()
+ val Z(v2, f2) = item2()
+
+ val f =
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)
else if (isJDouble(v1) && isJDouble(v2)) asJDouble(v1) >=
asJDouble(v2)
else
throw rtBinaryOpError(">=", v1, v2)
- },
- usedTok
- )
+
+ Z(f, f1 || f2)
+ })
+ }
}
/**
@@ -224,56 +221,53 @@ trait NCDslCompilerBase {
* @param mod
* @param div
*/
- def parseMultDivModExpr(mult: TN, mod: TN, div: TN)(implicit ctx: PRC):
Instr = (_, stack: StackType, _) ⇒ {
- implicit val s: StackType = stack
-
- val (v1f, v2f, f1, f2) = pop2()
- val usedTok = f1 || f2
+ def parseMultDivModExpr(mult: TN, mod: TN, div: TN)(implicit ctx: PRC):
Instr = (_, stack: Stack, _) ⇒ {
+ val (item1, item2) = pop2()(stack)
if (mult != null)
- push(
- () ⇒ {
- val v1 = v1f()
- val v2 = v2f()
+ stack.push(() ⇒ {
+ val Z(v1, f1) = item1()
+ val Z(v2, f2) = item2()
+ val f =
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)
else if (isJDouble(v1) && isJDouble(v2)) asJDouble(v1) *
asJDouble(v2)
else
throw rtBinaryOpError("*", v1, v2)
- },
- usedTok
- )
+
+ Z(f, f1 || f2)
+ })
else if (mod != null)
- push(
- () ⇒ {
- val v1 = v1f()
- val v2 = v2f()
+ stack.push(() ⇒ {
+ val Z(v1, f1) = item1()
+ val Z(v2, f2) = item2()
+ val f =
if (isJLong(v1) && isJLong(v2)) asJLong(v1) % asJLong(v2)
else
throw rtBinaryOpError("%", v1, v2)
- },
- usedTok
- )
+
+ Z(f, f1 || f2)
+ })
else {
assert(div != null)
- push(
- () ⇒ {
- val v1 = v1f()
- val v2 = v2f()
+ stack.push(() ⇒ {
+ val Z(v1, f1) = item1()
+ val Z(v2, f2) = item2()
+ val f =
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)
else if (isJDouble(v1) && isJDouble(v2)) asJDouble(v1) /
asJDouble(v2)
else
throw rtBinaryOpError("/", v1, v2)
- },
- usedTok
- )
+
+ Z(f, f1 || f2)
+ })
}
}
@@ -283,33 +277,29 @@ trait NCDslCompilerBase {
* @param or
* @return
*/
- def parseAndOrExpr(and: TN, or: TN)(implicit ctx: PRC): Instr = (_, stack:
StackType, _) ⇒ {
- implicit val s: StackType = stack
+ def parseAndOrExpr(and: TN, or: TN)(implicit ctx: PRC): Instr = (_, stack:
Stack, _) ⇒ {
+ val (item1, item2) = pop2()(stack)
- val (v1f, v2f, f1, f2) = pop2()
- val (op, usedTok, flag) = if (and != null) ("&&", f1 || f2, false)
else ("||", f1 && f2, true)
+ stack.push(() ⇒ {
+ val (op, flag) = if (and != null) ("&&", false) else ("||", true)
- push(
- () ⇒ {
- val v1 = v1f()
+ val v1 = item1()
- if (!isBool(v1))
- throw rtBinaryOpError(op, v1, v2f())
+ if (!isBool(v1))
+ throw rtBinaryOpError(op, v1, item2())
- // NOTE: check v1 first and only if it is {true|false} check
the v2.
- if (asBool(v1) == flag)
- flag
- else {
- val v2 = v2f()
+ // NOTE: check v1 first and only if it is {true|false} check the
v2.
+ if (asBool(v1) == flag)
+ Z(flag, v1.usedTok)
+ else {
+ val v2 = item2()
- if (!isBool(v2))
- throw rtBinaryOpError(op, v2, v1)
+ if (!isBool(v2))
+ throw rtBinaryOpError(op, v2, v1)
- asBool(v2)
- }
- },
- usedTok
- )
+ Z(asBool(v2), if (and != null) v1.usedTok || v2.usedTok else
v1.usedTok && v2.usedTok)
+ }
+ })
}
/**
@@ -318,36 +308,26 @@ trait NCDslCompilerBase {
* @param neq
* @return
*/
- def parseEqNeqExpr(eq: TN, neq: TN)(implicit ctx: PRC): Instr = (_, stack:
StackType, _) ⇒ {
- implicit val s: StackType = stack
-
- val (v1f, v2f, f1, f2) = pop2()
- val usedTok = f1 || f2
+ def parseEqNeqExpr(eq: TN, neq: TN)(implicit ctx: PRC): Instr = (_, stack:
Stack, _) ⇒ {
+ val (item1, item2) = pop2()(stack)
def doEq(op: String, v1: Object, v2: Object): Boolean = {
- if (v1 == null && v2 == null)
- true
- else if ((v1 == null && v2 != null) || (v1 != null && v2 == null))
- false
- else if (isJLong(v1) && isJLong(v2))
- asJLong(v1) == asJLong(v2)
- else if (isJDouble(v1) && isJDouble(v2))
- asJDouble(v1) == asJDouble(v2)
- else if (isBool(v1) && isBool(v2))
- asBool(v1) == asBool(v2)
- else if (isStr(v1) && isStr(v2))
- asStr(v1) == asStr(v2)
- else if (isJList(v1) && isJList(v2))
- asJList(v1).equals(asJList(v2))
+ if (v1 == null && v2 == null) true
+ else if ((v1 == null && v2 != null) || (v1 != null && v2 == null))
false
+ else if (isJLong(v1) && isJLong(v2)) asJLong(v1) == asJLong(v2)
+ else if (isJDouble(v1) && isJDouble(v2)) asJDouble(v1) ==
asJDouble(v2)
+ else if (isBool(v1) && isBool(v2)) asBool(v1) == asBool(v2)
+ else if (isStr(v1) && isStr(v2)) asStr(v1) == asStr(v2)
+ else if (isJList(v1) && isJList(v2))
asJList(v1).equals(asJList(v2))
else {
throw rtBinaryOpError(op, v1, v2)
}}
- push(
- () ⇒ {
- val v1 = v1f()
- val v2 = v2f()
+ stack.push(() ⇒ {
+ val Z(v1, f1) = item1()
+ val Z(v2, f2) = item2()
+ val f =
if (eq != null)
doEq("==", v1, v2)
else {
@@ -355,9 +335,9 @@ trait NCDslCompilerBase {
!doEq("!='", v1, v2)
}
- },
- usedTok
- )
+
+ Z(f, f1 || f2)
+ })
}
/**
@@ -365,18 +345,15 @@ trait NCDslCompilerBase {
* @param plus
* @param minus
*/
- def parsePlusMinusExpr(plus: TN, minus: TN)(implicit ctx: PRC): Instr =
(_, stack: StackType, _) ⇒ {
- implicit val s: StackType = stack
-
- val (v1f, v2f, f1, f2) = pop2()
- val usedTok = f1 || f2
+ def parsePlusMinusExpr(plus: TN, minus: TN)(implicit ctx: PRC): Instr =
(_, stack: Stack, _) ⇒ {
+ val (item1, item2) = pop2()(stack)
if (plus != null)
- push(
- () ⇒ {
- val v1 = v1f()
- val v2 = v2f()
+ stack.push(() ⇒ {
+ val Z(v1, f1) = item1()
+ val Z(v2, f2) = item2()
+ val f: Object =
if (isStr(v1) && isStr(v2)) asStr(v1) + asStr(v2)
else if (isJLong(v1) && isJLong(v2)) asJLong(v1) +
asJLong(v2)
else if (isJLong(v1) && isJDouble(v2)) asJLong(v1) +
asJDouble(v2)
@@ -384,27 +361,26 @@ trait NCDslCompilerBase {
else if (isJDouble(v1) && isJDouble(v2)) asJDouble(v1) +
asJDouble(v2)
else
throw rtBinaryOpError("+", v1, v2)
- },
- usedTok
- )
+
+ Z(f, f1 || f2)
+ })
else {
assert(minus != null)
- push(
- () ⇒ {
- val v1 = v1f()
- val v2 = v2f()
+ stack.push(() ⇒ {
+ val v1 = item1()
+ val v2 = item2()
+ val f =
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)
else if (isJDouble(v1) && isJDouble(v2)) asJDouble(v1) -
asJDouble(v2)
else
throw rtBinaryOpError("-", v1, v2)
- },
- usedTok
- )
- }
+
+ Z(f, v1.usedTok || v2.usedTok)
+ })
}
@@ -413,36 +389,31 @@ trait NCDslCompilerBase {
* @param not
* @return
*/
- def parseUnaryExpr(minus: TN, not: TN)(implicit ctx: PRC): Instr = (_,
stack: StackType, _) ⇒ {
- implicit val s: StackType = stack
-
- val (vf, usedTok) = pop1()
+ def parseUnaryExpr(minus: TN, not: TN)(implicit ctx: PRC): Instr = (_,
stack: Stack, _) ⇒ {
+ val item = pop1()(stack)
if (minus != null)
- push(
- () ⇒ {
- val v = vf()
+ stack.push(() ⇒ {
+ val Z(v, f) = item()
+ val z =
if (isJDouble(v)) -asJDouble(v)
else if (isJLong(v)) -asJLong(v)
else
throw rtUnaryOpError("-", v)
- },
- usedTok
- )
+
+ Z(z, f)
+ })
else {
assert(not != null)
- push(
- () ⇒ {
- val v = vf()
+ stack.push(() ⇒ {
+ val Z(v, f) = item()
- if (isBool(v)) !asBool(v)
- else
- throw rtUnaryOpError("!", v)
- },
- usedTok
- )
+ if (isBool(v)) Z(!asBool(v), f)
+ else
+ throw rtUnaryOpError("!", v)
+ })
}
}
@@ -473,7 +444,7 @@ trait NCDslCompilerBase {
}
}
- (_, stack, _) ⇒ push(() ⇒ atom, false)(stack)
+ (_, stack, _) ⇒ stack.push(() ⇒ Z(atom, false))
}
/**
@@ -481,130 +452,55 @@ trait NCDslCompilerBase {
* @param id
* @return
*/
- def parseCallExpr(id: TN)(implicit ctx: PRC): Instr = (tok, stack:
StackType, termCtx) ⇒ {
+ def parseCallExpr(id: TN)(implicit ctx: PRC): Instr = (tok, stack: Stack,
termCtx) ⇒ {
val fun = id.getText
- implicit val evidence: StackType = stack
+ implicit val evidence: Stack = stack
def ensureStack(min: Int): Unit =
if (stack.size < min)
throw rtMinParamNumError(min, fun)
-// def get1[T](typ: String, is: Object ⇒ Boolean, as: Object ⇒ T): (()
⇒ T, Boolean) = {
-// val (vf, f) = pop1()
-//
-// (
-// () ⇒ {
-// val v = vf()
-//
-// if (!is(v))
-// throw rtParamTypeError(fun, v, typ)
-//
-// as(v)
-// },
-// f
-// )
-// }
-// def get2[T](typ: String, is: Object ⇒ Boolean, as: Object ⇒ T): (()
⇒ T, () ⇒ T, Boolean) = {
-// val (vf1, vf2, f1, f2) = pop2()
-//
-// (
-// () ⇒ {
-// val v = vf1()
-//
-// if (!is(v))
-// throw rtParamTypeError(fun, v, typ)
-//
-// as(v)
-// },
-// () ⇒ {
-// val v = vf2()
-//
-// if (!is(v))
-// throw rtParamTypeError(fun, v, typ)
-//
-// as(v)
-// },
-// f1 || f2
-// )
-// }
-//
-// def get1Map(): (() ⇒ JMap[_, _], Boolean) = get1("map", isJMap,
asJMap)
-// def get1Double(): (() ⇒ JDouble, Boolean) = get1("double",
isJDouble, asJDouble)
-// def get1List(): (() ⇒ JList[_], Boolean) = get1("list", isJList,
asJList)
-// def get1Str(): (() ⇒ String, Boolean) = get1("string", isStr, asStr)
-// def get2Doubles(): (() ⇒ JDouble, () ⇒ JDouble, Boolean) =
get2("double", isJDouble, asJDouble)
-// def get2Str(): (() ⇒ String, () ⇒ String, Boolean) = get2("string",
isStr, asStr)
-// def get1Tok1Str(): (() ⇒ NCToken, () ⇒ String, Boolean) = {
-// val (vf1, vf2, f1, f2) = pop2()
-//
-// (
-// () ⇒ {
-// val v = vf1()
-//
-// if (!isToken(v))
-// throw rtParamTypeError(fun, v, "token")
-//
-// asToken(v)
-// },
-// () ⇒ {
-// val v = vf2()
-//
-// if (!isStr(v))
-// throw rtParamTypeError(fun, v, "string")
-//
-// asStr(v)
-// },
-// f1 || f2
-// )
-// }
-// def get1Any(): (() ⇒ Any, Boolean) = {
-// val (vf, f) = pop1()
-//
-// (() ⇒ vf(), f)
-// }
-
- def toStr(v: () ⇒ Object): String = {
- val s = v()
-
- if (!isStr(s))
- throw rtParamTypeError(fun, v, "string")
-
- asStr(s)
- }
+ def toX[T](typ: String, v: Object, is: Object ⇒ Boolean, as: Object ⇒
T): T = {
+ if (!is(v))
+ throw rtParamTypeError(fun, v, typ)
- def toJDouble(v: () ⇒ Object): JDouble = {
- val d = v()
-
- if (!isJDouble(d))
- throw rtParamTypeError(fun, v, "double")
-
- asJDouble(d)
+ as(v)
}
+ def toStr(v: Object): String = toX("string", v, isStr, asStr)
+ def toJDouble(v: Object): JDouble = toX("double", v, isJDouble,
asJDouble)
+ def toJLong(v: Object): JDouble = toX("long", v, isJLong, asJLong)
+ def toJList(v: Object): JList[_] = toX("list", v, isJList, asJList)
+ def toJMap(v: Object): JMap[_, _] = toX("map", v, isJMap, asJMap)
+ def toToken(v: Object): NCToken = toX("token", v, isToken, asToken)
+
def optToken(): NCToken =
if (stack.nonEmpty && stack.top.isInstanceOf[NCToken])
stack.pop().asInstanceOf[NCToken] else tok
-
def doSplit(): Unit = {
- val (v1f, v2f, f1, f2) = pop2()
+ val (item1, item2) = pop2()
- push(
+ stack.push(
() ⇒ {
- util.Arrays.asList(toStr(v1f).split(toStr(v2f)))
- },
- f1 || f2
+ val Z(v1, f1) = item1()
+ val Z(v2, f2) = item2()
+
+ Z(util.Arrays.asList(toStr(v1).split(toStr(v2))), f1 || f2)
+ }
)
}
def doSplitTrim(): Unit = {
- val (v1f, v2f, f1, f2) = pop2()
+ val (item1, item2) = pop2()
- push(
+ stack.push(
() ⇒ {
-
util.Arrays.asList(toStr(v1f).split(toStr(v2f)).toList.map(_.strip))
- },
- f1 || f2
+ val Z(v1, f1) = item1()
+ val Z(v2, f2) = item2()
+
+
Z(util.Arrays.asList(toStr(v1).split(toStr(v2)).toList.map(_.strip)), f1 || f2)
+ }
)
}
@@ -634,17 +530,24 @@ trait NCDslCompilerBase {
* Collection, statistical operations.
*/
def doList(): Unit = {
- val jl = new util.ArrayList[Object]() // Empty list is allowed.
- var f = false
+ val dump = new Stack() // Empty list is allowed.
- stack.drain { x ⇒
- jl.add(x.valFun())
- f = f || x.usedTok
- }
+ stack.drain { dump += _ }
+
+ stack.push(() ⇒ {
+ val jl = new util.ArrayList[Object]()
+ var f: Boolean = true
+
+ dump.reverse.foreach { x ⇒
+ val v = x()
- Collections.reverse(jl)
+ f = f || v.usedTok
- pushAny(() ⇒ jl, f)
+ jl.add(v.value)
+ }
+
+ Z(jl, f)
+ })
}
def doSize(): Unit = get1List() match { case (list, f) ⇒ pushLong(() ⇒
list().size(), f) }
@@ -762,7 +665,7 @@ trait NCDslCompilerBase {
fun match {
// Metadata access.
- case "meta_part" ⇒ get1Tok1Str() match { case (t, s, f) ⇒
pushAny(t.meta(s), f) }
+ case "meta_part" ⇒ pop2() match { case (t, s, f1, f2) ⇒ push(() ⇒
toToken(t).meta(toStr(s)), f1 || f2) }
case "meta_token" ⇒ pop1() match { case (s, _) ⇒ push(() ⇒
tok.meta(toStr(s)), true) }
case "meta_model" ⇒ pop1() match { case (s, _) ⇒ push(() ⇒
tok.getModel.meta(toStr(s)), false) }
case "meta_intent" ⇒ pop1() match { case (s, _) ⇒ push(() ⇒
termCtx.intentMeta.get(toStr(s)).orNull, false) }
@@ -794,28 +697,28 @@ trait NCDslCompilerBase {
// Request data.
case "req_id" ⇒ push(() ⇒ termCtx.req.getServerRequestId, false)
- case "req_normtext" ⇒
- case "req_tstamp" ⇒
- case "req_addr" ⇒
- case "req_agent" ⇒
+ case "req_normtext" ⇒ push(() ⇒ termCtx.req.getNormalizedText,
false)
+ case "req_tstamp" ⇒ push(() ⇒ termCtx.req.getReceiveTimestamp,
false)
+ case "req_addr" ⇒ push(() ⇒
termCtx.req.getRemoteAddress.orElse(null), false)
+ case "req_agent" ⇒ push(() ⇒
termCtx.req.getClientAgent.orElse(null), false)
// User data.
case "user_id" ⇒ push(() ⇒ termCtx.req.getUser.getId, false)
- case "user_fname" ⇒
- case "user_lname" ⇒
- case "user_email" ⇒
- case "user_admin" ⇒
- case "user_signup_tstamp" ⇒
+ case "user_fname" ⇒ push(() ⇒ termCtx.req.getUser.getFirstName,
false)
+ case "user_lname" ⇒ push(() ⇒ termCtx.req.getUser.getLastName,
false)
+ case "user_email" ⇒ push(() ⇒ termCtx.req.getUser.getEmail, false)
+ case "user_admin" ⇒ push(() ⇒ termCtx.req.getUser.isAdmin, false)
+ case "user_signup_tstamp" ⇒ push(() ⇒
termCtx.req.getUser.getSignupTimestamp, false)
// Company data.
case "comp_id" ⇒ push(() ⇒ termCtx.req.getCompany.getId, false)
- case "comp_name" ⇒
- case "comp_website" ⇒
- case "comp_country" ⇒
- case "comp_region" ⇒
- case "comp_city" ⇒
- case "comp_addr" ⇒
- case "comp_postcode" ⇒
+ case "comp_name" ⇒ push(() ⇒ termCtx.req.getCompany.getName, false)
+ case "comp_website" ⇒ push(() ⇒ termCtx.req.getCompany.getWebsite,
false)
+ case "comp_country" ⇒ push(() ⇒ termCtx.req.getCompany.getCountry,
false)
+ case "comp_region" ⇒ push(() ⇒ termCtx.req.getCompany.getRegion,
false)
+ case "comp_city" ⇒ push(() ⇒ termCtx.req.getCompany.getCity, false)
+ case "comp_addr" ⇒ push(() ⇒ termCtx.req.getCompany.getAddress,
false)
+ case "comp_postcode" ⇒ push(() ⇒
termCtx.req.getCompany.getPostalCode, false)
// String functions.
case "trim" ⇒ pop1() match { case (s, f) ⇒ push(() ⇒
toStr(s).trim, f) }
@@ -881,17 +784,23 @@ trait NCDslCompilerBase {
case "remove" ⇒
case "first" ⇒
case "last" ⇒
- case "keys" ⇒ get1Map() match { case (map, f) ⇒ pushAny(new
util.ArrayList(map.keySet()), f) }
- case "values" ⇒ get1Map() match { case (map, f) ⇒ pushAny(new
util.ArrayList(map.values()), f) }
+ case "keys" ⇒ pop1() match { case (map, f) ⇒ push(() ⇒ new
util.ArrayList(toJMap(map).keySet()), f) }
+ case "values" ⇒ pop1() match { case (map, f) ⇒ push(() ⇒ new
util.ArrayList(toJMap(map).values()), f) }
case "take" ⇒
case "drop" ⇒
case "size" ⇒ doSize()
case "count" ⇒ doSize()
case "length" ⇒ doSize()
- case "reverse" ⇒ get1List() match { case (list, f) ⇒
Collections.reverse(list); pushAny(list, f) }
- case "is_empty" ⇒ get1List() match { case (list, f) ⇒
pushBool(list.isEmpty, f) }
- case "non_empty" ⇒ get1List() match { case (list, f) ⇒
pushBool(!list.isEmpty, f) }
- case "to_string" ⇒ get1List() match { case (list, f) ⇒
pushAny(list.asScala.map(_.toString).asJava, f) }
+ case "reverse" ⇒ pop1() match { case (list, f) ⇒ push(() ⇒ {
+ val jl = toJList(list)
+
+ Collections.reverse(jl)
+
+ jl
+ }, f) }
+ case "is_empty" ⇒ pop1() match { case (list, f) ⇒ push(() ⇒
toJList(list).isEmpty, f) }
+ case "non_empty" ⇒ pop1() match { case (list, f) ⇒ push(() ⇒
!toJList(list).isEmpty, f) }
+ case "to_string" ⇒ pop1() match { case (list, f) ⇒ push(() ⇒
toJList(list).asScala.map(_.toString).asJava, f) }
// Statistical operations.
case "avg" ⇒
@@ -901,18 +810,18 @@ trait NCDslCompilerBase {
case "sum" ⇒
// Date-time functions.
- case "year" ⇒ pushLong(LocalDate.now.getYear, false) // 2021.
- case "month" ⇒ pushLong(LocalDate.now.getMonthValue, false) // 1
... 12.
- case "day_of_month" ⇒ pushLong(LocalDate.now.getDayOfMonth, false)
// 1 ... 31.
- case "day_of_week" ⇒ pushLong(LocalDate.now.getDayOfWeek.getValue,
false)
- case "day_of_year" ⇒ pushLong(LocalDate.now.getDayOfYear, false)
+ case "year" ⇒ push(() ⇒ LocalDate.now.getYear, false) // 2021.
+ case "month" ⇒ push(() ⇒ LocalDate.now.getMonthValue, false) // 1
... 12.
+ case "day_of_month" ⇒ push(() ⇒ LocalDate.now.getDayOfMonth,
false) // 1 ... 31.
+ case "day_of_week" ⇒ push(() ⇒
LocalDate.now.getDayOfWeek.getValue, false)
+ case "day_of_year" ⇒ push(() ⇒ LocalDate.now.getDayOfYear, false)
case "hour" ⇒
case "minute" ⇒
case "second" ⇒
case "week_of_month" ⇒
case "week_of_year" ⇒
case "quarter" ⇒
- case "now" ⇒ pushLong(System.currentTimeMillis(), false) // Epoc
time.
+ case "now" ⇒ push(() ⇒ System.currentTimeMillis(), false) // Epoc
time.
case _ ⇒ throw rtUnknownFunError(fun) // Assertion.
}
diff --git
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslStackItem.scala
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslStackItem.scala
index 82244a7..0cc19a2 100644
---
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslStackItem.scala
+++
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCDslStackItem.scala
@@ -23,10 +23,6 @@ import
org.apache.nlpcraft.model.intent.compiler.NCDslStackItem.StackValue
*
*/
case class NCDslStackItem(
- valFun: StackValue,
+ value: Object,
usedTok: Boolean
)
-
-object NCDslStackItem {
- type StackValue = () ⇒ Object
-}