Пример #1
0
        public void Test()
        {
            try
            {
                ScopeChain scope = new ScopeChain();
                AllBuiltins.RegisterAll(scope);
                EvalFile.Do("l3/bootstrap.l3", scope);
                EvalFile.Do("l3/unittest.l3", scope);

                // use the loki3 unittest framework to test the code
                {
                    Value v = TestSupport.ToValue("unittest [ :l3/help.l3 :l3/help_tests.l3 ]", scope);
                    Assert.True(v.AsBool);
                }
                {
                    Value v = TestSupport.ToValue("unittest [ :l3/test.l3 :l3/test_tests.l3 ]", scope);
                    Assert.True(v.AsBool);
                }
                {
                    Value v = TestSupport.ToValue("runTestFile :l3/pattern_tests.l3", scope);
                    Assert.True(v.AsBool);
                }
            }
            catch (Loki3Exception e)
            {
                Assert.Fail(e.ToString());
            }
        }
Пример #2
0
 static ScopeChain Bootstrap()
 {
     ScopeChain scope = new ScopeChain();
     AllBuiltins.RegisterAll(scope);
     EvalFile.Do("bootstrap.l3", scope);
     EvalFile.Do("help.l3", scope);
     return scope;
 }
Пример #3
0
        static IScope CreateScope()
        {
            ScopeChain scope = new ScopeChain();
            Conditional.Register(scope);

            scope.SetValue("[", new ValueDelimiter("]", DelimiterType.AsArray));
            scope.SetValue("'", new ValueDelimiter("'", DelimiterType.AsString));

            return scope;
        }
Пример #4
0
        static IScope CreateValueScope()
        {
            ScopeChain scope = new ScopeChain();
            Logic.Register(scope);

            scope.SetValue("[", new ValueDelimiter("]", DelimiterType.AsArray));
            scope.SetValue("`", new ValueDelimiter("`", DelimiterType.AsRaw));

            return scope;
        }
Пример #5
0
        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;
        }
Пример #6
0
        public void TestComplex()
        {
            try
            {
                IScope scope = new ScopeChain(GetBootstrapScope());

                // define complex math
                string[] lines = {
                    // complex [ 1 2 ] -> 1+2i
                    ":complex v= func1 [ ->x ->y ]",
                    "	{ :real x :imaginary y }",
                    ":complex @order 1",
                    // 5 i -> 5i
                    ":i v= .( ->y 1func",
                    "	{ :real 0 :imaginary y }",
                    ":i @order 1",
                    // addition
                    // todo: adjust when we have function overloading & default values
                    ":+c v= .( { :real ->x1 :imaginary ->y1 } 1func1 { :real ->x2 :imaginary ->y2 }",
                    "	{ :real ( x1 + x2 ) :imaginary ( y1 + y2 ) }",
                    ":+i v= .( ->x1 1func1 { :real ->x2 :imaginary ->y2 }",
                    "	{ :real ( x1 + x2 ) :imaginary y2 }",
                };
                LineConsumer requestor = new LineConsumer(lines);
                EvalLines.Do(requestor, scope);

                {
                    Value value = TestSupport.ToValue("complex [ 1 2 ]", scope);
                    Assert.AreEqual("{ :real 1 , :imaginary 2 }", value.ToString());
                }

                {
                    Value value = TestSupport.ToValue("4 i", scope);
                    Assert.AreEqual("{ :real 0 , :imaginary 4 }", value.ToString());
                }

                {
                    Value value = TestSupport.ToValue("1 +i 3 i", scope);
                    Assert.AreEqual("{ :real 1 , :imaginary 3 }", value.ToString());
                }

                {
                    Value value = TestSupport.ToValue("( 1 +i 3 i ) +c complex [ 4 6 ]", scope);
                    Assert.AreEqual("{ :real 5 , :imaginary 9 }", value.ToString());
                }
            }
            catch (Loki3Exception e)
            {
                Assert.Fail(e.ToString());
            }
        }
