// 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); }
PieceImages ParsePieceImages(NodeListParser nlp) { return(new PieceImages { Player = DefPlayer(nlp.GetIdent()), Images = nlp.While(n => n.IsString, n => n.GetText()).ToList(), }); }
// 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); }
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 }); }
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); }
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); }
// 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); }
// 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); } }
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); } }