public IEnumerable <MondValue> Enumerate(MondState state) { var enumerator = this; var moveNext = enumerator["moveNext"]; if (moveNext.Type != MondValueType.Function) { var getEnumerator = this["getEnumerator"]; if (getEnumerator.Type != MondValueType.Function) { throw new MondRuntimeException("Value is not enumerable"); } enumerator = state.Call(getEnumerator); moveNext = enumerator["moveNext"]; if (moveNext.Type != MondValueType.Function) { throw new MondRuntimeException("Value is not enumerable"); } } while (state.Call(moveNext)) { yield return(enumerator["current"]); } }
internal bool TryDispatch(string name, out MondValue result, params MondValue[] args) { if (Type != MondValueType.Object) { result = Undefined; return(false); } // we can't use the indexer for metamethod lookups because that // could lead to infinite recursion, so we have a simplified // lookup here MondState state = null; MondValue callable; var current = this; while (true) { if (current.AsDictionary.TryGetValue(name, out callable)) { // we need to use the state from the metamethod's object state = current.ObjectValue.State; // and we need to wrap functions if needed callable = CheckWrapFunction(callable); break; } current = current.Prototype; if (current == null || current.Type != MondValueType.Object) { break; } } if (callable == null) { result = Undefined; return(false); } if (state == null) { throw new MondRuntimeException("MondValue must have an attached state to use metamethods"); } result = state.Call(callable, args); return(true); }
static void Main() { /*const string source1 = @" var a = [1, 2, 3]; return a.length(); ";*/ const string source1 = @" fun fibonacci(n) { fun inner(m, a, b) { if (m == 0) return a; return inner(m - 1, b, a + b); } return inner(n, 0, 1); } return fibonacci(50); "; try { var state = new MondState(); state["call"] = new MondFunction((_, args) => state.Call(args[0], args[1])); var program1 = MondProgram.Compile(source1, "test1.mnd"); //var program2 = MondProgram.Compile(source2, "test2.mnd"); var result1 = state.Load(program1); //var result2 = state.Load(program2); Console.WriteLine(result1.ToString()); //Console.WriteLine(result2.ToString()); } catch (MondException e) { Console.WriteLine(e.Message); } Console.ReadLine(); }