/// <summary> /// Registers an item for usage in a particular direction /// </summary> /// <param name="scope">The scope to use</param> /// <param name="item">The item to register</param> /// <param name="direction">The direction to register</param> /// <param name="sourceExpr">The source expression used for error messages</param> public void RegisterItemUsageDirection(Instance.IParameterizedInstance scope, object item, ItemUsageDirection direction, AST.ParsedItem sourceExpr) { if (scope == null) { throw new ArgumentNullException(nameof(scope)); } if (item == null) { throw new ArgumentNullException(nameof(item)); } if (!ItemDirection.TryGetValue(scope, out var usagescope)) { ItemDirection[scope] = usagescope = new Dictionary <object, ItemUsageDirection>(); } if (item is Instance.Signal signalInstance) { // Get list of parameters with direction from instantiation var directionParam = scope .MappedParameters .Zip( Enumerable.Range(0, scope.MappedParameters.Count), (x, i) => new { Direction = scope.SourceParameters[i].Direction, Bus = x.MappedItem } ) .Where(x => x.Bus == signalInstance.ParentBus) .FirstOrDefault(); // Local bus is bi-directional and does not need checking if (directionParam != null) { var definedDirection = directionParam.Direction; // Flip the signal if it has inverse direction if (signalInstance.Source.Direction == SignalDirection.Inverse) { definedDirection = definedDirection == ParameterDirection.In ? ParameterDirection.Out : ParameterDirection.In; } if (definedDirection == ParameterDirection.Out && direction != ItemUsageDirection.Write) { throw new ParserException($"Can only write to output signal: {signalInstance.Name}", sourceExpr); } if (definedDirection == ParameterDirection.In && direction != ItemUsageDirection.Read) { throw new ParserException($"Can only read from input signal: {signalInstance.Name}", sourceExpr); } } } if (!usagescope.TryGetValue(item, out var d)) { usagescope[item] = direction; } else if (d != direction) { usagescope[item] = ItemUsageDirection.Both; } }
/// <summary> /// Tries to add a new symbol to the table and throws an exception pointing to the offending location /// </summary> /// <param name="name">The name of the item to add</param> /// <param name="item">The item to add</param> /// <param name="token">The token used in the error message</param> public void TryAddSymbol(string name, object item, AST.ParsedItem token) { TryAddSymbol(name, item, token.SourceToken); }