/// <summary> /// Creates all sub-instances from declarations /// </summary> /// <param name="state">The state to use</param> /// <param name="declarations">The declarations to process</param> /// <param name="parentInstances">The collection of instances to append to</param> private void CreateAndRegisterInstancesForDeclarations(Validation.ValidationState state, IEnumerable <AST.Declaration> declarations, List <Instance.IInstance> parentInstances) { var scope = state.CurrentScope; // Add all variables and locally defined busses foreach (var decl in declarations) { if (decl is EnumDeclaration en) { var e = new Instance.EnumTypeReference(en); scope.TryAddSymbol(e.Name, e, en.Name); using (state.StartScope(e)) CreateAndRegisterInstance(state, e); parentInstances.Add(e); } else if (decl is FunctionDefinition fdef) { scope.TryAddSymbol(fdef.Name.Name, decl, fdef.Name); } else if (decl is ConstantDeclaration cdecl) { var c = new Instance.ConstantReference(cdecl); scope.TryAddSymbol(c.Name, c, cdecl.Name); parentInstances.Add(c); } else if (decl is VariableDeclaration variable) { var v = new Instance.Variable(variable); scope.TryAddSymbol(v.Name, v, variable.Name); parentInstances.Add(v); } else if (decl is BusDeclaration bus) { var b = new Instance.Bus(bus); scope.TryAddSymbol(b.Name, b, bus.Name); using (state.StartScope(b)) CreateAndRegisterInstance(state, b); parentInstances.Add(b); } else { throw new ParserException($"Unable to process {decl.GetType()} inside a process", decl); } } }
/// <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); } }