void CompileSexpr(SexprNode sexpr, NodeListParser nlp) { Logger.WriteLine(4, "CompileSexpr {0} <{1}>", sexpr, nlp); var snlp = NodeListParser.Create(sexpr.Args, Symbols); _currentparser = snlp; // intrinsics with individual parser and code generator if (sexpr.Sym.IsControl) { if (_controllookup.ContainsKey(sexpr.Sym.Keyword)) { _controllookup[sexpr.Sym.Keyword](sexpr.Sym, snlp, this); } else { nlp.Unexpected("unknown control function"); } } else { CompileBuiltin(sexpr.Sym as BuiltinSymbol, snlp); } }
// 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); }
// 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(); }
// 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); } }
// 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)); }