Пример #7
0
        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;
        }
Пример #8
0
        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);
        }
Пример #9
0
            internal override Value Eval(Value arg, IScope scope)
            {
                Map map = arg.AsMap;

                List<DelimiterNode> check = (map["check"] as ValueRaw).GetValue().Nodes;
                Value changeVal = map["change"];
                List<DelimiterNode> change = changeVal is ValueNil ? null : (changeVal as ValueRaw).GetValue().Nodes;
                bool checkFirst = map["checkFirst?"].AsBool;
                // todo: consolidate these bodies, one from an explicit param & one from the following lines
                Value valueBody = map.ContainsKey("body") ? map["body"] : map[ValueFunction.keyBody];

                bool isFirst = true;
                Value result = ValueBool.False;
                while (true)
                {
                    // check if we should stop loop
                    if (!isFirst || checkFirst)
                    {
                        Value retval = EvalList.Do(check, scope);
                        if (!retval.AsBool)
                            return result;	// last value of body
                    }
                    else
                    {
                        isFirst = false;
                    }

                    // use bound scope if available
                    IScope parentScope = scope;
                    if (valueBody is ValueRaw)
                    {
                        IScope rawScope = (valueBody as ValueRaw).Scope;
                        if (rawScope != null)
                            parentScope = rawScope;
                    }

                    // eval body
                    IScope local = new ScopeChain(parentScope);
                    result = EvalBody.Do(valueBody, local);
                    local.Exit();

                    // if per-loop code was passed, run it
                    if (change != null)
                        EvalList.Do(change, scope);
                }
            }
Пример #10
0
            internal override Value Eval(Value arg, IScope scope)
            {
                Map map = arg.AsMap;
                ValueFunction function = map["function"] as ValueFunction;
                ValueMap mapOrScope = map["map"] as ValueMap;
                Value prevValue = map["previous"];
                Value nextValue = map["next"];

                // either use the scope the map represents
                // or dummy up a scope for the passed in map
                IScope where = mapOrScope.Scope;
                if (where == null)
                    where = new ScopeChain(mapOrScope.AsMap);

                DelimiterNodeValue prev = (prevValue == ValueNil.Nil ? null : new DelimiterNodeValue(prevValue));
                DelimiterNodeValue next = (nextValue == ValueNil.Nil ? null : new DelimiterNodeValue(nextValue));
                Value value = function.Eval(prev, next, where, where, null, null);
                where.Exit();
                return value;
            }
Пример #11
0
        public void Test()
        {
            try
            {
                IScope scope = new ScopeChain(GetBootstrapScope());

                {	// a function that needs params but doesn't get them is just a function
                    Value value = TestSupport.ToValue("=enum", scope);
                    Assert.AreEqual(ValueType.Function, value.Type);
                }

                {	// test eval order
                    Value value = TestSupport.ToValue("2 * 2 + 3", scope);
                    Assert.AreEqual(7, value.AsInt);
                    value = TestSupport.ToValue("2 + 2 * 3", scope);
                    Assert.AreEqual(8, value.AsInt);
                }
            }
            catch (Loki3Exception e)
            {
                Assert.Fail(e.ToString());
            }
        }
Пример #12
0
        public void RunUnittests()
        {
            try
            {
                IScope scope = new ScopeChain(GetBootstrapScope());
                EvalFile.Do("l3/unittest.l3", scope);
                EvalFile.Do("l3/help.l3", scope);

                // make sure all functions have @doc
                Value a = TestSupport.ToValue("checkDocs currentScope", scope);
                if (!a.AsArray[0].AsBool)	// make it obvious which functions need @doc
                    Assert.AreEqual("[ ]", a.AsArray[2].AsArray);

                // currently this runs checkDocs as well
                Value v = TestSupport.ToValue("unittest [ :l3/bootstrap.l3 :l3/bootstrap_tests.l3 ]", scope);
                // if this fails, there may be output that describes which unittest & which assert
                Assert.True(v.AsBool);
            }
            catch (Loki3Exception e)
            {
                Assert.Fail(e.ToString());
            }
        }
