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:
@@ -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,
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()))
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -43,6 +43,7 @@ const (
|
||||
keywordReturn = "RETURN"
|
||||
keywordSort = "SORT"
|
||||
keywordTimeout = "TIMEOUT"
|
||||
keywordTrigger = "TRIGGER"
|
||||
keywordUse = "USE"
|
||||
keywordUsing = "USING"
|
||||
keywordVar = "VAR"
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ Waitfor: 'WAITFOR';
|
||||
Dispatch: 'DISPATCH';
|
||||
Delete: 'DELETE';
|
||||
Options: 'OPTIONS';
|
||||
Trigger: 'TRIGGER';
|
||||
Timeout: 'TIMEOUT';
|
||||
Every: 'EVERY';
|
||||
Backoff: 'BACKOFF';
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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) {}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user