/// <summary> /// Parses a process and builds an AST component for it /// </summary> /// <param name="network">The top-level network.</param> /// <param name="process">The process to build the AST for.</param> protected virtual Process Parse(NetworkState network, ProcessMetadata process, Simulation simulation) { var st = process.Instance.GetType(); var inputbusses = process.Instance.InputBusses.Union(process.Instance.ClockedInputBusses).ToArray(); var outputbusses = process.Instance.OutputBusses.Distinct().ToArray(); var res = new ProcessState() { Name = NameWithoutPrefix(network, st.FullName, st), SourceType = st, CecilType = LoadType(st), SourceInstance = process, InstanceName = process.InstanceName, Parent = network, IsSimulation = process.Instance is SimulationProcess, IsClocked = st.GetCustomAttribute <ClockedProcessAttribute>() != null, Decompile = ( typeof(SimpleProcess).IsAssignableFrom(st) || typeof(StateProcess).IsAssignableFrom(st) ) && !st.HasAttribute <SuppressOutputAttribute>() && !st.HasAttribute <SuppressBodyAttribute>() }; var proctype = res.CecilType.Resolve(); if (res.CecilType is Mono.Cecil.GenericInstanceType) { var gp = res.CecilType as Mono.Cecil.GenericInstanceType; var names = gp.GenericArguments.ToArray(); var ga = proctype.GenericParameters.ToArray(); foreach (var g in ga) { res.GenericMap[g.Name] = g; res.GenericTypes[g.Name] = names[g.Position]; } } res.InputBusses = inputbusses.Select(x => Parse(network, res, x, simulation)).ToArray(); res.OutputBusses = outputbusses.Select(x => Parse(network, res, x, simulation)).ToArray(); res.InternalBusses = process.Instance.InternalBusses.Select(x => Parse(network, res, x, simulation)).ToArray(); foreach (var ib in res.InternalBusses) { ib.IsInternal = true; } // Set up the local names by finding the field that holds the instance reference foreach (var b in res.InputBusses.Union(res.OutputBusses).Union(res.InternalBusses)) { var f = st .GetFields(BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic) .FirstOrDefault(x => x.GetValue(process.Instance) == b.SourceInstance); if (f != null) { res.LocalBusNames[b] = f.Name; } } if (res.Decompile) { // Register all variables foreach (var f in proctype.Fields) { var ft = res.ResolveGenericType(f.FieldType); if (ft.IsBusType()) { RegisterBusReference(network, res, f); } else { RegisterVariable(network, res, f); } } } foreach (var f in process.Initialization) { if (f.Value == null) { continue; } Variable v; if (res.Variables.TryGetValue(f.Key, out v)) { SetDataElementDefaultValue(network, res, v, f.Value, false); } } res.SharedSignals = res.Signals.Values.ToArray(); res.SharedVariables = res.Variables.Values.ToArray(); res.InternalDataElements = new DataElement[0]; return(res); }
/// <summary> /// Parses a a field reference and returns the associated variable /// </summary> /// <returns>The constant element.</returns> /// <param name="network">The top-level network.</param> /// <param name="proc">The process where the method is located.</param> /// <param name="field">The field to parse.</param> protected virtual DataElement RegisterVariable(NetworkState network, ProcessState proc, FieldDefinition field) { DataElement res; var ceciltype = proc.ResolveGenericType(field.FieldType); object defaultvalue = null; proc.SourceInstance.Initialization.TryGetValue(field.Name, out defaultvalue); defaultvalue = field.Constant ?? defaultvalue; if (field.IsLiteral) { var c = new Constant() { CecilType = ceciltype, DefaultValue = defaultvalue, Name = field.Name, Source = field, Parent = proc }; res = c; network.ConstantLookup.Add(field, c); } else if (field.IsStatic && field.IsInitOnly) { var c = new Constant() { CecilType = ceciltype, DefaultValue = defaultvalue, Name = field.Name, Source = field, Parent = proc }; res = c; network.ConstantLookup[field] = c; } else if (field.IsStatic) { //Don't care res = null; } else if (field.GetAttribute <Signal>() == null) { var c = new Variable() { CecilType = ceciltype, DefaultValue = defaultvalue, Name = field.Name, Source = field, Type = null, Parent = proc }; res = c; proc.Variables.Add(field.Name, c); } else { var c = new Signal() { CecilType = ceciltype, DefaultValue = defaultvalue, Name = field.Name, Source = field, Type = null, Parent = proc }; res = c; proc.Signals.Add(field.Name, c); } return(res); }