Page 2 of 3 FirstFirst 1 2 3 LastLast
Results 11 to 20 of 21

Thread: Varargs in ASH

  1. #11
    Developer Veracity's Avatar
    Join Date
    Mar 2006
    Location
    The Unseelie Court
    Posts
    12,937

    Default

    Revision 19888 whacks Function lookup for function calls at compile time based on function name and the list of parameters in the call.
    Considering overloading, it wants to find the best - correct - function with the specified name which will handle the arguments.
    It makes 12 (!) passes over the symbol table before giving up and throwing an undefined function, although it short circuits at the first match.

    There are 3 kinds of comparison:

    1) EXACT - The parameter type and the argument type are the same - including typedefs. This allows the following to work:

    typedef int t1;
    typedef int t2;

    void f( t1 arg ) {}
    void f( t2 arg ) {}
    void f( int arg ) {}

    Three functions, same name, single int argument - but given a typedef argument, it will find the correct function

    2) BASE - compare the "base" types of arguments and parameters. For typedefs, the type it names.

    typedef int t3;
    f( t3 );

    ... will call the foo(int) version, since there is not one specialized for the typedef

    3) COERCE - if you can coerce the function call argument to the type of the function argument, cool.

    f( true );

    ... because you can coerc a boolean to an int.

    There are two kinds of check - no varargs, varargs.
    There are two places to look - current scope (and recursively up through parent to global scope), built-in library functions.

    3 * 2 * 2 = 12 searches in this order

    EXACT, no varargs, scope
    EXACT, no varargs, library
    EXACT, varargs, scope
    EXACT, varargs, library
    BASE, no varargs, scope
    BASE, no varargs, library
    BASE, varargs, scope
    BASE, varargs, library
    COERCE, no varargs, scope
    COERCE, no varargs, library
    COERCE, varargs, scope
    COERCE, varargs, library

    I imagine this could be optimized to make one pass through each source (scope, library) checking/collecting all six search types (EXACT, BASE, COERCE)(no varargs, varargs) and pick the first result from the potential 12 results.

    I also set up the RuntimeLibrary (built-in functions) to be able to handle varargs. I updated the built-in min() and max() functions to take any number of arguments:

    int min( int, int... )
    float min( float, float... )
    int max( int, int... )
    float max( float, float... )

    Because we can coerce, you can mix ints and floats in the argument list and you'll get a float result.

    There some other things I want to consider:

    1) compile-time checking:

    void func( int, int, int... )
    void func( int, int... )

    Whichever is first, the second has to be considered a redefinition, since we cannot decide which one would handle the call: func( 1, 2, 3)

    2) There is some run-time usage of looking up a function in a particular scope. In particular, for the "call" construct. BasicScope.findFunction has the old search logic in it. Perhaps I can move the new logic into a utility which is usable both by the Parser and at runtime.

    3) More of the same, Function.paramsMatch is used by the BasicScope search and also by UserDefinedFunction to determine if you are overriding a library function.

    There is no end...

  2. #12
    Senior Member
    Join Date
    Apr 2019
    Posts
    129

    Default

    Did this update change the way functions need to be defined or something? A lot of pre-existing scripts now generate errors upon being launched

  3. #13
    Developer Veracity's Avatar
    Join Date
    Mar 2006
    Location
    The Unseelie Court
    Posts
    12,937

    Default

    You are referring to "bugs" in KoLmafia.
    Perhaps you need to update to 19889 or later?

  4. #14
    Senior Member
    Join Date
    Apr 2019
    Posts
    129

    Default

    Mayyyyyyyybe... >_>

    (19888 was the latest at the time of writing this; had no way of really knowing if this was a bug or not, so it's why I "phrased" it like that, as I know it would've been rude to phrase it as if it was a bug, if it had been a "change of the required syntax")

    Btw, not really that informed in informatics, but that's a function that can be given a variable amount of arguments? Wow!

  5. #15
    Developer Veracity's Avatar
    Join Date
    Mar 2006
    Location
    The Unseelie Court
    Posts
    12,937

    Default

    No Problem.

    I most certainly did not intend to change function declaration syntax in a non-backwards-compatible way; everything I did was intended to be an extension. If existing programs break, that is unintended and I'll get on it as soon as possible to fix.

  6. #16
    Senior Member
    Join Date
    Oct 2013
    Posts
    247

    Default

    Did this update change the way functions need to be defined or something? A lot of pre-existing scripts now generate errors upon being launched
    Originally Posted by fredg1 View Post
    I just ran into this with 19888, rolled back to 19886, works.

  7. #17
    Developer Veracity's Avatar
    Join Date
    Mar 2006
    Location
    The Unseelie Court
    Posts
    12,937

    Default

    I just ran into this with 19888, rolled back to 19886, works.
    Originally Posted by fractalnavel View Post
    You are referring to "bugs" in KoLmafia.
    Perhaps you need to update to 19889 or later?
    Originally Posted by Veracity View Post
    That was the post immediately following the one you cited.

    It makes 12 (!) passes over the symbol table before giving up and throwing an undefined function, although it short circuits at the first match.
    ...
    I imagine this could be optimized to make one pass through each source (scope, library) checking/collecting all six search types (EXACT, BASE, COERCE)(no varargs, varargs) and pick the first result from the potential 12 results.
    Originally Posted by Veracity View Post
    I changed the search to make a single pass over the functions in the scope and a single pass over the functions in RuntimeLibrary, extracting only the functions with the name in question. It then makes (up to) six passes over each of the vastly smaller - and frequently empty, since you are calling EITHER a user function OR a built-in function - lists.

    That's probably good enough.

    1) compile-time checking:

    void func( int, int, int... )
    void func( int, int... )

    Whichever is first, the second has to be considered a redefinition, since we cannot decide which one would handle the call: func( 1, 2, 3)
    This looks like a pain. Still important to minimize surprises, but I'll put this off for a bit.

    2) There is some run-time usage of looking up a function in a particular scope. In particular, for the "call" construct.
    3) More of the same, Function.paramsMatch is used by the BasicScope search and also by UserDefinedFunction to determine if you are overriding a library function.
    Yeah. 19888 moved all the code to more logical places:

    Operator has the "is this coercable?" stuff
    Function has the "does this function's arguments match those parameters?" stuff.
    BasicScope has the "find the function (using up to 12 searches)" stuff.

    So I got rid of all the old-style stuff and thereby fixed issues #2 and #3.

    That's as much time as I want to spend on this right now. Time to fix more bugs - like the ones I bumped from the top 12 pages or so of the Bug Reports - and spin a new point release before the end of the month. Hopefully, that will give THIS feature enough soak time.
    Ph'nglui mglw'nafh Cthulhu
    R'lyeh wgah-nagl fhtagn.

  8. #18
    Junior Member
    Join Date
    Oct 2019
    Posts
    3

    Default

    To answer the original question: Yes, way cool. I have a library that allows one to create a script that performs steps in ascending numerical sequence, and if the script is interrupted, it can be rerun starting with the step that was interrupted. The steps are functions that have a particular signature; it would be cool if the step functions could take arbitrary numbers of arguments. This looks fun to play with, thanks!

  9. #19
    Developer Veracity's Avatar
    Join Date
    Mar 2006
    Location
    The Unseelie Court
    Posts
    12,937

    Default

    Revision 19911 adds the aforementioned checks for vararg clashes:

    f( int, int, int...)
    f( int, int... )

    clash with each other, since it is indeterminate which should be called with f( 1, 2 ).

    As submitted either also clashes with

    f( int, int)

    I'm going to think more about that. Perhaps the exact match with the non-vararg function should win?
    That is how I had it before.
    Hmm.

  10. #20
    Developer Veracity's Avatar
    Join Date
    Mar 2006
    Location
    The Unseelie Court
    Posts
    12,937

    Default

    Perhaps.

    f( int )
    f( int, int )
    f( int, int...)

    can coexist.

    f( 1 ) is an exact match for the first function, f( 1, 2 ) is an exact match for the second functionf, and f( 1, 2, 3 ) is a vararg match for the third function.

    Revision 19912

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •