internal override Value Eval(Value arg, IScope scope) { Map map = arg.AsMap; bool bInitOnly = map["initOnly?"].AsBool; bool bReturnSuccess = map["returnSuccess?"].AsBool; PatternAssign assign = new PatternAssign(map, scope); Value value = map["value"]; if (bReturnSuccess) { // if we want to know about success, we ignore exceptions, // since they're probably not interested try { bool bSuccess = assign.Assign(value, bInitOnly); return bSuccess ? ValueBool.True : ValueBool.False; } catch (Loki3Exception) { return ValueBool.False; } } else { if (assign.Assign(value, bInitOnly)) return value; return ValueNil.Nil; } }
internal override Value Eval(Value arg, IScope scope) { Map map = arg.AsMap; Value collection = map["collection"]; // todo: consolidate these bodies, one from an explicit param & one from the following lines Value valueBody = map.ContainsKey("body") ? map["body"] : map[ValueFunction.keyBody]; IScope bodyScope = scope; if (valueBody is ValueRaw) { IScope tempScope = (valueBody as ValueRaw).Scope; if (tempScope != null) bodyScope = tempScope; } // todo: abstract iteration to avoid these ifs Value result = ValueNil.Nil; if (collection is ValueString) { string s = collection.AsString; foreach (char c in s) { IScope local = new ScopeChain(bodyScope); PatternAssign assign = new PatternAssign(map, local, true/*bCreate*/); assign.Assign(new ValueString(c.ToString())); result = EvalBody.Do(valueBody, local); local.Exit(); } } else if (collection is ValueArray) { List<Value> list = collection.AsArray; foreach (Value v in list) { IScope local = new ScopeChain(bodyScope); PatternAssign assign = new PatternAssign(map, local, true/*bCreate*/); assign.Assign(v); result = EvalBody.Do(valueBody, local); local.Exit(); } } else if (collection is ValueMap) { Dictionary<string, Value> dict = collection.AsMap.Raw; foreach (string key in dict.Keys) { List<Value> list = new List<Value>(); list.Add(new ValueString(key)); list.Add(dict[key]); IScope local = new ScopeChain(bodyScope); PatternAssign assign = new PatternAssign(map, local, true/*bCreate*/); assign.Assign(new ValueArray(list)); result = EvalBody.Do(valueBody, local); local.Exit(); } } else if (collection is ValueLine) { List<DelimiterList> list = collection.AsLine; // if delimiter is specified, wrap each line w/ it ValueDelimiter delim = scope.GetValue(new Token(map["delim"].AsString)) as ValueDelimiter; if (delim != null) { List<DelimiterList> delimList = new List<DelimiterList>(); int indent = (list.Count > 0 ? list[0].Indent : 0); foreach (DelimiterList line in list) { DelimiterList newLine = line; // wrap lines & nested lines with proper delimiter, except for nested values that get evaled if (line.Indent == indent || (delim.DelimiterType != DelimiterType.AsValue && line.Indent >= indent)) { List<DelimiterNode> nodes = new List<DelimiterNode>(); string original = line.Original; if (delim.DelimiterType == DelimiterType.AsString && line.Indent > indent) { // put the indentation back if portions of the body were indented original = ""; for (int i = 0; i < line.Indent - indent; i++) original += " "; original += line.Original; } nodes.Add(new DelimiterNodeList(new DelimiterList(delim, line.Nodes, line.Indent, "", original, line.Scope))); newLine = new DelimiterList(delim, nodes, indent, "", original, line.Scope); } delimList.Add(newLine); } list = delimList; } // for each line, eval it then eval the body ILineRequestor lines = new LineConsumer(list); while (lines.HasCurrent()) { IScope local = new ScopeChain(bodyScope); Value value = EvalLines.DoOne(lines, local); PatternAssign assign = new PatternAssign(map, local, true/*bCreate*/); assign.Assign(value); result = EvalBody.Do(valueBody, local); local.Exit(); } } return result; }