/// <summary> /// Returns all output signals for a process or connection /// </summary> /// <param name="state">The state object</param> /// <returns>The output signals</returns> public IEnumerable <Instance.Signal> OutputSignals(ValidationState state, Instance.Process process) { return(process.MappedParameters .Where(x => x.MappedItem is Instance.Bus) .SelectMany(x => { var isOut = x.MatchedParameter.Direction == AST.ParameterDirection.Out; var parentBus = x.MappedItem as Instance.Bus; return parentBus .Instances .OfType <Instance.Signal>() .Where(y => y.Source.Direction == SignalDirection.Normal ? isOut : !isOut ); }) .Concat( process.Instances .OfType <Instance.Bus>() .SelectMany(x => x.Instances.OfType <Instance.Signal>()) .Where(x => state.ItemDirection[process].ContainsKey(x) && state.ItemDirection[process][x] == ItemUsageDirection.Write ) ) .Distinct()); }
/// <summary> /// Creates all sub-instances for a process /// </summary> /// <param name="state">The state to use</param> /// <param name="parent">The parent process</param> private void CreateAndRegisterInstance(Validation.ValidationState state, Instance.Process parent) { var scope = state.CurrentScope; CreateAndRegisterInstancesForDeclarations(state, parent.ProcessDefinition.Declarations, parent.Instances); // TODO: The scope should work within the statement tree. We can have nested statements.... foreach (var loop in parent.Statements.All().OfType <AST.ForStatement>()) { var l = new Instance.ForLoop(loop.Current); using (var sc = state.StartScope(l, loop.Current)) { var varinst = new Instance.Variable(loop.Current.Variable); sc.TryAddSymbol(loop.Current.Variable.Name.Name, varinst, loop.Current.Variable.SourceToken); } parent.Instances.Add(l); } // Find all function invocations so we can map parameters foreach (var func in parent.Statements.All().OfType <AST.FunctionStatement>()) { var fdef = state.FindSymbol(func.Current.Name, scope); if (fdef == null) { throw new ParserException($"No function named {func.Current.Name.AsString} found", func.Current); } if (!(fdef is AST.FunctionDefinition ffdef)) { throw new ParserException($"Expected a function for {func.Current.Name.AsString}, but found {fdef.GetType()}", func.Current); } var f = new Instance.FunctionInvocation(ffdef, func.Current); using (var sc = state.StartScope(f)) CreateAndRegisterInstancesForDeclarations(state, ffdef.Declarations, f.Instances); parent.Instances.Add(f); } }
/// <summary> /// Creates and registers all network declaration instances /// </summary> /// <param name="state">The state to use</param> /// <param name="networkDecls">The network declarations to instantiate</param> /// <param name="parentCollection"></param> private void CreateAndRegisterInstances(Validation.ValidationState state, IEnumerable <NetworkDeclaration> networkDecls, IList <Instance.IInstance> parentCollection) { var scope = state.CurrentScope; foreach (var decl in networkDecls) { if (decl is AST.BusDeclaration bus) { var b = new Instance.Bus(bus); scope.TryAddSymbol(b.Name, b, bus.Name); using (state.StartScope(b)) CreateAndRegisterInstance(state, b); parentCollection.Add(b); } else if (decl is AST.ConstantDeclaration cdecl) { var cref = new Instance.ConstantReference(cdecl); scope.TryAddSymbol(cref.Name, cref, cdecl.Name); parentCollection.Add(cref); continue; } else if (decl is AST.GeneratorDeclaration genDecl) { var startSymbol = state.ResolveToInteger(genDecl.SourceExpression, scope); var finishSymbol = state.ResolveToInteger(genDecl.TargetExpression, scope); // TODO: Need to fix array support for this to work correctly? for (var i = startSymbol; i < finishSymbol; i++) { CreateAndRegisterInstances(state, genDecl.Networks, parentCollection); } } else if (decl is AST.InstanceDeclaration instDecl) { var sym = state.FindSymbol(instDecl.SourceItem, scope); if (sym != null && sym is AST.Network netw) { // Recursively create network // TODO: Guard against infinite recursion parentCollection.Add(CreateAndRegisterInstance(state, instDecl, netw)); } else if (sym != null && sym is AST.Process proc) { var p = new Instance.Process(instDecl, proc, Instance.ProcessType.Normal); if (instDecl.Name.Name != null) { scope.TryAddSymbol(instDecl.Name.Name.Name, p, instDecl.Name.Name); } using (state.StartScope(p, instDecl)) CreateAndRegisterInstance(state, p); parentCollection.Add(p); } else { if (sym == null) { throw new ParserException($"No item found with the name {instDecl.SourceItem}", decl); } else { throw new ParserException($"The item {instDecl.SourceItem} is not a process, but a {sym.GetType().Name}", decl); } } } else if (decl is AST.ConnectDeclaration connDecl) { foreach (var connEntry in connDecl.Entries) { var p = IdentityHelper.CreateConnectProcess(state, scope, connEntry); using (state.StartScope(p, connEntry)) CreateAndRegisterInstance(state, p); parentCollection.Add(p); } } else { throw new ParserException($"Attempted to create an instance of type: {decl.GetType()}", decl); } } }