예제 #1
0
 // 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)));
 }
예제 #2
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);
        }
예제 #3
0
 bool CanDefGlobal(string name)
 {
     return(Symbols.CanDefGlobal(name));
 }