Пример #1
0
        // Compile a literal, symbol or expression that returns a typed value
        // Return datatype to caller for type checking
        DataTypes CompileValue(Type type, NodeListParser nlp)
        {
            Logger.WriteLine(4, "CompileValue {0} <{1}>", type, nlp);

            // bracketed expression with arguments
            if (nlp.IsSexpr)
            {
                var sexpr = nlp.GetSexprNode();
                CompileSexpr(sexpr, nlp);
                return(sexpr.DataType);
            }
            if (nlp.IsFunc)
            {
                // bare function no arguments
                var sym = nlp.GetIdent().Sym as BuiltinSymbol;
                CompileBuiltin(sym, NodeListParser.Null);
                return(sym.DataType);
            }
            if (nlp.IsVariable)
            {
                var sym = nlp.GetIdent().Sym;
                _gen.EmitLoadVar(sym);
                return(sym.DataType);
            }
            if (nlp.IsAttribute || (nlp.IsList && nlp.CheckedHead.IsAttribute))
            {
                var handler = Symbols.Find("--attribute") as BuiltinSymbol;
                if (handler != null)
                {
                    CompileBuiltin(handler, nlp.GetParser());
                }
                else
                {
                    nlp.Syntax("attribute not allowed here");
                }
                return(handler.DataType);
            }
            var func = _typeactiondict.SafeLookup(type);

            if (func != null)
            {
                // direct lookup to get constant value
                var value = func(type, nlp, this) as TypedValue;
                _gen.EmitLoadValue(value);
                return(value.DataType);
            }
            nlp.Unexpected("unknown type {0}", type);
            return(DataTypes.Unknown);
        }
Пример #2
0
        // compile a prog block inside an existing scope
        internal void CompileProg(NodeListParser nlp)
        {
            Logger.WriteLine(2, "CompileProg <{0}>", nlp);
            // iterate over the action items in the prog block
            while (!nlp.Done)
            {
                // value -- special handler
                if (nlp.IsValue || nlp.IsValueCallable)
                {
                    if (!CompileHandler("--value", nlp))
                    {
                        nlp.Syntax("bare value not allowed");
                    }

                    // callable function, call it
                }
                else if (nlp.IsCallable)
                {
                    if (nlp.IsFunc && nlp.CurrentIdent.Sym.Keyword == Keywords.ELSE)
                    {
                        return;                                                    // sneaky!
                    }
                    var sexpr = nlp.GetSexprNode();
                    nlp.Expect(sexpr.DataType == DataTypes.Void, "void function");
                    CompileSexpr(sexpr, nlp);

                    // list -- special handler
                }
                else if (nlp.IsList)
                {
                    var handler = Symbols.Find("--list") as BuiltinSymbol;
                    if (handler != null)
                    {
                        CompileBuiltin(handler, nlp.GetParser());
                    }
                    else
                    {
                        nlp.Unexpected("unknown function");
                    }
                }
                else
                {
                    nlp.Expected("function call");
                }
            }
        }
Пример #3
0
 // these functions serve to ensure that symbols in nodes are defined as the right type
 protected TypedValue DefSymbolValue(IdentNode node, TypedValue value)
 {
     if (node.Sym.IsValue && node.Sym.DataType == value.DataType)
     {
         return(node.Sym.Value);
     }
     Logger.WriteLine(3, "Getsym adding {0} value:{1} type:{2}", node.Sym.Name, value, value.DataType);
     // will create new symbol and store in symbol table, so other nodes see the same thing
     if (node.Sym.IsUndef)
     {
         Symbols.DefineValue(node.Name, value);
     }
     else if (value.GetType() == typeof(IdentValue) && node.Sym.Value is IdentValue)
     {
         ; // any subclass will do for flag. TODO: reverse operation if flag defined first
     }
     else
     {
         _currentparser.Syntax("already defined {0} as type {1}", node.Name, node.Sym.DataType);
     }
     return(value);
 }
Пример #4
0
        // Compile an argument of given type
        void CompileArg(Type type, NodeListParser nlp)
        {
            Logger.WriteLine(4, "CompileArg {0} <{1}>", type, nlp);

            var func = _typeactiondict.SafeLookup(type);

            // special for variable assignment and implicit definition
            if (type == typeof(Variable))
            {
                var ident    = nlp.GetIdent();
                var datatype = DataTypes.Bool; // TODO: handle other types
                if (ident.Sym.IsVariable)
                {
                    nlp.Expect(ident.Sym.DataType == datatype, "variable of type {0}", datatype);
                }
                else if (ident.Sym.IsUndef)
                {
                    Symbols.DefineVariable(ident.Name, datatype, BoolValue.False);
                }
                else
                {
                    nlp.Expected("defined variable");
                }
                _gen.EmitRefVar(ident.Sym);

                // handle these separately, could be variable or function
            }
            else if (type.IsSubclassOf(typeof(TypedValue)))
            {
                // TODO: type checking
                CompileValue(type, nlp);
                //var exptype = TypedValue.DataTypeDict.SafeLookup(type);
                //var rettype = CompileValue(type, nlp);
                //nlp.Expect(rettype == exptype, "value of type {0}", exptype);

                // direct lookup gets special cases; else continue
            }
            else if (func != null)
            {
                var value = func(type, nlp, this);
                _gen.EmitLoadValue(value);

                // Array means parse a list of this type
            }
            else if (type.IsArray)
            {
                var nargs = 0;
                for (var nlp2 = nlp.GetParser(); !nlp2.Done; nargs++)
                {
                    CompileArg(type.GetElementType(), nlp2);
                }
                _gen.EmitToArray(type, nargs);

                // List<> means parse a tail of this type
            }
            else if (type.IsGenericType && type.Name.StartsWith("List"))
            {
                var nargs = 0;
                for (; !nlp.Done; ++nargs)
                {
                    CompileArg(type.GetGenericArguments()[0], nlp);
                }
                _gen.EmitToList(type, nargs);

                // Pair<> means parse a pair of arbitrary types
            }
            else if (type.IsGenericType && type.Name.StartsWith("Pair"))
            {
                var nlp2 = nlp.GetParser();
                foreach (var subtype in type.GetGenericArguments())
                {
                    CompileArg(subtype, nlp2);
                }
                _gen.EmitToPair(type);

                // nested prog block
            }
            else if (type.IsSubclassOf(typeof(CodeBase)))
            {
                var info = Symbols.PredefScopeDict.First(kv => kv.Value.CodeType == type).Value;
                CompileProg(info, nlp);
            }
            else if (type == typeof(PositionOrDirection))
            {
                CompilePositionOrDirection(nlp);

                // function call on built in
            }
            else if (nlp.IsSexpr)
            {
                var sexpr    = nlp.GetSexprNode();
                var datatype = TypedValue.DataTypeDict.SafeLookup(type);
                nlp.Expect(sexpr.DataType == datatype, "value of type {0}", datatype);
                CompileBuiltin(sexpr.Sym as BuiltinSymbol, NodeListParser.Create(sexpr.Args, Symbols));
            }
            else
            {
                nlp.Syntax("unknown type {0}", type);
            }
        }