Пример #13
0
            internal override Value Eval(Value arg, IScope scope)
            {
                Map map = arg.AsMap;
                Value value = map["value"];

                IScope where = scope;
                Value valueMap = map["map"];
                if (!valueMap.IsNil)
                {
                    // either use the scope the map represents
                    // or dummy up a scope for the passed in map
                    ValueMap mapOrScope = valueMap as ValueMap;
                    where = mapOrScope.Scope;
                    if (where == null)
                        where = new ScopeChain(mapOrScope.AsMap);
                }

                Value retval = Utility.EvalValue(value, where);
                where.Exit();
                return retval;
            }
Пример #14
0
            internal override Value Eval(Value arg, IScope scope)
            {
                Map map = arg.AsMap;
                Value obj = map["map"];
                string prompt = map["prompt"].AsString;
                bool registerBuiltins = map["registerBuiltins?"].AsBool;

                IScope scopeToUse = scope;
                if (obj != ValueNil.Nil)
                {
                    ValueMap vMap = obj as ValueMap;
                    if (vMap.Scope != null)
                        scopeToUse = vMap.Scope;
                    else
                        scopeToUse = new ScopeChain(vMap.AsMap);
                }

                if (registerBuiltins)
                    AllBuiltins.RegisterAll(scopeToUse);

                if (map["fileToLoad"].Type == ValueType.String)
                {
                    string file = map["fileToLoad"].AsString;
                    EvalFile.Do(file, scopeToUse);
                }

                loki3.core.Repl.Do(scopeToUse, prompt);
                scopeToUse.Exit();
                return ValueNil.Nil;
            }
Пример #15
0
            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;
            }
Пример #16
0
        /// <summary>
        /// Get the scope to modify based on values in 'map'.
        ///		:level = the number of parents up the chain to modify
        ///		:map   = if present, the map to modify
        /// </summary>
        internal static IScope GetScopeToModify(Map map, IScope scope, bool bIncludeMap)
        {
            if (!map.ContainsKey("map") && !map.ContainsKey("level"))
                return scope;

            ValueMap valueMap = (bIncludeMap ? map["map"] as ValueMap : null);
            int level = (map.ContainsKey("level") ? map["level"].AsInt : 0);

            // scope we're going to modify
            IScope toModify = scope;
            if (valueMap != null)
                toModify = new ScopeChain(valueMap.AsMap);
            else
                for (int i = 0; i < level && toModify.Parent != null; i++)
                    toModify = toModify.Parent;
            if (toModify == null)
                toModify = scope;
            return toModify;
        }
