Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Advanced function arguments #8

Closed
differentmatt opened this issue Jul 3, 2014 · 2 comments
Closed

Advanced function arguments #8

differentmatt opened this issue Jul 3, 2014 · 2 comments

Comments

@differentmatt
Copy link
Owner

Default arguments
Keyword arguments
Arbitrary argument lists
Unpacking argument lists

https://docs.python.org/3.4/tutorial/controlflow.html#more-on-defining-functions

This may need to be broken up into separate pieces. Please feel free to take on a subset of this work instead of the whole enchilada.

@differentmatt
Copy link
Owner Author

Tentative plan:

  1. Modify function calls - For calls to user functions and runtime library functions, convert all parameters to a single parameters object that JavaScript can handle, such as {formals:[], keywords:{}}.
  2. Modify function definitions - For all user function and library function definitions, move parameter variables to function body, and function body to internal iife.

What does this get us?

  • Our original Python parameters have been converted to something JavaScript understands.
  • We can process the parameters in the function definition, while maintaining the original function's body (scope and code).

The example below doesn't include unpacking argument lists, but we can imagine passing a similar object containing the correct parameters.

Python input:

def foo(voltage, amps='a', charge='high', *args, **keywords):
  print('voltage', voltage)
  print('amps', amps)
  print('charge', charge)
  print('args', [a for a in args])
  print('keywords', [(k, keywords[k]) for k in keywords])
  print('')

foo(3)
foo(amps=4, voltage=7)
foo(1, 2, 3, 4, 5, 6, p="hi", q='boo')

JavaScript output:

// print() is in runtime library, included here for completeness
function print() {
  var s = '';
  for (var i = 0; i < arguments.length; i++)
    s += arguments[i] + ' ';
  console.log(s);
}

function foo() {
  var _p = arguments[0];
  var _fi = 0;
  var voltage;
  if (_fi < _p.formals.length) {
    voltage = _p.formals[_fi];
    _fi++;
  } else if ('voltage' in _p.keywords) {
    voltage = _p.keywords['voltage'];
    delete _p.keywords['voltage'];
  }
  var amps = 'a';
  if (_fi < _p.formals.length) {
    amps = _p.formals[_fi];
    _fi++;
  } else if ('amps' in _p.keywords) {
    amps = _p.keywords['amps'];
    delete _p.keywords['amps'];
  }
  var charge = 'high';
  if (_fi < _p.formals.length) {
    charge = _p.formals[_fi];
    _fi++;
  } else if ('charge' in _p.keywords) {
    charge = _p.keywords['charge'];
    delete _p.keywords['charge'];
  }
  var args = [];
  while (_fi < _p.formals.length) {
    args.push(_p.formals[_fi]);
    _fi++;
  }
  var keywords = _p.keywords;

  return (function() {
    print('voltage', voltage)
    print('amps', amps)
    print('charge', charge)
    print('args', args)
    var kws = '{'
    for (var k in keywords) {
      kws += k + ":" + keywords[k] + " ";
    }
    kws += '}';
    print('keywords', kws)
    print('')
  })();
}

foo({formals:[3], keywords:{}});
foo({formals:[], keywords:{amps:4, voltage:7}})
foo({formals:[1, 2, 3, 4, 5, 6], keywords:{p:"hi", q:'boo'}})

differentmatt added a commit that referenced this issue Jul 23, 2014
Argument defaults, keywords, and arbitrary lists for user-defined
functions.  Part of issue #8.

Parse-time changes:
1. Function parameters are moved to function body, along with extra code
to process them if Python-style arguments are passed.
2. Calls to user-defined functions are converted to JavaScript-friendly
parameters.

Runtime changes:
1. User-defined functions do some extra processing to setup the expected
arguments, if necessary.
2. User-defined function calls do some extra parameter processing before
making their call

Not supported by these changes:
1. Calling user-defined class functions with Python-style arguments
2. Calling built-in functions with Python-style arguments
3. Unpacking argument lists
@differentmatt
Copy link
Owner Author

Closing this uber-issue, and will open separate ones for remaining work.

Example for user-defined functions:

def foo(voltage, amps='a', charge='high', *args, **keywords):
  print('voltage', voltage)
  print('amps', amps)
  print('charge', charge)
  print('args length', len(args))
  print('keywords length', keywords.length)
  print('')

foo(3)
foo(amps=4, voltage=7)
foo(1, 2, 3, 4, 5, 6, p="hi", q='boo')
function foo() {
    var __params0 = arguments.length === 1 && arguments[0].formals && arguments[0].keywords ? arguments[0] : null;
    var __formalsIndex0 = 0;
    var __args0 = arguments;
    function __getParam0(v, d) {
        var r = d;
        if (__params0) {
            if (__formalsIndex0 < __params0.formals.length) {
                r = __params0.formals[__formalsIndex0++];
            } else if (v in __params0.keywords) {
                r = __params0.keywords[v];
                delete __params0.keywords[v];
            }
        } else if (__formalsIndex0 < __args0.length) {
            r = __args0[__formalsIndex0++];
        }
        return r;
    }
    var voltage = __getParam0('voltage');
    var amps = __getParam0('amps', 'a');
    var charge = __getParam0('charge', 'high');
    var args = [];
    var keywords = {};
    if (__params0) {
        while (__formalsIndex0 < __params0.formals.length) {
            args.push(__params0.formals[__formalsIndex0++]);
        }
        keywords = __params0.keywords;
    } else {
        while (__formalsIndex0 < __args0.length) {
            args.push(__args0[__formalsIndex0++]);
        }
    }
    return function () {
        __pythonRuntime.functions.print('voltage', voltage);
        __pythonRuntime.functions.print('amps', amps);
        __pythonRuntime.functions.print('charge', charge);
        __pythonRuntime.functions.print('args length', __pythonRuntime.functions.len(args));
        __pythonRuntime.functions.print('keywords length', keywords.length);
        __pythonRuntime.functions.print('');
    }.call(this);
}
foo(__pythonRuntime.utils.createParamsObj(3));
foo(__pythonRuntime.utils.createParamsObj({
    amps: 4,
    __kwp: true
}, {
    voltage: 7,
    __kwp: true
}));
foo(__pythonRuntime.utils.createParamsObj(1, 2, 3, 4, 5, 6, {
    p: 'hi',
    __kwp: true
}, {
    q: 'boo',
    __kwp: true
}));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant