///============================================================================================ /// /// 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); }