Exemplo n.º 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);
        }
Exemplo n.º 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");
                }
            }
        }
Exemplo n.º 3
0
        // Compile a scoped expression that returns a typed value
        DataTypes CompileExpr(PredefScopes predef, NodeListParser nlp)
        {
            Logger.WriteLine(2, "CompileExpr {0} <{1}>", predef, nlp);

            Symbols.PushPredefScope(predef);
            var codetype = Symbols.PredefScopeDict[predef].CodeType;

            _gen.EmitEntry(codetype);

            nlp.Expect(nlp.IsCallable, "callable function");
            var sexpr = nlp.GetSexprNode();

            nlp.Expect(sexpr.DataType != DataTypes.Void, "typed function");
            CompileSexpr(sexpr, nlp);

            Symbols.PopPredefScope();
            _gen.EmitExit(true);
            return(sexpr.DataType);
        }
Exemplo n.º 4
0
        //void CompileValue(Type type, NodeListParser nlp) {
        //  Logger.WriteLine(4, "CompileValue {0} <{1}>", type, nlp);

        //  var func = _typeactiondict.SafeLookup(type);
        //  // bracketed expression with arguments
        //  if (nlp.IsSexpr) {
        //    var sexpr = nlp.GetSexprNode();
        //    var datatype = TypedValue.DataTypeDict.SafeLookup(type);
        //    nlp.Expect(sexpr.DataType == datatype, "value of type {0}", datatype);
        //    CompileSexpr(sexpr, nlp);
        //  } else if (nlp.IsFunc) {
        //    // bare function no arguments
        //    var sym = nlp.GetIdent().Sym as BuiltinSymbol;
        //    CompileBuiltin(sym, NodeListParser.Null);
        //  } else if (nlp.IsVariable) {
        //    var sym = nlp.GetIdent().Sym;
        //    _gen.EmitLoadVar(sym);
        //  } else if (nlp.IsAttribute || (nlp.IsList && nlp.PeekList.IsAttribute)) {
        //    var handler = Symbols.Find("--attribute") as BuiltinSymbol;
        //    if (handler != null)
        //      CompileBuiltin(handler, nlp.GetParser());
        //    else nlp.Syntax("attribute not allowed here");
        //  } else if (func != null) {
        //    // direct lookup to get constant value
        //    var value = func(type, nlp, this);
        //    _gen.EmitLoadValue(value);
        //  } else nlp.Unexpected("unknown type {0}", type);
        //}

        //--------------------------------------------------------------------------
        // Compile control constructs that generate GOTOs and emit custom code

        void CompileIf(Symbol sym, NodeListParser nlp)
        {
            CompileArg(typeof(BoolValue), nlp);
            var pos1 = _gen.Counter;

            _gen.EmitGoFalse(0);
            CompileProg(nlp); // will return without taking else
            if (nlp.IsCallable && nlp.CurrentIdent.Sym.Keyword == Keywords.ELSE)
            {
                nlp.GetSexprNode();
                var pos2 = _gen.Counter;
                _gen.EmitGoTo(0);
                _gen.Fixup(pos1);
                CompileProg(nlp);
                _gen.Fixup(pos2);
            }
            else
            {
                _gen.Fixup(pos1);
            }
        }
Exemplo n.º 5
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);
            }
        }