require'opal/nodes/base'moduleOpalmoduleNodes# Node responsible for extracting post-splat args# 1. There can be some arguments after the splat, this is why this node exist.# In this case if:# a. JS arguments length > args sexp length - then our splat has some items# and we know how many of them should come to splat# b. JS arguments length < args sexp length - then our splat is blank## 2. Super important:# a) optional arg always goes BEFORE the rest arg# b) optional args always appear in the sequence (i.e. you can't have def m(a=1,b,c=1))# c) precedence order:# 1. required arg (norm arg, mlhs arg)# 2. optional argument (optarg)# 3. splat/rest argument (restarg)# These statements simplify everything, keep them in mind.# 3. post_args here _always_ have the same structure:# 1. list of required arguments (only for mlhs, can be blank)# 2. list of optargs (only for post-args, can be blank)# 3. restarg (for both mlhs/post-args, can be nil)# 4. list of required args (for both mlhs/post-args, can be blank)#classPostArgsNode<Basehandle:post_args# kwargs contains the list of all post-kw* arguments# all of them can be processed in the first oderattr_reader:kwargs# required_left_args contains the list of required post args# like normarg or mlhs# For post-args: always blank (post args always start with optarg/restarg)# For mlhs: can be provided from# mlhs = (a, b, c)# required_left_args = [(:arg, :a), (:arg, :b)]attr_reader:required_left_args# optargs contains the list of optarg arguments# all of them must be populated depending on the "arguments.length"# if we have enough arguments - we fill them,# if not - we populate it with its default value# For post-args: can be provided from# def m(a=1, *b)# post-args = [(:optarg, :a, (:int, 1)), (:restarg, :b)]# optargs = [(:optarg, :a, (:int, 1))]# For mlhs: always blankattr_reader:optargs# returns a restarg sexp# if we have enough "arguments" - we fill it# if not - we populate it with "[]"# For post-args: can be provided from# def m(a=1, *b)# post-args = [(:optarg, :a, (:int, 1)), (:restarg, :b)]# restarg (:restarg, :b)attr_reader:restarg# required_right_args contains the list of required post args# like normarg and mlhs arg# For post-args: can be provided from# def m(a=1,*b,c)# post-args = [(:optarg, :a, (:int, 1)), (:restarg, :b), (:arg, :c)]# required_right_args = [(:arg, :c)]# For mlhs: can be provided from# (*a, b)# required_right_args = [(:arg, :b)]attr_reader:required_right_argsdefinitialize(*)super@kwargs=[]@required_left_args=[]@optargs=[]@restarg=nil@required_right_args=[]enddefextract_argumentsfound_opt_or_rest=falsechildren.eachdo|arg|arg.meta[:post]=truecasearg.typewhen:kwarg,:kwoptarg,:kwrestarg@kwargs<<argwhen:restarg@restarg=argfound_opt_or_rest=truewhen:optarg@optargs<<argfound_opt_or_rest=truewhen:arg,:mlhsiffound_opt_or_rest@required_right_args<<argelse@required_left_args<<argendendendenddefcompilereturnifchildren.empty?old_working_arguments=scope.working_argumentsif@sexp.meta[:js_source]js_source=@sexp.meta[:js_source]scope.working_arguments="#{js_source}_args"elsejs_source="arguments"scope.working_arguments="$post_args"endadd_temp"#{scope.working_arguments}"line"#{scope.working_arguments} = Opal.slice.call(#{js_source}, #{scope.inline_args.size}, #{js_source}.length);"extract_argumentspushprocess(kwargs_sexp)required_left_args.eachdo|arg|compile_required_arg(arg)endoptargs.eachdo|optarg|compile_optarg(optarg)endcompile_restargrequired_right_args.eachdo|arg|compile_required_arg(arg)endscope.working_arguments=old_working_argumentsenddefcompile_optarg(optarg)var_name=variable(optarg[1].to_sym)add_tempvar_nameline"if (#{required_right_args.size} < #{scope.working_arguments}.length) {"indentdoline"#{var_name} = #{scope.working_arguments}.splice(0,1)[0];"endline"}"pushprocess(optarg)enddefcompile_required_arg(arg)pushprocess(arg)enddefcompile_restargreturnunlessrestargline"if (#{required_right_args.size} < #{scope.working_arguments}.length) {"indentdo# there are some items coming to the splat, extracting themextract_restargendline"} else {"indentdo# splat is emptyextract_blank_restargendline"}"enddefextract_restargextract_code="#{scope.working_arguments}.splice(0, #{scope.working_arguments}.length - #{required_right_args.size});"ifrestarg[1]var_name=variable(restarg[1].to_sym)add_tempvar_nameline"#{var_name} = #{extract_code}"elselineextract_codeendenddefextract_blank_restargifrestarg[1]var_name=variable(restarg[1].to_sym)add_tempvar_nameline"#{var_name} = [];"endenddefkwargs_sexps(:post_kwargs,*kwargs)endendendend