Пример #17
0
        public void TestParamMetadata2()
        {
            try
            {
                IScope scope = new ScopeChain(GetBootstrapScope());

                {
                    ScopeChain nested = new ScopeChain(scope);
                    Value value = TestSupport.ToValue("{ :a :a :remainder ( :remainder ... ) } v= { :a 4 :b 5 :c 6 }", nested);
                    // value should be { :a 4 :b 5 :c 6 }
                    Assert.AreEqual(3, value.AsMap.Count);
                    // nested should now contain "a" and "remainder"
                    Assert.AreEqual(4, nested.GetValue(new Token("a")).AsInt);
                    Map rest = nested.GetValue(new Token("remainder")).AsMap;
                    Assert.AreEqual(2, rest.Count);
                    Assert.AreEqual(5, rest["b"].AsInt);
                    Assert.AreEqual(6, rest["c"].AsInt);
                }

                {
                    ScopeChain nested = new ScopeChain(scope);
                    Value value = TestSupport.ToValue("[ ->a ( ->remainder ... ) ] v= { :a 4 :b 5 :c 6 }", nested);
                    // value should be { :a 4 :b 5 :c 6 }
                    Assert.AreEqual(3, value.AsMap.Count);
                    // nested should now contain "a" and "remainder"
                    Assert.AreEqual(4, nested.GetValue(new Token("a")).AsInt);
                    Map rest = nested.GetValue(new Token("remainder")).AsMap;
                    Assert.AreEqual(2, rest.Count);
                    Assert.AreEqual(5, rest["b"].AsInt);
                    Assert.AreEqual(6, rest["c"].AsInt);
                }

                {
                    ScopeChain nested = new ScopeChain(scope);
                    Value value = TestSupport.ToValue("[ ->a ( ->remainder ... ) ] v= [ 7 8 9 ]", nested);
                    // value should be [ 7 8 9 ]
                    Assert.AreEqual(3, value.AsArray.Count);
                    // nested should now contain "a" and "remainder"
                    Assert.AreEqual(7, nested.GetValue(new Token("a")).AsInt);
                    System.Collections.Generic.List<Value> rest = nested.GetValue(new Token("remainder")).AsArray;
                    Assert.AreEqual(2, rest.Count);
                    Assert.AreEqual(8, rest[0].AsInt);
                    Assert.AreEqual(9, rest[1].AsInt);
                }
            }
            catch (Loki3Exception e)
            {
                Assert.Fail(e.ToString());
            }
        }
Пример #18
0
        public void TestParamMetadata()
        {
            try
            {
                IScope scope = new ScopeChain(GetBootstrapScope());

                string[] lines = {
                    ":addUp v= func1 [ ( ->a : :int ) ( ->b d= 5 ) ]",
                    "	a + b",
                };
                LineConsumer requestor = new LineConsumer(lines);
                EvalLines.Do(requestor, scope);

                {	// pass expected parameters
                    Value value = TestSupport.ToValue("addUp [ 1 2 ]", scope);
                    Assert.AreEqual(3, value.AsInt);
                }

                {	// leave off 2nd, use default
                    Value value = TestSupport.ToValue("addUp [ 1 ]", scope);
                    Assert.AreEqual(6, value.AsInt);
                }

                // it throws if we pass wrong type
                bool bThrew = false;
                try
                {
                    TestSupport.ToValue("addUp [ true 1 ]", scope);
                }
                catch (Loki3Exception)
                {
                    bThrew = true;
                }
                Assert.IsTrue(bThrew);
            }
            catch (Loki3Exception e)
            {
                Assert.Fail(e.ToString());
            }
        }
Пример #19
0
        static IScope CreateMathScope()
        {
            ScopeChain scope = new ScopeChain();
            Math.Register(scope);

            ValueDelimiter square = new ValueDelimiter("]", DelimiterType.AsArray);
            scope.SetValue("[", square);

            return scope;
        }
Пример #20
0
        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;
        }
Пример #21
0
 internal override Value Eval(Value arg, IScope scope)
 {
     Map map = arg.AsMap;
     IScope theScope = Utility.GetScopeToModify(map, scope, false/*bIncludeMap*/);
     if (map["createChild?"].AsBool)
         theScope = new ScopeChain(theScope);
     return theScope.AsValue;
 }
