Ejemplo n.º 1
0
        // Create piece index from array of section nodes
        // Note: Also does sanity check (first peek inside game/variant definition)
        // The passed in parser is used to generate meaningful errors
        Dictionary <string, Node> CreatePieceLookup(NodeListParser nlp)
        {
            Dictionary <string, Node> lookup = new Dictionary <string, Node>();

            while (!nlp.Done)
            {
                var pnode = nlp.Current; // could be a piece section
                var nlp2  = nlp.GetParser();
                // note: cannot use anything that relies on CheckedIdent
                nlp.Expect(nlp2.IsIdent, "section identifier");
                if (nlp2.GetNode().AsIdent.Name == "piece")
                {
                    while (true)
                    {
                        nlp2.Expect(nlp2.IsList, "piece name");
                        var nlp3 = nlp2.GetParser();
                        if (nlp3.IsIdent && nlp3.GetNode().AsIdent.Name == "name")
                        {
                            if (nlp3.IsIdent)
                            {
                                lookup[nlp3.GetNode().AsIdent.Name] = pnode;
                                break;
                            }
                        }
                    }
                }
            }
            return(lookup);
        }
Ejemplo n.º 2
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);
        }
Ejemplo n.º 3
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");
                }
            }
        }
Ejemplo n.º 4
0
        //--------------------------------------------------------------------------
        // 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
            });
        }
Ejemplo n.º 5
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);
        }
Ejemplo n.º 6
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);
            }
        }
Ejemplo n.º 7
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);
        }
    }