예제 #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
 PieceImages ParsePieceImages(NodeListParser nlp)
 {
     return(new PieceImages {
         Player = DefPlayer(nlp.GetIdent()),
         Images = nlp.While(n => n.IsString, n => n.GetText()).ToList(),
     });
 }
예제 #3
0
파일: Node.cs 프로젝트: david-pfx/Polygamo
        // take a list of headed nodes and return as a dictionary
        // note: key is name of head ident
        internal static Dictionary <string, List <List <Node> > > GetDict(IList <Node> nn)
        {
            var dict = new Dictionary <string, List <List <Node> > >();

            foreach (var n in nn)
            {
                NodeListParser nlp = NodeListParser.Create(n);
                //dict.AddMulti(nlp.Current.AsIdent.Ident, nlp.Nodes.ToList()); // breaking!!!
                dict.AddMulti(nlp.GetIdent().Name, nlp.GetTail().ToList());
            }
            return(dict);
        }
예제 #4
0
        PlacementDef ParsePlacement(NodeListParser nlp)
        {
            var off     = 0;
            var poslist = new List <PositionValue>();
            var piece   = DefPiece(nlp.GetIdent());

            while (!nlp.Done)
            {
                var ident = nlp.GetIdent();
                if (ident.Name == "off")
                {
                    off = nlp.GetInt();
                }
                else
                {
                    poslist.Add(DefPosition(ident));
                }
            }
            return(new PlacementDef {
                Piece = piece, OffQuantity = off, Positions = poslist
            });
        }
예제 #5
0
 protected OptionValue GetOption(NodeListParser nlp)
 {
     if (nlp.IsNumber)
     {
         return(OptionValue.Create(nlp.GetNumber().Value));
     }
     if (nlp.IsBool)
     {
         return(OptionValue.Create(nlp.GetBool().Value ? 1 : 0));
     }
     // note that options are case insensitive
     if (nlp.IsIdent && _optionlookup.ContainsKey(nlp.CurrentIdent.Name.ToLower()))
     {
         return(_optionlookup[nlp.GetIdent().Name.ToLower()]);
     }
     nlp.Expected("number or option keyword");
     return(OptionValue.Default);
 }
예제 #6
0
        OccupierDef ParseOccupier(NodeListParser nlp)
        {
            //NOTE: this change allows dropping parens, but breaks order dependence
            //if (nlp.IsIdent && (nlp.CurrentIdent.IsPiece || nlp.CurrentIdent.IsDirection)) {

            // take ident; define as piece if not direction
            if (nlp.IsIdent)
            {
                var ident = nlp.GetIdent();
                if (ident.IsDirection) // only used by relative-config
                {
                    return(OccupierDef.Create(ident.AsValue as DirectionValue));
                }
                else
                {
                    return(OccupierDef.Create(PlayerKinds.Friend, DefPiece(ident)));
                }
            }
            // note: relies on dummy functions defined in scope
            if (nlp.IsList && nlp.IsCallable)
            {
                var nlp2  = nlp.GetParser();
                var ident = nlp2.GetIdent();
                if (ident.Sym.Name == "not")
                {
                    return(ParseOccupier(nlp2).SetNot());
                }
                else
                {
                    var piece = DefPiece(nlp2.GetIdent());
                    nlp2.CheckDone();
                    if (ident.Sym.Name == "opponent")
                    {
                        return(OccupierDef.Create(PlayerKinds.Enemy, piece));
                    }
                    if (ident.Sym.Name == "any-owner")
                    {
                        return(OccupierDef.Create(PlayerKinds.Any, piece));
                    }
                }
            }
            return(null);
        }
예제 #7
0
        // Compile a function with given arguments
        void CompileBuiltin(BuiltinSymbol funcsym, NodeListParser nlp)
        {
            Logger.WriteLine(3, "CompileBuiltin {0} <{1}>", funcsym.Name, nlp);
            var ci = funcsym.CallInfo;

            for (int i = 0; i < ci.Arguments.Count; i++)
            {
                if (ci.ArgOptional[i] && nlp.Done)
                {
                    _gen.EmitLoadValue(null);
                }
                else if (ci.Arguments[i] == typeof(AttributeValue))
                {
                    _gen.EmitLoadValue(DefAttribute(nlp.GetIdent())); // special for attribute
                }
                // TODO: could possibly check for combo of boolean expected and undefined ident, and emit false
                else
                {
                    CompileArg(ci.Arguments[i], nlp);
                }
            }
            nlp.Expect(nlp.Done, "no more arguments for {0}", funcsym.Name);
            _gen.EmitCall(funcsym);
        }
예제 #8
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);
            }
        }
예제 #9
0
        Maybe <PositionOrZone> ParseMaybePositionOrZone(NodeListParser nlp)
        {
            if (nlp.IsConstant)
            {
                var value = nlp.Current.AsValue;
                if (value is PositionValue || value is ZoneValue)
                {
                    return new Maybe <PositionOrZone> {
                               Value = ParsePositionOrZone(nlp)
                    }
                }
                ;
            }
            return(new Maybe <PositionOrZone> {
            });
        }

        // parse a term which may be a position, direction or opposite
        void CompilePositionOrDirection(NodeListParser nlp)
        {
            var rettype = CompileValue(typeof(TypedValue), nlp);

            nlp.Expect(rettype == DataTypes.Position || rettype == DataTypes.Direction, "position or direction");
            var funcsym = Symbols.Find("--pos-or-dir");

            _gen.EmitCall(funcsym as BuiltinSymbol);
        }

        //protected PositionOrDirection ParsePositionOrDirection(NodeListParser nlp) {
        //  if (nlp.IsValue) {
        //    var value = nlp.GetValue();
        //    if (value is PositionValue || value is DirectionValue)
        //      return new PositionOrDirection { Value = value };
        //  }
        //  nlp.Expected("position or direction");
        //  return null;
        //}

        GoKinds ParseGoKind(NodeListParser nlp)
        {
            var ident = nlp.GetIdent();
            var gosym = Symbols.Find(ident.Name, PredefKinds.GO);

            nlp.Expect(gosym != null, "valid go target");
            return(gosym.GoKind);
        }

        Maybe <PlayerValue[]> ParseMaybePlayers(NodeListParser nlp)
        {
            if (!(nlp.IsList && nlp.CheckedHead.IsPlayer))
            {
                return(Maybe <PlayerValue[]> .Null);
            }
            return(Maybe <PlayerValue[]> .Create(nlp.GetParser().UntilDone(n => DefPlayer(n.GetIdent())).ToArray()));
        }

        Maybe <PieceValue> ParseMaybePiece(NodeListParser nlp)
        {
            return((nlp.IsIdent && nlp.Current.IsPiece)
        ? Maybe <PieceValue> .Create(DefPiece(nlp.GetIdent()))
        : Maybe <PieceValue> .Null);
        }

        Maybe <PlayerValue> ParseMaybePlayer(NodeListParser nlp)
        {
            return((nlp.IsIdent && nlp.Current.IsPlayer)
        ? Maybe <PlayerValue> .Create(DefPlayer(nlp.GetIdent()))
        : Maybe <PlayerValue> .Null);
        }
    }