Branch: Tag:

2022-10-20

2022-10-20 08:35:17 by Henrik Grubbström (Grubba) <grubba@grubba.org>

Compiler: Improved handling of argument default values.

For improved backward compatibility (and DWIM) allow 0
(in addition to UNDEFINED) to select the default value
when 0 is not a valid value for the argument.

This improves backward compatibility where eg code like

mixed foo(string|void bar) {
if (!bar) bar = "bar";
[...]
}

has been replaced with

mixed foo(string bar = "bar") {
[...]
}

Improves #10086.

814:    }       A o = A(); -  return ({ o->foo(), o->foo(UNDEFINED), o->foo("bar") }); - ]], ({ "foo", "foo", "bar" })) +  return ({ o->foo(), o->foo(UNDEFINED), o->foo(0), o->foo("bar") }); + ]], ({ "foo", "foo", "foo", "bar" })) + test_any_equal([[ +  class A { +  int foo(int bar = 17) { return bar; } +  }    -  +  A o = A(); +  return ({ o->foo(), o->foo(UNDEFINED), o->foo(0), o->foo(18) }); + ]], ({ 17, 17, 0, 18 })) +    dnl Generator with default value.      dnl Lambda with default value.   test_any_equal([[    function(string|void:string) f = lambda(string bar = "foo") { return bar; }; -  return ({ f(), f(UNDEFINED), f("bar") }); - ]], ({ "foo", "foo", "bar" })) +  return ({ f(), f(UNDEFINED), f(0), f("bar") }); + ]], ({ "foo", "foo", "foo", "bar" })) + test_any_equal([[ +  function(int|void:int) f = lambda(int bar = 17) { return bar; }; +  return ({ f(), f(UNDEFINED), f(0), f(18) }); + ]], ({ 17, 17, 0, 18 }))      dnl Local function with default value.   test_any_equal([[    string f(string bar = "foo") { return bar; }; -  return ({ f(), f(UNDEFINED), f("bar") }); - ]], ({ "foo", "foo", "bar" })) +  return ({ f(), f(UNDEFINED), f(0), f("bar") }); + ]], ({ "foo", "foo", "foo", "bar" })) + test_any_equal([[ +  int f(int bar = 17) { return bar; }; +  return ({ f(), f(UNDEFINED), f(0), f(18) }); + ]], ({ 17, 17, 0, 18 }))      dnl Local generator with default value.   
839:    protected void create(string blag = bar) { bar += blag; }    }    -  return ({ foo(), foo(UNDEFINED), foo("bar"), foo("bar", UNDEFINED), +  return ({ foo(), foo(UNDEFINED), foo(0), foo("bar"), foo("bar", UNDEFINED), +  foo("bar", 0), foo(0, "bar"), foo(UNDEFINED, UNDEFINED), foo(0, 0),    foo("bar", "baz"), foo(UNDEFINED, "bar") })->bar; - ]], ({ "foofoo", "foofoo", "barbar", "barbar", + ]], ({ "foofoo", "foofoo", "foofoo", "barbar", "barbar", +  "barbar", "foobar", "foofoo", "foofoo",    "barbaz", "foobar" })) -  + test_any_equal([[ +  class foo(int bar = 17) { +  protected void create(int blag = bar) { bar += blag; } +  }    -  +  return ({ foo(), foo(UNDEFINED), foo(0), foo(18), foo(18, UNDEFINED), +  foo(18, 0), foo(0, 18), foo(UNDEFINED, UNDEFINED), foo(0, 0), +  foo(18, 19), foo(UNDEFINED, 18) })->bar; + ]], ({ 34, 34, 0, 36, 36, +  18, 18, 34, 0, +  37, 35 })) +    dnl Anonymous class with implicit create with default value.   test_any_equal([[    program foo = class(string bar = "foo") {    protected void create(string blag = bar) { bar += blag; }    };    -  return ({ foo(), foo(UNDEFINED), foo("bar"), foo("bar", UNDEFINED), +  return ({ foo(), foo(UNDEFINED), foo(0), foo("bar"), foo("bar", UNDEFINED), +  foo("bar", 0), foo(0, "bar"), foo(UNDEFINED, UNDEFINED), foo(0, 0),    foo("bar", "baz"), foo(UNDEFINED, "bar") })->bar; - ]], ({ "foofoo", "foofoo", "barbar", "barbar", + ]], ({ "foofoo", "foofoo", "foofoo", "barbar", "barbar", +  "barbar", "foobar", "foofoo", "foofoo",    "barbaz", "foobar" })) -  + test_any_equal([[ +  program foo = class(int bar = 17) { +  protected void create(int blag = bar) { bar += blag; } +  };    -  +  return ({ foo(), foo(UNDEFINED), foo(0), foo(18), foo(18, UNDEFINED), +  foo(18, 0), foo(0, 18), foo(UNDEFINED, UNDEFINED), foo(0, 0), +  foo(18, 19), foo(UNDEFINED, 18) })->bar; + ]], ({ 34, 34, 0, 36, 36, +  18, 18, 34, 0, +  37, 35 })) +    dnl bug in for loop optimization in combination with +=   test_any([[   array v=({1,2,3});