static IScope CreateScope() { ScopeChain scope = new ScopeChain(); Conditional.Register(scope); scope.SetValue("[", new ValueDelimiter("]", DelimiterType.AsArray)); scope.SetValue("'", new ValueDelimiter("'", DelimiterType.AsString)); return scope; }
static IScope CreateValueScope() { ScopeChain scope = new ScopeChain(); Logic.Register(scope); scope.SetValue("[", new ValueDelimiter("]", DelimiterType.AsArray)); scope.SetValue("`", new ValueDelimiter("`", DelimiterType.AsRaw)); return scope; }
static IScope CreateModuleScope() { ScopeChain scope = new ScopeChain(); Module.Register(scope); Values.Register(scope); scope.SetValue("'", new ValueDelimiter("'", DelimiterType.AsString)); scope.SetValue("{", new ValueDelimiter("}", DelimiterType.AsArray, new CreateMap())); return scope; }
static IScope CreateStringScope() { ScopeChain scope = new ScopeChain(); String.Register(scope); ValueDelimiter square = new ValueDelimiter("]", DelimiterType.AsArray); scope.SetValue("[", square); ValueDelimiter str = new ValueDelimiter("'", DelimiterType.AsString); scope.SetValue("'", str); ValueDelimiter curly = new ValueDelimiter("}", DelimiterType.AsArray, new CreateMap()); scope.SetValue("{", curly); return scope; }
public void TestBindFunction() { IScope scope = CreateValueScope(); // a scope with a value for a IScope scopeA = new ScopeChain(scope); scopeA.SetValue("a", new ValueInt(3)); // create a new function that returns a & is bound to a map where a=42 TestSupport.ToValue("l3.setValue { :key :testBound :value ( l3.bindFunction { :function ( l3.createFunction { :post :x :body [ ' a ' ] } ) :map { :a 42 } } ) }", scope); // then eval it against a scope where a!=42 Value value = TestSupport.ToValue("testBound 1", scopeA); Assert.AreEqual(42, value.AsInt); value = TestSupport.ToValue("a", scopeA); Assert.AreEqual(3, value.AsInt); }
internal override Value Eval(DelimiterNode prev, DelimiterNode next, IScope paramScope, IScope bodyScope, INodeRequestor nodes, ILineRequestor requestor) { // if we need prev or next params but they're not there, simply return the function if ((m_usePrevious || m_useNext) && prev == null && next == null) return this; // scope we'll add prev/next/body params to ScopeChain localScope = new ScopeChain(); if (m_usePrevious) { if (prev == null) { if (m_useNext) return new PartialFunctionIn(this, null, next); throw new Loki3Exception().AddMissingValue(true/*bPrevious*/); } Value value1 = ComputeParam(Metadata[keyPreviousPattern], prev, paramScope, nodes, requestor); Value match, leftover; if (!PatternChecker.Do(value1, Metadata[keyPreviousPattern], false/*bShortPat*/, out match, out leftover)) throw new Loki3Exception().AddWrongPattern(Metadata[keyPreviousPattern], value1); if (leftover != null) { if (m_useNext) // currently can't do partials for infix throw new Loki3Exception().AddWrongPattern(Metadata[keyPreviousPattern], value1); // create a partial function that starts w/ match & still needs leftover return new UserFunction(this, match, leftover, null); } Utility.AddToScope(m_pattern1, match, localScope); } if (m_useNext) { if (next == null) { if (m_usePrevious) return new PartialFunctionIn(this, prev, null); throw new Loki3Exception().AddMissingValue(false/*bPrevious*/); } Value value2 = ComputeParam(Metadata[keyNextPattern], next, paramScope, nodes, requestor); Value match, leftover; if (!PatternChecker.Do(value2, Metadata[keyNextPattern], false/*bShortPat*/, out match, out leftover)) throw new Loki3Exception().AddWrongPattern(Metadata[keyNextPattern], value2); // if we created a function that needs a body, add it if present ValueFunction matchFunc = match as ValueFunction; if (matchFunc != null && matchFunc.RequiresBody() && requestor != null) match = EvalList.DoAddBody(matchFunc, bodyScope, requestor); if (leftover != null) { if (m_usePrevious) // currently can't do partials for infix throw new Loki3Exception().AddWrongPattern(Metadata[keyNextPattern], value2); // create a partial function that starts w/ match & still needs leftover return new UserFunction(this, match, null, leftover); } Utility.AddToScope(m_pattern2, match, localScope); } // tack on body if requested if (Metadata.GetOptionalT<bool>("body?", false)) { bool foundBody = false; // if there's a following node, use it DelimiterNode possibleBody = nodes.GetNext(); if (possibleBody != null) { localScope.SetValue("body", UseNodeAsBody(possibleBody)); foundBody = true; } // if no body, use the following lines if (!foundBody && requestor != null) { List<DelimiterList> body = EvalList.DoGetBody(bodyScope, requestor); if (body.Count != 0) { localScope.SetValue("body", new ValueLine(body, bodyScope)); foundBody = true; } } if (!foundBody) // create a partial function that only needs a body return new UserFunction(this, localScope); } // create a new scope and add passed in arguments... ScopeChain scope = (ShouldCreateScope ? new ScopeChain(bodyScope) : bodyScope as ScopeChain); scope.Function = this; if (m_fullPattern != null && m_passed != null) Utility.AddToScope(m_fullPattern, m_passed, scope); // ...and the prev/next/body params we just extracted Utility.AddToScope(localScope, scope); if (m_passedScope != null) Utility.AddToScope(m_passedScope, scope); // lazily parse EnsureParsed(bodyScope); // eval each line using current scope try { Value retval = EvalBody.Do(m_parsedLines, scope); scope.Exit(); return retval; } catch (PopStackException pop) { // if we're supposed to pop back to here then return, else keep throwing up the stack if (pop.ScopeName == scope.Name) return pop.Return; throw pop; } catch (Loki3Exception e) { // if this scope catches exceptions, stop here if (Loki3Exception.catchScopeName == scope.Name) { if (scope.Parent != null) scope.Parent.SetValue(Loki3Exception.exceptionKey, new ValueMap(e.Errors)); return ValueNil.Nil; } throw e; } }
static IScope CreateMathScope() { ScopeChain scope = new ScopeChain(); Math.Register(scope); ValueDelimiter square = new ValueDelimiter("]", DelimiterType.AsArray); scope.SetValue("[", square); return scope; }
static IScope CreateScope() { ScopeChain scope = new ScopeChain(); MapFunctions.Register(scope); scope.SetValue("create-map", new CreateMap()); scope.SetValue("[", new ValueDelimiter("]", DelimiterType.AsArray)); scope.SetValue("{", new ValueDelimiter("}", DelimiterType.AsArray, new CreateMap())); return scope; }
public void TestNested() { try { IScope scope = new ScopeChain(GetBootstrapScope()); string[] lines = { ":result v= 0", "if flag1?", " if flag2?", " :result = 1", " else", " :result = 2", "else", " if flag3?", " :result = 3", " else", " :result = 4", }; { // nested if block is run scope.SetValue("flag1?", ValueBool.True); scope.SetValue("flag2?", ValueBool.True); LineConsumer requestor = new LineConsumer(lines); EvalLines.Do(requestor, scope); Assert.AreEqual(1, scope.GetValue(new Token("result")).AsInt); } { // nested else is run scope.SetValue("flag1?", ValueBool.True); scope.SetValue("flag2?", ValueBool.False); LineConsumer requestor = new LineConsumer(lines); EvalLines.Do(requestor, scope); Assert.AreEqual(2, scope.GetValue(new Token("result")).AsInt); } { // top level else block is run, nested if scope.SetValue("flag1?", ValueBool.False); scope.SetValue("flag3?", ValueBool.True); LineConsumer requestor = new LineConsumer(lines); EvalLines.Do(requestor, scope); Assert.AreEqual(3, scope.GetValue(new Token("result")).AsInt); } { // top level else block is run, nested else scope.SetValue("flag1?", ValueBool.False); scope.SetValue("flag3?", ValueBool.False); LineConsumer requestor = new LineConsumer(lines); EvalLines.Do(requestor, scope); Assert.AreEqual(4, scope.GetValue(new Token("result")).AsInt); } } catch (Loki3Exception e) { Assert.Fail(e.ToString()); } }
static IScope CreateValueScope() { ScopeChain scope = new ScopeChain(); Values.Register(scope); scope.SetValue("(", new ValueDelimiter(")", DelimiterType.AsValue)); scope.SetValue("[", new ValueDelimiter("]", DelimiterType.AsArray)); scope.SetValue("'", new ValueDelimiter("'", DelimiterType.AsString)); scope.SetValue("{", new ValueDelimiter("}", DelimiterType.AsArray, new CreateMap())); scope.SetValue("`", new ValueDelimiter("`", DelimiterType.AsRaw)); return scope; }