Пример #22
0
        public void TestSetValue()
        {
            IScope scope = CreateValueScope();

            {
                Value value = TestSupport.ToValue("l3.setValue { :key :a :value 5 }", scope);
                Assert.AreEqual(5, value.AsInt);

                Value fetch = scope.GetValue(new Token("a"));
                Assert.AreEqual(5, fetch.AsInt);
            }

            {	// change a
                Value value = TestSupport.ToValue("l3.setValue { :key :a :value 7.5 }", scope);
                Assert.AreEqual(7.5, value.AsFloat);

                Value fetch = scope.GetValue(new Token("a"));
                Assert.AreEqual(7.5, fetch.AsFloat);
            }

            {	// set an array
                Value value = TestSupport.ToValue("l3.setValue { :key :key :value [ a 2 false ] }", scope);
                List<Value> array = value.AsArray;
                Assert.AreEqual(3, array.Count);
                Assert.AreEqual(7.5, array[0].AsFloat);
                Assert.AreEqual(2, array[1].AsInt);
                Assert.AreEqual(false, array[2].AsBool);

                Value fetch = scope.GetValue(new Token("key"));
                List<Value> fetchArray = fetch.AsArray;
                Assert.AreEqual(3, fetchArray.Count);
                Assert.AreEqual(7.5, fetchArray[0].AsFloat);
                Assert.AreEqual(2, fetchArray[1].AsInt);
                Assert.AreEqual(false, fetchArray[2].AsBool);
            }

            // create a nested scope
            IScope nested = new ScopeChain(scope);

            {	// explicitly say create-if-needed
                TestSupport.ToValue("l3.setValue { :key :created :value 3 :create? true }", nested);
                Value fetch = nested.GetValue(new Token("created"));
                Assert.AreEqual(3, fetch.AsInt);
            }

            {	// asking to reuse non-existent var throws
                bool bThrew = false;
                try
                {
                    Value value = TestSupport.ToValue("l3.setValue { :key :doesnt-exist :value 3 :create? false }", nested);
                }
                catch (Loki3Exception e)
                {
                    bThrew = true;
                    Assert.AreEqual("doesnt-exist", e.Errors[Loki3Exception.keyBadToken].AsString);
                }
                Assert.IsTrue(bThrew);
            }

            {	// set var on parent scope & reuse on nested scope
                TestSupport.ToValue("l3.setValue { :key :on-parent :value 5 :create? true }", scope);
                Assert.AreEqual(5, scope.AsMap["on-parent"].AsInt);
                TestSupport.ToValue("l3.setValue { :key :on-parent :value 4 :create? false }", nested);
                Assert.AreEqual(4, scope.AsMap["on-parent"].AsInt);
                Assert.AreNotEqual(null, nested.Exists("on-parent"));
                Assert.IsFalse(nested.AsMap.ContainsKey("on-parent"));
            }

            {	// set a value on a map
                Map map = new Map();
                map["one"] = new ValueInt(1);
                map["two"] = new ValueInt(2);
                ValueMap valueMap = new ValueMap(map);
                scope.SetValue("mymap", valueMap);

                Value value = TestSupport.ToValue("l3.setValue { :key :one :value 3 :map mymap }", scope);
                Assert.AreEqual(3, value.AsInt);
                Assert.AreEqual(3, map["one"].AsInt);
            }

            {	// pattern matching: extract values out of an array
                Value value = TestSupport.ToValue("l3.setValue { :key [ :first :second :third ] :value [ 11 22 33 ] :create? true }", scope);
                Assert.AreEqual(11, scope.AsMap["first"].AsInt);
                Assert.AreEqual(22, scope.AsMap["second"].AsInt);
                Assert.AreEqual(33, scope.AsMap["third"].AsInt);
            }

            {	// special case: initialize every token in array to nil
                Value value = TestSupport.ToValue("l3.setValue { :key [ :first :second :third ] :value nil :create? true }", scope);
                Assert.IsTrue(scope.AsMap["first"].IsNil);
                Assert.IsTrue(scope.AsMap["second"].IsNil);
                Assert.IsTrue(scope.AsMap["third"].IsNil);
            }

            {	// if initOnly?, don't overwrite existing values
                Value value = TestSupport.ToValue("l3.setValue { :key [ :aa :bb ] :value [ 2 3 ] :create? true :initOnly? true }", scope);
                Assert.AreEqual(2, scope.AsMap["aa"].AsInt);
                Assert.AreEqual(3, scope.AsMap["bb"].AsInt);
                value = TestSupport.ToValue("l3.setValue { :key [ :aa :bb ] :value [ 4 5 ] :create? true :initOnly? true }", scope);
                Assert.AreEqual(2, scope.AsMap["aa"].AsInt);
                Assert.AreEqual(3, scope.AsMap["bb"].AsInt);
                value = TestSupport.ToValue("l3.setValue { :key [ :bb :cc ] :value nil :create? true :initOnly? true }", scope);
                Assert.AreEqual(3, scope.AsMap["bb"].AsInt);
                Assert.IsTrue(scope.AsMap["cc"].IsNil);
            }

            {	// if returnSuccess?, return value tells whether a value was set
                Value value = TestSupport.ToValue("l3.setValue { :key [ :x :y ] :value [ 2 3 ] :returnSuccess? true }", scope);
                Assert.IsTrue(value.AsBool);
                value = TestSupport.ToValue("l3.setValue { :key [ :x :y :z ] :value [ 2 3 ] :returnSuccess? true }", scope);
                Assert.IsFalse(value.AsBool);
            }
        }
