// Assignment:: VAR? ident := value // If ident does not exist, creates a typed catalog entry (using return type if Funval) // Sets initial value, or updates but only if was VAR and same type public AstStatement Assignment(string ident, AstValue value, string varopt) { if (Symbols.CanDefGlobal(ident)) { if (value is AstFunval) { var cvalue = (value as AstFunval).Value; Symbols.AddDeffun(ident, cvalue.DataType, cvalue.Lookup.Columns, cvalue.Accums, varopt != null); } else { Symbols.AddVariable(ident, value.DataType, SymKinds.CATVAR, varopt != null); } Symbols.AddCatalog(Symbols.FindIdent(ident)); } else { var sym = FindCatVar(ident); if (sym == null || sym.IsCallable || !sym.Mutable) { Parser.ParseError("cannot assign to '{0}'", sym.Name); } if (sym.DataType != value.DataType) { Parser.ParseError("type mismatch: '{0}'", sym.Name); } } return(GenFunCall(FindFunc(SymNames.Assign), Args(Text(ident), value))); }
///============================================================================================ /// /// 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); }
bool CanDefGlobal(string name) { return(Symbols.CanDefGlobal(name)); }