public override SValue Evaluate(ExecEnvironment env) { var dict = this.dict.Evaluate(env); for (var i = 0; i < keys.Count; i++) { if (dict is SDict) { var key = this.keys[i].Evaluate(env) as SString; if (key == null) { throw new VMException("it only take a string as the key", headAtom); } var d = dict.Get <Dictionary <String, SValue> >(); var k = key.Get <String>(); if (!d.ContainsKey(k)) { d[k] = new SNull(); } d[k].RefDict = dict as SDict; d[k].RefDictKey = k; d[k].RefList = null; dict = d[k]; } else if (dict is SList) { var index = this.keys[i].Evaluate(env) as SNumber; if (index == null) { throw new VMException("it only take a number as the index", headAtom); } var l = dict.Get <List <SValue> >(); var idx = (int)index.Get <Decimal>(); if (idx >= l.Count) { throw new VMException("index out of range", headAtom); } l[idx].RefList = dict as SList; l[idx].RefListIndex = idx; l[idx].RefDict = null; dict = l[idx]; } else { throw new VMException("it only take a list or a dict as the first argument", headAtom); } } return(dict); }
public override SValue Evaluate(ExecEnvironment env) { var body = this.body.Evaluate(env) as SClosure; if (body == null) { throw new VMException("the second argument must be a lambda or a named function", headAtom); } SValue _list = this.list.Evaluate(env); List <SValue> values = new List <SValue>(); SList list = new SList(values); bool whileLoop = false; bool condAlwaysTrue = false; if (_list is SList) { list = _list as SList; values = list.Get <List <SValue> >(); if (values.Count == 0) { whileLoop = true; condAlwaysTrue = true; } } else if (_list is SBool) { whileLoop = true; condAlwaysTrue = false; } else { throw new VMException("the first argument must be a list or a bool", headAtom); } if (whileLoop) { while (condAlwaysTrue || this.list.Evaluate(env).Get <bool>()) { var ret = execLoop(body, new SNull(), 0); if (ret.Is <bool>() && !ret.Get <bool>()) { break; } } } else { for (var i = 0; i < values.Count; i++) { var ret = execLoop(body, values[i], i); if (ret.Is <bool>() && !ret.Get <bool>()) { break; } } } return(new SBool(true)); }