예제 #1
0
        public Expression Emit(StateMachineEmitter <TComparand, TInput> emitter, Expression contextExpression, ref bool saveContext)
        {
            var body = new List <Expression>();

            if (saveContext)
            {
                body.Add(Expression.Assign(
                             emitter.ContextParameter,
                             Expression.Convert(contextExpression, typeof(object))));
            }
            if (this.Yield)
            {
                body.Add(Expression.Constant(this.Target.GetValueOrDefault(emitter.BreakState)));
            }
            else
            {
                body.Add(Expression.Assign(
                             emitter.StateParameter,
                             Expression.Constant(this.Target.GetValueOrDefault(emitter.BreakState))));
                body.Add(Expression.Goto(
                             emitter.StartLabel,
                             typeof(int)));
            }
            return(Expression.Block(body));
        }
예제 #2
0
        public Expression Emit(StateMachineEmitter <TComparand, TInput> emitter, Expression contextExpression, ref bool saveContext)
        {
            var body = new List <Expression>();

            if (saveContext)
            {
                body.Add(Expression.Assign(
                             emitter.ContextParameter,
                             Expression.Convert(
                                 contextExpression,
                                 typeof(object))));
            }
            var computeState = emitter.ReplaceBuildersByIds(this.computeState, emitter.InputParameter, contextExpression);

            if (this.Yield)
            {
                body.Add(computeState.Body);
            }
            else
            {
                body.Add(Expression.Assign(
                             emitter.StateParameter,
                             computeState.Body));
                body.Add(Expression.Goto(
                             emitter.StartLabel,
                             typeof(int)));
            }
            return(body.Count == 1 ? body[0] : Expression.Block(body));
        }
예제 #3
0
        public void TestCounter(int expectedCount, string input)
        {
            // Define the state machine
            var root = new StateSwitchBuilder <char, char, int>();

            root.On('\n', i => false);
            root.On((i, ctx) => false);
            root.On('\n').Do(i => i + 1).Yield(root);
            root.Default.Yield(root);
            // Compile the state machine
            var emitter = new StateMachineEmitter <char, char>(root, EquatableConditionEmitter <char> .Default);

            emitter.OnEnter <object>((i, d) => this.output.WriteLine("+"));
            emitter.OnLeave <object>((i, d) => this.output.WriteLine("-"));
            var stateExpr = emitter.Emit();

            this.output.WriteLine(stateExpr.ToReadableString());
            var stateFn = stateExpr.Compile();
            // Run the state machine for some input
            var    state   = 0;
            object context = 0;

            foreach (var ch in input)
            {
                stateFn(ch, ref state, ref context);
            }
            // The context is now an integer with the number of newlines
            this.output.WriteLine(context.ToString());
            Assert.Equal(expectedCount, (int)context);
            Assert.True(state >= 0);
        }
예제 #4
0
        public override Expression EmitCondition(StateMachineEmitter <TComparand, TInput> emitter, ParameterExpression varContext)
        {
            var condition = emitter.ConditionEmitter.Emit(this.Comparand, emitter.InputParameter);

            if (this.Condition == null)
            {
                return(condition);
            }
            return(Expression.AndAlso(
                       condition,
                       emitter.ReplaceBuildersByIds(this.Condition, varContext).Body));
        }
예제 #5
0
        public void TestTypedContext()
        {
            var emitter = new StateMachineEmitter <char, char, ITestOutputHelper>(EquatableConditionEmitter <char> .Default);

            emitter.Root.Default.Do((ch, ctx) => ctx.WriteLine(ch.ToString())).Yield();
            var stateExpr = emitter.Emit();
            var stateFn   = stateExpr.Compile();
            var state     = 0;

            stateFn('X', ref state, this.output);
            Assert.NotEqual(0, state);
        }
예제 #6
0
        public void ExpressionReplaceTest()
        {
            var root    = new StateSwitchBuilder <bool, bool, ITestOutputHelper>();
            var emitter = new StateMachineEmitter <bool, bool>(root, EquatableConditionEmitter <bool> .Default);

            root.Default.Do(o => o.WriteLine(((int)root).ToString()));
            var    stateExpr = emitter.Emit();
            var    stateFn   = stateExpr.Compile();
            var    state     = 0;
            object context   = this.output;

            Assert.False(stateFn(true, ref state, ref context));
        }
예제 #7
0
        public void TestMergeOptimization()
        {
            // Define the state machine
            var root = new StateSwitchBuilder <char, char, int>();

            root.On('x', i => false).Yield(root);
            root.On('a').Yield(root);
            root.On('x').Yield(root);
            root.On('b').Yield(root);
            // Compile the state machine
            var emitter   = new StateMachineEmitter <char, char>(root, EquatableConditionEmitter <char> .Default);
            var stateExpr = emitter.Emit();

            this.output.WriteLine(stateExpr.ToReadableString());
        }
예제 #8
0
        public void TestRangeSet(bool accept, string input)
        {
            var root    = new StateSwitchBuilder <RangeSet <char>, char, ITestOutputHelper>();
            var emitter = new StateMachineEmitter <RangeSet <char>, char>(root, RangesConditionEmitter <RangeSet <char>, char> .Default);

            root.OnSequence("test").Do(o => o.WriteLine("Done")).Yield(-2);
            root.On(new RangeSet <char>(" \t\r\n")).Yield(o => (int)root);
            var    stateExpr = emitter.Emit();
            var    stateFn   = stateExpr.Compile();
            var    state     = 0;
            object context   = this.output;

            foreach (var ch in input)
            {
                this.output.WriteLine(stateFn(ch, ref state, ref context).ToString());
            }
            Assert.Equal(accept, state == -2);
        }
 public override Expression Emit(StateMachineEmitter <TComparand, TInput> emitter, Expression contextExpression, ref bool saveContext)
 {
     emitter.AssertCanChangeContext();
     saveContext = true;
     return(base.Emit(emitter, emitter.ReplaceBuildersByIds(this.transition, emitter.StateParameter, contextExpression).Body, ref saveContext));
 }
예제 #10
0
 public override Expression EmitCondition(StateMachineEmitter <TComparand, TInput> emitter, ParameterExpression varContext)
 {
     return(emitter.ReplaceBuildersByIds(this.Condition, emitter.InputParameter, varContext).Body);
 }
예제 #11
0
 public virtual Expression Emit(StateMachineEmitter <TComparand, TInput> emitter, Expression contextExpression, ref bool saveContext)
 {
     return(this.Next.Emit(emitter, contextExpression, ref saveContext));
 }
예제 #12
0
 public override Expression Emit(StateMachineEmitter <TComparand, TInput> emitter, Expression contextExpression, ref bool saveContext)
 {
     return(Expression.Block(
                emitter.ReplaceBuildersByIds(this.action, emitter.StateParameter, contextExpression).Body,
                base.Emit(emitter, contextExpression, ref saveContext)));
 }
예제 #13
0
 public StateReferenceReplacer(StateMachineEmitter <TComparand, TInput> emitter)
 {
     this.emitter = emitter;
 }
예제 #14
0
 public abstract Expression EmitCondition(StateMachineEmitter <TComparand, TInput> emitter, ParameterExpression varContext);
예제 #15
0
 /// <summary>Emits the state machine fragment as <see cref="Expression" />.</summary>
 /// <param name="emitter">The emitter.</param>
 /// <returns>An Expression.</returns>
 internal abstract Expression Emit(StateMachineEmitter <TComparand, TInput> emitter);