1
0
mirror of https://github.com/MontFerret/ferret.git synced 2026-06-20 01:17:53 +02:00

feat: add support for TRIGGER clause in WAITFOR EVENT statements (#943)

* feat: add support for TRIGGER clause in WAITFOR EVENT statements

* feat: add inline trigger support for WAITFOR EVENT statements

* feat: enhance WAITFOR EVENT support with trigger and timeout clauses

* feat: implement cleanup and error handling for WAITFOR EVENT with TRIGGER clause

* feat: remove redundant operation in WAITFOR EVENT cleanup process
This commit is contained in:
Tim Voronov
2026-06-01 14:12:19 -04:00
committed by GitHub
parent 9b83b5f9ff
commit 12a344fb39
43 changed files with 5458 additions and 2774 deletions
+2
View File
@@ -343,6 +343,8 @@ func disasmLine(ip int, instr bytecode.Instruction, p *bytecode.Program, labels
if ops[0].IsConstant() {
out += formatComment(constValue(p, ops[0].Constant()))
}
case bytecode.OpRethrow:
out = fmt.Sprintf("%d: %s", ip, opcode)
// Op R R
case bytecode.OpMove, bytecode.OpMoveTracked, bytecode.OpMakeCell, bytecode.OpLoadCell, bytecode.OpStoreCell,
+3
View File
@@ -172,6 +172,7 @@ const (
OpJumpIfMissingPropertyConst
OpFail // Raises a runtime failure with a constant message
OpFailTimeout // Raises a runtime timeout failure
OpRethrow // Raises the currently handled runtime failure
// Internal Aggregate Operations
OpLoadAggregateKey // Creates an internal grouped-aggregate selector key
@@ -214,6 +215,8 @@ func (op Opcode) String() string {
return "FAIL"
case OpFailTimeout:
return "FAILTIMEOUT"
case OpRethrow:
return "RETHROW"
case OpLoadAggregateKey:
return "LOADAGGK"
+2 -2
View File
@@ -140,7 +140,7 @@ func opcodeClass(op Opcode) OpcodeClass {
OpNoneEq, OpNoneNe, OpNoneGt, OpNoneGte, OpNoneLt, OpNoneLte, OpNoneIn,
OpAllEq, OpAllNe, OpAllGt, OpAllGte, OpAllLt, OpAllLte, OpAllIn:
return OpcodeClassArray
case OpLength, OpClose, OpSleep, OpExists, OpRand, OpDispatch, OpFail, OpFailTimeout, OpStoreCell:
case OpLength, OpClose, OpSleep, OpExists, OpRand, OpDispatch, OpFail, OpFailTimeout, OpRethrow, OpStoreCell:
return OpcodeClassUtility
case OpHCall, OpProtectedHCall, OpCall, OpProtectedCall, OpTailCall:
return OpcodeClassCall
@@ -166,7 +166,7 @@ func controlFlowRole(op Opcode) ControlFlowRole {
OpJumpIfMissingProperty, OpJumpIfMissingPropertyConst, OpMatchLoadPropertyConst,
OpIterNext, OpIterNextTimeout, OpIterLimit, OpIterSkip:
return ControlFlowJumpConditional
case OpReturn, OpTailCall, OpFail, OpFailTimeout:
case OpReturn, OpTailCall, OpFail, OpFailTimeout, OpRethrow:
return ControlFlowTerminator
default:
return ControlFlowNone
+5
View File
@@ -128,6 +128,11 @@ func TestOpcodeInfoControlFlowMetadata(t *testing.T) {
op: OpFailTimeout,
wantTerminator: true,
},
{
name: "rethrow is terminator",
op: OpRethrow,
wantTerminator: true,
},
}
for _, tt := range tests {
+2
View File
@@ -589,6 +589,8 @@ func validateInstructions(program *Program) error {
}
case OpFailTimeout:
// No operands.
case OpRethrow:
// No operands.
default:
return fmt.Errorf("%w: opcode %d at pc %d is not supported by validator", ErrInvalidInstruction, op, pc)
}
+34 -23
View File
@@ -48,27 +48,42 @@ func (c *DispatchCompiler) Compile(ctx fql.IDispatchExpressionContext) bytecode.
Owner: ctx,
JumpMode: core.CatchJumpModeNone,
CompilePlain: func() bytecode.Operand {
targetReg := ensureDispatchOperandRegister(c.ctx, c.facts, c.compileTarget(ctx.DispatchTarget()))
eventReg := ensureDispatchOperandRegister(c.ctx, c.facts, c.compileEventName(ctx.DispatchEventName()))
payloadReg := ensureDispatchOperandRegister(c.ctx, c.facts, c.compilePayload(ctx.DispatchWithClause()))
optionsReg := ensureDispatchOperandRegister(c.ctx, c.facts, c.compileOptions(ctx.DispatchOptionsClause()))
argsReg := c.buildDispatchArgs(payloadReg, optionsReg)
dst := c.ctx.Function.Registers.Allocate()
span := c.dispatchSpan(ctx)
c.ctx.Program.Emitter.WithSpan(span, func() {
c.ctx.Program.Emitter.EmitMove(dst, targetReg)
c.ctx.Program.Emitter.EmitABC(bytecode.OpDispatch, dst, eventReg, argsReg)
})
c.ctx.Function.Types.Set(dst, core.TypeNone)
return dst
return c.compileCore(
ctx.DispatchTarget(),
ctx.DispatchEventName(),
ctx.DispatchWithClause(),
ctx.DispatchOptionsClause(),
c.dispatchSpan(ctx),
)
},
})
}
func (c *DispatchCompiler) compileCore(
target fql.IDispatchTargetContext,
event fql.IDispatchEventNameContext,
with fql.IDispatchWithClauseContext,
options fql.IDispatchOptionsClauseContext,
span source.Span,
) bytecode.Operand {
targetReg := ensureDispatchOperandRegister(c.ctx, c.facts, c.compileTarget(target))
eventReg := ensureDispatchOperandRegister(c.ctx, c.facts, c.compileEventName(event))
payloadReg := ensureDispatchOperandRegister(c.ctx, c.facts, c.compilePayload(with))
optionsReg := ensureDispatchOperandRegister(c.ctx, c.facts, c.compileOptions(options))
argsReg := c.buildDispatchArgs(payloadReg, optionsReg)
dst := c.ctx.Function.Registers.Allocate()
c.ctx.Program.Emitter.WithSpan(span, func() {
c.ctx.Program.Emitter.EmitMove(dst, targetReg)
c.ctx.Program.Emitter.EmitABC(bytecode.OpDispatch, dst, eventReg, argsReg)
})
c.ctx.Function.Types.Set(dst, core.TypeNone)
return dst
}
func (c *DispatchCompiler) compileEventName(ctx fql.IDispatchEventNameContext) bytecode.Operand {
if ctx == nil {
return bytecode.NoopOperand
@@ -150,14 +165,10 @@ func (c *DispatchCompiler) buildDispatchArgs(payload, options bytecode.Operand)
return dst
}
func (c *DispatchCompiler) dispatchSpan(ctx fql.IDispatchExpressionContext) source.Span {
func (c *DispatchCompiler) dispatchSpan(ctx antlr.ParserRuleContext) source.Span {
if ctx == nil {
return source.Span{Start: -1, End: -1}
}
if prc, ok := ctx.(antlr.ParserRuleContext); ok {
return diagnostics.SpanFromRuleContext(prc)
}
return source.Span{Start: -1, End: -1}
return diagnostics.SpanFromRuleContext(ctx)
}
+4
View File
@@ -57,6 +57,10 @@ func (c *ExprCompiler) CompileFunctionCallExpression(ctx fql.IFunctionCallExpres
return c.callCompiler.compileFunctionCallExpression(ctx)
}
func (c *ExprCompiler) CompileFunctionCallNoRecoveryExpression(ctx fql.IFunctionCallNoRecoveryExpressionContext) bytecode.Operand {
return c.callCompiler.compileFunctionCallNoRecoveryExpression(ctx)
}
func (c *ExprCompiler) CompileFunctionCall(ctx fql.IFunctionCallContext, protected bool) bytecode.Operand {
return c.callCompiler.compileFunctionCall(ctx, protected)
}
@@ -136,6 +136,21 @@ func (c *exprCallCompiler) compileFunctionCallExpression(ctx fql.IFunctionCallEx
})
}
func (c *exprCallCompiler) compileFunctionCallNoRecoveryExpression(ctx fql.IFunctionCallNoRecoveryExpressionContext) bytecode.Operand {
if ctx == nil {
return bytecode.NoopOperand
}
call := ctx.FunctionCall()
if ctx.ErrorOperator() != nil {
return c.recovery.CompileWithErrorPolicy(core.ErrorPolicySuppress, core.CatchJumpModeNone, func() bytecode.Operand {
return c.compileFunctionCall(call, true)
})
}
return c.compileFunctionCall(call, false)
}
func (c *exprCallCompiler) compileFunctionCall(ctx fql.IFunctionCallContext, protected bool) bytecode.Operand {
return c.compileFunctionCallWith(ctx, protected, c.compileArgumentList(ctx.ArgumentList()))
}
+1 -1
View File
@@ -51,7 +51,7 @@ func NewCompilationFrontend(session *CompilationSession) *CompilationFrontend {
front.Sorts.bind(front.Expressions, front.TypeFacts)
front.Recovery.bind(front.Expressions, front.Literals, front.TypeFacts)
front.Dispatch.bind(front.Expressions, front.Literals, front.Recovery, front.TypeFacts)
front.Wait.bind(front.Expressions, front.Literals, front.Recovery, front.TypeFacts)
front.Wait.bind(front.Bindings, front.Dispatch, front.Expressions, front.Literals, front.Recovery, front.TypeFacts)
front.Collects.bind(front.Bindings, front.Calls, front.Expressions, front.Recovery, front.TypeFacts)
front.Statements.bind(front.Bindings, front.Dispatch, front.Expressions, front.Loops, front.TypeFacts, front.Wait)
front.UDFs.bind(front.Calls, front.Expressions, front.TypeFacts, front.Recovery, front.Statements)
@@ -325,7 +325,7 @@ func operandIsRegister(op bytecode.Opcode, idx int) bool {
return idx == 0
case bytecode.OpFail:
return false
case bytecode.OpFailTimeout:
case bytecode.OpFailTimeout, bytecode.OpRethrow:
return false
case bytecode.OpIncr, bytecode.OpDecr, bytecode.OpClose, bytecode.OpSleep, bytecode.OpReturn:
return idx == 0
@@ -257,7 +257,7 @@ func applyControlFlowUseDef(opcode bytecode.Opcode, src1, src2 bytecode.Operand,
collector.addUse(src1)
collector.addUse(src2)
return true
case bytecode.OpJump, bytecode.OpFail:
case bytecode.OpJump, bytecode.OpFail, bytecode.OpRethrow:
return true
default:
return false
+2 -8
View File
@@ -220,10 +220,7 @@ func (c *RecoveryCompiler) compileOperationWithErrorReturn(
buildProtected func(recoveryLabel, timeoutLabel, endLabel core.Label) ProtectedRecoveryRegion,
) bytecode.Operand {
recoveryLabel := c.ctx.Program.Emitter.NewLabel("recovery", "error", "handle")
var timeoutLabel core.Label
if plan.OnTimeout != nil {
timeoutLabel = c.ctx.Program.Emitter.NewLabel("recovery", "timeout", "handle")
}
timeoutLabel := c.ctx.Program.Emitter.NewLabel("recovery", "timeout", "handle")
endLabel := c.ctx.Program.Emitter.NewLabel("recovery", "error", "end")
region := buildProtected(recoveryLabel, timeoutLabel, endLabel)
@@ -279,10 +276,7 @@ func (c *RecoveryCompiler) compileOperationWithErrorRetry(
state := c.initRetryDelayState(retry)
retryStart := c.ctx.Program.Emitter.NewLabel("recovery", "retry", "start")
recoveryLabel := c.ctx.Program.Emitter.NewLabel("recovery", "retry", "handle")
var timeoutLabel core.Label
if plan.OnTimeout != nil {
timeoutLabel = c.ctx.Program.Emitter.NewLabel("recovery", "timeout", "handle")
}
timeoutLabel := c.ctx.Program.Emitter.NewLabel("recovery", "timeout", "handle")
endLabel := c.ctx.Program.Emitter.NewLabel("recovery", "retry", "end")
var finalAttemptLabel core.Label
+204 -1
View File
@@ -16,6 +16,10 @@ type waitEventCompileState struct {
}
func (c *WaitCompiler) compileEvent(ctx fql.IWaitForEventExpressionContext) bytecode.Operand {
if waitForEventTriggerClause(ctx) != nil {
return c.compileEventWithTriggerCleanup(ctx)
}
state, ok := c.buildWaitEventState(ctx)
if !ok {
return bytecode.NoopOperand
@@ -26,6 +30,7 @@ func (c *WaitCompiler) compileEvent(ctx fql.IWaitForEventExpressionContext) byte
c.ctx.Program.Emitter.EmitLoadNone(resultReg)
c.emitWaitEventStreamSetup(state, streamReg)
c.compileWaitEventTrigger(ctx)
start := c.ctx.Program.Emitter.NewLabel()
end := c.ctx.Program.Emitter.NewLabel()
@@ -43,6 +48,10 @@ func (c *WaitCompiler) compileEventWithTimeoutRecovery(
ctx fql.IWaitForEventExpressionContext,
timeoutLabel, endLabel core.Label,
) bytecode.Operand {
if waitForEventTriggerClause(ctx) != nil {
return c.compileEventWithTriggerTimeoutCleanup(ctx, timeoutLabel, endLabel)
}
streamReg := c.ctx.Function.Registers.Allocate()
resultReg := c.ctx.Function.Registers.Allocate()
timeoutStateReg := c.ctx.Function.Registers.Allocate()
@@ -56,6 +65,7 @@ func (c *WaitCompiler) compileEventWithTimeoutRecovery(
}
c.emitWaitEventStreamSetup(state, streamReg)
c.compileWaitEventTrigger(ctx)
start := c.ctx.Program.Emitter.NewLabel()
iterationDone := c.ctx.Program.Emitter.NewLabel()
@@ -77,6 +87,96 @@ func (c *WaitCompiler) compileEventWithTimeoutRecovery(
return resultReg
}
func (c *WaitCompiler) compileEventWithTriggerCleanup(ctx fql.IWaitForEventExpressionContext) bytecode.Operand {
streamReg := c.ctx.Function.Registers.Allocate()
resultReg := c.ctx.Function.Registers.Allocate()
streamReadyReg := c.ctx.Function.Registers.Allocate()
c.ctx.Program.Emitter.EmitLoadNone(resultReg)
c.ctx.Program.Emitter.EmitBoolean(streamReadyReg, false)
startCatch := c.ctx.Program.Emitter.Size()
state, ok := c.buildWaitEventState(ctx)
if !ok {
return bytecode.NoopOperand
}
c.emitWaitEventStreamSetupWithReady(state, streamReg, streamReadyReg)
c.compileWaitEventTrigger(ctx)
start := c.ctx.Program.Emitter.NewLabel()
iterationDone := c.ctx.Program.Emitter.NewLabel()
exit := c.ctx.Program.Emitter.NewLabel("waitfor", "event", "trigger", "exit")
c.ctx.Program.Emitter.MarkLabel(start)
c.emitWaitEventIteration(ctx, state, streamReg, resultReg, bytecode.NoopOperand, start, iterationDone)
c.ctx.Program.Emitter.MarkLabel(iterationDone)
c.emitWaitEventCleanupIfReady(state, streamReg, streamReadyReg)
c.ctx.Program.Emitter.EmitJump(exit)
endCatchExclusive := c.ctx.Program.Emitter.Size()
errorHandlerPC := c.ctx.Program.Emitter.Size()
c.emitWaitEventCleanupIfReady(state, streamReg, streamReadyReg)
c.ctx.Program.Emitter.Emit(bytecode.OpRethrow)
c.ctx.Program.Emitter.MarkLabel(exit)
c.ctx.Program.Emitter.EmitAB(bytecode.OpMove, resultReg, resultReg)
c.ctx.Program.CatchTable.Push(startCatch, endCatchExclusive-1, errorHandlerPC)
return resultReg
}
func (c *WaitCompiler) compileEventWithTriggerTimeoutCleanup(
ctx fql.IWaitForEventExpressionContext,
timeoutLabel, endLabel core.Label,
) bytecode.Operand {
streamReg := c.ctx.Function.Registers.Allocate()
resultReg := c.ctx.Function.Registers.Allocate()
timeoutStateReg := c.ctx.Function.Registers.Allocate()
streamReadyReg := c.ctx.Function.Registers.Allocate()
c.ctx.Program.Emitter.EmitLoadNone(resultReg)
c.ctx.Program.Emitter.EmitBoolean(timeoutStateReg, false)
c.ctx.Program.Emitter.EmitBoolean(streamReadyReg, false)
startCatch := c.ctx.Program.Emitter.Size()
state, ok := c.buildWaitEventState(ctx)
if !ok {
return bytecode.NoopOperand
}
c.emitWaitEventStreamSetupWithReady(state, streamReg, streamReadyReg)
c.compileWaitEventTrigger(ctx)
start := c.ctx.Program.Emitter.NewLabel()
iterationDone := c.ctx.Program.Emitter.NewLabel()
cleanup := c.ctx.Program.Emitter.NewLabel()
c.ctx.Program.Emitter.MarkLabel(start)
c.emitWaitEventIteration(ctx, state, streamReg, resultReg, timeoutStateReg, start, iterationDone)
c.ctx.Program.Emitter.EmitJump(cleanup)
c.ctx.Program.Emitter.MarkLabel(iterationDone)
c.ctx.Program.Emitter.EmitJump(cleanup)
c.ctx.Program.Emitter.MarkLabel(cleanup)
c.emitWaitEventCleanupIfReady(state, streamReg, streamReadyReg)
c.ctx.Program.Emitter.EmitJumpIfTrue(timeoutStateReg, timeoutLabel)
c.ctx.Program.Emitter.EmitJump(endLabel)
endCatchExclusive := c.ctx.Program.Emitter.Size()
errorHandlerPC := c.ctx.Program.Emitter.Size()
c.emitWaitEventCleanupIfReady(state, streamReg, streamReadyReg)
c.ctx.Program.Emitter.Emit(bytecode.OpRethrow)
c.ctx.Program.CatchTable.Push(startCatch, endCatchExclusive-1, errorHandlerPC)
return resultReg
}
func (c *WaitCompiler) buildWaitEventState(ctx fql.IWaitForEventExpressionContext) (waitEventCompileState, bool) {
state := waitEventCompileState{
span: waitForSpan(ctx.WaitForEventSource(), ctx),
@@ -88,7 +188,7 @@ func (c *WaitCompiler) buildWaitEventState(ctx fql.IWaitForEventExpressionContex
state.optsReg = c.CompileOptionsClause(opts)
}
if timeout := ctx.TimeoutClause(); timeout != nil {
if timeout := waitForEventTimeoutClause(ctx); timeout != nil {
state.timeoutReg = c.recovery.CompileDurationOperand(timeout)
if state.timeoutReg == bytecode.NoopOperand {
return waitEventCompileState{}, false
@@ -99,13 +199,103 @@ func (c *WaitCompiler) buildWaitEventState(ctx fql.IWaitForEventExpressionContex
}
func (c *WaitCompiler) emitWaitEventStreamSetup(state waitEventCompileState, streamReg bytecode.Operand) {
c.emitWaitEventStreamSetupWithReady(state, streamReg, bytecode.NoopOperand)
}
func (c *WaitCompiler) emitWaitEventStreamSetupWithReady(state waitEventCompileState, streamReg, streamReadyReg bytecode.Operand) {
c.ctx.Program.Emitter.WithSpan(state.span, func() {
c.ctx.Program.Emitter.EmitMove(streamReg, state.srcReg)
c.ctx.Program.Emitter.EmitABC(bytecode.OpStream, streamReg, state.eventReg, state.optsReg)
if streamReadyReg != bytecode.NoopOperand {
c.ctx.Program.Emitter.EmitBoolean(streamReadyReg, true)
}
c.ctx.Program.Emitter.EmitABC(bytecode.OpStreamIter, streamReg, streamReg, state.timeoutReg)
})
}
func (c *WaitCompiler) compileWaitEventTrigger(ctx fql.IWaitForEventExpressionContext) {
if ctx == nil {
return
}
trigger := waitForEventTriggerClause(ctx)
if trigger == nil {
return
}
c.compileWaitForTriggerClause(trigger)
}
func (c *WaitCompiler) compileWaitForTriggerClause(ctx fql.IWaitForTriggerClauseContext) {
if ctx == nil {
return
}
c.ctx.Function.Symbols.EnterScope()
defer c.ctx.Function.Symbols.ExitScope()
if inline := ctx.WaitForTriggerInlineStatement(); inline != nil {
c.compileWaitForTriggerInlineStatement(inline)
return
}
for _, stmt := range ctx.AllWaitForTriggerStatement() {
c.compileWaitForTriggerStatement(stmt)
}
}
func (c *WaitCompiler) compileWaitForTriggerStatement(ctx fql.IWaitForTriggerStatementContext) {
if ctx == nil {
return
}
if vd := ctx.VariableDeclaration(); vd != nil {
c.bindings.CompileVariableDeclaration(vd)
} else if as := ctx.AssignmentStatement(); as != nil {
c.bindings.CompileAssignmentStatement(as)
} else if ds := ctx.DeleteStatement(); ds != nil {
c.bindings.CompileDeleteStatement(ds)
} else if fce := ctx.FunctionCallExpression(); fce != nil {
c.exprs.CompileFunctionCallExpression(fce)
} else if wfe := ctx.WaitForExpression(); wfe != nil {
c.Compile(wfe)
} else if de := ctx.DispatchExpression(); de != nil {
c.dispatch.Compile(de)
}
}
func (c *WaitCompiler) compileWaitForTriggerInlineStatement(ctx fql.IWaitForTriggerInlineStatementContext) {
if ctx == nil {
return
}
if vd := ctx.VariableDeclaration(); vd != nil {
c.bindings.CompileVariableDeclaration(vd)
} else if as := ctx.AssignmentStatement(); as != nil {
c.bindings.CompileAssignmentStatement(as)
} else if ds := ctx.DeleteStatement(); ds != nil {
c.bindings.CompileDeleteStatement(ds)
} else if fce := ctx.FunctionCallNoRecoveryExpression(); fce != nil {
c.exprs.CompileFunctionCallNoRecoveryExpression(fce)
} else if dispatch := ctx.WaitForTriggerInlineDispatchStatement(); dispatch != nil {
c.compileWaitForTriggerInlineDispatchStatement(dispatch)
}
}
func (c *WaitCompiler) compileWaitForTriggerInlineDispatchStatement(ctx fql.IWaitForTriggerInlineDispatchStatementContext) {
if ctx == nil {
return
}
c.dispatch.compileCore(
ctx.DispatchTarget(),
ctx.DispatchEventName(),
ctx.DispatchWithClause(),
ctx.DispatchOptionsClause(),
c.dispatch.dispatchSpan(ctx),
)
}
func (c *WaitCompiler) emitWaitEventIteration(
ctx fql.IWaitForEventExpressionContext,
state waitEventCompileState,
@@ -151,6 +341,19 @@ func (c *WaitCompiler) emitWaitEventCleanup(state waitEventCompileState, streamR
})
}
func (c *WaitCompiler) emitWaitEventCleanupIfReady(state waitEventCompileState, streamReg, streamReadyReg bytecode.Operand) {
if streamReadyReg == bytecode.NoopOperand {
c.emitWaitEventCleanup(state, streamReg)
return
}
skip := c.ctx.Program.Emitter.NewLabel("waitfor", "event", "cleanup", "skip")
c.ctx.Program.Emitter.EmitJumpIfFalse(streamReadyReg, skip)
c.emitWaitEventCleanup(state, streamReg)
c.ctx.Program.Emitter.EmitBoolean(streamReadyReg, false)
c.ctx.Program.Emitter.MarkLabel(skip)
}
// CompileWaitForEventName processes the event name expression in a WAITFOR statement.
func (c *WaitCompiler) CompileWaitForEventName(ctx fql.IWaitForEventNameContext) bytecode.Operand {
sl := ctx.StringLiteral()
+29
View File
@@ -0,0 +1,29 @@
package internal
import "github.com/MontFerret/ferret/v2/pkg/parser/fql"
func waitForEventTriggerClause(ctx fql.IWaitForEventExpressionContext) fql.IWaitForTriggerClauseContext {
if ctx == nil {
return nil
}
tail := ctx.WaitForEventTail()
if tail == nil {
return nil
}
return tail.WaitForTriggerClause()
}
func waitForEventTimeoutClause(ctx fql.IWaitForEventExpressionContext) fql.ITimeoutClauseContext {
if ctx == nil {
return nil
}
tail := ctx.WaitForEventTail()
if tail == nil {
return nil
}
return tail.TimeoutClause()
}
+1 -1
View File
@@ -200,7 +200,7 @@ func waitForHasExplicitTimeoutClause(ctx fql.IWaitForExpressionContext) bool {
return false
}
if ev := ctx.WaitForEventExpression(); ev != nil && ev.TimeoutClause() != nil {
if ev := ctx.WaitForEventExpression(); ev != nil && waitForEventTimeoutClause(ev) != nil {
return true
}
+12 -5
View File
@@ -10,6 +10,8 @@ import (
// It transforms wait operations into VM instructions for event streaming and polling.
type WaitCompiler struct {
ctx *CompilationSession
bindings *BindingCompiler
dispatch *DispatchCompiler
exprs *ExprCompiler
literals *LiteralCompiler
recovery *RecoveryCompiler
@@ -23,11 +25,13 @@ func NewWaitCompiler(ctx *CompilationSession) *WaitCompiler {
}
}
func (c *WaitCompiler) bind(exprs *ExprCompiler, literals *LiteralCompiler, recovery *RecoveryCompiler, facts *TypeFacts) {
func (c *WaitCompiler) bind(bindings *BindingCompiler, dispatch *DispatchCompiler, exprs *ExprCompiler, literals *LiteralCompiler, recovery *RecoveryCompiler, facts *TypeFacts) {
if c == nil {
return
}
c.bindings = bindings
c.dispatch = dispatch
c.exprs = exprs
c.literals = literals
c.recovery = recovery
@@ -74,7 +78,7 @@ func (c *WaitCompiler) newWaitOperationRecoverySpec(ctx fql.IWaitForExpressionCo
return c.buildProtectedEventRecovery(ev, recoveryLabel, timeoutLabel, endLabel)
}
if ev.TimeoutClause() != nil {
if waitForEventTimeoutClause(ev) != nil {
spec.CompileTimeoutAware = func(timeoutLabel, endLabel core.Label) bytecode.Operand {
return c.compileEventWithTimeoutRecovery(ev, timeoutLabel, endLabel)
}
@@ -108,10 +112,11 @@ func (c *WaitCompiler) buildProtectedEventRecovery(
ctx fql.IWaitForEventExpressionContext,
recoveryLabel, timeoutLabel, endLabel core.Label,
) ProtectedRecoveryRegion {
hasTimeout := ctx != nil && ctx.TimeoutClause() != nil
hasTimeout := waitForEventTimeoutClause(ctx) != nil
streamReg := c.ctx.Function.Registers.Allocate()
resultReg := c.ctx.Function.Registers.Allocate()
errorStateReg := c.ctx.Function.Registers.Allocate()
streamReadyReg := c.ctx.Function.Registers.Allocate()
timeoutStateReg := bytecode.NoopOperand
if hasTimeout {
@@ -121,6 +126,7 @@ func (c *WaitCompiler) buildProtectedEventRecovery(
c.ctx.Program.Emitter.EmitLoadNone(resultReg)
c.ctx.Program.Emitter.EmitBoolean(errorStateReg, false)
c.ctx.Program.Emitter.EmitBoolean(streamReadyReg, false)
startCatch := c.ctx.Program.Emitter.Size()
state, ok := c.buildWaitEventState(ctx)
@@ -128,7 +134,8 @@ func (c *WaitCompiler) buildProtectedEventRecovery(
return ProtectedRecoveryRegion{Result: bytecode.NoopOperand}
}
c.emitWaitEventStreamSetup(state, streamReg)
c.emitWaitEventStreamSetupWithReady(state, streamReg, streamReadyReg)
c.compileWaitEventTrigger(ctx)
start := c.ctx.Program.Emitter.NewLabel()
iterationDone := c.ctx.Program.Emitter.NewLabel()
@@ -143,7 +150,7 @@ func (c *WaitCompiler) buildProtectedEventRecovery(
c.ctx.Program.Emitter.EmitJump(cleanup)
c.ctx.Program.Emitter.MarkLabel(cleanup)
c.emitWaitEventCleanup(state, streamReg)
c.emitWaitEventCleanupIfReady(state, streamReg, streamReadyReg)
endCatchExclusive := c.ctx.Program.Emitter.Size()
+60
View File
@@ -121,6 +121,66 @@ func TestFormatter_WaitForEventFilterUsesWhenAndRemainsParseable(t *testing.T) {
}
}
func TestFormatter_WaitForEventTriggerRemainsParseable(t *testing.T) {
input := "LET obs = []\nLET button = @button\nWAITFOR EVENT \"test\" IN obs WHEN .type == \"match\" TRIGGER (button <- \"click\") TIMEOUT 1\nRETURN 1"
src := source.NewAnonymous(input)
var buf bytes.Buffer
fmt := New()
if err := fmt.Format(&buf, src); err != nil {
t.Fatalf("format failed: %v", err)
}
out := buf.String()
whenIdx := strings.Index(out, "WHEN .type == \"match\"")
triggerIdx := strings.Index(out, "TRIGGER (")
timeoutIdx := strings.Index(out, "TIMEOUT 1")
if whenIdx < 0 || triggerIdx < 0 || timeoutIdx < 0 {
t.Fatalf("expected WAITFOR trigger clauses in formatted output; got:\n%s", out)
}
if !(whenIdx < triggerIdx && triggerIdx < timeoutIdx) {
t.Fatalf("expected WHEN -> TRIGGER -> TIMEOUT order; got:\n%s", out)
}
if !strings.Contains(out, "\n button <- \"click\"\n") {
t.Fatalf("expected trigger body to be formatted as a block; got:\n%s", out)
}
var roundTrip bytes.Buffer
if err := fmt.Format(&roundTrip, source.NewAnonymous(out)); err != nil {
t.Fatalf("formatted output must remain parseable: %v\nformatted:\n%s", err, out)
}
}
func TestFormatter_WaitForEventInlineTriggerRemainsInline(t *testing.T) {
input := "LET obs = []\nLET button = @button\nWAITFOR EVENT \"test\" IN obs WHEN .type == \"match\" TRIGGER button <- \"click\" TIMEOUT 1\nRETURN 1"
src := source.NewAnonymous(input)
var buf bytes.Buffer
fmt := New()
if err := fmt.Format(&buf, src); err != nil {
t.Fatalf("format failed: %v", err)
}
out := buf.String()
whenIdx := strings.Index(out, "WHEN .type == \"match\"")
triggerIdx := strings.Index(out, "TRIGGER button <- \"click\"")
timeoutIdx := strings.Index(out, "TIMEOUT 1")
if whenIdx < 0 || triggerIdx < 0 || timeoutIdx < 0 {
t.Fatalf("expected inline WAITFOR trigger clauses in formatted output; got:\n%s", out)
}
if !(whenIdx < triggerIdx && triggerIdx < timeoutIdx) {
t.Fatalf("expected WHEN -> TRIGGER -> TIMEOUT order; got:\n%s", out)
}
if strings.Contains(out, "TRIGGER (") {
t.Fatalf("expected trigger shorthand to remain inline; got:\n%s", out)
}
var roundTrip bytes.Buffer
if err := fmt.Format(&roundTrip, source.NewAnonymous(out)); err != nil {
t.Fatalf("formatted output must remain parseable: %v\nformatted:\n%s", err, out)
}
}
func TestFormatter_WaitForPredicateRepeatedWhenRemainsParseable(t *testing.T) {
input := "LET value = WAITFOR VALUE { ok: true } WHEN .ok WHEN .ok == true TIMEOUT 1\nRETURN value"
src := source.NewAnonymous(input)
+12
View File
@@ -868,6 +868,18 @@ func (f *expressionFormatter) formatFunctionCallExpression(ctx *fql.FunctionCall
f.formatRecoveryTails(ctx.RecoveryTails())
}
func (f *expressionFormatter) formatFunctionCallNoRecoveryExpression(ctx *fql.FunctionCallNoRecoveryExpressionContext) {
if ctx == nil {
return
}
f.formatFunctionCall(ctx.FunctionCall().(*fql.FunctionCallContext))
if ctx.ErrorOperator() != nil {
f.p.write("?")
}
}
func (f *expressionFormatter) formatFunctionCall(ctx *fql.FunctionCallContext) {
if ctx == nil {
return
+14
View File
@@ -302,6 +302,20 @@ func TestExpressionFormatter_MatchExpressionObjectPattern(t *testing.T) {
}
}
func TestExpressionFormatter_MatchExpressionTriggerObjectPattern(t *testing.T) {
input := `RETURN MATCH obj({ TRIGGER: v }=>v,_=>0)`
program := parseProgram(t, input)
expr := mustFirst[*fql.ExpressionContext](t, program)
var buf bytes.Buffer
e := newEngine(source.NewAnonymous(input), &buf, DefaultOptions())
e.expression.formatExpression(expr)
if got := buf.String(); got != `MATCH obj ( { TRIGGER: v } => v, _ => 0 )` {
t.Fatalf("unexpected MATCH object pattern formatting: %q", got)
}
}
func TestExpressionFormatter_MatchExpressionDispatchShorthand(t *testing.T) {
input := `RETURN MATCH kind("click"=>btn<-"click",_=>input<-"focus")`
program := parseProgram(t, input)
+1
View File
@@ -43,6 +43,7 @@ const (
keywordReturn = "RETURN"
keywordSort = "SORT"
keywordTimeout = "TIMEOUT"
keywordTrigger = "TRIGGER"
keywordUse = "USE"
keywordUsing = "USING"
keywordVar = "VAR"
+148 -2
View File
@@ -559,9 +559,155 @@ func (f *statementFormatter) formatWaitForEventExpression(ctx *fql.WaitForEventE
f.clause.formatEventFilterClause(filter.(*fql.EventFilterClauseContext))
}
if timeout := ctx.TimeoutClause(); timeout != nil {
if tail := ctx.WaitForEventTail(); tail != nil {
if trigger := tail.WaitForTriggerClause(); trigger != nil {
f.p.space()
f.formatWaitForTriggerClause(trigger.(*fql.WaitForTriggerClauseContext))
}
if timeout := tail.TimeoutClause(); timeout != nil {
f.p.space()
f.clause.formatTimeoutClause(timeout.(*fql.TimeoutClauseContext))
}
}
}
func (f *statementFormatter) formatWaitForTriggerClause(ctx *fql.WaitForTriggerClauseContext) {
if ctx == nil {
return
}
f.writeKeyword(keywordTrigger)
f.p.space()
if inline := ctx.WaitForTriggerInlineStatement(); inline != nil {
f.formatWaitForTriggerInlineStatement(inline.(*fql.WaitForTriggerInlineStatementContext))
return
}
f.p.write("(")
stmts := ctx.AllWaitForTriggerStatement()
if len(stmts) == 0 {
f.p.write(")")
return
}
start := f.trivia.stopIndex(ctx) + 1
if openParen := ctx.OpenParen(); openParen != nil {
if sym := openParen.GetSymbol(); sym != nil {
start = sym.GetStop() + 1
}
}
first := stmts[0].(antlr.ParserRuleContext)
f.p.withIndent(func() {
f.trivia.emitBetweenIndices(start, f.trivia.startIndex(first))
for i, stmt := range stmts {
f.formatWaitForTriggerStatement(stmt.(*fql.WaitForTriggerStatementContext))
if i < len(stmts)-1 {
f.trivia.emitBetween(stmt.(antlr.ParserRuleContext), stmts[i+1].(antlr.ParserRuleContext))
}
}
})
if !f.p.atLineStart {
f.p.newline()
}
f.p.write(")")
}
func (f *statementFormatter) formatWaitForTriggerStatement(ctx *fql.WaitForTriggerStatementContext) {
if ctx == nil {
return
}
switch {
case ctx.VariableDeclaration() != nil:
f.formatVariableDeclaration(ctx.VariableDeclaration().(*fql.VariableDeclarationContext))
case ctx.AssignmentStatement() != nil:
f.formatAssignmentStatement(ctx.AssignmentStatement().(*fql.AssignmentStatementContext))
case ctx.DeleteStatement() != nil:
f.formatDeleteStatement(ctx.DeleteStatement().(*fql.DeleteStatementContext))
case ctx.FunctionCallExpression() != nil:
f.expression.formatFunctionCallExpression(ctx.FunctionCallExpression().(*fql.FunctionCallExpressionContext))
case ctx.WaitForExpression() != nil:
f.formatWaitForExpression(ctx.WaitForExpression().(*fql.WaitForExpressionContext))
case ctx.DispatchExpression() != nil:
f.formatDispatchExpression(ctx.DispatchExpression().(*fql.DispatchExpressionContext))
}
}
func (f *statementFormatter) formatWaitForTriggerInlineStatement(ctx *fql.WaitForTriggerInlineStatementContext) {
if ctx == nil {
return
}
switch {
case ctx.VariableDeclaration() != nil:
f.formatVariableDeclaration(ctx.VariableDeclaration().(*fql.VariableDeclarationContext))
case ctx.AssignmentStatement() != nil:
f.formatAssignmentStatement(ctx.AssignmentStatement().(*fql.AssignmentStatementContext))
case ctx.DeleteStatement() != nil:
f.formatDeleteStatement(ctx.DeleteStatement().(*fql.DeleteStatementContext))
case ctx.FunctionCallNoRecoveryExpression() != nil:
f.expression.formatFunctionCallNoRecoveryExpression(
ctx.FunctionCallNoRecoveryExpression().(*fql.FunctionCallNoRecoveryExpressionContext),
)
case ctx.WaitForTriggerInlineDispatchStatement() != nil:
f.formatWaitForTriggerInlineDispatchStatement(
ctx.WaitForTriggerInlineDispatchStatement().(*fql.WaitForTriggerInlineDispatchStatementContext),
)
}
}
func (f *statementFormatter) formatWaitForTriggerInlineDispatchStatement(ctx *fql.WaitForTriggerInlineDispatchStatementContext) {
if ctx == nil {
return
}
if ctx.Dispatch() != nil {
f.writeKeyword(keywordDispatch)
f.p.space()
f.clause.formatTimeoutClause(timeout.(*fql.TimeoutClauseContext))
if name := ctx.DispatchEventName(); name != nil {
f.formatDispatchEventName(name.(*fql.DispatchEventNameContext))
}
f.p.space()
f.writeKeyword(keywordIn)
f.p.space()
if tgt := ctx.DispatchTarget(); tgt != nil {
f.formatDispatchTarget(tgt.(*fql.DispatchTargetContext))
}
if with := ctx.DispatchWithClause(); with != nil {
f.p.space()
f.formatDispatchWithClause(with.(*fql.DispatchWithClauseContext))
}
if opt := ctx.DispatchOptionsClause(); opt != nil {
f.p.space()
f.formatDispatchOptionsClause(opt.(*fql.DispatchOptionsClauseContext))
}
return
}
if tgt := ctx.DispatchTarget(); tgt != nil {
f.formatDispatchTarget(tgt.(*fql.DispatchTargetContext))
}
f.p.space()
f.p.write("<-")
f.p.space()
if name := ctx.DispatchEventName(); name != nil {
f.formatDispatchEventName(name.(*fql.DispatchEventNameContext))
}
}
+1
View File
@@ -78,6 +78,7 @@ Waitfor: 'WAITFOR';
Dispatch: 'DISPATCH';
Delete: 'DELETE';
Options: 'OPTIONS';
Trigger: 'TRIGGER';
Timeout: 'TIMEOUT';
Every: 'EVERY';
Backoff: 'BACKOFF';
+40 -2
View File
@@ -33,7 +33,7 @@ options { tokenVocab=FqlLexer; }
FqlParserLimit, FqlParserCollect, FqlParserSortDirection, FqlParserInto, FqlParserKeep, FqlParserWith,
FqlParserAll, FqlParserAny, FqlParserAt, FqlParserLeast, FqlParserAggregate, FqlParserEvent, FqlParserTimeout,
FqlParserOptions, FqlParserEvery, FqlParserBackoff, FqlParserJitter, FqlParserExists, FqlParserValue,
FqlParserOne, FqlParserCount:
FqlParserOne, FqlParserCount, FqlParserTrigger:
return true
default:
return false
@@ -514,7 +514,40 @@ dispatchOptionsClause
;
waitForEventExpression
: Event waitForEventName In waitForEventSource (optionsClause)? (eventFilterClause)* (timeoutClause)?
: Event waitForEventName In waitForEventSource (optionsClause)? (eventFilterClause)* waitForEventTail
;
waitForEventTail
: waitForTriggerClause (timeoutClause)?
| timeoutClause
| {p.GetTokenStream().LA(1) != FqlParserTrigger && p.GetTokenStream().LA(1) != FqlParserTimeout}?
;
waitForTriggerClause
: Trigger OpenParen waitForTriggerStatement* CloseParen
| Trigger {p.GetTokenStream().LA(1) != FqlParserOpenParen}? waitForTriggerInlineStatement
;
waitForTriggerStatement
: variableDeclaration
| assignmentStatement
| deleteStatement
| functionCallExpression
| waitForExpression
| dispatchExpression
;
waitForTriggerInlineStatement
: variableDeclaration
| assignmentStatement
| deleteStatement
| functionCallNoRecoveryExpression
| waitForTriggerInlineDispatchStatement
;
waitForTriggerInlineDispatchStatement
: Dispatch dispatchEventName In dispatchTarget (dispatchWithClause)? (dispatchOptionsClause)?
| dispatchTarget DispatchReceive dispatchEventName
;
waitForPredicateExpression
@@ -794,6 +827,10 @@ functionCallExpression
: functionCall (errorOperator | recoveryTails)?
;
functionCallNoRecoveryExpression
: functionCall errorOperator?
;
functionCall
: namespace functionName OpenParen argumentList? CloseParen
;
@@ -893,6 +930,7 @@ safeReservedWord
| Exists
| Value
| One
| Trigger
;
unsafeReservedWord
@@ -37,6 +37,26 @@ func matchWaitForErrors(src *source.Source, err *diagnostics.Diagnostic, offendi
}
}
if spanNode := waitForTriggerInlineWaitfor(offending); spanNode != nil {
span := spanFromTokenSafe(spanNode.Token(), src)
err.Message = "Nested WAITFOR in TRIGGER shorthand must use a parenthesized block"
err.Hint = "Use TRIGGER (...), e.g. TRIGGER (WAITFOR EVENT \"ready\" IN target)."
err.Spans = []diagnostics.ErrorSpan{
diagnostics.NewMainErrorSpan(span, "parenthesize nested wait"),
}
return true
}
if spanNode := waitForTriggerInvalidBody(offending); spanNode != nil {
span := spanFromTokenSafe(spanNode.Token(), src)
err.Message = "Expected trigger statement after 'TRIGGER' in WAITFOR EVENT"
err.Hint = "Use a side-effect statement or TRIGGER (...), e.g. TRIGGER target <- \"click\"."
err.Spans = []diagnostics.ErrorSpan{
diagnostics.NewMainErrorSpan(span, "missing trigger statement"),
}
return true
}
if clause, spanNode := waitForMissingClauseValue(offending); clause != "" {
span := spanFromTokenSafe(spanNode.Token(), src)
err.Message = fmt.Sprintf("Expected value after '%s' in WAITFOR clause", clause)
@@ -87,6 +107,45 @@ func waitForPredicateKeyword(offending *TokenNode) (string, *TokenNode) {
return "", nil
}
func waitForTriggerInlineWaitfor(offending *TokenNode) *TokenNode {
if offending == nil {
return nil
}
if is(offending, "TRIGGER") && is(offending.Next(), "WAITFOR") && hasWaitforBefore(offending) {
return offending
}
for curr := offending; curr != nil; curr = curr.Prev() {
if is(curr, "TRIGGER") {
return nil
}
if is(curr, "WAITFOR") && is(curr.Prev(), "TRIGGER") && hasWaitforBefore(curr.Prev()) {
return curr.Prev()
}
}
return nil
}
func waitForTriggerInvalidBody(offending *TokenNode) *TokenNode {
if offending == nil {
return nil
}
if is(offending, "TRIGGER") && hasWaitforBefore(offending) {
return offending
}
prev := offending.Prev()
if is(prev, "TRIGGER") && hasWaitforBefore(prev) {
return prev
}
return nil
}
func waitForMissingClauseValue(offending *TokenNode) (string, *TokenNode) {
if offending == nil {
return "", nil
File diff suppressed because one or more lines are too long
+84 -82
View File
@@ -52,54 +52,55 @@ Waitfor=51
Dispatch=52
Delete=53
Options=54
Timeout=55
Every=56
Backoff=57
Jitter=58
Exists=59
Count=60
Value=61
One=62
Distinct=63
Filter=64
Sort=65
Limit=66
Let=67
Var=68
Collect=69
SortDirection=70
None=71
Null=72
BooleanLiteral=73
Use=74
As=75
At=76
Least=77
Into=78
Keep=79
With=80
All=81
Any=82
Aggregate=83
Event=84
Like=85
Not=86
In=87
Do=88
While=89
Param=90
Identifier=91
IgnoreIdentifier=92
StringLiteral=93
BacktickOpen=94
DurationLiteral=95
IntegerLiteral=96
FloatLiteral=97
NamespaceSegment=98
UnknownIdentifier=99
TemplateExprStart=100
TemplateChars=101
BacktickClose=102
Trigger=55
Timeout=56
Every=57
Backoff=58
Jitter=59
Exists=60
Count=61
Value=62
One=63
Distinct=64
Filter=65
Sort=66
Limit=67
Let=68
Var=69
Collect=70
SortDirection=71
None=72
Null=73
BooleanLiteral=74
Use=75
As=76
At=77
Least=78
Into=79
Keep=80
With=81
All=82
Any=83
Aggregate=84
Event=85
Like=86
Not=87
In=88
Do=89
While=90
Param=91
Identifier=92
IgnoreIdentifier=93
StringLiteral=94
BacktickOpen=95
DurationLiteral=96
IntegerLiteral=97
FloatLiteral=98
NamespaceSegment=99
UnknownIdentifier=100
TemplateExprStart=101
TemplateChars=102
BacktickClose=103
':'=6
';'=7
'.'=8
@@ -146,37 +147,38 @@ BacktickClose=102
'DISPATCH'=52
'DELETE'=53
'OPTIONS'=54
'TIMEOUT'=55
'EVERY'=56
'BACKOFF'=57
'JITTER'=58
'EXISTS'=59
'COUNT'=60
'VALUE'=61
'ONE'=62
'DISTINCT'=63
'FILTER'=64
'SORT'=65
'LIMIT'=66
'LET'=67
'VAR'=68
'COLLECT'=69
'NONE'=71
'NULL'=72
'USE'=74
'AS'=75
'AT'=76
'LEAST'=77
'INTO'=78
'KEEP'=79
'WITH'=80
'ALL'=81
'ANY'=82
'AGGREGATE'=83
'EVENT'=84
'LIKE'=85
'IN'=87
'DO'=88
'WHILE'=89
'@'=90
'${'=100
'TRIGGER'=55
'TIMEOUT'=56
'EVERY'=57
'BACKOFF'=58
'JITTER'=59
'EXISTS'=60
'COUNT'=61
'VALUE'=62
'ONE'=63
'DISTINCT'=64
'FILTER'=65
'SORT'=66
'LIMIT'=67
'LET'=68
'VAR'=69
'COLLECT'=70
'NONE'=72
'NULL'=73
'USE'=75
'AS'=76
'AT'=77
'LEAST'=78
'INTO'=79
'KEEP'=80
'WITH'=81
'ALL'=82
'ANY'=83
'AGGREGATE'=84
'EVENT'=85
'LIKE'=86
'IN'=88
'DO'=89
'WHILE'=90
'@'=91
'${'=101
File diff suppressed because one or more lines are too long
+84 -82
View File
@@ -52,54 +52,55 @@ Waitfor=51
Dispatch=52
Delete=53
Options=54
Timeout=55
Every=56
Backoff=57
Jitter=58
Exists=59
Count=60
Value=61
One=62
Distinct=63
Filter=64
Sort=65
Limit=66
Let=67
Var=68
Collect=69
SortDirection=70
None=71
Null=72
BooleanLiteral=73
Use=74
As=75
At=76
Least=77
Into=78
Keep=79
With=80
All=81
Any=82
Aggregate=83
Event=84
Like=85
Not=86
In=87
Do=88
While=89
Param=90
Identifier=91
IgnoreIdentifier=92
StringLiteral=93
BacktickOpen=94
DurationLiteral=95
IntegerLiteral=96
FloatLiteral=97
NamespaceSegment=98
UnknownIdentifier=99
TemplateExprStart=100
TemplateChars=101
BacktickClose=102
Trigger=55
Timeout=56
Every=57
Backoff=58
Jitter=59
Exists=60
Count=61
Value=62
One=63
Distinct=64
Filter=65
Sort=66
Limit=67
Let=68
Var=69
Collect=70
SortDirection=71
None=72
Null=73
BooleanLiteral=74
Use=75
As=76
At=77
Least=78
Into=79
Keep=80
With=81
All=82
Any=83
Aggregate=84
Event=85
Like=86
Not=87
In=88
Do=89
While=90
Param=91
Identifier=92
IgnoreIdentifier=93
StringLiteral=94
BacktickOpen=95
DurationLiteral=96
IntegerLiteral=97
FloatLiteral=98
NamespaceSegment=99
UnknownIdentifier=100
TemplateExprStart=101
TemplateChars=102
BacktickClose=103
':'=6
';'=7
'.'=8
@@ -146,37 +147,38 @@ BacktickClose=102
'DISPATCH'=52
'DELETE'=53
'OPTIONS'=54
'TIMEOUT'=55
'EVERY'=56
'BACKOFF'=57
'JITTER'=58
'EXISTS'=59
'COUNT'=60
'VALUE'=61
'ONE'=62
'DISTINCT'=63
'FILTER'=64
'SORT'=65
'LIMIT'=66
'LET'=67
'VAR'=68
'COLLECT'=69
'NONE'=71
'NULL'=72
'USE'=74
'AS'=75
'AT'=76
'LEAST'=77
'INTO'=78
'KEEP'=79
'WITH'=80
'ALL'=81
'ANY'=82
'AGGREGATE'=83
'EVENT'=84
'LIKE'=85
'IN'=87
'DO'=88
'WHILE'=89
'@'=90
'${'=100
'TRIGGER'=55
'TIMEOUT'=56
'EVERY'=57
'BACKOFF'=58
'JITTER'=59
'EXISTS'=60
'COUNT'=61
'VALUE'=62
'ONE'=63
'DISTINCT'=64
'FILTER'=65
'SORT'=66
'LIMIT'=67
'LET'=68
'VAR'=69
'COLLECT'=70
'NONE'=72
'NULL'=73
'USE'=75
'AS'=76
'AT'=77
'LEAST'=78
'INTO'=79
'KEEP'=80
'WITH'=81
'ALL'=82
'ANY'=83
'AGGREGATE'=84
'EVENT'=85
'LIKE'=86
'IN'=88
'DO'=89
'WHILE'=90
'@'=91
'${'=101
+404 -398
View File
@@ -50,13 +50,13 @@ func fqllexerLexerInit() {
"'!='", "'*='", "'/='", "'+='", "'-='", "'*'", "'/'", "'%'", "'+'",
"'-'", "'++'", "'--'", "", "", "", "'=>'", "'<-'", "'='", "'?'", "'!~'",
"'=~'", "'MATCH'", "'WHEN'", "'FUNC'", "'FOR'", "'RETURN'", "'QUERY'",
"'USING'", "'WAITFOR'", "'DISPATCH'", "'DELETE'", "'OPTIONS'", "'TIMEOUT'",
"'EVERY'", "'BACKOFF'", "'JITTER'", "'EXISTS'", "'COUNT'", "'VALUE'",
"'ONE'", "'DISTINCT'", "'FILTER'", "'SORT'", "'LIMIT'", "'LET'", "'VAR'",
"'COLLECT'", "", "'NONE'", "'NULL'", "", "'USE'", "'AS'", "'AT'", "'LEAST'",
"'INTO'", "'KEEP'", "'WITH'", "'ALL'", "'ANY'", "'AGGREGATE'", "'EVENT'",
"'LIKE'", "", "'IN'", "'DO'", "'WHILE'", "'@'", "", "", "", "", "",
"", "", "", "", "'${'",
"'USING'", "'WAITFOR'", "'DISPATCH'", "'DELETE'", "'OPTIONS'", "'TRIGGER'",
"'TIMEOUT'", "'EVERY'", "'BACKOFF'", "'JITTER'", "'EXISTS'", "'COUNT'",
"'VALUE'", "'ONE'", "'DISTINCT'", "'FILTER'", "'SORT'", "'LIMIT'", "'LET'",
"'VAR'", "'COLLECT'", "", "'NONE'", "'NULL'", "", "'USE'", "'AS'", "'AT'",
"'LEAST'", "'INTO'", "'KEEP'", "'WITH'", "'ALL'", "'ANY'", "'AGGREGATE'",
"'EVENT'", "'LIKE'", "", "'IN'", "'DO'", "'WHILE'", "'@'", "", "", "",
"", "", "", "", "", "", "'${'",
}
staticData.SymbolicNames = []string{
"", "TemplateExprEnd", "MultiLineComment", "SingleLineComment", "WhiteSpaces",
@@ -67,10 +67,10 @@ func fqllexerLexerInit() {
"Minus", "Increment", "Decrement", "And", "Or", "Range", "Arrow", "DispatchReceive",
"Assign", "QuestionMark", "RegexNotMatch", "RegexMatch", "Match", "When",
"Func", "For", "Return", "Query", "Using", "Waitfor", "Dispatch", "Delete",
"Options", "Timeout", "Every", "Backoff", "Jitter", "Exists", "Count",
"Value", "One", "Distinct", "Filter", "Sort", "Limit", "Let", "Var",
"Collect", "SortDirection", "None", "Null", "BooleanLiteral", "Use",
"As", "At", "Least", "Into", "Keep", "With", "All", "Any", "Aggregate",
"Options", "Trigger", "Timeout", "Every", "Backoff", "Jitter", "Exists",
"Count", "Value", "One", "Distinct", "Filter", "Sort", "Limit", "Let",
"Var", "Collect", "SortDirection", "None", "Null", "BooleanLiteral",
"Use", "As", "At", "Least", "Into", "Keep", "With", "All", "Any", "Aggregate",
"Event", "Like", "Not", "In", "Do", "While", "Param", "Identifier",
"IgnoreIdentifier", "StringLiteral", "BacktickOpen", "DurationLiteral",
"IntegerLiteral", "FloatLiteral", "NamespaceSegment", "UnknownIdentifier",
@@ -85,10 +85,10 @@ func fqllexerLexerInit() {
"Decrement", "And", "Or", "Range", "Arrow", "DispatchReceive", "Assign",
"QuestionMark", "RegexNotMatch", "RegexMatch", "Match", "When", "Func",
"For", "Return", "Query", "Using", "Waitfor", "Dispatch", "Delete",
"Options", "Timeout", "Every", "Backoff", "Jitter", "Exists", "Count",
"Value", "One", "Distinct", "Filter", "Sort", "Limit", "Let", "Var",
"Collect", "SortDirection", "None", "Null", "BooleanLiteral", "Use",
"As", "At", "Least", "Into", "Keep", "With", "All", "Any", "Aggregate",
"Options", "Trigger", "Timeout", "Every", "Backoff", "Jitter", "Exists",
"Count", "Value", "One", "Distinct", "Filter", "Sort", "Limit", "Let",
"Var", "Collect", "SortDirection", "None", "Null", "BooleanLiteral",
"Use", "As", "At", "Least", "Into", "Keep", "With", "All", "Any", "Aggregate",
"Event", "Like", "Not", "In", "Do", "While", "Param", "Identifier",
"IgnoreIdentifier", "StringLiteral", "BacktickOpen", "DurationLiteral",
"IntegerLiteral", "FloatLiteral", "NamespaceSegment", "UnknownIdentifier",
@@ -98,7 +98,7 @@ func fqllexerLexerInit() {
}
staticData.PredictionContextCache = antlr.NewPredictionContextCache()
staticData.serializedATN = []int32{
4, 0, 102, 824, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3,
4, 0, 103, 834, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3,
7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9,
7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7,
14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19,
@@ -120,68 +120,69 @@ func fqllexerLexerInit() {
98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103,
7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107,
2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112,
7, 112, 1, 0, 1, 0, 1, 0, 1, 0, 5, 0, 233, 8, 0, 10, 0, 12, 0, 236, 9,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 247, 8,
1, 10, 1, 12, 1, 250, 9, 1, 1, 1, 1, 1, 1, 2, 4, 2, 255, 8, 2, 11, 2, 12,
2, 256, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1,
6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11,
1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1,
15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19,
1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 23, 1,
23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27,
1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1,
32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 3, 33, 341, 8, 33,
1, 34, 1, 34, 1, 34, 1, 34, 3, 34, 347, 8, 34, 1, 35, 1, 35, 1, 35, 1,
36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 39, 1, 39, 1, 40,
1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1,
42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44,
1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1,
46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48,
1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1,
50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51,
1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1,
52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53,
1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1,
55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56,
1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1,
58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60,
1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1,
61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63,
1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1,
65, 1, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67,
1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 3,
68, 541, 8, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70,
1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1,
71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 3, 71,
571, 8, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 1, 74, 1,
74, 1, 74, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76,
1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1,
78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 1, 81,
1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1,
82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 84,
1, 84, 1, 84, 1, 84, 3, 84, 637, 8, 84, 1, 85, 1, 85, 1, 85, 1, 86, 1,
86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 87, 1, 87, 1, 87, 1, 88, 1, 88, 1, 89,
4, 89, 654, 8, 89, 11, 89, 12, 89, 655, 1, 89, 1, 89, 5, 89, 660, 8, 89,
10, 89, 12, 89, 663, 9, 89, 5, 89, 665, 8, 89, 10, 89, 12, 89, 668, 9,
89, 1, 89, 1, 89, 5, 89, 672, 8, 89, 10, 89, 12, 89, 675, 9, 89, 5, 89,
677, 8, 89, 10, 89, 12, 89, 680, 9, 89, 1, 90, 1, 90, 1, 91, 1, 91, 1,
91, 3, 91, 687, 8, 91, 1, 92, 1, 92, 1, 92, 1, 92, 1, 93, 1, 93, 1, 93,
4, 93, 696, 8, 93, 11, 93, 12, 93, 697, 3, 93, 700, 8, 93, 1, 93, 3, 93,
703, 8, 93, 1, 93, 1, 93, 1, 94, 4, 94, 708, 8, 94, 11, 94, 12, 94, 709,
1, 95, 1, 95, 1, 95, 4, 95, 715, 8, 95, 11, 95, 12, 95, 716, 1, 95, 3,
95, 720, 8, 95, 1, 95, 1, 95, 3, 95, 724, 8, 95, 3, 95, 726, 8, 95, 1,
96, 1, 96, 1, 96, 1, 97, 1, 97, 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, 5, 99,
738, 8, 99, 10, 99, 12, 99, 741, 9, 99, 3, 99, 743, 8, 99, 1, 100, 1, 100,
3, 100, 747, 8, 100, 1, 100, 4, 100, 750, 8, 100, 11, 100, 12, 100, 751,
1, 101, 1, 101, 1, 102, 1, 102, 1, 103, 1, 103, 1, 104, 1, 104, 1, 105,
1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 5, 105, 768, 8, 105, 10, 105, 12,
105, 771, 9, 105, 1, 105, 1, 105, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106,
1, 106, 5, 106, 781, 8, 106, 10, 106, 12, 106, 784, 9, 106, 1, 106, 1,
106, 1, 107, 1, 107, 1, 107, 1, 107, 5, 107, 792, 8, 107, 10, 107, 12,
107, 795, 9, 107, 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 109, 1, 109,
1, 109, 3, 109, 805, 8, 109, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1,
111, 1, 111, 1, 111, 1, 111, 1, 111, 4, 111, 817, 8, 111, 11, 111, 12,
111, 818, 1, 112, 1, 112, 1, 112, 1, 112, 1, 234, 0, 113, 2, 2, 4, 3, 6,
7, 112, 2, 113, 7, 113, 1, 0, 1, 0, 1, 0, 1, 0, 5, 0, 235, 8, 0, 10, 0,
12, 0, 238, 9, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
5, 1, 249, 8, 1, 10, 1, 12, 1, 252, 9, 1, 1, 1, 1, 1, 1, 2, 4, 2, 257,
8, 2, 11, 2, 12, 2, 258, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4,
1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10,
1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1,
15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 19,
1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1,
22, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 26,
1, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1,
31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 3, 33,
343, 8, 33, 1, 34, 1, 34, 1, 34, 1, 34, 3, 34, 349, 8, 34, 1, 35, 1, 35,
1, 35, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 39, 1,
39, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42,
1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1,
44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46,
1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1,
48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49,
1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1,
51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52,
1, 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1,
53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55,
1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1,
56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58,
1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1,
59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61,
1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1,
63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64,
1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 66, 1,
66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68,
1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 3, 69, 551,
8, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1,
71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72,
1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 3, 72, 581, 8,
72, 1, 73, 1, 73, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 75,
1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1,
77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79,
1, 80, 1, 80, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 1,
82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83,
1, 83, 1, 83, 1, 83, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, 1,
85, 1, 85, 3, 85, 647, 8, 85, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87,
1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 89, 1, 89, 1, 90, 4, 90, 664,
8, 90, 11, 90, 12, 90, 665, 1, 90, 1, 90, 5, 90, 670, 8, 90, 10, 90, 12,
90, 673, 9, 90, 5, 90, 675, 8, 90, 10, 90, 12, 90, 678, 9, 90, 1, 90, 1,
90, 5, 90, 682, 8, 90, 10, 90, 12, 90, 685, 9, 90, 5, 90, 687, 8, 90, 10,
90, 12, 90, 690, 9, 90, 1, 91, 1, 91, 1, 92, 1, 92, 1, 92, 3, 92, 697,
8, 92, 1, 93, 1, 93, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 4, 94, 706, 8,
94, 11, 94, 12, 94, 707, 3, 94, 710, 8, 94, 1, 94, 3, 94, 713, 8, 94, 1,
94, 1, 94, 1, 95, 4, 95, 718, 8, 95, 11, 95, 12, 95, 719, 1, 96, 1, 96,
1, 96, 4, 96, 725, 8, 96, 11, 96, 12, 96, 726, 1, 96, 3, 96, 730, 8, 96,
1, 96, 1, 96, 3, 96, 734, 8, 96, 3, 96, 736, 8, 96, 1, 97, 1, 97, 1, 97,
1, 98, 1, 98, 1, 99, 1, 99, 1, 100, 1, 100, 1, 100, 5, 100, 748, 8, 100,
10, 100, 12, 100, 751, 9, 100, 3, 100, 753, 8, 100, 1, 101, 1, 101, 3,
101, 757, 8, 101, 1, 101, 4, 101, 760, 8, 101, 11, 101, 12, 101, 761, 1,
102, 1, 102, 1, 103, 1, 103, 1, 104, 1, 104, 1, 105, 1, 105, 1, 106, 1,
106, 1, 106, 1, 106, 1, 106, 1, 106, 5, 106, 778, 8, 106, 10, 106, 12,
106, 781, 9, 106, 1, 106, 1, 106, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107,
1, 107, 5, 107, 791, 8, 107, 10, 107, 12, 107, 794, 9, 107, 1, 107, 1,
107, 1, 108, 1, 108, 1, 108, 1, 108, 5, 108, 802, 8, 108, 10, 108, 12,
108, 805, 9, 108, 1, 108, 1, 108, 1, 109, 1, 109, 1, 109, 1, 110, 1, 110,
1, 110, 3, 110, 815, 8, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1,
112, 1, 112, 1, 112, 1, 112, 1, 112, 4, 112, 827, 8, 112, 11, 112, 12,
112, 828, 1, 113, 1, 113, 1, 113, 1, 113, 1, 236, 0, 114, 2, 2, 4, 3, 6,
4, 8, 5, 10, 6, 12, 7, 14, 8, 16, 9, 18, 10, 20, 11, 22, 12, 24, 13, 26,
14, 28, 15, 30, 16, 32, 17, 34, 18, 36, 19, 38, 20, 40, 21, 42, 22, 44,
23, 46, 24, 48, 25, 50, 26, 52, 27, 54, 28, 56, 29, 58, 30, 60, 31, 62,
@@ -193,276 +194,280 @@ func fqllexerLexerInit() {
74, 148, 75, 150, 76, 152, 77, 154, 78, 156, 79, 158, 80, 160, 81, 162,
82, 164, 83, 166, 84, 168, 85, 170, 86, 172, 87, 174, 88, 176, 89, 178,
90, 180, 91, 182, 92, 184, 93, 186, 94, 188, 95, 190, 96, 192, 97, 194,
98, 196, 99, 198, 0, 200, 0, 202, 0, 204, 0, 206, 0, 208, 0, 210, 0, 212,
0, 214, 0, 216, 0, 218, 0, 220, 0, 222, 100, 224, 101, 226, 102, 2, 0,
1, 13, 3, 0, 10, 10, 13, 13, 8232, 8233, 4, 0, 9, 9, 11, 12, 32, 32, 160,
160, 1, 0, 48, 57, 3, 0, 48, 57, 65, 70, 97, 102, 1, 0, 49, 57, 2, 0, 69,
69, 101, 101, 2, 0, 43, 43, 45, 45, 2, 0, 65, 90, 97, 122, 2, 0, 34, 34,
92, 92, 2, 0, 39, 39, 92, 92, 1, 0, 180, 180, 4, 0, 68, 68, 72, 72, 77,
77, 83, 83, 3, 0, 36, 36, 92, 92, 96, 96, 851, 0, 2, 1, 0, 0, 0, 0, 4,
1, 0, 0, 0, 0, 6, 1, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 10, 1, 0, 0, 0, 0, 12,
1, 0, 0, 0, 0, 14, 1, 0, 0, 0, 0, 16, 1, 0, 0, 0, 0, 18, 1, 0, 0, 0, 0,
20, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 24, 1, 0, 0, 0, 0, 26, 1, 0, 0, 0,
0, 28, 1, 0, 0, 0, 0, 30, 1, 0, 0, 0, 0, 32, 1, 0, 0, 0, 0, 34, 1, 0, 0,
0, 0, 36, 1, 0, 0, 0, 0, 38, 1, 0, 0, 0, 0, 40, 1, 0, 0, 0, 0, 42, 1, 0,
0, 0, 0, 44, 1, 0, 0, 0, 0, 46, 1, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 50, 1,
0, 0, 0, 0, 52, 1, 0, 0, 0, 0, 54, 1, 0, 0, 0, 0, 56, 1, 0, 0, 0, 0, 58,
1, 0, 0, 0, 0, 60, 1, 0, 0, 0, 0, 62, 1, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0,
66, 1, 0, 0, 0, 0, 68, 1, 0, 0, 0, 0, 70, 1, 0, 0, 0, 0, 72, 1, 0, 0, 0,
0, 74, 1, 0, 0, 0, 0, 76, 1, 0, 0, 0, 0, 78, 1, 0, 0, 0, 0, 80, 1, 0, 0,
0, 0, 82, 1, 0, 0, 0, 0, 84, 1, 0, 0, 0, 0, 86, 1, 0, 0, 0, 0, 88, 1, 0,
0, 0, 0, 90, 1, 0, 0, 0, 0, 92, 1, 0, 0, 0, 0, 94, 1, 0, 0, 0, 0, 96, 1,
0, 0, 0, 0, 98, 1, 0, 0, 0, 0, 100, 1, 0, 0, 0, 0, 102, 1, 0, 0, 0, 0,
104, 1, 0, 0, 0, 0, 106, 1, 0, 0, 0, 0, 108, 1, 0, 0, 0, 0, 110, 1, 0,
0, 0, 0, 112, 1, 0, 0, 0, 0, 114, 1, 0, 0, 0, 0, 116, 1, 0, 0, 0, 0, 118,
1, 0, 0, 0, 0, 120, 1, 0, 0, 0, 0, 122, 1, 0, 0, 0, 0, 124, 1, 0, 0, 0,
0, 126, 1, 0, 0, 0, 0, 128, 1, 0, 0, 0, 0, 130, 1, 0, 0, 0, 0, 132, 1,
0, 0, 0, 0, 134, 1, 0, 0, 0, 0, 136, 1, 0, 0, 0, 0, 138, 1, 0, 0, 0, 0,
140, 1, 0, 0, 0, 0, 142, 1, 0, 0, 0, 0, 144, 1, 0, 0, 0, 0, 146, 1, 0,
0, 0, 0, 148, 1, 0, 0, 0, 0, 150, 1, 0, 0, 0, 0, 152, 1, 0, 0, 0, 0, 154,
1, 0, 0, 0, 0, 156, 1, 0, 0, 0, 0, 158, 1, 0, 0, 0, 0, 160, 1, 0, 0, 0,
0, 162, 1, 0, 0, 0, 0, 164, 1, 0, 0, 0, 0, 166, 1, 0, 0, 0, 0, 168, 1,
0, 0, 0, 0, 170, 1, 0, 0, 0, 0, 172, 1, 0, 0, 0, 0, 174, 1, 0, 0, 0, 0,
176, 1, 0, 0, 0, 0, 178, 1, 0, 0, 0, 0, 180, 1, 0, 0, 0, 0, 182, 1, 0,
0, 0, 0, 184, 1, 0, 0, 0, 0, 186, 1, 0, 0, 0, 0, 188, 1, 0, 0, 0, 0, 190,
1, 0, 0, 0, 0, 192, 1, 0, 0, 0, 0, 194, 1, 0, 0, 0, 0, 196, 1, 0, 0, 0,
1, 222, 1, 0, 0, 0, 1, 224, 1, 0, 0, 0, 1, 226, 1, 0, 0, 0, 2, 228, 1,
0, 0, 0, 4, 242, 1, 0, 0, 0, 6, 254, 1, 0, 0, 0, 8, 260, 1, 0, 0, 0, 10,
264, 1, 0, 0, 0, 12, 266, 1, 0, 0, 0, 14, 268, 1, 0, 0, 0, 16, 270, 1,
0, 0, 0, 18, 272, 1, 0, 0, 0, 20, 275, 1, 0, 0, 0, 22, 277, 1, 0, 0, 0,
24, 279, 1, 0, 0, 0, 26, 281, 1, 0, 0, 0, 28, 283, 1, 0, 0, 0, 30, 285,
1, 0, 0, 0, 32, 288, 1, 0, 0, 0, 34, 291, 1, 0, 0, 0, 36, 293, 1, 0, 0,
0, 38, 295, 1, 0, 0, 0, 40, 298, 1, 0, 0, 0, 42, 301, 1, 0, 0, 0, 44, 304,
1, 0, 0, 0, 46, 307, 1, 0, 0, 0, 48, 310, 1, 0, 0, 0, 50, 313, 1, 0, 0,
0, 52, 316, 1, 0, 0, 0, 54, 319, 1, 0, 0, 0, 56, 321, 1, 0, 0, 0, 58, 323,
1, 0, 0, 0, 60, 325, 1, 0, 0, 0, 62, 327, 1, 0, 0, 0, 64, 329, 1, 0, 0,
0, 66, 332, 1, 0, 0, 0, 68, 340, 1, 0, 0, 0, 70, 346, 1, 0, 0, 0, 72, 348,
1, 0, 0, 0, 74, 351, 1, 0, 0, 0, 76, 354, 1, 0, 0, 0, 78, 357, 1, 0, 0,
0, 80, 359, 1, 0, 0, 0, 82, 361, 1, 0, 0, 0, 84, 364, 1, 0, 0, 0, 86, 367,
1, 0, 0, 0, 88, 373, 1, 0, 0, 0, 90, 378, 1, 0, 0, 0, 92, 383, 1, 0, 0,
0, 94, 387, 1, 0, 0, 0, 96, 394, 1, 0, 0, 0, 98, 400, 1, 0, 0, 0, 100,
406, 1, 0, 0, 0, 102, 414, 1, 0, 0, 0, 104, 423, 1, 0, 0, 0, 106, 430,
1, 0, 0, 0, 108, 438, 1, 0, 0, 0, 110, 446, 1, 0, 0, 0, 112, 452, 1, 0,
0, 0, 114, 460, 1, 0, 0, 0, 116, 467, 1, 0, 0, 0, 118, 474, 1, 0, 0, 0,
120, 480, 1, 0, 0, 0, 122, 486, 1, 0, 0, 0, 124, 490, 1, 0, 0, 0, 126,
499, 1, 0, 0, 0, 128, 506, 1, 0, 0, 0, 130, 511, 1, 0, 0, 0, 132, 517,
1, 0, 0, 0, 134, 521, 1, 0, 0, 0, 136, 525, 1, 0, 0, 0, 138, 540, 1, 0,
0, 0, 140, 542, 1, 0, 0, 0, 142, 547, 1, 0, 0, 0, 144, 570, 1, 0, 0, 0,
146, 572, 1, 0, 0, 0, 148, 576, 1, 0, 0, 0, 150, 579, 1, 0, 0, 0, 152,
582, 1, 0, 0, 0, 154, 588, 1, 0, 0, 0, 156, 593, 1, 0, 0, 0, 158, 598,
1, 0, 0, 0, 160, 603, 1, 0, 0, 0, 162, 607, 1, 0, 0, 0, 164, 611, 1, 0,
0, 0, 166, 621, 1, 0, 0, 0, 168, 627, 1, 0, 0, 0, 170, 636, 1, 0, 0, 0,
172, 638, 1, 0, 0, 0, 174, 641, 1, 0, 0, 0, 176, 644, 1, 0, 0, 0, 178,
650, 1, 0, 0, 0, 180, 653, 1, 0, 0, 0, 182, 681, 1, 0, 0, 0, 184, 686,
1, 0, 0, 0, 186, 688, 1, 0, 0, 0, 188, 692, 1, 0, 0, 0, 190, 707, 1, 0,
0, 0, 192, 725, 1, 0, 0, 0, 194, 727, 1, 0, 0, 0, 196, 730, 1, 0, 0, 0,
198, 732, 1, 0, 0, 0, 200, 742, 1, 0, 0, 0, 202, 744, 1, 0, 0, 0, 204,
753, 1, 0, 0, 0, 206, 755, 1, 0, 0, 0, 208, 757, 1, 0, 0, 0, 210, 759,
1, 0, 0, 0, 212, 761, 1, 0, 0, 0, 214, 774, 1, 0, 0, 0, 216, 787, 1, 0,
0, 0, 218, 798, 1, 0, 0, 0, 220, 804, 1, 0, 0, 0, 222, 806, 1, 0, 0, 0,
224, 816, 1, 0, 0, 0, 226, 820, 1, 0, 0, 0, 228, 229, 5, 47, 0, 0, 229,
230, 5, 42, 0, 0, 230, 234, 1, 0, 0, 0, 231, 233, 9, 0, 0, 0, 232, 231,
1, 0, 0, 0, 233, 236, 1, 0, 0, 0, 234, 235, 1, 0, 0, 0, 234, 232, 1, 0,
0, 0, 235, 237, 1, 0, 0, 0, 236, 234, 1, 0, 0, 0, 237, 238, 5, 42, 0, 0,
238, 239, 5, 47, 0, 0, 239, 240, 1, 0, 0, 0, 240, 241, 6, 0, 0, 0, 241,
3, 1, 0, 0, 0, 242, 243, 5, 47, 0, 0, 243, 244, 5, 47, 0, 0, 244, 248,
1, 0, 0, 0, 245, 247, 8, 0, 0, 0, 246, 245, 1, 0, 0, 0, 247, 250, 1, 0,
0, 0, 248, 246, 1, 0, 0, 0, 248, 249, 1, 0, 0, 0, 249, 251, 1, 0, 0, 0,
250, 248, 1, 0, 0, 0, 251, 252, 6, 1, 0, 0, 252, 5, 1, 0, 0, 0, 253, 255,
7, 1, 0, 0, 254, 253, 1, 0, 0, 0, 255, 256, 1, 0, 0, 0, 256, 254, 1, 0,
0, 0, 256, 257, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 259, 6, 2, 0, 0,
259, 7, 1, 0, 0, 0, 260, 261, 7, 0, 0, 0, 261, 262, 1, 0, 0, 0, 262, 263,
6, 3, 0, 0, 263, 9, 1, 0, 0, 0, 264, 265, 5, 58, 0, 0, 265, 11, 1, 0, 0,
0, 266, 267, 5, 59, 0, 0, 267, 13, 1, 0, 0, 0, 268, 269, 5, 46, 0, 0, 269,
15, 1, 0, 0, 0, 270, 271, 5, 44, 0, 0, 271, 17, 1, 0, 0, 0, 272, 273, 5,
126, 0, 0, 273, 274, 5, 63, 0, 0, 274, 19, 1, 0, 0, 0, 275, 276, 5, 126,
0, 0, 276, 21, 1, 0, 0, 0, 277, 278, 5, 91, 0, 0, 278, 23, 1, 0, 0, 0,
279, 280, 5, 93, 0, 0, 280, 25, 1, 0, 0, 0, 281, 282, 5, 40, 0, 0, 282,
27, 1, 0, 0, 0, 283, 284, 5, 41, 0, 0, 284, 29, 1, 0, 0, 0, 285, 286, 5,
123, 0, 0, 286, 287, 6, 14, 1, 0, 287, 31, 1, 0, 0, 0, 288, 289, 5, 125,
0, 0, 289, 290, 6, 15, 2, 0, 290, 33, 1, 0, 0, 0, 291, 292, 5, 62, 0, 0,
292, 35, 1, 0, 0, 0, 293, 294, 5, 60, 0, 0, 294, 37, 1, 0, 0, 0, 295, 296,
5, 61, 0, 0, 296, 297, 5, 61, 0, 0, 297, 39, 1, 0, 0, 0, 298, 299, 5, 62,
0, 0, 299, 300, 5, 61, 0, 0, 300, 41, 1, 0, 0, 0, 301, 302, 5, 60, 0, 0,
302, 303, 5, 61, 0, 0, 303, 43, 1, 0, 0, 0, 304, 305, 5, 33, 0, 0, 305,
306, 5, 61, 0, 0, 306, 45, 1, 0, 0, 0, 307, 308, 5, 42, 0, 0, 308, 309,
5, 61, 0, 0, 309, 47, 1, 0, 0, 0, 310, 311, 5, 47, 0, 0, 311, 312, 5, 61,
0, 0, 312, 49, 1, 0, 0, 0, 313, 314, 5, 43, 0, 0, 314, 315, 5, 61, 0, 0,
315, 51, 1, 0, 0, 0, 316, 317, 5, 45, 0, 0, 317, 318, 5, 61, 0, 0, 318,
53, 1, 0, 0, 0, 319, 320, 5, 42, 0, 0, 320, 55, 1, 0, 0, 0, 321, 322, 5,
47, 0, 0, 322, 57, 1, 0, 0, 0, 323, 324, 5, 37, 0, 0, 324, 59, 1, 0, 0,
0, 325, 326, 5, 43, 0, 0, 326, 61, 1, 0, 0, 0, 327, 328, 5, 45, 0, 0, 328,
63, 1, 0, 0, 0, 329, 330, 5, 43, 0, 0, 330, 331, 5, 43, 0, 0, 331, 65,
1, 0, 0, 0, 332, 333, 5, 45, 0, 0, 333, 334, 5, 45, 0, 0, 334, 67, 1, 0,
0, 0, 335, 336, 5, 65, 0, 0, 336, 337, 5, 78, 0, 0, 337, 341, 5, 68, 0,
0, 338, 339, 5, 38, 0, 0, 339, 341, 5, 38, 0, 0, 340, 335, 1, 0, 0, 0,
340, 338, 1, 0, 0, 0, 341, 69, 1, 0, 0, 0, 342, 343, 5, 79, 0, 0, 343,
347, 5, 82, 0, 0, 344, 345, 5, 124, 0, 0, 345, 347, 5, 124, 0, 0, 346,
342, 1, 0, 0, 0, 346, 344, 1, 0, 0, 0, 347, 71, 1, 0, 0, 0, 348, 349, 3,
14, 6, 0, 349, 350, 3, 14, 6, 0, 350, 73, 1, 0, 0, 0, 351, 352, 5, 61,
0, 0, 352, 353, 5, 62, 0, 0, 353, 75, 1, 0, 0, 0, 354, 355, 5, 60, 0, 0,
355, 356, 5, 45, 0, 0, 356, 77, 1, 0, 0, 0, 357, 358, 5, 61, 0, 0, 358,
79, 1, 0, 0, 0, 359, 360, 5, 63, 0, 0, 360, 81, 1, 0, 0, 0, 361, 362, 5,
33, 0, 0, 362, 363, 5, 126, 0, 0, 363, 83, 1, 0, 0, 0, 364, 365, 5, 61,
0, 0, 365, 366, 5, 126, 0, 0, 366, 85, 1, 0, 0, 0, 367, 368, 5, 77, 0,
0, 368, 369, 5, 65, 0, 0, 369, 370, 5, 84, 0, 0, 370, 371, 5, 67, 0, 0,
371, 372, 5, 72, 0, 0, 372, 87, 1, 0, 0, 0, 373, 374, 5, 87, 0, 0, 374,
375, 5, 72, 0, 0, 375, 376, 5, 69, 0, 0, 376, 377, 5, 78, 0, 0, 377, 89,
1, 0, 0, 0, 378, 379, 5, 70, 0, 0, 379, 380, 5, 85, 0, 0, 380, 381, 5,
78, 0, 0, 381, 382, 5, 67, 0, 0, 382, 91, 1, 0, 0, 0, 383, 384, 5, 70,
0, 0, 384, 385, 5, 79, 0, 0, 385, 386, 5, 82, 0, 0, 386, 93, 1, 0, 0, 0,
387, 388, 5, 82, 0, 0, 388, 389, 5, 69, 0, 0, 389, 390, 5, 84, 0, 0, 390,
391, 5, 85, 0, 0, 391, 392, 5, 82, 0, 0, 392, 393, 5, 78, 0, 0, 393, 95,
1, 0, 0, 0, 394, 395, 5, 81, 0, 0, 395, 396, 5, 85, 0, 0, 396, 397, 5,
69, 0, 0, 397, 398, 5, 82, 0, 0, 398, 399, 5, 89, 0, 0, 399, 97, 1, 0,
0, 0, 400, 401, 5, 85, 0, 0, 401, 402, 5, 83, 0, 0, 402, 403, 5, 73, 0,
0, 403, 404, 5, 78, 0, 0, 404, 405, 5, 71, 0, 0, 405, 99, 1, 0, 0, 0, 406,
407, 5, 87, 0, 0, 407, 408, 5, 65, 0, 0, 408, 409, 5, 73, 0, 0, 409, 410,
5, 84, 0, 0, 410, 411, 5, 70, 0, 0, 411, 412, 5, 79, 0, 0, 412, 413, 5,
82, 0, 0, 413, 101, 1, 0, 0, 0, 414, 415, 5, 68, 0, 0, 415, 416, 5, 73,
0, 0, 416, 417, 5, 83, 0, 0, 417, 418, 5, 80, 0, 0, 418, 419, 5, 65, 0,
0, 419, 420, 5, 84, 0, 0, 420, 421, 5, 67, 0, 0, 421, 422, 5, 72, 0, 0,
422, 103, 1, 0, 0, 0, 423, 424, 5, 68, 0, 0, 424, 425, 5, 69, 0, 0, 425,
426, 5, 76, 0, 0, 426, 427, 5, 69, 0, 0, 427, 428, 5, 84, 0, 0, 428, 429,
5, 69, 0, 0, 429, 105, 1, 0, 0, 0, 430, 431, 5, 79, 0, 0, 431, 432, 5,
80, 0, 0, 432, 433, 5, 84, 0, 0, 433, 434, 5, 73, 0, 0, 434, 435, 5, 79,
0, 0, 435, 436, 5, 78, 0, 0, 436, 437, 5, 83, 0, 0, 437, 107, 1, 0, 0,
0, 438, 439, 5, 84, 0, 0, 439, 440, 5, 73, 0, 0, 440, 441, 5, 77, 0, 0,
441, 442, 5, 69, 0, 0, 442, 443, 5, 79, 0, 0, 443, 444, 5, 85, 0, 0, 444,
445, 5, 84, 0, 0, 445, 109, 1, 0, 0, 0, 446, 447, 5, 69, 0, 0, 447, 448,
5, 86, 0, 0, 448, 449, 5, 69, 0, 0, 449, 450, 5, 82, 0, 0, 450, 451, 5,
89, 0, 0, 451, 111, 1, 0, 0, 0, 452, 453, 5, 66, 0, 0, 453, 454, 5, 65,
0, 0, 454, 455, 5, 67, 0, 0, 455, 456, 5, 75, 0, 0, 456, 457, 5, 79, 0,
0, 457, 458, 5, 70, 0, 0, 458, 459, 5, 70, 0, 0, 459, 113, 1, 0, 0, 0,
460, 461, 5, 74, 0, 0, 461, 462, 5, 73, 0, 0, 462, 463, 5, 84, 0, 0, 463,
464, 5, 84, 0, 0, 464, 465, 5, 69, 0, 0, 465, 466, 5, 82, 0, 0, 466, 115,
1, 0, 0, 0, 467, 468, 5, 69, 0, 0, 468, 469, 5, 88, 0, 0, 469, 470, 5,
73, 0, 0, 470, 471, 5, 83, 0, 0, 471, 472, 5, 84, 0, 0, 472, 473, 5, 83,
0, 0, 473, 117, 1, 0, 0, 0, 474, 475, 5, 67, 0, 0, 475, 476, 5, 79, 0,
0, 476, 477, 5, 85, 0, 0, 477, 478, 5, 78, 0, 0, 478, 479, 5, 84, 0, 0,
479, 119, 1, 0, 0, 0, 480, 481, 5, 86, 0, 0, 481, 482, 5, 65, 0, 0, 482,
483, 5, 76, 0, 0, 483, 484, 5, 85, 0, 0, 484, 485, 5, 69, 0, 0, 485, 121,
1, 0, 0, 0, 486, 487, 5, 79, 0, 0, 487, 488, 5, 78, 0, 0, 488, 489, 5,
69, 0, 0, 489, 123, 1, 0, 0, 0, 490, 491, 5, 68, 0, 0, 491, 492, 5, 73,
0, 0, 492, 493, 5, 83, 0, 0, 493, 494, 5, 84, 0, 0, 494, 495, 5, 73, 0,
0, 495, 496, 5, 78, 0, 0, 496, 497, 5, 67, 0, 0, 497, 498, 5, 84, 0, 0,
498, 125, 1, 0, 0, 0, 499, 500, 5, 70, 0, 0, 500, 501, 5, 73, 0, 0, 501,
502, 5, 76, 0, 0, 502, 503, 5, 84, 0, 0, 503, 504, 5, 69, 0, 0, 504, 505,
5, 82, 0, 0, 505, 127, 1, 0, 0, 0, 506, 507, 5, 83, 0, 0, 507, 508, 5,
79, 0, 0, 508, 509, 5, 82, 0, 0, 509, 510, 5, 84, 0, 0, 510, 129, 1, 0,
0, 0, 511, 512, 5, 76, 0, 0, 512, 513, 5, 73, 0, 0, 513, 514, 5, 77, 0,
0, 514, 515, 5, 73, 0, 0, 515, 516, 5, 84, 0, 0, 516, 131, 1, 0, 0, 0,
517, 518, 5, 76, 0, 0, 518, 519, 5, 69, 0, 0, 519, 520, 5, 84, 0, 0, 520,
133, 1, 0, 0, 0, 521, 522, 5, 86, 0, 0, 522, 523, 5, 65, 0, 0, 523, 524,
5, 82, 0, 0, 524, 135, 1, 0, 0, 0, 525, 526, 5, 67, 0, 0, 526, 527, 5,
79, 0, 0, 527, 528, 5, 76, 0, 0, 528, 529, 5, 76, 0, 0, 529, 530, 5, 69,
0, 0, 530, 531, 5, 67, 0, 0, 531, 532, 5, 84, 0, 0, 532, 137, 1, 0, 0,
0, 533, 534, 5, 65, 0, 0, 534, 535, 5, 83, 0, 0, 535, 541, 5, 67, 0, 0,
536, 537, 5, 68, 0, 0, 537, 538, 5, 69, 0, 0, 538, 539, 5, 83, 0, 0, 539,
541, 5, 67, 0, 0, 540, 533, 1, 0, 0, 0, 540, 536, 1, 0, 0, 0, 541, 139,
1, 0, 0, 0, 542, 543, 5, 78, 0, 0, 543, 544, 5, 79, 0, 0, 544, 545, 5,
78, 0, 0, 545, 546, 5, 69, 0, 0, 546, 141, 1, 0, 0, 0, 547, 548, 5, 78,
0, 0, 548, 549, 5, 85, 0, 0, 549, 550, 5, 76, 0, 0, 550, 551, 5, 76, 0,
0, 551, 143, 1, 0, 0, 0, 552, 553, 5, 84, 0, 0, 553, 554, 5, 82, 0, 0,
554, 555, 5, 85, 0, 0, 555, 571, 5, 69, 0, 0, 556, 557, 5, 116, 0, 0, 557,
558, 5, 114, 0, 0, 558, 559, 5, 117, 0, 0, 559, 571, 5, 101, 0, 0, 560,
561, 5, 70, 0, 0, 561, 562, 5, 65, 0, 0, 562, 563, 5, 76, 0, 0, 563, 564,
5, 83, 0, 0, 564, 571, 5, 69, 0, 0, 565, 566, 5, 102, 0, 0, 566, 567, 5,
97, 0, 0, 567, 568, 5, 108, 0, 0, 568, 569, 5, 115, 0, 0, 569, 571, 5,
101, 0, 0, 570, 552, 1, 0, 0, 0, 570, 556, 1, 0, 0, 0, 570, 560, 1, 0,
0, 0, 570, 565, 1, 0, 0, 0, 571, 145, 1, 0, 0, 0, 572, 573, 5, 85, 0, 0,
573, 574, 5, 83, 0, 0, 574, 575, 5, 69, 0, 0, 575, 147, 1, 0, 0, 0, 576,
577, 5, 65, 0, 0, 577, 578, 5, 83, 0, 0, 578, 149, 1, 0, 0, 0, 579, 580,
5, 65, 0, 0, 580, 581, 5, 84, 0, 0, 581, 151, 1, 0, 0, 0, 582, 583, 5,
76, 0, 0, 583, 584, 5, 69, 0, 0, 584, 585, 5, 65, 0, 0, 585, 586, 5, 83,
0, 0, 586, 587, 5, 84, 0, 0, 587, 153, 1, 0, 0, 0, 588, 589, 5, 73, 0,
0, 589, 590, 5, 78, 0, 0, 590, 591, 5, 84, 0, 0, 591, 592, 5, 79, 0, 0,
592, 155, 1, 0, 0, 0, 593, 594, 5, 75, 0, 0, 594, 595, 5, 69, 0, 0, 595,
596, 5, 69, 0, 0, 596, 597, 5, 80, 0, 0, 597, 157, 1, 0, 0, 0, 598, 599,
5, 87, 0, 0, 599, 600, 5, 73, 0, 0, 600, 601, 5, 84, 0, 0, 601, 602, 5,
72, 0, 0, 602, 159, 1, 0, 0, 0, 603, 604, 5, 65, 0, 0, 604, 605, 5, 76,
0, 0, 605, 606, 5, 76, 0, 0, 606, 161, 1, 0, 0, 0, 607, 608, 5, 65, 0,
0, 608, 609, 5, 78, 0, 0, 609, 610, 5, 89, 0, 0, 610, 163, 1, 0, 0, 0,
611, 612, 5, 65, 0, 0, 612, 613, 5, 71, 0, 0, 613, 614, 5, 71, 0, 0, 614,
615, 5, 82, 0, 0, 615, 616, 5, 69, 0, 0, 616, 617, 5, 71, 0, 0, 617, 618,
5, 65, 0, 0, 618, 619, 5, 84, 0, 0, 619, 620, 5, 69, 0, 0, 620, 165, 1,
0, 0, 0, 621, 622, 5, 69, 0, 0, 622, 623, 5, 86, 0, 0, 623, 624, 5, 69,
0, 0, 624, 625, 5, 78, 0, 0, 625, 626, 5, 84, 0, 0, 626, 167, 1, 0, 0,
0, 627, 628, 5, 76, 0, 0, 628, 629, 5, 73, 0, 0, 629, 630, 5, 75, 0, 0,
630, 631, 5, 69, 0, 0, 631, 169, 1, 0, 0, 0, 632, 633, 5, 78, 0, 0, 633,
634, 5, 79, 0, 0, 634, 637, 5, 84, 0, 0, 635, 637, 5, 33, 0, 0, 636, 632,
1, 0, 0, 0, 636, 635, 1, 0, 0, 0, 637, 171, 1, 0, 0, 0, 638, 639, 5, 73,
0, 0, 639, 640, 5, 78, 0, 0, 640, 173, 1, 0, 0, 0, 641, 642, 5, 68, 0,
0, 642, 643, 5, 79, 0, 0, 643, 175, 1, 0, 0, 0, 644, 645, 5, 87, 0, 0,
645, 646, 5, 72, 0, 0, 646, 647, 5, 73, 0, 0, 647, 648, 5, 76, 0, 0, 648,
649, 5, 69, 0, 0, 649, 177, 1, 0, 0, 0, 650, 651, 5, 64, 0, 0, 651, 179,
1, 0, 0, 0, 652, 654, 3, 204, 101, 0, 653, 652, 1, 0, 0, 0, 654, 655, 1,
0, 0, 0, 655, 653, 1, 0, 0, 0, 655, 656, 1, 0, 0, 0, 656, 666, 1, 0, 0,
0, 657, 661, 3, 206, 102, 0, 658, 660, 3, 180, 89, 0, 659, 658, 1, 0, 0,
0, 660, 663, 1, 0, 0, 0, 661, 659, 1, 0, 0, 0, 661, 662, 1, 0, 0, 0, 662,
665, 1, 0, 0, 0, 663, 661, 1, 0, 0, 0, 664, 657, 1, 0, 0, 0, 665, 668,
1, 0, 0, 0, 666, 664, 1, 0, 0, 0, 666, 667, 1, 0, 0, 0, 667, 678, 1, 0,
0, 0, 668, 666, 1, 0, 0, 0, 669, 673, 3, 210, 104, 0, 670, 672, 3, 180,
89, 0, 671, 670, 1, 0, 0, 0, 672, 675, 1, 0, 0, 0, 673, 671, 1, 0, 0, 0,
673, 674, 1, 0, 0, 0, 674, 677, 1, 0, 0, 0, 675, 673, 1, 0, 0, 0, 676,
669, 1, 0, 0, 0, 677, 680, 1, 0, 0, 0, 678, 676, 1, 0, 0, 0, 678, 679,
1, 0, 0, 0, 679, 181, 1, 0, 0, 0, 680, 678, 1, 0, 0, 0, 681, 682, 3, 208,
103, 0, 682, 183, 1, 0, 0, 0, 683, 687, 3, 214, 106, 0, 684, 687, 3, 212,
105, 0, 685, 687, 3, 216, 107, 0, 686, 683, 1, 0, 0, 0, 686, 684, 1, 0,
0, 0, 686, 685, 1, 0, 0, 0, 687, 185, 1, 0, 0, 0, 688, 689, 5, 96, 0, 0,
689, 690, 1, 0, 0, 0, 690, 691, 6, 92, 3, 0, 691, 187, 1, 0, 0, 0, 692,
699, 3, 200, 99, 0, 693, 695, 3, 14, 6, 0, 694, 696, 7, 2, 0, 0, 695, 694,
1, 0, 0, 0, 696, 697, 1, 0, 0, 0, 697, 695, 1, 0, 0, 0, 697, 698, 1, 0,
0, 0, 698, 700, 1, 0, 0, 0, 699, 693, 1, 0, 0, 0, 699, 700, 1, 0, 0, 0,
700, 702, 1, 0, 0, 0, 701, 703, 3, 202, 100, 0, 702, 701, 1, 0, 0, 0, 702,
703, 1, 0, 0, 0, 703, 704, 1, 0, 0, 0, 704, 705, 3, 220, 109, 0, 705, 189,
1, 0, 0, 0, 706, 708, 7, 2, 0, 0, 707, 706, 1, 0, 0, 0, 708, 709, 1, 0,
0, 0, 709, 707, 1, 0, 0, 0, 709, 710, 1, 0, 0, 0, 710, 191, 1, 0, 0, 0,
711, 712, 3, 200, 99, 0, 712, 714, 3, 14, 6, 0, 713, 715, 7, 2, 0, 0, 714,
713, 1, 0, 0, 0, 715, 716, 1, 0, 0, 0, 716, 714, 1, 0, 0, 0, 716, 717,
1, 0, 0, 0, 717, 719, 1, 0, 0, 0, 718, 720, 3, 202, 100, 0, 719, 718, 1,
0, 0, 0, 719, 720, 1, 0, 0, 0, 720, 726, 1, 0, 0, 0, 721, 723, 3, 200,
99, 0, 722, 724, 3, 202, 100, 0, 723, 722, 1, 0, 0, 0, 723, 724, 1, 0,
0, 0, 724, 726, 1, 0, 0, 0, 725, 711, 1, 0, 0, 0, 725, 721, 1, 0, 0, 0,
726, 193, 1, 0, 0, 0, 727, 728, 3, 180, 89, 0, 728, 729, 3, 218, 108, 0,
729, 195, 1, 0, 0, 0, 730, 731, 9, 0, 0, 0, 731, 197, 1, 0, 0, 0, 732,
733, 7, 3, 0, 0, 733, 199, 1, 0, 0, 0, 734, 743, 5, 48, 0, 0, 735, 739,
7, 4, 0, 0, 736, 738, 7, 2, 0, 0, 737, 736, 1, 0, 0, 0, 738, 741, 1, 0,
0, 0, 739, 737, 1, 0, 0, 0, 739, 740, 1, 0, 0, 0, 740, 743, 1, 0, 0, 0,
741, 739, 1, 0, 0, 0, 742, 734, 1, 0, 0, 0, 742, 735, 1, 0, 0, 0, 743,
201, 1, 0, 0, 0, 744, 746, 7, 5, 0, 0, 745, 747, 7, 6, 0, 0, 746, 745,
1, 0, 0, 0, 746, 747, 1, 0, 0, 0, 747, 749, 1, 0, 0, 0, 748, 750, 7, 2,
0, 0, 749, 748, 1, 0, 0, 0, 750, 751, 1, 0, 0, 0, 751, 749, 1, 0, 0, 0,
751, 752, 1, 0, 0, 0, 752, 203, 1, 0, 0, 0, 753, 754, 7, 7, 0, 0, 754,
205, 1, 0, 0, 0, 755, 756, 3, 208, 103, 0, 756, 207, 1, 0, 0, 0, 757, 758,
5, 95, 0, 0, 758, 209, 1, 0, 0, 0, 759, 760, 2, 48, 57, 0, 760, 211, 1,
0, 0, 0, 761, 769, 5, 34, 0, 0, 762, 763, 5, 92, 0, 0, 763, 768, 9, 0,
0, 0, 764, 765, 5, 34, 0, 0, 765, 768, 5, 34, 0, 0, 766, 768, 8, 8, 0,
0, 767, 762, 1, 0, 0, 0, 767, 764, 1, 0, 0, 0, 767, 766, 1, 0, 0, 0, 768,
771, 1, 0, 0, 0, 769, 767, 1, 0, 0, 0, 769, 770, 1, 0, 0, 0, 770, 772,
1, 0, 0, 0, 771, 769, 1, 0, 0, 0, 772, 773, 5, 34, 0, 0, 773, 213, 1, 0,
0, 0, 774, 782, 5, 39, 0, 0, 775, 776, 5, 92, 0, 0, 776, 781, 9, 0, 0,
0, 777, 778, 5, 39, 0, 0, 778, 781, 5, 39, 0, 0, 779, 781, 8, 9, 0, 0,
780, 775, 1, 0, 0, 0, 780, 777, 1, 0, 0, 0, 780, 779, 1, 0, 0, 0, 781,
784, 1, 0, 0, 0, 782, 780, 1, 0, 0, 0, 782, 783, 1, 0, 0, 0, 783, 785,
1, 0, 0, 0, 784, 782, 1, 0, 0, 0, 785, 786, 5, 39, 0, 0, 786, 215, 1, 0,
0, 0, 787, 793, 5, 180, 0, 0, 788, 789, 5, 92, 0, 0, 789, 792, 5, 180,
0, 0, 790, 792, 8, 10, 0, 0, 791, 788, 1, 0, 0, 0, 791, 790, 1, 0, 0, 0,
792, 795, 1, 0, 0, 0, 793, 791, 1, 0, 0, 0, 793, 794, 1, 0, 0, 0, 794,
796, 1, 0, 0, 0, 795, 793, 1, 0, 0, 0, 796, 797, 5, 180, 0, 0, 797, 217,
1, 0, 0, 0, 798, 799, 5, 58, 0, 0, 799, 800, 5, 58, 0, 0, 800, 219, 1,
0, 0, 0, 801, 802, 5, 77, 0, 0, 802, 805, 5, 83, 0, 0, 803, 805, 7, 11,
0, 0, 804, 801, 1, 0, 0, 0, 804, 803, 1, 0, 0, 0, 805, 221, 1, 0, 0, 0,
806, 807, 5, 36, 0, 0, 807, 808, 5, 123, 0, 0, 808, 809, 1, 0, 0, 0, 809,
810, 6, 110, 4, 0, 810, 223, 1, 0, 0, 0, 811, 812, 5, 92, 0, 0, 812, 817,
9, 0, 0, 0, 813, 817, 8, 12, 0, 0, 814, 815, 5, 36, 0, 0, 815, 817, 4,
111, 0, 0, 816, 811, 1, 0, 0, 0, 816, 813, 1, 0, 0, 0, 816, 814, 1, 0,
0, 0, 817, 818, 1, 0, 0, 0, 818, 816, 1, 0, 0, 0, 818, 819, 1, 0, 0, 0,
819, 225, 1, 0, 0, 0, 820, 821, 5, 96, 0, 0, 821, 822, 1, 0, 0, 0, 822,
823, 6, 112, 5, 0, 823, 227, 1, 0, 0, 0, 37, 0, 1, 234, 248, 256, 340,
346, 540, 570, 636, 655, 661, 666, 673, 678, 686, 697, 699, 702, 709, 716,
719, 723, 725, 739, 742, 746, 751, 767, 769, 780, 782, 791, 793, 804, 816,
818, 6, 0, 1, 0, 1, 14, 0, 1, 15, 1, 5, 1, 0, 1, 110, 2, 4, 0, 0,
98, 196, 99, 198, 100, 200, 0, 202, 0, 204, 0, 206, 0, 208, 0, 210, 0,
212, 0, 214, 0, 216, 0, 218, 0, 220, 0, 222, 0, 224, 101, 226, 102, 228,
103, 2, 0, 1, 13, 3, 0, 10, 10, 13, 13, 8232, 8233, 4, 0, 9, 9, 11, 12,
32, 32, 160, 160, 1, 0, 48, 57, 3, 0, 48, 57, 65, 70, 97, 102, 1, 0, 49,
57, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 2, 0, 65, 90, 97, 122,
2, 0, 34, 34, 92, 92, 2, 0, 39, 39, 92, 92, 1, 0, 180, 180, 4, 0, 68, 68,
72, 72, 77, 77, 83, 83, 3, 0, 36, 36, 92, 92, 96, 96, 861, 0, 2, 1, 0,
0, 0, 0, 4, 1, 0, 0, 0, 0, 6, 1, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 10, 1, 0,
0, 0, 0, 12, 1, 0, 0, 0, 0, 14, 1, 0, 0, 0, 0, 16, 1, 0, 0, 0, 0, 18, 1,
0, 0, 0, 0, 20, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 24, 1, 0, 0, 0, 0, 26,
1, 0, 0, 0, 0, 28, 1, 0, 0, 0, 0, 30, 1, 0, 0, 0, 0, 32, 1, 0, 0, 0, 0,
34, 1, 0, 0, 0, 0, 36, 1, 0, 0, 0, 0, 38, 1, 0, 0, 0, 0, 40, 1, 0, 0, 0,
0, 42, 1, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 46, 1, 0, 0, 0, 0, 48, 1, 0, 0,
0, 0, 50, 1, 0, 0, 0, 0, 52, 1, 0, 0, 0, 0, 54, 1, 0, 0, 0, 0, 56, 1, 0,
0, 0, 0, 58, 1, 0, 0, 0, 0, 60, 1, 0, 0, 0, 0, 62, 1, 0, 0, 0, 0, 64, 1,
0, 0, 0, 0, 66, 1, 0, 0, 0, 0, 68, 1, 0, 0, 0, 0, 70, 1, 0, 0, 0, 0, 72,
1, 0, 0, 0, 0, 74, 1, 0, 0, 0, 0, 76, 1, 0, 0, 0, 0, 78, 1, 0, 0, 0, 0,
80, 1, 0, 0, 0, 0, 82, 1, 0, 0, 0, 0, 84, 1, 0, 0, 0, 0, 86, 1, 0, 0, 0,
0, 88, 1, 0, 0, 0, 0, 90, 1, 0, 0, 0, 0, 92, 1, 0, 0, 0, 0, 94, 1, 0, 0,
0, 0, 96, 1, 0, 0, 0, 0, 98, 1, 0, 0, 0, 0, 100, 1, 0, 0, 0, 0, 102, 1,
0, 0, 0, 0, 104, 1, 0, 0, 0, 0, 106, 1, 0, 0, 0, 0, 108, 1, 0, 0, 0, 0,
110, 1, 0, 0, 0, 0, 112, 1, 0, 0, 0, 0, 114, 1, 0, 0, 0, 0, 116, 1, 0,
0, 0, 0, 118, 1, 0, 0, 0, 0, 120, 1, 0, 0, 0, 0, 122, 1, 0, 0, 0, 0, 124,
1, 0, 0, 0, 0, 126, 1, 0, 0, 0, 0, 128, 1, 0, 0, 0, 0, 130, 1, 0, 0, 0,
0, 132, 1, 0, 0, 0, 0, 134, 1, 0, 0, 0, 0, 136, 1, 0, 0, 0, 0, 138, 1,
0, 0, 0, 0, 140, 1, 0, 0, 0, 0, 142, 1, 0, 0, 0, 0, 144, 1, 0, 0, 0, 0,
146, 1, 0, 0, 0, 0, 148, 1, 0, 0, 0, 0, 150, 1, 0, 0, 0, 0, 152, 1, 0,
0, 0, 0, 154, 1, 0, 0, 0, 0, 156, 1, 0, 0, 0, 0, 158, 1, 0, 0, 0, 0, 160,
1, 0, 0, 0, 0, 162, 1, 0, 0, 0, 0, 164, 1, 0, 0, 0, 0, 166, 1, 0, 0, 0,
0, 168, 1, 0, 0, 0, 0, 170, 1, 0, 0, 0, 0, 172, 1, 0, 0, 0, 0, 174, 1,
0, 0, 0, 0, 176, 1, 0, 0, 0, 0, 178, 1, 0, 0, 0, 0, 180, 1, 0, 0, 0, 0,
182, 1, 0, 0, 0, 0, 184, 1, 0, 0, 0, 0, 186, 1, 0, 0, 0, 0, 188, 1, 0,
0, 0, 0, 190, 1, 0, 0, 0, 0, 192, 1, 0, 0, 0, 0, 194, 1, 0, 0, 0, 0, 196,
1, 0, 0, 0, 0, 198, 1, 0, 0, 0, 1, 224, 1, 0, 0, 0, 1, 226, 1, 0, 0, 0,
1, 228, 1, 0, 0, 0, 2, 230, 1, 0, 0, 0, 4, 244, 1, 0, 0, 0, 6, 256, 1,
0, 0, 0, 8, 262, 1, 0, 0, 0, 10, 266, 1, 0, 0, 0, 12, 268, 1, 0, 0, 0,
14, 270, 1, 0, 0, 0, 16, 272, 1, 0, 0, 0, 18, 274, 1, 0, 0, 0, 20, 277,
1, 0, 0, 0, 22, 279, 1, 0, 0, 0, 24, 281, 1, 0, 0, 0, 26, 283, 1, 0, 0,
0, 28, 285, 1, 0, 0, 0, 30, 287, 1, 0, 0, 0, 32, 290, 1, 0, 0, 0, 34, 293,
1, 0, 0, 0, 36, 295, 1, 0, 0, 0, 38, 297, 1, 0, 0, 0, 40, 300, 1, 0, 0,
0, 42, 303, 1, 0, 0, 0, 44, 306, 1, 0, 0, 0, 46, 309, 1, 0, 0, 0, 48, 312,
1, 0, 0, 0, 50, 315, 1, 0, 0, 0, 52, 318, 1, 0, 0, 0, 54, 321, 1, 0, 0,
0, 56, 323, 1, 0, 0, 0, 58, 325, 1, 0, 0, 0, 60, 327, 1, 0, 0, 0, 62, 329,
1, 0, 0, 0, 64, 331, 1, 0, 0, 0, 66, 334, 1, 0, 0, 0, 68, 342, 1, 0, 0,
0, 70, 348, 1, 0, 0, 0, 72, 350, 1, 0, 0, 0, 74, 353, 1, 0, 0, 0, 76, 356,
1, 0, 0, 0, 78, 359, 1, 0, 0, 0, 80, 361, 1, 0, 0, 0, 82, 363, 1, 0, 0,
0, 84, 366, 1, 0, 0, 0, 86, 369, 1, 0, 0, 0, 88, 375, 1, 0, 0, 0, 90, 380,
1, 0, 0, 0, 92, 385, 1, 0, 0, 0, 94, 389, 1, 0, 0, 0, 96, 396, 1, 0, 0,
0, 98, 402, 1, 0, 0, 0, 100, 408, 1, 0, 0, 0, 102, 416, 1, 0, 0, 0, 104,
425, 1, 0, 0, 0, 106, 432, 1, 0, 0, 0, 108, 440, 1, 0, 0, 0, 110, 448,
1, 0, 0, 0, 112, 456, 1, 0, 0, 0, 114, 462, 1, 0, 0, 0, 116, 470, 1, 0,
0, 0, 118, 477, 1, 0, 0, 0, 120, 484, 1, 0, 0, 0, 122, 490, 1, 0, 0, 0,
124, 496, 1, 0, 0, 0, 126, 500, 1, 0, 0, 0, 128, 509, 1, 0, 0, 0, 130,
516, 1, 0, 0, 0, 132, 521, 1, 0, 0, 0, 134, 527, 1, 0, 0, 0, 136, 531,
1, 0, 0, 0, 138, 535, 1, 0, 0, 0, 140, 550, 1, 0, 0, 0, 142, 552, 1, 0,
0, 0, 144, 557, 1, 0, 0, 0, 146, 580, 1, 0, 0, 0, 148, 582, 1, 0, 0, 0,
150, 586, 1, 0, 0, 0, 152, 589, 1, 0, 0, 0, 154, 592, 1, 0, 0, 0, 156,
598, 1, 0, 0, 0, 158, 603, 1, 0, 0, 0, 160, 608, 1, 0, 0, 0, 162, 613,
1, 0, 0, 0, 164, 617, 1, 0, 0, 0, 166, 621, 1, 0, 0, 0, 168, 631, 1, 0,
0, 0, 170, 637, 1, 0, 0, 0, 172, 646, 1, 0, 0, 0, 174, 648, 1, 0, 0, 0,
176, 651, 1, 0, 0, 0, 178, 654, 1, 0, 0, 0, 180, 660, 1, 0, 0, 0, 182,
663, 1, 0, 0, 0, 184, 691, 1, 0, 0, 0, 186, 696, 1, 0, 0, 0, 188, 698,
1, 0, 0, 0, 190, 702, 1, 0, 0, 0, 192, 717, 1, 0, 0, 0, 194, 735, 1, 0,
0, 0, 196, 737, 1, 0, 0, 0, 198, 740, 1, 0, 0, 0, 200, 742, 1, 0, 0, 0,
202, 752, 1, 0, 0, 0, 204, 754, 1, 0, 0, 0, 206, 763, 1, 0, 0, 0, 208,
765, 1, 0, 0, 0, 210, 767, 1, 0, 0, 0, 212, 769, 1, 0, 0, 0, 214, 771,
1, 0, 0, 0, 216, 784, 1, 0, 0, 0, 218, 797, 1, 0, 0, 0, 220, 808, 1, 0,
0, 0, 222, 814, 1, 0, 0, 0, 224, 816, 1, 0, 0, 0, 226, 826, 1, 0, 0, 0,
228, 830, 1, 0, 0, 0, 230, 231, 5, 47, 0, 0, 231, 232, 5, 42, 0, 0, 232,
236, 1, 0, 0, 0, 233, 235, 9, 0, 0, 0, 234, 233, 1, 0, 0, 0, 235, 238,
1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 236, 234, 1, 0, 0, 0, 237, 239, 1, 0,
0, 0, 238, 236, 1, 0, 0, 0, 239, 240, 5, 42, 0, 0, 240, 241, 5, 47, 0,
0, 241, 242, 1, 0, 0, 0, 242, 243, 6, 0, 0, 0, 243, 3, 1, 0, 0, 0, 244,
245, 5, 47, 0, 0, 245, 246, 5, 47, 0, 0, 246, 250, 1, 0, 0, 0, 247, 249,
8, 0, 0, 0, 248, 247, 1, 0, 0, 0, 249, 252, 1, 0, 0, 0, 250, 248, 1, 0,
0, 0, 250, 251, 1, 0, 0, 0, 251, 253, 1, 0, 0, 0, 252, 250, 1, 0, 0, 0,
253, 254, 6, 1, 0, 0, 254, 5, 1, 0, 0, 0, 255, 257, 7, 1, 0, 0, 256, 255,
1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 256, 1, 0, 0, 0, 258, 259, 1, 0,
0, 0, 259, 260, 1, 0, 0, 0, 260, 261, 6, 2, 0, 0, 261, 7, 1, 0, 0, 0, 262,
263, 7, 0, 0, 0, 263, 264, 1, 0, 0, 0, 264, 265, 6, 3, 0, 0, 265, 9, 1,
0, 0, 0, 266, 267, 5, 58, 0, 0, 267, 11, 1, 0, 0, 0, 268, 269, 5, 59, 0,
0, 269, 13, 1, 0, 0, 0, 270, 271, 5, 46, 0, 0, 271, 15, 1, 0, 0, 0, 272,
273, 5, 44, 0, 0, 273, 17, 1, 0, 0, 0, 274, 275, 5, 126, 0, 0, 275, 276,
5, 63, 0, 0, 276, 19, 1, 0, 0, 0, 277, 278, 5, 126, 0, 0, 278, 21, 1, 0,
0, 0, 279, 280, 5, 91, 0, 0, 280, 23, 1, 0, 0, 0, 281, 282, 5, 93, 0, 0,
282, 25, 1, 0, 0, 0, 283, 284, 5, 40, 0, 0, 284, 27, 1, 0, 0, 0, 285, 286,
5, 41, 0, 0, 286, 29, 1, 0, 0, 0, 287, 288, 5, 123, 0, 0, 288, 289, 6,
14, 1, 0, 289, 31, 1, 0, 0, 0, 290, 291, 5, 125, 0, 0, 291, 292, 6, 15,
2, 0, 292, 33, 1, 0, 0, 0, 293, 294, 5, 62, 0, 0, 294, 35, 1, 0, 0, 0,
295, 296, 5, 60, 0, 0, 296, 37, 1, 0, 0, 0, 297, 298, 5, 61, 0, 0, 298,
299, 5, 61, 0, 0, 299, 39, 1, 0, 0, 0, 300, 301, 5, 62, 0, 0, 301, 302,
5, 61, 0, 0, 302, 41, 1, 0, 0, 0, 303, 304, 5, 60, 0, 0, 304, 305, 5, 61,
0, 0, 305, 43, 1, 0, 0, 0, 306, 307, 5, 33, 0, 0, 307, 308, 5, 61, 0, 0,
308, 45, 1, 0, 0, 0, 309, 310, 5, 42, 0, 0, 310, 311, 5, 61, 0, 0, 311,
47, 1, 0, 0, 0, 312, 313, 5, 47, 0, 0, 313, 314, 5, 61, 0, 0, 314, 49,
1, 0, 0, 0, 315, 316, 5, 43, 0, 0, 316, 317, 5, 61, 0, 0, 317, 51, 1, 0,
0, 0, 318, 319, 5, 45, 0, 0, 319, 320, 5, 61, 0, 0, 320, 53, 1, 0, 0, 0,
321, 322, 5, 42, 0, 0, 322, 55, 1, 0, 0, 0, 323, 324, 5, 47, 0, 0, 324,
57, 1, 0, 0, 0, 325, 326, 5, 37, 0, 0, 326, 59, 1, 0, 0, 0, 327, 328, 5,
43, 0, 0, 328, 61, 1, 0, 0, 0, 329, 330, 5, 45, 0, 0, 330, 63, 1, 0, 0,
0, 331, 332, 5, 43, 0, 0, 332, 333, 5, 43, 0, 0, 333, 65, 1, 0, 0, 0, 334,
335, 5, 45, 0, 0, 335, 336, 5, 45, 0, 0, 336, 67, 1, 0, 0, 0, 337, 338,
5, 65, 0, 0, 338, 339, 5, 78, 0, 0, 339, 343, 5, 68, 0, 0, 340, 341, 5,
38, 0, 0, 341, 343, 5, 38, 0, 0, 342, 337, 1, 0, 0, 0, 342, 340, 1, 0,
0, 0, 343, 69, 1, 0, 0, 0, 344, 345, 5, 79, 0, 0, 345, 349, 5, 82, 0, 0,
346, 347, 5, 124, 0, 0, 347, 349, 5, 124, 0, 0, 348, 344, 1, 0, 0, 0, 348,
346, 1, 0, 0, 0, 349, 71, 1, 0, 0, 0, 350, 351, 3, 14, 6, 0, 351, 352,
3, 14, 6, 0, 352, 73, 1, 0, 0, 0, 353, 354, 5, 61, 0, 0, 354, 355, 5, 62,
0, 0, 355, 75, 1, 0, 0, 0, 356, 357, 5, 60, 0, 0, 357, 358, 5, 45, 0, 0,
358, 77, 1, 0, 0, 0, 359, 360, 5, 61, 0, 0, 360, 79, 1, 0, 0, 0, 361, 362,
5, 63, 0, 0, 362, 81, 1, 0, 0, 0, 363, 364, 5, 33, 0, 0, 364, 365, 5, 126,
0, 0, 365, 83, 1, 0, 0, 0, 366, 367, 5, 61, 0, 0, 367, 368, 5, 126, 0,
0, 368, 85, 1, 0, 0, 0, 369, 370, 5, 77, 0, 0, 370, 371, 5, 65, 0, 0, 371,
372, 5, 84, 0, 0, 372, 373, 5, 67, 0, 0, 373, 374, 5, 72, 0, 0, 374, 87,
1, 0, 0, 0, 375, 376, 5, 87, 0, 0, 376, 377, 5, 72, 0, 0, 377, 378, 5,
69, 0, 0, 378, 379, 5, 78, 0, 0, 379, 89, 1, 0, 0, 0, 380, 381, 5, 70,
0, 0, 381, 382, 5, 85, 0, 0, 382, 383, 5, 78, 0, 0, 383, 384, 5, 67, 0,
0, 384, 91, 1, 0, 0, 0, 385, 386, 5, 70, 0, 0, 386, 387, 5, 79, 0, 0, 387,
388, 5, 82, 0, 0, 388, 93, 1, 0, 0, 0, 389, 390, 5, 82, 0, 0, 390, 391,
5, 69, 0, 0, 391, 392, 5, 84, 0, 0, 392, 393, 5, 85, 0, 0, 393, 394, 5,
82, 0, 0, 394, 395, 5, 78, 0, 0, 395, 95, 1, 0, 0, 0, 396, 397, 5, 81,
0, 0, 397, 398, 5, 85, 0, 0, 398, 399, 5, 69, 0, 0, 399, 400, 5, 82, 0,
0, 400, 401, 5, 89, 0, 0, 401, 97, 1, 0, 0, 0, 402, 403, 5, 85, 0, 0, 403,
404, 5, 83, 0, 0, 404, 405, 5, 73, 0, 0, 405, 406, 5, 78, 0, 0, 406, 407,
5, 71, 0, 0, 407, 99, 1, 0, 0, 0, 408, 409, 5, 87, 0, 0, 409, 410, 5, 65,
0, 0, 410, 411, 5, 73, 0, 0, 411, 412, 5, 84, 0, 0, 412, 413, 5, 70, 0,
0, 413, 414, 5, 79, 0, 0, 414, 415, 5, 82, 0, 0, 415, 101, 1, 0, 0, 0,
416, 417, 5, 68, 0, 0, 417, 418, 5, 73, 0, 0, 418, 419, 5, 83, 0, 0, 419,
420, 5, 80, 0, 0, 420, 421, 5, 65, 0, 0, 421, 422, 5, 84, 0, 0, 422, 423,
5, 67, 0, 0, 423, 424, 5, 72, 0, 0, 424, 103, 1, 0, 0, 0, 425, 426, 5,
68, 0, 0, 426, 427, 5, 69, 0, 0, 427, 428, 5, 76, 0, 0, 428, 429, 5, 69,
0, 0, 429, 430, 5, 84, 0, 0, 430, 431, 5, 69, 0, 0, 431, 105, 1, 0, 0,
0, 432, 433, 5, 79, 0, 0, 433, 434, 5, 80, 0, 0, 434, 435, 5, 84, 0, 0,
435, 436, 5, 73, 0, 0, 436, 437, 5, 79, 0, 0, 437, 438, 5, 78, 0, 0, 438,
439, 5, 83, 0, 0, 439, 107, 1, 0, 0, 0, 440, 441, 5, 84, 0, 0, 441, 442,
5, 82, 0, 0, 442, 443, 5, 73, 0, 0, 443, 444, 5, 71, 0, 0, 444, 445, 5,
71, 0, 0, 445, 446, 5, 69, 0, 0, 446, 447, 5, 82, 0, 0, 447, 109, 1, 0,
0, 0, 448, 449, 5, 84, 0, 0, 449, 450, 5, 73, 0, 0, 450, 451, 5, 77, 0,
0, 451, 452, 5, 69, 0, 0, 452, 453, 5, 79, 0, 0, 453, 454, 5, 85, 0, 0,
454, 455, 5, 84, 0, 0, 455, 111, 1, 0, 0, 0, 456, 457, 5, 69, 0, 0, 457,
458, 5, 86, 0, 0, 458, 459, 5, 69, 0, 0, 459, 460, 5, 82, 0, 0, 460, 461,
5, 89, 0, 0, 461, 113, 1, 0, 0, 0, 462, 463, 5, 66, 0, 0, 463, 464, 5,
65, 0, 0, 464, 465, 5, 67, 0, 0, 465, 466, 5, 75, 0, 0, 466, 467, 5, 79,
0, 0, 467, 468, 5, 70, 0, 0, 468, 469, 5, 70, 0, 0, 469, 115, 1, 0, 0,
0, 470, 471, 5, 74, 0, 0, 471, 472, 5, 73, 0, 0, 472, 473, 5, 84, 0, 0,
473, 474, 5, 84, 0, 0, 474, 475, 5, 69, 0, 0, 475, 476, 5, 82, 0, 0, 476,
117, 1, 0, 0, 0, 477, 478, 5, 69, 0, 0, 478, 479, 5, 88, 0, 0, 479, 480,
5, 73, 0, 0, 480, 481, 5, 83, 0, 0, 481, 482, 5, 84, 0, 0, 482, 483, 5,
83, 0, 0, 483, 119, 1, 0, 0, 0, 484, 485, 5, 67, 0, 0, 485, 486, 5, 79,
0, 0, 486, 487, 5, 85, 0, 0, 487, 488, 5, 78, 0, 0, 488, 489, 5, 84, 0,
0, 489, 121, 1, 0, 0, 0, 490, 491, 5, 86, 0, 0, 491, 492, 5, 65, 0, 0,
492, 493, 5, 76, 0, 0, 493, 494, 5, 85, 0, 0, 494, 495, 5, 69, 0, 0, 495,
123, 1, 0, 0, 0, 496, 497, 5, 79, 0, 0, 497, 498, 5, 78, 0, 0, 498, 499,
5, 69, 0, 0, 499, 125, 1, 0, 0, 0, 500, 501, 5, 68, 0, 0, 501, 502, 5,
73, 0, 0, 502, 503, 5, 83, 0, 0, 503, 504, 5, 84, 0, 0, 504, 505, 5, 73,
0, 0, 505, 506, 5, 78, 0, 0, 506, 507, 5, 67, 0, 0, 507, 508, 5, 84, 0,
0, 508, 127, 1, 0, 0, 0, 509, 510, 5, 70, 0, 0, 510, 511, 5, 73, 0, 0,
511, 512, 5, 76, 0, 0, 512, 513, 5, 84, 0, 0, 513, 514, 5, 69, 0, 0, 514,
515, 5, 82, 0, 0, 515, 129, 1, 0, 0, 0, 516, 517, 5, 83, 0, 0, 517, 518,
5, 79, 0, 0, 518, 519, 5, 82, 0, 0, 519, 520, 5, 84, 0, 0, 520, 131, 1,
0, 0, 0, 521, 522, 5, 76, 0, 0, 522, 523, 5, 73, 0, 0, 523, 524, 5, 77,
0, 0, 524, 525, 5, 73, 0, 0, 525, 526, 5, 84, 0, 0, 526, 133, 1, 0, 0,
0, 527, 528, 5, 76, 0, 0, 528, 529, 5, 69, 0, 0, 529, 530, 5, 84, 0, 0,
530, 135, 1, 0, 0, 0, 531, 532, 5, 86, 0, 0, 532, 533, 5, 65, 0, 0, 533,
534, 5, 82, 0, 0, 534, 137, 1, 0, 0, 0, 535, 536, 5, 67, 0, 0, 536, 537,
5, 79, 0, 0, 537, 538, 5, 76, 0, 0, 538, 539, 5, 76, 0, 0, 539, 540, 5,
69, 0, 0, 540, 541, 5, 67, 0, 0, 541, 542, 5, 84, 0, 0, 542, 139, 1, 0,
0, 0, 543, 544, 5, 65, 0, 0, 544, 545, 5, 83, 0, 0, 545, 551, 5, 67, 0,
0, 546, 547, 5, 68, 0, 0, 547, 548, 5, 69, 0, 0, 548, 549, 5, 83, 0, 0,
549, 551, 5, 67, 0, 0, 550, 543, 1, 0, 0, 0, 550, 546, 1, 0, 0, 0, 551,
141, 1, 0, 0, 0, 552, 553, 5, 78, 0, 0, 553, 554, 5, 79, 0, 0, 554, 555,
5, 78, 0, 0, 555, 556, 5, 69, 0, 0, 556, 143, 1, 0, 0, 0, 557, 558, 5,
78, 0, 0, 558, 559, 5, 85, 0, 0, 559, 560, 5, 76, 0, 0, 560, 561, 5, 76,
0, 0, 561, 145, 1, 0, 0, 0, 562, 563, 5, 84, 0, 0, 563, 564, 5, 82, 0,
0, 564, 565, 5, 85, 0, 0, 565, 581, 5, 69, 0, 0, 566, 567, 5, 116, 0, 0,
567, 568, 5, 114, 0, 0, 568, 569, 5, 117, 0, 0, 569, 581, 5, 101, 0, 0,
570, 571, 5, 70, 0, 0, 571, 572, 5, 65, 0, 0, 572, 573, 5, 76, 0, 0, 573,
574, 5, 83, 0, 0, 574, 581, 5, 69, 0, 0, 575, 576, 5, 102, 0, 0, 576, 577,
5, 97, 0, 0, 577, 578, 5, 108, 0, 0, 578, 579, 5, 115, 0, 0, 579, 581,
5, 101, 0, 0, 580, 562, 1, 0, 0, 0, 580, 566, 1, 0, 0, 0, 580, 570, 1,
0, 0, 0, 580, 575, 1, 0, 0, 0, 581, 147, 1, 0, 0, 0, 582, 583, 5, 85, 0,
0, 583, 584, 5, 83, 0, 0, 584, 585, 5, 69, 0, 0, 585, 149, 1, 0, 0, 0,
586, 587, 5, 65, 0, 0, 587, 588, 5, 83, 0, 0, 588, 151, 1, 0, 0, 0, 589,
590, 5, 65, 0, 0, 590, 591, 5, 84, 0, 0, 591, 153, 1, 0, 0, 0, 592, 593,
5, 76, 0, 0, 593, 594, 5, 69, 0, 0, 594, 595, 5, 65, 0, 0, 595, 596, 5,
83, 0, 0, 596, 597, 5, 84, 0, 0, 597, 155, 1, 0, 0, 0, 598, 599, 5, 73,
0, 0, 599, 600, 5, 78, 0, 0, 600, 601, 5, 84, 0, 0, 601, 602, 5, 79, 0,
0, 602, 157, 1, 0, 0, 0, 603, 604, 5, 75, 0, 0, 604, 605, 5, 69, 0, 0,
605, 606, 5, 69, 0, 0, 606, 607, 5, 80, 0, 0, 607, 159, 1, 0, 0, 0, 608,
609, 5, 87, 0, 0, 609, 610, 5, 73, 0, 0, 610, 611, 5, 84, 0, 0, 611, 612,
5, 72, 0, 0, 612, 161, 1, 0, 0, 0, 613, 614, 5, 65, 0, 0, 614, 615, 5,
76, 0, 0, 615, 616, 5, 76, 0, 0, 616, 163, 1, 0, 0, 0, 617, 618, 5, 65,
0, 0, 618, 619, 5, 78, 0, 0, 619, 620, 5, 89, 0, 0, 620, 165, 1, 0, 0,
0, 621, 622, 5, 65, 0, 0, 622, 623, 5, 71, 0, 0, 623, 624, 5, 71, 0, 0,
624, 625, 5, 82, 0, 0, 625, 626, 5, 69, 0, 0, 626, 627, 5, 71, 0, 0, 627,
628, 5, 65, 0, 0, 628, 629, 5, 84, 0, 0, 629, 630, 5, 69, 0, 0, 630, 167,
1, 0, 0, 0, 631, 632, 5, 69, 0, 0, 632, 633, 5, 86, 0, 0, 633, 634, 5,
69, 0, 0, 634, 635, 5, 78, 0, 0, 635, 636, 5, 84, 0, 0, 636, 169, 1, 0,
0, 0, 637, 638, 5, 76, 0, 0, 638, 639, 5, 73, 0, 0, 639, 640, 5, 75, 0,
0, 640, 641, 5, 69, 0, 0, 641, 171, 1, 0, 0, 0, 642, 643, 5, 78, 0, 0,
643, 644, 5, 79, 0, 0, 644, 647, 5, 84, 0, 0, 645, 647, 5, 33, 0, 0, 646,
642, 1, 0, 0, 0, 646, 645, 1, 0, 0, 0, 647, 173, 1, 0, 0, 0, 648, 649,
5, 73, 0, 0, 649, 650, 5, 78, 0, 0, 650, 175, 1, 0, 0, 0, 651, 652, 5,
68, 0, 0, 652, 653, 5, 79, 0, 0, 653, 177, 1, 0, 0, 0, 654, 655, 5, 87,
0, 0, 655, 656, 5, 72, 0, 0, 656, 657, 5, 73, 0, 0, 657, 658, 5, 76, 0,
0, 658, 659, 5, 69, 0, 0, 659, 179, 1, 0, 0, 0, 660, 661, 5, 64, 0, 0,
661, 181, 1, 0, 0, 0, 662, 664, 3, 206, 102, 0, 663, 662, 1, 0, 0, 0, 664,
665, 1, 0, 0, 0, 665, 663, 1, 0, 0, 0, 665, 666, 1, 0, 0, 0, 666, 676,
1, 0, 0, 0, 667, 671, 3, 208, 103, 0, 668, 670, 3, 182, 90, 0, 669, 668,
1, 0, 0, 0, 670, 673, 1, 0, 0, 0, 671, 669, 1, 0, 0, 0, 671, 672, 1, 0,
0, 0, 672, 675, 1, 0, 0, 0, 673, 671, 1, 0, 0, 0, 674, 667, 1, 0, 0, 0,
675, 678, 1, 0, 0, 0, 676, 674, 1, 0, 0, 0, 676, 677, 1, 0, 0, 0, 677,
688, 1, 0, 0, 0, 678, 676, 1, 0, 0, 0, 679, 683, 3, 212, 105, 0, 680, 682,
3, 182, 90, 0, 681, 680, 1, 0, 0, 0, 682, 685, 1, 0, 0, 0, 683, 681, 1,
0, 0, 0, 683, 684, 1, 0, 0, 0, 684, 687, 1, 0, 0, 0, 685, 683, 1, 0, 0,
0, 686, 679, 1, 0, 0, 0, 687, 690, 1, 0, 0, 0, 688, 686, 1, 0, 0, 0, 688,
689, 1, 0, 0, 0, 689, 183, 1, 0, 0, 0, 690, 688, 1, 0, 0, 0, 691, 692,
3, 210, 104, 0, 692, 185, 1, 0, 0, 0, 693, 697, 3, 216, 107, 0, 694, 697,
3, 214, 106, 0, 695, 697, 3, 218, 108, 0, 696, 693, 1, 0, 0, 0, 696, 694,
1, 0, 0, 0, 696, 695, 1, 0, 0, 0, 697, 187, 1, 0, 0, 0, 698, 699, 5, 96,
0, 0, 699, 700, 1, 0, 0, 0, 700, 701, 6, 93, 3, 0, 701, 189, 1, 0, 0, 0,
702, 709, 3, 202, 100, 0, 703, 705, 3, 14, 6, 0, 704, 706, 7, 2, 0, 0,
705, 704, 1, 0, 0, 0, 706, 707, 1, 0, 0, 0, 707, 705, 1, 0, 0, 0, 707,
708, 1, 0, 0, 0, 708, 710, 1, 0, 0, 0, 709, 703, 1, 0, 0, 0, 709, 710,
1, 0, 0, 0, 710, 712, 1, 0, 0, 0, 711, 713, 3, 204, 101, 0, 712, 711, 1,
0, 0, 0, 712, 713, 1, 0, 0, 0, 713, 714, 1, 0, 0, 0, 714, 715, 3, 222,
110, 0, 715, 191, 1, 0, 0, 0, 716, 718, 7, 2, 0, 0, 717, 716, 1, 0, 0,
0, 718, 719, 1, 0, 0, 0, 719, 717, 1, 0, 0, 0, 719, 720, 1, 0, 0, 0, 720,
193, 1, 0, 0, 0, 721, 722, 3, 202, 100, 0, 722, 724, 3, 14, 6, 0, 723,
725, 7, 2, 0, 0, 724, 723, 1, 0, 0, 0, 725, 726, 1, 0, 0, 0, 726, 724,
1, 0, 0, 0, 726, 727, 1, 0, 0, 0, 727, 729, 1, 0, 0, 0, 728, 730, 3, 204,
101, 0, 729, 728, 1, 0, 0, 0, 729, 730, 1, 0, 0, 0, 730, 736, 1, 0, 0,
0, 731, 733, 3, 202, 100, 0, 732, 734, 3, 204, 101, 0, 733, 732, 1, 0,
0, 0, 733, 734, 1, 0, 0, 0, 734, 736, 1, 0, 0, 0, 735, 721, 1, 0, 0, 0,
735, 731, 1, 0, 0, 0, 736, 195, 1, 0, 0, 0, 737, 738, 3, 182, 90, 0, 738,
739, 3, 220, 109, 0, 739, 197, 1, 0, 0, 0, 740, 741, 9, 0, 0, 0, 741, 199,
1, 0, 0, 0, 742, 743, 7, 3, 0, 0, 743, 201, 1, 0, 0, 0, 744, 753, 5, 48,
0, 0, 745, 749, 7, 4, 0, 0, 746, 748, 7, 2, 0, 0, 747, 746, 1, 0, 0, 0,
748, 751, 1, 0, 0, 0, 749, 747, 1, 0, 0, 0, 749, 750, 1, 0, 0, 0, 750,
753, 1, 0, 0, 0, 751, 749, 1, 0, 0, 0, 752, 744, 1, 0, 0, 0, 752, 745,
1, 0, 0, 0, 753, 203, 1, 0, 0, 0, 754, 756, 7, 5, 0, 0, 755, 757, 7, 6,
0, 0, 756, 755, 1, 0, 0, 0, 756, 757, 1, 0, 0, 0, 757, 759, 1, 0, 0, 0,
758, 760, 7, 2, 0, 0, 759, 758, 1, 0, 0, 0, 760, 761, 1, 0, 0, 0, 761,
759, 1, 0, 0, 0, 761, 762, 1, 0, 0, 0, 762, 205, 1, 0, 0, 0, 763, 764,
7, 7, 0, 0, 764, 207, 1, 0, 0, 0, 765, 766, 3, 210, 104, 0, 766, 209, 1,
0, 0, 0, 767, 768, 5, 95, 0, 0, 768, 211, 1, 0, 0, 0, 769, 770, 2, 48,
57, 0, 770, 213, 1, 0, 0, 0, 771, 779, 5, 34, 0, 0, 772, 773, 5, 92, 0,
0, 773, 778, 9, 0, 0, 0, 774, 775, 5, 34, 0, 0, 775, 778, 5, 34, 0, 0,
776, 778, 8, 8, 0, 0, 777, 772, 1, 0, 0, 0, 777, 774, 1, 0, 0, 0, 777,
776, 1, 0, 0, 0, 778, 781, 1, 0, 0, 0, 779, 777, 1, 0, 0, 0, 779, 780,
1, 0, 0, 0, 780, 782, 1, 0, 0, 0, 781, 779, 1, 0, 0, 0, 782, 783, 5, 34,
0, 0, 783, 215, 1, 0, 0, 0, 784, 792, 5, 39, 0, 0, 785, 786, 5, 92, 0,
0, 786, 791, 9, 0, 0, 0, 787, 788, 5, 39, 0, 0, 788, 791, 5, 39, 0, 0,
789, 791, 8, 9, 0, 0, 790, 785, 1, 0, 0, 0, 790, 787, 1, 0, 0, 0, 790,
789, 1, 0, 0, 0, 791, 794, 1, 0, 0, 0, 792, 790, 1, 0, 0, 0, 792, 793,
1, 0, 0, 0, 793, 795, 1, 0, 0, 0, 794, 792, 1, 0, 0, 0, 795, 796, 5, 39,
0, 0, 796, 217, 1, 0, 0, 0, 797, 803, 5, 180, 0, 0, 798, 799, 5, 92, 0,
0, 799, 802, 5, 180, 0, 0, 800, 802, 8, 10, 0, 0, 801, 798, 1, 0, 0, 0,
801, 800, 1, 0, 0, 0, 802, 805, 1, 0, 0, 0, 803, 801, 1, 0, 0, 0, 803,
804, 1, 0, 0, 0, 804, 806, 1, 0, 0, 0, 805, 803, 1, 0, 0, 0, 806, 807,
5, 180, 0, 0, 807, 219, 1, 0, 0, 0, 808, 809, 5, 58, 0, 0, 809, 810, 5,
58, 0, 0, 810, 221, 1, 0, 0, 0, 811, 812, 5, 77, 0, 0, 812, 815, 5, 83,
0, 0, 813, 815, 7, 11, 0, 0, 814, 811, 1, 0, 0, 0, 814, 813, 1, 0, 0, 0,
815, 223, 1, 0, 0, 0, 816, 817, 5, 36, 0, 0, 817, 818, 5, 123, 0, 0, 818,
819, 1, 0, 0, 0, 819, 820, 6, 111, 4, 0, 820, 225, 1, 0, 0, 0, 821, 822,
5, 92, 0, 0, 822, 827, 9, 0, 0, 0, 823, 827, 8, 12, 0, 0, 824, 825, 5,
36, 0, 0, 825, 827, 4, 112, 0, 0, 826, 821, 1, 0, 0, 0, 826, 823, 1, 0,
0, 0, 826, 824, 1, 0, 0, 0, 827, 828, 1, 0, 0, 0, 828, 826, 1, 0, 0, 0,
828, 829, 1, 0, 0, 0, 829, 227, 1, 0, 0, 0, 830, 831, 5, 96, 0, 0, 831,
832, 1, 0, 0, 0, 832, 833, 6, 113, 5, 0, 833, 229, 1, 0, 0, 0, 37, 0, 1,
236, 250, 258, 342, 348, 550, 580, 646, 665, 671, 676, 683, 688, 696, 707,
709, 712, 719, 726, 729, 733, 735, 749, 752, 756, 761, 777, 779, 790, 792,
801, 803, 814, 826, 828, 6, 0, 1, 0, 1, 14, 0, 1, 15, 1, 5, 1, 0, 1, 111,
2, 4, 0, 0,
}
deserializer := antlr.NewATNDeserializer(nil)
staticData.atn = deserializer.Deserialize(staticData.serializedATN)
@@ -557,54 +562,55 @@ const (
FqlLexerDispatch = 52
FqlLexerDelete = 53
FqlLexerOptions = 54
FqlLexerTimeout = 55
FqlLexerEvery = 56
FqlLexerBackoff = 57
FqlLexerJitter = 58
FqlLexerExists = 59
FqlLexerCount = 60
FqlLexerValue = 61
FqlLexerOne = 62
FqlLexerDistinct = 63
FqlLexerFilter = 64
FqlLexerSort = 65
FqlLexerLimit = 66
FqlLexerLet = 67
FqlLexerVar = 68
FqlLexerCollect = 69
FqlLexerSortDirection = 70
FqlLexerNone = 71
FqlLexerNull = 72
FqlLexerBooleanLiteral = 73
FqlLexerUse = 74
FqlLexerAs = 75
FqlLexerAt = 76
FqlLexerLeast = 77
FqlLexerInto = 78
FqlLexerKeep = 79
FqlLexerWith = 80
FqlLexerAll = 81
FqlLexerAny = 82
FqlLexerAggregate = 83
FqlLexerEvent = 84
FqlLexerLike = 85
FqlLexerNot = 86
FqlLexerIn = 87
FqlLexerDo = 88
FqlLexerWhile = 89
FqlLexerParam = 90
FqlLexerIdentifier = 91
FqlLexerIgnoreIdentifier = 92
FqlLexerStringLiteral = 93
FqlLexerBacktickOpen = 94
FqlLexerDurationLiteral = 95
FqlLexerIntegerLiteral = 96
FqlLexerFloatLiteral = 97
FqlLexerNamespaceSegment = 98
FqlLexerUnknownIdentifier = 99
FqlLexerTemplateExprStart = 100
FqlLexerTemplateChars = 101
FqlLexerBacktickClose = 102
FqlLexerTrigger = 55
FqlLexerTimeout = 56
FqlLexerEvery = 57
FqlLexerBackoff = 58
FqlLexerJitter = 59
FqlLexerExists = 60
FqlLexerCount = 61
FqlLexerValue = 62
FqlLexerOne = 63
FqlLexerDistinct = 64
FqlLexerFilter = 65
FqlLexerSort = 66
FqlLexerLimit = 67
FqlLexerLet = 68
FqlLexerVar = 69
FqlLexerCollect = 70
FqlLexerSortDirection = 71
FqlLexerNone = 72
FqlLexerNull = 73
FqlLexerBooleanLiteral = 74
FqlLexerUse = 75
FqlLexerAs = 76
FqlLexerAt = 77
FqlLexerLeast = 78
FqlLexerInto = 79
FqlLexerKeep = 80
FqlLexerWith = 81
FqlLexerAll = 82
FqlLexerAny = 83
FqlLexerAggregate = 84
FqlLexerEvent = 85
FqlLexerLike = 86
FqlLexerNot = 87
FqlLexerIn = 88
FqlLexerDo = 89
FqlLexerWhile = 90
FqlLexerParam = 91
FqlLexerIdentifier = 92
FqlLexerIgnoreIdentifier = 93
FqlLexerStringLiteral = 94
FqlLexerBacktickOpen = 95
FqlLexerDurationLiteral = 96
FqlLexerIntegerLiteral = 97
FqlLexerFloatLiteral = 98
FqlLexerNamespaceSegment = 99
FqlLexerUnknownIdentifier = 100
FqlLexerTemplateExprStart = 101
FqlLexerTemplateChars = 102
FqlLexerBacktickClose = 103
)
// FqlLexerTEMPLATE is the FqlLexer mode.
@@ -618,7 +624,7 @@ func (l *FqlLexer) Action(localctx antlr.RuleContext, ruleIndex, actionIndex int
case 15:
l.CloseBrace_Action(localctx, actionIndex)
case 110:
case 111:
l.TemplateExprStart_Action(localctx, actionIndex)
default:
@@ -668,7 +674,7 @@ func (l *FqlLexer) TemplateExprStart_Action(localctx antlr.RuleContext, actionIn
func (l *FqlLexer) Sempred(localctx antlr.RuleContext, ruleIndex, predIndex int) bool {
switch ruleIndex {
case 111:
case 112:
return l.TemplateChars_Sempred(localctx, predIndex)
default:
+3515 -2154
View File
File diff suppressed because it is too large Load Diff
+42
View File
@@ -342,6 +342,40 @@ func (s *BaseFqlParserListener) EnterWaitForEventExpression(ctx *WaitForEventExp
// ExitWaitForEventExpression is called when production waitForEventExpression is exited.
func (s *BaseFqlParserListener) ExitWaitForEventExpression(ctx *WaitForEventExpressionContext) {}
// EnterWaitForEventTail is called when production waitForEventTail is entered.
func (s *BaseFqlParserListener) EnterWaitForEventTail(ctx *WaitForEventTailContext) {}
// ExitWaitForEventTail is called when production waitForEventTail is exited.
func (s *BaseFqlParserListener) ExitWaitForEventTail(ctx *WaitForEventTailContext) {}
// EnterWaitForTriggerClause is called when production waitForTriggerClause is entered.
func (s *BaseFqlParserListener) EnterWaitForTriggerClause(ctx *WaitForTriggerClauseContext) {}
// ExitWaitForTriggerClause is called when production waitForTriggerClause is exited.
func (s *BaseFqlParserListener) ExitWaitForTriggerClause(ctx *WaitForTriggerClauseContext) {}
// EnterWaitForTriggerStatement is called when production waitForTriggerStatement is entered.
func (s *BaseFqlParserListener) EnterWaitForTriggerStatement(ctx *WaitForTriggerStatementContext) {}
// ExitWaitForTriggerStatement is called when production waitForTriggerStatement is exited.
func (s *BaseFqlParserListener) ExitWaitForTriggerStatement(ctx *WaitForTriggerStatementContext) {}
// EnterWaitForTriggerInlineStatement is called when production waitForTriggerInlineStatement is entered.
func (s *BaseFqlParserListener) EnterWaitForTriggerInlineStatement(ctx *WaitForTriggerInlineStatementContext) {
}
// ExitWaitForTriggerInlineStatement is called when production waitForTriggerInlineStatement is exited.
func (s *BaseFqlParserListener) ExitWaitForTriggerInlineStatement(ctx *WaitForTriggerInlineStatementContext) {
}
// EnterWaitForTriggerInlineDispatchStatement is called when production waitForTriggerInlineDispatchStatement is entered.
func (s *BaseFqlParserListener) EnterWaitForTriggerInlineDispatchStatement(ctx *WaitForTriggerInlineDispatchStatementContext) {
}
// ExitWaitForTriggerInlineDispatchStatement is called when production waitForTriggerInlineDispatchStatement is exited.
func (s *BaseFqlParserListener) ExitWaitForTriggerInlineDispatchStatement(ctx *WaitForTriggerInlineDispatchStatementContext) {
}
// EnterWaitForPredicateExpression is called when production waitForPredicateExpression is entered.
func (s *BaseFqlParserListener) EnterWaitForPredicateExpression(ctx *WaitForPredicateExpressionContext) {
}
@@ -664,6 +698,14 @@ func (s *BaseFqlParserListener) EnterFunctionCallExpression(ctx *FunctionCallExp
// ExitFunctionCallExpression is called when production functionCallExpression is exited.
func (s *BaseFqlParserListener) ExitFunctionCallExpression(ctx *FunctionCallExpressionContext) {}
// EnterFunctionCallNoRecoveryExpression is called when production functionCallNoRecoveryExpression is entered.
func (s *BaseFqlParserListener) EnterFunctionCallNoRecoveryExpression(ctx *FunctionCallNoRecoveryExpressionContext) {
}
// ExitFunctionCallNoRecoveryExpression is called when production functionCallNoRecoveryExpression is exited.
func (s *BaseFqlParserListener) ExitFunctionCallNoRecoveryExpression(ctx *FunctionCallNoRecoveryExpressionContext) {
}
// EnterFunctionCall is called when production functionCall is entered.
func (s *BaseFqlParserListener) EnterFunctionCall(ctx *FunctionCallContext) {}
+24
View File
@@ -219,6 +219,26 @@ func (v *BaseFqlParserVisitor) VisitWaitForEventExpression(ctx *WaitForEventExpr
return v.VisitChildren(ctx)
}
func (v *BaseFqlParserVisitor) VisitWaitForEventTail(ctx *WaitForEventTailContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BaseFqlParserVisitor) VisitWaitForTriggerClause(ctx *WaitForTriggerClauseContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BaseFqlParserVisitor) VisitWaitForTriggerStatement(ctx *WaitForTriggerStatementContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BaseFqlParserVisitor) VisitWaitForTriggerInlineStatement(ctx *WaitForTriggerInlineStatementContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BaseFqlParserVisitor) VisitWaitForTriggerInlineDispatchStatement(ctx *WaitForTriggerInlineDispatchStatementContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BaseFqlParserVisitor) VisitWaitForPredicateExpression(ctx *WaitForPredicateExpressionContext) interface{} {
return v.VisitChildren(ctx)
}
@@ -431,6 +451,10 @@ func (v *BaseFqlParserVisitor) VisitFunctionCallExpression(ctx *FunctionCallExpr
return v.VisitChildren(ctx)
}
func (v *BaseFqlParserVisitor) VisitFunctionCallNoRecoveryExpression(ctx *FunctionCallNoRecoveryExpressionContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BaseFqlParserVisitor) VisitFunctionCall(ctx *FunctionCallContext) interface{} {
return v.VisitChildren(ctx)
}
+36
View File
@@ -166,6 +166,21 @@ type FqlParserListener interface {
// EnterWaitForEventExpression is called when entering the waitForEventExpression production.
EnterWaitForEventExpression(c *WaitForEventExpressionContext)
// EnterWaitForEventTail is called when entering the waitForEventTail production.
EnterWaitForEventTail(c *WaitForEventTailContext)
// EnterWaitForTriggerClause is called when entering the waitForTriggerClause production.
EnterWaitForTriggerClause(c *WaitForTriggerClauseContext)
// EnterWaitForTriggerStatement is called when entering the waitForTriggerStatement production.
EnterWaitForTriggerStatement(c *WaitForTriggerStatementContext)
// EnterWaitForTriggerInlineStatement is called when entering the waitForTriggerInlineStatement production.
EnterWaitForTriggerInlineStatement(c *WaitForTriggerInlineStatementContext)
// EnterWaitForTriggerInlineDispatchStatement is called when entering the waitForTriggerInlineDispatchStatement production.
EnterWaitForTriggerInlineDispatchStatement(c *WaitForTriggerInlineDispatchStatementContext)
// EnterWaitForPredicateExpression is called when entering the waitForPredicateExpression production.
EnterWaitForPredicateExpression(c *WaitForPredicateExpressionContext)
@@ -325,6 +340,9 @@ type FqlParserListener interface {
// EnterFunctionCallExpression is called when entering the functionCallExpression production.
EnterFunctionCallExpression(c *FunctionCallExpressionContext)
// EnterFunctionCallNoRecoveryExpression is called when entering the functionCallNoRecoveryExpression production.
EnterFunctionCallNoRecoveryExpression(c *FunctionCallNoRecoveryExpressionContext)
// EnterFunctionCall is called when entering the functionCall production.
EnterFunctionCall(c *FunctionCallContext)
@@ -652,6 +670,21 @@ type FqlParserListener interface {
// ExitWaitForEventExpression is called when exiting the waitForEventExpression production.
ExitWaitForEventExpression(c *WaitForEventExpressionContext)
// ExitWaitForEventTail is called when exiting the waitForEventTail production.
ExitWaitForEventTail(c *WaitForEventTailContext)
// ExitWaitForTriggerClause is called when exiting the waitForTriggerClause production.
ExitWaitForTriggerClause(c *WaitForTriggerClauseContext)
// ExitWaitForTriggerStatement is called when exiting the waitForTriggerStatement production.
ExitWaitForTriggerStatement(c *WaitForTriggerStatementContext)
// ExitWaitForTriggerInlineStatement is called when exiting the waitForTriggerInlineStatement production.
ExitWaitForTriggerInlineStatement(c *WaitForTriggerInlineStatementContext)
// ExitWaitForTriggerInlineDispatchStatement is called when exiting the waitForTriggerInlineDispatchStatement production.
ExitWaitForTriggerInlineDispatchStatement(c *WaitForTriggerInlineDispatchStatementContext)
// ExitWaitForPredicateExpression is called when exiting the waitForPredicateExpression production.
ExitWaitForPredicateExpression(c *WaitForPredicateExpressionContext)
@@ -811,6 +844,9 @@ type FqlParserListener interface {
// ExitFunctionCallExpression is called when exiting the functionCallExpression production.
ExitFunctionCallExpression(c *FunctionCallExpressionContext)
// ExitFunctionCallNoRecoveryExpression is called when exiting the functionCallNoRecoveryExpression production.
ExitFunctionCallNoRecoveryExpression(c *FunctionCallNoRecoveryExpressionContext)
// ExitFunctionCall is called when exiting the functionCall production.
ExitFunctionCall(c *FunctionCallContext)
+18
View File
@@ -166,6 +166,21 @@ type FqlParserVisitor interface {
// Visit a parse tree produced by FqlParser#waitForEventExpression.
VisitWaitForEventExpression(ctx *WaitForEventExpressionContext) interface{}
// Visit a parse tree produced by FqlParser#waitForEventTail.
VisitWaitForEventTail(ctx *WaitForEventTailContext) interface{}
// Visit a parse tree produced by FqlParser#waitForTriggerClause.
VisitWaitForTriggerClause(ctx *WaitForTriggerClauseContext) interface{}
// Visit a parse tree produced by FqlParser#waitForTriggerStatement.
VisitWaitForTriggerStatement(ctx *WaitForTriggerStatementContext) interface{}
// Visit a parse tree produced by FqlParser#waitForTriggerInlineStatement.
VisitWaitForTriggerInlineStatement(ctx *WaitForTriggerInlineStatementContext) interface{}
// Visit a parse tree produced by FqlParser#waitForTriggerInlineDispatchStatement.
VisitWaitForTriggerInlineDispatchStatement(ctx *WaitForTriggerInlineDispatchStatementContext) interface{}
// Visit a parse tree produced by FqlParser#waitForPredicateExpression.
VisitWaitForPredicateExpression(ctx *WaitForPredicateExpressionContext) interface{}
@@ -325,6 +340,9 @@ type FqlParserVisitor interface {
// Visit a parse tree produced by FqlParser#functionCallExpression.
VisitFunctionCallExpression(ctx *FunctionCallExpressionContext) interface{}
// Visit a parse tree produced by FqlParser#functionCallNoRecoveryExpression.
VisitFunctionCallNoRecoveryExpression(ctx *FunctionCallNoRecoveryExpressionContext) interface{}
// Visit a parse tree produced by FqlParser#functionCall.
VisitFunctionCall(ctx *FunctionCallContext) interface{}
+41 -1
View File
@@ -17,6 +17,7 @@ type (
err error
fallback runtime.Value
pc int
originPC int
dst bytecode.Operand
kind errorKind
mode recoveryMode
@@ -37,9 +38,11 @@ type (
aliases mem.AliasTracker
deferred mem.DeferredClosers
failure pendingFailure
caught pendingFailure
pc int
lastPC int
hasFail bool
hasCaught bool
}
)
@@ -62,6 +65,7 @@ func (s *execState) startRun(env *Environment) error {
s.pc = 0
s.lastPC = -1
s.clearFailure()
s.clearCaughtFailure()
return s.bindParams(env)
}
@@ -136,6 +140,7 @@ func (s *execState) resetRunStorage() {
s.pc = 0
s.lastPC = -1
s.clearFailure()
s.clearCaughtFailure()
}
func (s *execState) bindParams(env *Environment) error {
@@ -187,6 +192,7 @@ func (s *execState) raise(pc int, err error, kind errorKind, mode recoveryMode,
kind: kind,
mode: mode,
pc: pc,
originPC: pc,
dst: dst,
fallback: fallback,
setFallback: setFallback,
@@ -194,6 +200,25 @@ func (s *execState) raise(pc int, err error, kind errorKind, mode recoveryMode,
s.hasFail = true
}
func (s *execState) rethrowRuntimeAt(pc int) {
if !s.hasCaught {
err := runtime.Error(runtime.ErrInvalidOperation, "RETHROW requires a caught runtime failure")
s.raiseRuntimeAt(pc, err, recoverDefault, bytecode.NoopOperand, nil, false)
return
}
caught := s.caught
originPC := caught.originPC
if originPC < 0 {
originPC = caught.pc
}
s.raise(pc, caught.err, caught.kind, recoverDefault, bytecode.NoopOperand, nil, false)
if s.hasFail {
s.failure.originPC = originPC
}
}
func (s *execState) hasFailure() bool {
return s.hasFail
}
@@ -215,6 +240,20 @@ func (s *execState) clearFailure() {
s.hasFail = false
}
func (s *execState) rememberCaughtFailure(failure pendingFailure) {
s.caught = failure
s.hasCaught = true
}
func (s *execState) clearCaughtFailure() {
if !s.hasCaught {
return
}
s.caught = pendingFailure{}
s.hasCaught = false
}
func (s *execState) resolveFailure() errAction {
if !s.hasFail {
return errOK
@@ -257,6 +296,7 @@ func (s *execState) resolveFailure() errAction {
func (s *execState) resolveRuntimeDefault(failure pendingFailure) errAction {
if catch, ok := s.tryCatch(failure.pc); ok {
s.rememberCaughtFailure(failure)
s.applyFailureFallback(failure)
if catch[2] >= 0 {
@@ -300,7 +340,7 @@ func (s *execState) isNullMemberDereference(err error) bool {
func (s *execState) errorPC() int {
if s.hasFail {
return s.failure.pc
return s.failure.originPC
}
if s.lastPC >= 0 {
+2
View File
@@ -308,6 +308,8 @@ loop:
state.raiseRuntimeAt(pc, callErr, recoverDefault, bytecode.NoopOperand, nil, false)
case bytecode.OpFailTimeout:
state.raiseRuntimeAt(pc, runtime.ErrTimeout, recoverDefault, bytecode.NoopOperand, nil, false)
case bytecode.OpRethrow:
state.rethrowRuntimeAt(pc)
case bytecode.OpHCall, bytecode.OpProtectedHCall:
hostID := inst.InlineSlot
if hostID < 0 || hostID >= len(hostFunctions) {
+85
View File
@@ -2378,6 +2378,91 @@ func TestOpFail_CaughtUsesCatchJumpTarget(t *testing.T) {
}
}
func TestOpRethrow_CaughtUsesOuterCatchJumpTarget(t *testing.T) {
instance := mustNewVM(t, &bytecode.Program{
ISAVersion: bytecode.Version,
Registers: 1,
Bytecode: []bytecode.Instruction{
bytecode.NewInstruction(bytecode.OpFail, bytecode.NewConstant(0)),
bytecode.NewInstruction(bytecode.OpRethrow),
bytecode.NewInstruction(bytecode.OpReturn, bytecode.NewRegister(0)),
bytecode.NewInstruction(bytecode.OpLoadConst, bytecode.NewRegister(0), bytecode.NewConstant(1)),
bytecode.NewInstruction(bytecode.OpReturn, bytecode.NewRegister(0)),
},
Constants: []runtime.Value{
runtime.NewString("boom"),
runtime.NewInt(7),
},
CatchTable: []bytecode.Catch{
{0, 0, 1},
{1, 1, 3},
},
})
result := mustRunResult(t, instance, nil)
defer func() {
_ = result.Close()
}()
if got := result.Root(); got != runtime.NewInt(7) {
t.Fatalf("expected outer catch target return value 7, got %v", got)
}
}
func TestRethrowRuntimeAt_PreservesOriginAndUsesRethrowPCForCatch(t *testing.T) {
instance := mustNewVM(t, &bytecode.Program{
ISAVersion: bytecode.Version,
Registers: 1,
Bytecode: []bytecode.Instruction{
bytecode.NewInstruction(bytecode.OpLoadNone, bytecode.NewRegister(0)),
bytecode.NewInstruction(bytecode.OpLoadNone, bytecode.NewRegister(0)),
bytecode.NewInstruction(bytecode.OpLoadNone, bytecode.NewRegister(0)),
bytecode.NewInstruction(bytecode.OpLoadNone, bytecode.NewRegister(0)),
bytecode.NewInstruction(bytecode.OpLoadNone, bytecode.NewRegister(0)),
bytecode.NewInstruction(bytecode.OpLoadNone, bytecode.NewRegister(0)),
bytecode.NewInstruction(bytecode.OpLoadNone, bytecode.NewRegister(0)),
bytecode.NewInstruction(bytecode.OpLoadNone, bytecode.NewRegister(0)),
},
CatchTable: []bytecode.Catch{
{1, 1, 3},
{3, 3, 7},
},
})
state := mustAcquireRunState(t, instance)
defer state.endRun()
wantErr := errors.New("boom")
state.raiseRuntimeAt(1, wantErr, recoverDefault, bytecode.NoopOperand, nil, false)
if action := state.resolveFailure(); action != errContinue {
t.Fatalf("expected initial catch to continue, got %v", action)
}
if got, want := state.pc, 3; got != want {
t.Fatalf("expected initial catch target %d, got %d", want, got)
}
state.rethrowRuntimeAt(3)
if !state.hasFailure() {
t.Fatal("expected rethrow to record a pending failure")
}
if got, want := state.failure.pc, 3; got != want {
t.Fatalf("expected rethrow catch pc %d, got %d", want, got)
}
if got, want := state.failure.originPC, 1; got != want {
t.Fatalf("expected original diagnostic pc %d, got %d", want, got)
}
if got := state.failureError(); !errors.Is(got, wantErr) {
t.Fatalf("expected original error, got %v", got)
}
if action := state.resolveFailure(); action != errContinue {
t.Fatalf("expected outer catch to continue, got %v", action)
}
if got, want := state.pc, 7; got != want {
t.Fatalf("expected outer catch target %d, got %d", want, got)
}
}
func TestOpFail_InvalidMessageTypeReturnsTypeError(t *testing.T) {
instance := mustNewVM(t, &bytecode.Program{
ISAVersion: bytecode.Version,
@@ -217,12 +217,20 @@ func TestCompiler_WaitForEventSuppressCatchUsesCleanupJump(t *testing.T) {
return err
}
if got, want := catch[1], closePC; got != want {
cleanupDonePC := closePC + 1
if cleanupDonePC >= len(program.Bytecode) {
return fmt.Errorf("waitfor event cleanup completion pc %d out of range", cleanupDonePC)
}
if got, want := program.Bytecode[cleanupDonePC].Opcode, bytecode.OpLoadBool; got != want {
return fmt.Errorf("unexpected waitfor event cleanup completion opcode at pc %d: got %s, want %s", cleanupDonePC, got, want)
}
if got, want := catch[1], cleanupDonePC; got != want {
return fmt.Errorf("unexpected catch end: got %d, want %d", got, want)
}
if got := catch[2]; got <= closePC || got >= propPC {
return fmt.Errorf("unexpected waitfor event recovery jump: got %d, want (%d, %d)", got, closePC, propPC)
if got := catch[2]; got <= cleanupDonePC || got >= propPC {
return fmt.Errorf("unexpected waitfor event recovery jump: got %d, want (%d, %d)", got, cleanupDonePC, propPC)
}
return nil
@@ -247,12 +255,20 @@ func TestCompiler_WaitForEventRetryUsesCleanupJump(t *testing.T) {
return err
}
if got, want := catch[1], closePC; got != want {
cleanupDonePC := closePC + 1
if cleanupDonePC >= len(program.Bytecode) {
return fmt.Errorf("waitfor event cleanup completion pc %d out of range", cleanupDonePC)
}
if got, want := program.Bytecode[cleanupDonePC].Opcode, bytecode.OpLoadBool; got != want {
return fmt.Errorf("unexpected waitfor event cleanup completion opcode at pc %d: got %s, want %s", cleanupDonePC, got, want)
}
if got, want := catch[1], cleanupDonePC; got != want {
return fmt.Errorf("unexpected catch end: got %d, want %d", got, want)
}
if got := catch[2]; got <= closePC || got >= propPC {
return fmt.Errorf("unexpected waitfor event retry jump: got %d, want (%d, %d)", got, closePC, propPC)
if got := catch[2]; got <= cleanupDonePC || got >= propPC {
return fmt.Errorf("unexpected waitfor event retry jump: got %d, want (%d, %d)", got, cleanupDonePC, propPC)
}
return nil
@@ -85,5 +85,38 @@ func TestSyntaxErrorsWaitfor(t *testing.T) {
`, E{
Kind: parserd.SyntaxError,
}, "Legacy FILTER keyword is invalid in WAITFOR EVENT"),
Failure(`
LET obs = {}
LET ok = WAITFOR EVENT "test" IN obs
TRIGGER
TIMEOUT 5s
RETURN ok
`, E{
Kind: parserd.SyntaxError,
Message: "Expected trigger statement after 'TRIGGER' in WAITFOR EVENT",
Hint: "Use a side-effect statement or TRIGGER (...), e.g. TRIGGER target <- \"click\".",
}, "WAITFOR EVENT TRIGGER requires a body"),
Failure(`
LET obs = {}
LET ok = WAITFOR EVENT "test" IN obs
TRIGGER WAITFOR EVENT "inner" IN obs
TIMEOUT 5s
RETURN ok
`, E{
Kind: parserd.SyntaxError,
Message: "Nested WAITFOR in TRIGGER shorthand must use a parenthesized block",
Hint: "Use TRIGGER (...), e.g. TRIGGER (WAITFOR EVENT \"ready\" IN target).",
}, "WAITFOR EVENT TRIGGER shorthand rejects nested WAITFOR"),
Failure(`
LET obs = {}
LET ok = WAITFOR EVENT "test" IN obs
TRIGGER 1 + 2
TIMEOUT 5s
RETURN ok
`, E{
Kind: parserd.SyntaxError,
Message: "Expected trigger statement after 'TRIGGER' in WAITFOR EVENT",
Hint: "Use a side-effect statement or TRIGGER (...), e.g. TRIGGER target <- \"click\".",
}, "WAITFOR EVENT TRIGGER shorthand rejects arbitrary expressions"),
})
}
@@ -96,9 +96,61 @@ func TestWaitforPredicateWhenCompiles(t *testing.T) {
RETURN WAITFOR EVENT "test" IN obs
WHEN .type == "match"
WHEN BOOM(.)
TRIGGER (
LET local = 1
)
TIMEOUT 5ms
ON TIMEOUT RETURN NONE
`, expectHostFunction("BOOM", 1), "WAITFOR EVENT should compile repeated WHEN host calls and timeout tail"),
`, expectHostFunction("BOOM", 1), "WAITFOR EVENT should compile repeated WHEN, trigger, and timeout tail"),
ProgramCheck(`
LET obs = []
RETURN WAITFOR EVENT "test" IN obs
WHEN .TRIGGER == "match"
TIMEOUT 5ms
ON TIMEOUT RETURN NONE
`, noCompilerError, "WAITFOR EVENT should compile TRIGGER as an implicit-current property"),
ProgramCheck(`
LET obs = []
RETURN WAITFOR EVENT "test" IN obs
TRIGGER (
LET local = 1
)
TIMEOUT 5ms
ON TIMEOUT RETURN NONE
`, noCompilerError, "WAITFOR EVENT should compile a trigger before timeout"),
ProgramCheck(`
LET obs = []
LET button = {}
RETURN WAITFOR EVENT "test" IN obs
TRIGGER button <- "click"
TIMEOUT 5ms
ON TIMEOUT RETURN NONE
`, noCompilerError, "WAITFOR EVENT should compile inline dispatch trigger before timeout"),
ProgramCheck(`
LET obs = []
VAR clicked = false
RETURN WAITFOR EVENT "test" IN obs
TRIGGER clicked = true
TIMEOUT 5ms
ON TIMEOUT RETURN NONE
`, noCompilerError, "WAITFOR EVENT should compile inline assignment trigger before timeout"),
ProgramCheck(`
LET obs = []
RETURN WAITFOR EVENT "test" IN obs
TRIGGER ()
TIMEOUT 5ms
ON TIMEOUT RETURN NONE
`, noCompilerError, "WAITFOR EVENT should compile empty trigger block before timeout"),
ProgramCheck(`
LET TRIGGER = 1
RETURN TRIGGER
`, noCompilerError, "TRIGGER should compile as a safe reserved variable name"),
ProgramCheck(`
RETURN @TRIGGER
`, noCompilerError, "TRIGGER should compile as a safe reserved param name"),
ProgramCheck(`
RETURN TRIGGER()
`, expectHostFunction("TRIGGER", 0), "TRIGGER should compile as a safe reserved function name"),
ProgramCheck(`
LET obs = []
FOR i IN [1, 2]
@@ -1,6 +1,10 @@
package vm_test
import (
"context"
"errors"
"fmt"
"strings"
"testing"
"github.com/MontFerret/ferret/v2/pkg/runtime"
@@ -133,3 +137,243 @@ RETURN (WAITFOR EVENT "test" IN obs TIMEOUT 1ms) ON ERROR RETURN "error"`, "Grou
})),
})
}
func TestWaitforEventTrigger(t *testing.T) {
RunSpecFactory(t, func() []spec.Spec {
armed := NewTriggerObservable()
timeout := NewTriggerObservable()
triggerFailure := NewTriggerObservable()
triggerFailure.FailNextDispatches(1, errors.New("trigger failed"))
triggerCallFailure := NewTriggerObservable()
waitFailure := NewTriggerObservable()
waitFailure.FailReadsWith(errors.New("stream failed"))
retry := NewTriggerObservable()
retry.FailNextDispatches(1, errors.New("trigger failed once"))
return []spec.Spec{
Fn(`LET target = @target
LET evt = WAITFOR EVENT "test" IN target
TRIGGER target <- "test"
TIMEOUT 20ms
RETURN evt.type`, expectTriggerObservable(armed, "test", 1, 1, 1), "WAITFOR EVENT trigger should run after subscription is armed").Env(vm.WithParams(map[string]runtime.Value{
"target": armed,
})),
Fn(`LET target = @target
RETURN WAITFOR EVENT "test" IN target
TRIGGER ()
TIMEOUT 1ms
ON TIMEOUT RETURN "timeout"`, expectTriggerObservable(timeout, "timeout", 1, 0, 1), "WAITFOR EVENT trigger no-op should preserve timeout cleanup").Env(vm.WithParams(map[string]runtime.Value{
"target": timeout,
})),
Fn(`LET target = @target
RETURN WAITFOR EVENT "test" IN target
TRIGGER (
target <- "test"
)
TIMEOUT 20ms
ON ERROR RETURN "error"`, expectTriggerObservable(triggerFailure, "error", 1, 1, 1), "WAITFOR EVENT trigger failure should clean up and use ON ERROR").Env(vm.WithParams(map[string]runtime.Value{
"target": triggerFailure,
})),
Fn(`LET target = @target
RETURN WAITFOR EVENT "test" IN target
TRIGGER FAIL()
TIMEOUT 1ms
ON ERROR RETURN "error"`, expectTriggerObservable(triggerCallFailure, "error", 1, 0, 1), "WAITFOR EVENT inline trigger call failure should belong to outer recovery").Env(
vm.WithParams(map[string]runtime.Value{
"target": triggerCallFailure,
}),
vm.WithFunction("FAIL", func(context.Context, ...runtime.Value) (runtime.Value, error) {
return runtime.None, errors.New("trigger failed")
}),
),
Fn(`LET target = @target
RETURN WAITFOR EVENT "test" IN target
TRIGGER (
target <- "test"
)
TIMEOUT 20ms
ON ERROR RETURN "error"`, expectTriggerObservable(waitFailure, "error", 1, 1, 1), "WAITFOR EVENT stream failure after trigger should clean up and use ON ERROR").Env(vm.WithParams(map[string]runtime.Value{
"target": waitFailure,
})),
Fn(`LET target = @target
LET evt = WAITFOR EVENT "test" IN target
TRIGGER (
target <- "test"
)
TIMEOUT 20ms
ON ERROR RETRY 2 DELAY 0 OR RETURN "error"
RETURN evt.type`, expectTriggerObservable(retry, "test", 2, 2, 2), "WAITFOR EVENT trigger should be retried through protected cleanup").Env(vm.WithParams(map[string]runtime.Value{
"target": retry,
})),
}
})
}
func TestWaitforEventTriggerCleanupOnTriggerError(t *testing.T) {
failFn := vm.WithFunction("FAIL", func(context.Context, ...runtime.Value) (runtime.Value, error) {
return runtime.None, errors.New("trigger failed")
})
t.Run("plain trigger dispatch failure closes before returning error", func(t *testing.T) {
target := NewTriggerObservable()
target.FailNextDispatches(1, errors.New("trigger failed"))
result, err := runWaitforEventTriggerProgram(t, `LET target = @target
RETURN WAITFOR EVENT "test" IN target
TRIGGER target <- "test"`, target)
if result != nil {
_ = result.Close()
}
assertTriggerRuntimeError(t, err, "trigger failed")
assertTriggerObservableCounts(t, target, 1, 1, 1)
})
t.Run("plain trigger call failure closes before returning error", func(t *testing.T) {
target := NewTriggerObservable()
result, err := runWaitforEventTriggerProgram(t, `LET target = @target
RETURN WAITFOR EVENT "test" IN target
TRIGGER FAIL()`, target, failFn)
if result != nil {
_ = result.Close()
}
assertTriggerRuntimeError(t, err, "trigger failed")
assertTriggerObservableCounts(t, target, 1, 0, 1)
})
t.Run("timeout-only trigger call failure closes before returning error", func(t *testing.T) {
target := NewTriggerObservable()
result, err := runWaitforEventTriggerProgram(t, `LET target = @target
RETURN WAITFOR EVENT "test" IN target
TRIGGER FAIL()
TIMEOUT 1ms
ON TIMEOUT RETURN "timeout"`, target, failFn)
if result != nil {
_ = result.Close()
}
assertTriggerRuntimeError(t, err, "trigger failed")
assertTriggerObservableCounts(t, target, 1, 0, 1)
})
t.Run("outer suppression closes before result close", func(t *testing.T) {
target := NewTriggerObservable()
result, err := runWaitforEventTriggerProgram(t, `LET target = @target
LET out = (WAITFOR EVENT "test" IN target
TRIGGER FAIL())?
RETURN out`, target, failFn)
if err != nil {
t.Fatalf("expected suppressed trigger failure, got %v", err)
}
defer func() {
_ = result.Close()
}()
assertTriggerObservableCounts(t, target, 1, 0, 1)
})
t.Run("timeout-aware outer suppression closes before result close", func(t *testing.T) {
target := NewTriggerObservable()
result, err := runWaitforEventTriggerProgram(t, `LET target = @target
LET out = (WAITFOR EVENT "test" IN target
TRIGGER FAIL()
TIMEOUT 1ms
ON TIMEOUT RETURN "timeout")?
RETURN out`, target, failFn)
if err != nil {
t.Fatalf("expected suppressed trigger failure, got %v", err)
}
defer func() {
_ = result.Close()
}()
assertTriggerObservableCounts(t, target, 1, 0, 1)
})
}
func expectTriggerObservable(target *TriggerObservable, expected any, subscribes, dispatches, closes int32) func(any) error {
return func(actual any) error {
if actual != expected {
return fmt.Errorf("expected return value %v, got %v", expected, actual)
}
if got := target.SubscribeCount(); got != subscribes {
return fmt.Errorf("expected %d subscribes, got %d", subscribes, got)
}
if got := target.DispatchCount(); got != dispatches {
return fmt.Errorf("expected %d dispatches, got %d", dispatches, got)
}
if got := target.CloseCount(); got != closes {
return fmt.Errorf("expected %d closes, got %d", closes, got)
}
return nil
}
}
func runWaitforEventTriggerProgram(
t *testing.T,
query string,
target *TriggerObservable,
opts ...vm.EnvironmentOption,
) (*vm.Result, error) {
t.Helper()
prog, err := spec.Compile(query)
if err != nil {
t.Fatalf("compile failed: %v", err)
}
instance, err := vm.NewWith(prog)
if err != nil {
t.Fatalf("vm init failed: %v", err)
}
t.Cleanup(func() {
_ = instance.Close()
})
envOpts := []vm.EnvironmentOption{
vm.WithNamespace(spec.Stdlib()),
vm.WithParam("target", target),
}
envOpts = append(envOpts, opts...)
env, err := vm.NewEnvironment(envOpts)
if err != nil {
t.Fatalf("environment build failed: %v", err)
}
return instance.Run(context.Background(), env)
}
func assertTriggerRuntimeError(t *testing.T, err error, contains string) {
t.Helper()
if err == nil {
t.Fatal("expected runtime error")
}
var rtErr *vm.RuntimeError
if !errors.As(err, &rtErr) {
t.Fatalf("expected runtime error, got %T", err)
}
if !strings.Contains(rtErr.Format(), contains) {
t.Fatalf("expected runtime error to contain %q, got:\n%s", contains, rtErr.Format())
}
}
func assertTriggerObservableCounts(t *testing.T, target *TriggerObservable, subscribes, dispatches, closes int32) {
t.Helper()
if got := target.SubscribeCount(); got != subscribes {
t.Fatalf("expected %d subscribes, got %d", subscribes, got)
}
if got := target.DispatchCount(); got != dispatches {
t.Fatalf("expected %d dispatches, got %d", dispatches, got)
}
if got := target.CloseCount(); got != closes {
t.Fatalf("expected %d closes, got %d", closes, got)
}
}
+10 -1
View File
@@ -2,6 +2,7 @@ package mock
import (
"context"
"sync"
"sync/atomic"
"github.com/MontFerret/ferret/v2/pkg/runtime"
@@ -47,7 +48,9 @@ func (o *Observable) Copy() runtime.Value {
}
type TestStream struct {
ch <-chan runtime.Message
ch <-chan runtime.Message
onClose func()
once sync.Once
}
func (s *TestStream) Read(ctx context.Context) <-chan runtime.Message {
@@ -55,6 +58,12 @@ func (s *TestStream) Read(ctx context.Context) <-chan runtime.Message {
}
func (s *TestStream) Close() error {
s.once.Do(func() {
if s.onClose != nil {
s.onClose()
}
})
return nil
}
+95
View File
@@ -0,0 +1,95 @@
package mock
import (
"context"
"sync/atomic"
"github.com/MontFerret/ferret/v2/pkg/runtime"
)
type TriggerObservable struct {
ch chan runtime.Message
dispatchErr error
readErr error
activeCount atomic.Int32
closeCount atomic.Int32
dispatchCount atomic.Int32
failDispatchRemaining atomic.Int32
subscribeCount atomic.Int32
}
func NewTriggerObservable() *TriggerObservable {
return &TriggerObservable{
ch: make(chan runtime.Message, 16),
}
}
func (o *TriggerObservable) Subscribe(_ context.Context, _ runtime.Subscription) (runtime.Stream, error) {
o.subscribeCount.Add(1)
o.activeCount.Add(1)
return &TestStream{
ch: o.ch,
onClose: func() {
o.activeCount.Add(-1)
o.closeCount.Add(1)
},
}, nil
}
func (o *TriggerObservable) Dispatch(_ context.Context, event runtime.DispatchEvent) error {
o.dispatchCount.Add(1)
if o.failDispatchRemaining.Load() > 0 {
o.failDispatchRemaining.Add(-1)
return o.dispatchErr
}
if o.activeCount.Load() <= 0 {
return nil
}
if o.readErr != nil {
o.ch <- runtime.NewErrorMessage(o.readErr)
return nil
}
o.ch <- runtime.NewValueMessage(runtime.NewObjectWith(map[string]runtime.Value{
"type": event.Name,
}))
return nil
}
func (o *TriggerObservable) FailNextDispatches(n int32, err error) {
o.failDispatchRemaining.Store(n)
o.dispatchErr = err
}
func (o *TriggerObservable) FailReadsWith(err error) {
o.readErr = err
}
func (o *TriggerObservable) SubscribeCount() int32 {
return o.subscribeCount.Load()
}
func (o *TriggerObservable) DispatchCount() int32 {
return o.dispatchCount.Load()
}
func (o *TriggerObservable) CloseCount() int32 {
return o.closeCount.Load()
}
func (o *TriggerObservable) String() string {
return "trigger_observable"
}
func (o *TriggerObservable) Hash() uint64 {
return 0
}
func (o *TriggerObservable) Copy() runtime.Value {
return o
}