示例#1
0
        /// <summary>
        /// Resolves a symbol to be a variable or a bus
        /// </summary>
        /// <param name="expression">The expression to resolve</param>
        /// <param name="scope">The scope to use</param>
        /// <returns>The resolved item or <c>null<c/></returns>
        public Instance.IInstance ResolveSymbol(Expression expression, ScopeState scope)
        {
            if (expression is NameExpression name)
            {
                var symbol = FindSymbol(name.Name, scope);
                if (symbol is Instance.IInstance || symbol == null)
                {
                    return((Instance.IInstance)symbol);
                }
                // We no longer quick-patch for constant declarations, but require that they are all inserted as instances
                // if (symbol is AST.ConstantDeclaration cdecl)
                //     return new Instance.ConstantReference(cdecl);

                // We need to be able to determine array lengths and others when creating the exports
                if (scope == m_rootscope && symbol is AST.ConstantDeclaration cdecl)
                {
                    return(new Instance.ConstantReference(cdecl));
                }

                throw new ParserException($"Got element of type {symbol.GetType().Name} but expected an instance", expression);
            }
            else if (expression is LiteralExpression literal)
            {
                return(new Instance.Literal(literal.Value));
            }
            else
            {
                throw new ParserException($"Expression not supported for binding parameters", expression);
            }
        }
示例#2
0
        /// <summary>
        /// Takes an instance and reduces it to an integer, or throws an exception if this is not possible
        /// </summary>
        /// <param name="source">The source line, used to give indicative error messags</param>
        /// <param name="instance">The instance to reduce</param>
        /// <param name="scope">The scope to use</param>
        /// <returns>An integer</returns>
        public int ResolveToInteger(ParsedItem source, IInstance instance, ScopeState scope)
        {
            if (instance is Instance.ConstantReference constDecl)
            {
                var dt = ResolveTypeName(constDecl.Source.DataType, scope);
                if (dt == null)
                {
                    throw new ParserException($"Failed to resolve data type: {constDecl.Source.DataType}", source);
                }

                if (!dt.IsInteger)
                {
                    throw new ParserException($"Cannot use item of type {constDecl.Source.DataType} as an integer is required", source);
                }
                return(((AST.IntegerConstant)((AST.LiteralExpression)constDecl.Source.Expression).Value).ToInt32);
            }
            else if (instance is Instance.Literal lit)
            {
                if (!(lit.Source is AST.IntegerConstant intConst))
                {
                    throw new ParserException($"Cannot use literal of type {lit.Source} as an integer is required", source);
                }

                return(intConst.ToInt32);
            }

            throw new ParserException($"Must use a constant or literal integer value, got {instance}", source);
        }
示例#3
0
        /// <summary>
        /// Starts a new scope using this as the base scope
        /// </summary>
        /// <param name="items">The items to register for the scope
        /// <returns>A disposable that will unset the current scope</returns>
        public ScopeState StartScope(params object[] items)
        {
            var sc = new ScopeState(SymbolScopes);

            if (items != null)
            {
                foreach (var item in items.Where(x => x != null))
                {
                    LocalScopes[item] = sc;
                }
            }
            return(sc);
        }
示例#4
0
 /// <summary>
 /// The instances
 /// </summary>
 /// <param name="state">The validation state</param>
 /// <param name="instances">The instances to assign types to</param>
 /// <param name="scope">The scope to use for lookup</param>
 private void ResolveTypes(ValidationState state, IEnumerable <Instance.IInstance> instances, ScopeState scope)
 {
     foreach (var r in instances)
     {
         if (r is Instance.ConstantReference cref)
         {
             if (cref.ResolvedType == null)
             {
                 cref.ResolvedType = state.ResolveTypeName(cref.Source.DataType, scope);
             }
         }
         else if (r is Instance.Variable v)
         {
             if (v.ResolvedType == null)
             {
                 v.ResolvedType = state.ResolveTypeName(v.Source.Type, scope);
             }
         }
     }
 }
示例#5
0
 /// <summary>
 /// Finds the item with the given name
 /// </summary>
 /// <param name="name">The name to look for</param>
 /// <param name="scope">The scope to use</param>
 /// <returns>The item matching the name, or null</returns>
 public object FindSymbol(AST.Identifier name, ScopeState scope)
 {
     return(FindSymbol(new AST.Name(name.SourceToken, new [] { name ?? throw new ArgumentNullException(nameof(name)) }, null), scope));
示例#6
0
 /// <summary>
 /// Finds the item with the given name
 /// </summary>
 /// <param name="name">The name to look for</param>
 /// <param name="scope">The scope to use</param>
 /// <returns>The item matching the name, or null</returns>
 public object FindSymbol(string name, ScopeState scope)
 {
     return(FindSymbol(AsName(name), scope));
 }
示例#7
0
 /// <summary>
 /// Resolves an expression to an integer constant, or throws an exception if this is not possible
 /// </summary>
 /// <param name="expression">The expression to resolve</param>
 /// <param name="scope">The scope to use</param>
 /// <returns>An integer</returns>
 public int ResolveToInteger(Expression expression, ScopeState scope)
 {
     return(ResolveToInteger(expression, ResolveSymbol(expression, scope), scope));
 }
示例#8
0
 /// <summary>
 /// Creates a new validation state shadowing the
 /// </summary>
 public ValidationState()
 {
     m_rootscope = new ScopeState(SymbolScopes);
 }
示例#9
0
        /// <summary>
        /// Performs a lookup to find the symbol and returns the datatype of the found symbol
        /// </summary>
        /// <param name="state">The current state</param>
        /// <param name="scope">The scope to use</param>
        /// <param name="name">The name to find</param>
        /// <returns>The datatype or <c>null</c></returns>
        private static DataType FindDataType(Validation.ValidationState state, AST.NameExpression name, ScopeState scope)
        {
            var symb = state.ResolveSymbol(name, scope);

            if (symb == null)
            {
                throw new ParserException($"Unable to find instance for name: {name.Name}", name);
            }

            if (symb is Instance.Variable variable)
            {
                return(variable.ResolvedType = state.ResolveTypeName(variable.Source.Type, scope));
            }
            else if (symb is Instance.Bus bus)
            {
                return(state.ResolveBusSignalTypes(bus, scope));
            }
            else if (symb is Instance.Signal signal)
            {
                return(signal.ResolvedType = state.ResolveTypeName(signal.Source.Type, scope));
            }
            else if (symb is Instance.ConstantReference constant)
            {
                return(constant.ResolvedType = state.ResolveTypeName(constant.Source.DataType, scope));
            }
            else if (symb is Instance.EnumFieldReference efr)
            {
                return(new AST.DataType(name.SourceToken, efr.ParentType.Source));
            }
            else if (symb is Instance.Literal literalInstance)
            {
                if (literalInstance.Source is AST.BooleanConstant)
                {
                    return(new AST.DataType(literalInstance.Source.SourceToken, ILType.Bool, 1));
                }
                else if (literalInstance.Source is AST.IntegerConstant)
                {
                    return(new AST.DataType(literalInstance.Source.SourceToken, ILType.SignedInteger, -1));
                }
                else if (literalInstance.Source is AST.FloatingConstant)
                {
                    return(new AST.DataType(literalInstance.Source.SourceToken, ILType.Float, -1));
                }
            }

            return(null);
        }