Пример #1
0
        ///============================================================================================
        ///
        /// scopes
        ///

        // Enter scope for a function definition, with accumulator tracking
        public bool Enter(string ident, AstType rettype, IList <AstField> arguments)
        {
            // missing args means lazy; else check for dups
            if (arguments != null)
            {
                var dups = arguments.GroupBy(a => a.Name).Where(g => g.Count() > 1).Select(d => d.Key);
                if (dups.Count() > 0)
                {
                    Parser.ParseError($"duplicate parameter '{dups.First()}'");
                }
            }
            var args = (arguments == null) ? null
        : arguments.Select(a => DataColumn.Create(a.Name, a.DataType)).ToArray();
            var rtype = (rettype == null) ? DataTypes.Unknown : rettype.DataType;

            // ident means it's func def not funval
            if (ident != null)
            {
                // if cannot define, then see if can overload
                Symbol overfunc = null;
                if (!Symbols.CanDefGlobal(ident))
                {
                    overfunc = Symbols.FindIdent(ident);
                    if (!overfunc.IsCallable)
                    {
                        overfunc = null;
                    }
                    if (overfunc == null)
                    {
                        Parser.ParseError("already defined: {0}", ident);
                    }
                }

                // create new symbol or add an overload
                // error if dup on args; return type not counter
                if (overfunc == null)
                {
                    Symbols.AddDeffun(ident, rtype, args, 0, false);
                }
                else
                {
                    if (args == null)
                    {
                        Parser.ParseError($"overload not allowed: '{ident}'");
                    }
                    if (!Symbols.AddOverload(overfunc, rtype, args))
                    {
                        Parser.ParseError($"overload argument type conflict: '{ident}'");
                    }
                }
            }

            // now prepare scope
            Symbols.CurrentScope.Push();
            if (args != null)
            {
                foreach (var a in args)
                {
                    Symbols.AddVariable(a.Name, a.DataType, SymKinds.PARAM, false);
                }
            }
            _accum = _accum.Push();
            return(true);
        }