() = evalfile ("inc.sl"); testing_feature ("qualifiers"); private define simple_test_function () { variable q = __qualifiers (); return q.qualifier; } if (3 != simple_test_function (;qualifier=3)) failed ("Simple qualifier test"); public define qualifier_function () { variable q = __qualifiers (); loop (3) q = __qualifiers (); return _NARGS, q; } public variable Arg_List, Qual_Struct, Func_Ref, Struct; private define call_qualifier_function (f, args, q) { Arg_List = args; Qual_Struct = q; loop (10) () = __qualifiers (;foo="bar"); variable args_expr = strjoin (array_map (String_Type, &sprintf, "Arg_List[%d]", [0:length(args)-1]), ","); variable fields = get_struct_field_names (q); variable q_expr = strjoin (array_map (String_Type, &sprintf, "%s=Qual_Struct.%s", fields, fields), ","); variable expr = sprintf ("%s (%s ; %s);", f, args_expr, q_expr); return eval (expr); } private define test_qualifiers (args, q) { variable n = length (args), n1, q1; Func_Ref = &qualifier_function; Struct = struct { method = &qualifier_function }; variable fs = ["qualifier_function", "(@Func_Ref)", "Struct.method"]; variable ns = [n, n, n+1]; variable f, i; _for i (0, 2, 1) { f = fs[i]; n = ns[i]; (n1, q1) = call_qualifier_function (f, args, q); if (n != n1) failed ("Expecting _NARGS to be %d, found %d -- f = %s", n, n1, f); if (not _eqs (q, q1)) failed ("Qualifiers to do match the expected values -- f = %s", f); } } test_qualifiers ({1, 2, 3}, struct {a=1, b=3, c="foo"}); test_qualifiers ({1, 2, test_qualifiers ({1,2}, struct{c=&cos})}, struct {a=1, b=3, c="foo"} ; foo=1, bar=length ([1:10];baz=3)); private define test_qualifiers () { variable q = __qualifiers (); variable n, q1; (n, q1) = qualifier_function (1,, ;; q); if (n != 3) failed ("function call did not handle implicit NULL arguments"); if (not _eqs (q, q1)) failed (";; form of qualifiers"); } test_qualifiers (); test_qualifiers (;); test_qualifiers (;;); test_qualifiers (;;struct {foo=7}); private define fun2 (x, y) { return qualifier ("x", x), qualifier ("y", y); } private define fun1 (x, y) { return fun2 (x, y;; __qualifiers ()); } private define test_qualifier () { variable x, y, x0, y0, x1, y1; x0 = 1; y0 = 2; x1 = "one"; y1 = "two"; (x, y) = fun1 (x0, y0; x=x1, y=y1); if ((x != x1) || (y != y1)) failed ("qualifier intrinsic 1"); (x, y) = fun1 (x0, y0; y=y1); if ((x != x0) || (y != y1)) failed ("qualifier intrinsic 2"); (x, y) = fun1 (x0, y0; x = x1); if ((x != x1) || (y != y0)) failed ("qualifier intrinsic 3"); } test_qualifier (); private define test_qualifier_exists (name, exists) { if (exists != qualifier_exists (name)) failed ("qualifier_exists (%s) != %d", name, exists); } test_qualifier_exists ("foo", 0); test_qualifier_exists ("foo", 1; goo, foo=7); test_qualifier_exists ("goo", 1; goo, foo=7); test_qualifier_exists ("foo", 1; goo, foo); test_qualifier_exists ("boo", 0; goo, foo); test_qualifier_exists ("foo", 0; food=7); test_qualifier_exists ("foo", 0;; struct{food=7}); test_qualifier_exists ("foo", 1;; struct{food=7, foo}); private variable Funcs = Assoc_Type[]; Funcs["f"] = &test_qualifier_exists; private define passthru (); private define test_qualifier_passing (name, exists) { (@Funcs["f"])(name, exists;; __qualifiers); (@Funcs["f"])(passthru(name, exists);; __qualifiers); (@Funcs["f"])(name, exists;; passthru(__qualifiers)); (@passthru(Funcs["f"]))(name, exists;; __qualifiers); } test_qualifier_passing ("foo", 0); test_qualifier_passing ("foo", 1; goo, foo=7); test_qualifier_passing ("goo", 1; goo, foo=7); test_qualifier_passing ("foo", 1; goo, foo); test_qualifier_passing ("boo", 0; goo, foo); test_qualifier_passing ("foo", 0; food=7); test_qualifier_passing ("foo", 0;; struct{food=7}); test_qualifier_passing ("foo", 1;; struct{food=7, foo}); private define fun2 (x, y) { return qualifier ("x", x), qualifier ("y", y); } private define fun1 (x, y) { if (_NARGS != 2) failed ("_NARGS=%d instead of 2 in fun1", _NARGS); return fun2 (x, y;; __qualifiers ()); } private define qualifiers_as_func (x,y,z) { if (_NARGS != 3) failed ("_NARGS=%d instead of 3 in qualifiers_as_func", _NARGS); return __qualifiers (); } private define test_mixed_qualifiers () { variable x, y, x0, y0, x1, y1; x0 = 1, y0 = 2; x1 = "one", y1="two"; (x,y) = fun1 (x0, y0; @qualifiers_as_func(1,2,3)); if ((x0 != x)||(y0!=y)) failed ("mixed qualifiers NULL"); (x,y) = fun1 (x0, y0; @qualifiers_as_func(1,2,3;x=x1)); if ((x != x1)||(y0!=y)) failed ("mixed qualifiers ;x=x1"); (x,y) = fun1 (x0, y0; x=x0, @qualifiers_as_func(1,2,3 ;x=x1)); if ((x != x1)||(y0!=y)) failed ("mixed qualifiers ;x=x0,x=x1"); (x,y) = fun1 (x0, y0; y=y0, @qualifiers_as_func(1,2,3;x=x1), x=x0); if ((x != x0)||(y0!=y)) failed ("mixed qualifiers ;x=x1,x=x0"); (x,y) = fun1 (x0, y0; @qualifiers_as_func(1,2,3;x=x1,y=y1), x=y1); if ((x != y1)||(y1!=y)) failed ("mixed qualifiers ;x=x1,y=y0,x=y1"); } test_mixed_qualifiers (); private define fun1_method (obj) { if (_NARGS != 1) { failed ("_NARGS=%d instead of 1 in fun1_method", _NARGS); } return fun1 (obj.x, obj.y ;; __qualifiers); } private define new_object () { return struct { method=&fun1_method, x=qualifier("x"), y=qualifier("y"), }; } private define test_qualifiers_in_methods () { variable x0 = 1, y0 = 2, x, y; variable obj = new_object (;x=x0, y=y0); (x,y) = obj.method (); if ((x != x0) || (y != y0)) failed ("passing object qualifiers"); x0 = 3; y0 = 4; (x,y) = obj.method (;x=3,y=4); if ((x != x0) || (y != y0)) failed ("obj.method qualifiers"); x0 = 5; y0 = 6; (x,y) = new_object (;x=x0,y=y0).method (); if ((x != x0) || (y != y0)) failed ("new_object.method default qualifiers"); x0 = 7; y0 = 8; (x,y) = new_object (;x=x0).method (;y=y0); if ((x != x0) || (y != y0)) failed ("new_object.method default and specified qualifiers"); } test_qualifiers_in_methods (); #iffalse % tests pre2.3.0-54 private define test_empty_qualifiers (qval, defval) { variable q; q = qualifier ("foo"); if (q != qval) failed ("test_empty_qualifiers 1"); q = qualifier ("foo", defval); if (qval == NULL) { if (q != defval) { failed ("test_empty_qualifiers 2"); } } else if (q != qval) failed ("test_empty_qualifiers 3"); } test_empty_qualifiers (2100, 3100; foo=2100); test_empty_qualifiers (2100, 3100; foo=2100, bar="x"); test_empty_qualifiers (2100, 3100; bar="x", foo=2100); test_empty_qualifiers (1, 3100; foo); test_empty_qualifiers (1, 3100; foo,); test_empty_qualifiers (1, 3100; bar,foo,); test_empty_qualifiers (1, 3100; foo, bar="x"); test_empty_qualifiers (NULL, 3100); #endif private define check_intrinsic_qualifier (func, qval, defval) { variable val; if (qval == NULL) { val = (@func)("foo", defval); if (val != defval) failed ("%S(%S,%S) returned %S instead of %S", func, "foo", defval, val, defval); % The integer 1 will get assigned to a qualifier without % a value. So, do not use this with strings if (func == &check_intrin_string_qualifier) return; #iffalse % pre2.3.0-54 semantics val = (@func)("foo", defval; foo); if (val != 1) failed ("%S(%S,%S; foo) returned %S instead of %S", func, "foo", defval, val, defval); #endif return; } val = (@func)("foo", defval; foo=qval); if (val != qval) failed ("%S(%S,%S ;%S=%S) returned %S instead of %S", func, "foo", defval, "foo", qval, val, qval); } private define test_intrinsic_qualifiers () { check_intrinsic_qualifier (&check_intrin_int_qualifier, 2718, 3141); check_intrinsic_qualifier (&check_intrin_int_qualifier, NULL, 3141); check_intrinsic_qualifier (&check_intrin_int_qualifier, 2718h, 3141); check_intrinsic_qualifier (&check_intrin_long_qualifier, NULL, 3141L); check_intrinsic_qualifier (&check_intrin_long_qualifier, 2718, 3141L); check_intrinsic_qualifier (&check_intrin_long_qualifier, 2718h, 3141L); check_intrinsic_qualifier (&check_intrin_double_qualifier, NULL, 3.141); check_intrinsic_qualifier (&check_intrin_double_qualifier, 2.718, 3.141); check_intrinsic_qualifier (&check_intrin_double_qualifier, 2718, 3.141); check_intrinsic_qualifier (&check_intrin_string_qualifier, NULL, "3.141"); check_intrinsic_qualifier (&check_intrin_string_qualifier, "2.718", "3.141"); check_intrinsic_qualifier (&check_intrin_string_qualifier, "2718"B, "3.141"); } test_intrinsic_qualifiers (); private define check_qualifier (x) { return x + qualifier ("bar", 0); } private define test_array_map_qualifiers (dx) { variable x = [1:10]; variable y = array_map (Int_Type, &check_qualifier, x; bar=dx); ifnot (_eqs (y, x+dx)) { () = array_map (Int_Type, &fprintf, stdout, "%d, %d\n", y, x+dx); failed ("array_map with explicit qualifiers failed"); } y = array_map (Int_Type, &check_qualifier, x;; __qualifiers); ifnot (_eqs (y, x + qualifier("bar", 0))) { failed ("array_map with implicit qualifier failed"); } } test_array_map_qualifiers (11; bar=130, foo=1); test_array_map_qualifiers (11); print ("Ok\n"); exit (0);