コード例 #1
0
ファイル: Compiler.cs プロジェクト: david-pfx/Polygamo
 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);
 }
コード例 #2
0
ファイル: Compiler.cs プロジェクト: david-pfx/Polygamo
 PositionOrZone ParsePositionOrZone(NodeListParser nlp)
 {
     if (nlp.IsConstant)
     {
         var value = nlp.GetValue();
         if (value is PositionValue || value is ZoneValue)
         {
             return new PositionOrZone {
                        Value = value
             }
         }
         ;
         else
         {
         }
     }
     nlp.Expected("position or zone");
     return(null);
 }
コード例 #3
0
ファイル: Compiler.cs プロジェクト: david-pfx/Polygamo
        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);
        }
コード例 #4
0
ファイル: Compiler.cs プロジェクト: david-pfx/Polygamo
        // 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);
        }
コード例 #5
0
ファイル: Compiler.cs プロジェクト: david-pfx/Polygamo
 // Compile top level scoped program block, scoped expression or variant merge
 private void CompileProg(BuiltinScopeInfo info, NodeListParser nlp)
 {
     if (info.Kind == PredefKinds.PROGM)
     {
         CompileGameOrVariant(info.Predef, nlp);
     }
     else if (info.Kind == PredefKinds.PROG)
     {
         CompileProg(info.Predef, nlp);
     }
     else if (info.Kind == PredefKinds.EXPR)
     {
         CompileExpr(info.Predef, nlp);
     }
     else
     {
         throw Error.Assert("{0}", info.Kind);
     }
 }
コード例 #6
0
ファイル: Compiler.cs プロジェクト: david-pfx/Polygamo
        //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);
            }
        }
コード例 #7
0
ファイル: Compiler.cs プロジェクト: david-pfx/Polygamo
        internal void CompileProg(PredefScopes predef, NodeListParser nlp)
        {
            Logger.WriteLine(2, "CompileProg {0} <{1}>", predef, nlp);

            _currentparser = nlp;
            Symbols.PushPredefScope(predef);
            if (predef == PredefScopes.GAME)
            {
                Symbols.CurrentScope.Push();
            }
            var codetype = Symbols.PredefScopeDict[predef].CodeType;

            _gen.EmitEntry(codetype);
            CompileProg(nlp);
            _gen.EmitExit(false);
            Symbols.PopPredefScope();
            if (predef == PredefScopes.GAME)
            {
                Symbols.CurrentScope.Pop();
            }
        }
コード例 #8
0
ファイル: Compiler.cs プロジェクト: david-pfx/Polygamo
        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
            });
        }
コード例 #9
0
ファイル: Compiler.cs プロジェクト: david-pfx/Polygamo
        //--------------------------------------------------------------------------
        // Parsers for individual productions that return a data structure

        //: (TURN-ORDER { player | ( player move-type ) | ( player player ) | ( player player move-type ) | REPEAT }+ )?
        TurnDef ParseTurnDef(NodeListParser nlparg)
        {
            Logger.WriteLine(4, "ParseTurnDef <{0}>", nlparg);
            nlparg.Expect(nlparg.IsIdent || nlparg.IsList, "player or list");

            var nlp   = nlparg.GetParser();
            var ident = nlp.GetIdent();

            if (ident.Name == "repeat")
            {
                nlp.CheckDone();
                return(TurnDef.Repeat);
            }
            var player = DefPlayer(ident);
            // default is to play as self
            var playeras = nlp.IsIdent && nlp.Current.IsPlayer ? DefPlayer(nlp.GetIdent()) : player;
            var movetype = nlp.IsIdent ? DefMoveType(nlp.GetIdent()) : MoveTypeValue.Any;

            nlp.CheckDone();
            return(new TurnDef {
                TurnPlayer = player, MovePlayer = playeras, MoveType = movetype
            });
        }
コード例 #10
0
ファイル: Compiler.cs プロジェクト: david-pfx/Polygamo
        // Compile and merge nodes from base game and variant
        internal void CompileGameOrVariant(PredefScopes predef, NodeListParser nlp)
        {
            Logger.WriteLine(1, "CompileGameOrVariant {0} <{1}>", predef, nlp);

            Symbols.PushPredefScope(predef);
            Symbols.CurrentScope.Push(); // game index will define pieces
            if (_game_index == null)
            {
                _game_index    = new GameIndex();
                _currentparser = NodeListParser.Create(_game_index.IndexGame(nlp), nlp.Symbols);
            }
            else
            {
                _currentparser = NodeListParser.Create(_game_index.MergeVariant(nlp), nlp.Symbols);
            }
            var codetype = Symbols.PredefScopeDict[predef].CodeType;

            _gen.EmitEntry(codetype);
            CompileProg(_currentparser);
            _gen.EmitExit(false);
            Symbols.CurrentScope.Pop();
            Symbols.PopPredefScope();
        }
コード例 #11
0
ファイル: Compiler.cs プロジェクト: david-pfx/Polygamo
        // merge game and variant to create new game
        internal IList <Node> MergeVariant(NodeListParser nlp)
        {
            // Rule 1. Remove all piece nodes -- special handling at end
            var plookup = CreatePieceLookup(nlp);
            var vnodes  = nlp.Nodes.Where(n => name(n) != "piece").ToList();

            // Rule 2. If variant has any conditions, remove all game conditions
            var hascond  = vnodes.Any(v => condlookup.Contains(name(v)));
            var gnodesng = (hascond) ? _gnodes.Where(n => !condlookup.Contains(name(n))) : _gnodes;

            // Rule 3. For each game node, replace with matching variant node if any
            // Note: must use each variant node only once; preserves order of input file
            var newnodes = new List <Node>();

            foreach (var n in gnodesng)
            {
                var i = vnodes.FindIndex(v => name(n) == name(v));
                if (i != -1)
                {
                    newnodes.Add(vnodes[i]);
                    vnodes.RemoveAt(i);
                }
                else
                {
                    newnodes.Add(n);
                }
            }

            // Rule 3. Append any unmatched variant nodes to the end, followed by pieces
            newnodes.AddRange(vnodes);
            newnodes.AddRange(GetPieceList(plookup));

//      Logger.WriteLine(3, "Merge {0} '{1}' '{2}'", hascond, vnodes.Select(n => name(n)).Join(),
//        newnodes.Select(n => name(n)).Join());
            return(newnodes);
        }
コード例 #12
0
ファイル: Compiler.cs プロジェクト: david-pfx/Polygamo
        // 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);
        }
コード例 #13
0
ファイル: Compiler.cs プロジェクト: david-pfx/Polygamo
        // 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);
            }
        }
コード例 #14
0
ファイル: Compiler.cs プロジェクト: david-pfx/Polygamo
 // main entry point, parses all the variants and returns a list
 internal void CompileMenu(IList <Node> nodes)
 {
     Logger.WriteLine(1, "CompileMenu {0} nodes", nodes.Count);
     CompileProg(PredefScopes.MENU, NodeListParser.Create(nodes, Symbols));
 }
コード例 #15
0
ファイル: Compiler.cs プロジェクト: david-pfx/Polygamo
        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);
        }
    }