Example #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)));
 }
Example #2
0
        // name, type and source of a single VAR declaration, can be
        // a) VAR ident : type
        // b) VAR ident [: typewithheading] (source)
        public AstStatement VarDecl(string ident, AstType type, AstLiteral source)
        {
            var what     = ident; // reserved for future use
            var isimport = (source != null);
            var datatype = (type == null) ? null
        : isimport?Types.Relof(type.DataType)
                               : type.DataType;

            if (isimport && datatype == null)
            {
                if (type != null)
                {
                    Parser.ParseError($"type with heading required for '{ident}'");
                }
                datatype = Cat.GetRelvarType(source.Value.ToString(), what); // peek the file
                if (datatype == null)
                {
                    Parser.ParseError("cannot find '{0}' as '{1}'", ident, source);
                }
            }
            Symbols.AddVariable(ident, datatype, SymKinds.CATVAR, true);
            Symbols.AddCatalog(Symbols.FindIdent(ident));
            return((isimport) ? GenFunCall(FindFunc(SymNames.Import), Args(source, Text(ident), Text(what), Text(Parser.Cat.SourcePath)))
        : GenFunCall(FindFunc(SymNames.Assign), Args(Text(ident), LitValue(datatype.DefaultValue()))));
        }
Example #3
0
        public AstTypedef UserType(string ident, AstField[] fields)
        {
            var ff = fields.Select(a => DataColumn.Create(a.Name, a.DataType)).ToArray();
            var ut = DataTypeUser.Get(ident, ff);

            Symbols.AddUserType(ident, ut);
            Symbols.AddCatalog(Symbols.FindIdent(ident));
            return(new AstUserType {
                DataType = DataTypes.Void
            });
        }
Example #4
0
        // finalise function definition, from basic definition previously created
        // set or check return type
        // null body just defines type
        // Note: null arguments means argless (lazy) rather than deffun
        // BUG: a persistent function must not reference a non-persistent global
        public AstStatement Deffun(string ident, AstType rettype, IList <AstField> arguments, AstBodyStatement body)
        {
            var op       = FindDefFunc(ident);
            var callinfo = op.CallInfo;

            if (callinfo.ReturnType == DataTypes.Unknown)
            {
                callinfo.ReturnType = body.DataType;
            }
            else if (callinfo.ReturnType != body.DataType)
            {
                Parser.ParseError($"{ident} return type mismatch");
            }
            if (op.DataType == DataTypes.Unknown)
            {
                if (arguments == null)
                {
                    op.DataType = callinfo.ReturnType;
                }
            }
            else if (op.DataType != callinfo.ReturnType)
            {
                Parser.ParseError("body does not match declared type");
            }

            // assume top overload is the one being defined
            //op.callinfo.ReturnType = op.DataType;
            callinfo.AccumCount = body.AccumCount;
            callinfo.HasWin     = body.HasWin;
            // symbol is foldable if all overloads are foldable
            // FIX: put this test where it's used
            var foldable = (callinfo.NumArgs == 2 && arguments[0].DataType == callinfo.ReturnType && arguments[1].DataType == callinfo.ReturnType) &&
                           (callinfo.OverLoad == null || op.IsFoldable);

            if (foldable && !op.IsFoldable)
            {
                op.Foldable = FoldableFlags.ANY;
            }
            Symbols.AddCatalog(op);

            // assemble node
            var code = Code(body.Statement as AstValue, Headingof(arguments), callinfo.Name, true, body.AccumCount, body.HasWin);

            return(GenFunCall(FindFunc(SymNames.Defer), Args(code)));
        }