<commit_before>import BaseTypeRegistry from './BaseTypeRegistry';
import Context from './Context';
import Callable from './Callable';
import JelObject from './JelObject';

/**
 * A type that can be called.
 */
export default class FunctionCallable extends Callable {
	argMapper: any;
	
	constructor(public f: Function, argMapper?: Array<string>|Object|string, public self?: any, public name?: string) {
		super();
		this.argMapper = this.convertArgMapper(argMapper);  // map argName -> index. Null if named-argument-methods
	}
	
	invokeWithObject(ctx: Context, args: any[], argObj?: any, ): JelObject|null|Promise<JelObject|null> {
		if (this.argMapper) {
			const allArgs = [ctx].concat(args);
			if (argObj)
				for (const name in argObj) {
					const idx = this.argMapper[name];
					if (idx == null){
						throw new Error(`Unknown argument name '${name}' can not be mapped for function '${this.name || 'anonymous'}'.`);
					}
					allArgs[idx] = argObj[name];
				}
			return BaseTypeRegistry.mapNativeTypes(this.f.apply(this.self, allArgs));
		}
		else {
			if (args.length)
				throw new Error(`Method only supports named arguments, but got ${args.length} anonymous argument(s).`);
			return BaseTypeRegistry.mapNativeTypes(this.f.apply(this.self, [ctx, argObj || {}]));
		}
	}
	
	invoke(ctx: Context, ...args: any[]): JelObject|null|Promise<JelObject|null> {
		return this.invokeWithObject(ctx, args, null);
	}
	
	// converts argmapper from array to object, if needed
	convertArgMapper(argMapper?: Object|Array<string>|string): Object|null {
		if (argMapper === 'named') // same as Runtime.NAMED_ARGUMENT_METHOD.
			return null;<commit_msg>start refactoring callables to support this<commit_after>import BaseTypeRegistry from './BaseTypeRegistry';
import Context from './Context';
import Callable from './Callable';
import JelObject from './JelObject';

/**
 * A type that can be called.
 */
export default class FunctionCallable extends Callable {
	argMapper: any;
	
	constructor(public f: Function, argMapper?: Array<string>|Object|string, public self?: any, public name?: string) {
		super();
		this.argMapper = this.convertArgMapper(argMapper);  // map argName -> index. Null if named-argument-methods
	}
	
  static invoke(ctx: Context, name: string|undefined, self: any, f: Function, args: any[], argObj?: any, argMapper?: any):  JelObject|null|Promise<JelObject|null> {
		if (argMapper) {
			const allArgs = [ctx].concat(args);
			if (argObj)
				for (const argName in argObj) {
					const idx = argMapper[argName];
					if (idx == null) {
						throw new Error(`Unknown argument name '${argName}' can not be mapped for function '${name || 'anonymous'}'.`);
					}
					allArgs[idx] = argObj[argName];
				}
			return BaseTypeRegistry.mapNativeTypes(f.apply(self, allArgs));
		}
		else {
			if (args.length)
				throw new Error(`Method only supports named arguments, but got ${args.length} anonymous argument(s).`);
			return BaseTypeRegistry.mapNativeTypes(f.apply(self, [ctx, argObj || {}]));
		}
  }
  
	invokeWithObject(ctx: Context, args: any[], argObj?: any): JelObject|null|Promise<JelObject|null> {
    return FunctionCallable.invoke(ctx, this.name, this.self, this.f, args, argObj, this.argMapper);
	}
	
	invoke(ctx: Context, ...args: any[]): JelObject|null|Promise<JelObject|null> {
		return this.invokeWithObject(ctx, args, null);
	}
	
	// converts argmapper from array to object, if needed
	convertArgMapper(argMapper?: Object|Array<string>|string): Object|undefined {
		if (argMapper === 'named') // same as Runtime.NAMED_ARGUMENT_METHOD.
			return undefined;
{'fraction_non_alphanumeric': 0.1416225257875662, 'fraction_numerical': 0.0, 'mean_word_length': 4.419939577039275, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '787212', 'n_tokens_mistral': 1214, 'n_tokens_neox': 1101, 'n_words': 310}