public static string BusSignalToValidName(AST.Process process, AST.Signal signal) { return(ToValidName(signal.Name)); }
public string Type(AST.Signal signal) { return(RS.TypeScope.GetType(signal).Name); }
/// <summary> /// Gets the Cpp type for the signal /// </summary> /// <returns>The cpp type.</returns> /// <param name="signal">The input signal.</param> public CppType GetType(AST.Signal signal) { return(GetType(signal.CecilType)); }
/// <summary> /// Applies the transformation /// </summary> /// <returns>The transformed item.</returns> /// <param name="item">The item to visit.</param> public ASTItem Transform(ASTItem item) { if (!(item is AST.Method) || !((Method)item).IsStateMachine) { return(item); } var method = item as AST.Method; if (!method.All().OfType <AwaitExpression>().Any()) { return(item); } var enumname = "FSM_" + method.Name + "_State"; // Construct an enum type that matches the desired states var enumtype = new Mono.Cecil.TypeDefinition("", enumname, Mono.Cecil.TypeAttributes.Public | Mono.Cecil.TypeAttributes.AutoClass | Mono.Cecil.TypeAttributes.AnsiClass | Mono.Cecil.TypeAttributes.Sealed, method.SourceMethod.Module.ImportReference(typeof(System.Enum))) { IsSealed = true, }; enumtype.DeclaringType = method.SourceMethod.DeclaringType; enumtype.Fields.Add(new Mono.Cecil.FieldDefinition($"value__", Mono.Cecil.FieldAttributes.Public | Mono.Cecil.FieldAttributes.SpecialName | Mono.Cecil.FieldAttributes.RTSpecialName, method.SourceMethod.Module.ImportReference(typeof(int)))); var statenametemplate = $"{enumtype.DeclaringType.FullName}_{enumname}_State"; var fragments = SplitIntoFragments(method.Statements); var statecount = fragments.Count; var enumfields = new Mono.Cecil.FieldDefinition[statecount]; // Add each of the states to the type for (var i = 0; i < statecount; i++) { enumtype.Fields.Add(enumfields[i] = new Mono.Cecil.FieldDefinition($"State{i}", Mono.Cecil.FieldAttributes.Public | Mono.Cecil.FieldAttributes.Static | Mono.Cecil.FieldAttributes.Literal, enumtype) { Constant = i }); } // The variable being updated internally in the method var run_state_var = new AST.Variable("FSM_RunState", enumfields[0]) { CecilType = enumtype, DefaultValue = 0, Source = new Mono.Cecil.ParameterDefinition("FSM_RunState", Mono.Cecil.ParameterAttributes.None, enumtype) }; // The current state used in the state machine process var current_state_signal = new AST.Signal("FSM_CurrentState", enumfields[0]) { CecilType = enumtype, DefaultValue = 0, Source = new Mono.Cecil.ParameterDefinition("FSM_CurrentState", Mono.Cecil.ParameterAttributes.None, enumtype) }; // The next state that is propagated to var next_state_signal = new AST.Signal("FSM_NextState", enumfields[0]) { CecilType = enumtype, DefaultValue = 0, Source = new Mono.Cecil.ParameterDefinition("FSM_NextState", Mono.Cecil.ParameterAttributes.None, enumtype) }; // Construct a state-machine method, that will be rendered as a process var stateMachineProcess = new AST.Method() { Name = "FSM_" + method.Name + "_Method", Parameters = new AST.Parameter[0], ReturnVariable = null, Parent = method.Parent, Variables = method.AllVariables.Concat(new Variable[] { run_state_var }).ToArray(), AllVariables = method.AllVariables.Concat(new Variable[] { }).ToArray(), IsStateMachine = true }; var enumdataitems = enumfields.Select(x => new Constant(x.Name, x) { CecilType = enumtype }).ToArray(); var isSimpleStatePossible = fragments.SelectMany(x => x.SelectMany(y => y.All().OfType <CaseGotoStatement>())).All(x => !x.FallThrough); List <Statement> cases; // If we have no fallthrough states, we build a switch if (isSimpleStatePossible) { cases = new List <Statement>(new[] { new EmptyStatement(), CreateSwitchStatement(fragments, current_state_signal, enumdataitems) }); } // Otherwise, we build an if-based state machine else { cases = WrapFragmentsWithLabels(fragments, run_state_var, enumdataitems); cases.Insert(0, new ExpressionStatement( new AssignmentExpression( new IdentifierExpression(run_state_var), new IdentifierExpression(current_state_signal) ) )); } stateMachineProcess.Statements = cases.ToArray(); foreach (var v in stateMachineProcess.Statements) { v.Parent = stateMachineProcess; v.UpdateParents(); ReplaceGotoWithVariables(v, run_state_var, next_state_signal, enumdataitems); } method.Statements = new Statement[] { new ExpressionStatement( new AssignmentExpression( new IdentifierExpression(current_state_signal), new IdentifierExpression(next_state_signal) ) ) { Parent = method } }; method.IsStateMachine = false; var proc = method.GetNearestParent <Process>(); proc.Methods = proc.Methods.Concat(new[] { stateMachineProcess }).ToArray(); // Move variables into the shared area proc.InternalDataElements = proc.InternalDataElements .Union(new[] { current_state_signal, next_state_signal }) //.Union(method.AllVariables) .ToArray(); proc.SharedVariables = proc.SharedVariables.Union(method.AllVariables).ToArray(); method.Variables = new Variable[0]; method.AllVariables = new Variable[0]; return(stateMachineProcess); }