Пример #23
0
        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;
        }
Пример #24
0
        public void TestLoop()
        {
            try
            {
                IScope scope = new ScopeChain(GetBootstrapScope());

                {	// l3.loop
                    string[] lines = {
                        ":total v= 0",
                        ":i v= 0",
                        "l3.loop .{ :check .` i !=? 5",
                        "	:i = i + 1",
                        "	:total = total + i",
                    };
                    LineConsumer requestor = new LineConsumer(lines);
                    Value result = EvalLines.Do(requestor, scope);
                    Assert.AreEqual(15, result.AsInt);
                }
            }
            catch (Loki3Exception e)
            {
                Assert.Fail(e.ToString());
            }
        }
Пример #25
0
        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());
            }
        }
Пример #26
0
            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;
                }
            }
Пример #27
0
        public void TestBasic()
        {
            ValueFunctionOverload overload = new ValueFunctionOverload();
            IScope scope = new ScopeChain();

            {	// add a single function & make sure it's called at right time & fails at right time
                ValueFunction numInt = new Add(ValueType.Number, ValueType.Int, 0);
                overload.Add(numInt);
                Value a = overload.Eval(null, MakePair(3, 4, true, true), scope, scope, null, null);
                Assert.AreEqual(7, a.AsInt);
                Value b = overload.Eval(null, MakePair(3, 5, false, true), scope, scope, null, null);
                Assert.AreEqual(8, b.AsFloat);

                bool bThrew = false;
                try
                {
                    overload.Eval(null, MakePair(3, 4, false, false), scope, scope, null, null);
                }
                catch (Loki3Exception)
                {
                    bThrew = true;
                }
                Assert.IsTrue(bThrew);
            }

            {	// add a second function & make sure both succeed & fail at right time
                // this one is more specific so should get called first when signature matches
                ValueFunction intInt = new Add(ValueType.Int, ValueType.Int, 1);
                overload.Add(intInt);
                Value a = overload.Eval(null, MakePair(3, 4, true, true), scope, scope, null, null);
                Assert.AreEqual(8, a.AsInt);	// calls 2nd version
                Value b = overload.Eval(null, MakePair(3, 5, false, true), scope, scope, null, null);
                Assert.AreEqual(8, b.AsFloat);	// calls 1st version

                bool bThrew = false;
                try
                {	// still no match for this one
                    overload.Eval(null, MakePair(3, 4, false, false), scope, scope, null, null);
                }
                catch (Loki3Exception)
                {
                    bThrew = true;
                }
                Assert.IsTrue(bThrew);
            }

            {	// try adding a postfix function to the overload
                bool bThrew = false;
                try
                {
                    ValueFunction post = new Post();
                    overload.Add(post);
                }
                catch (Loki3Exception e)
                {
                    Assert.AreEqual("prefix", e.Errors[Loki3Exception.keyExpectedFix].ToString());
                    Assert.AreEqual("postfix", e.Errors[Loki3Exception.keyActualFix].ToString());
                    bThrew = true;
                }
                Assert.IsTrue(bThrew);
            }
        }