Skip to content

Instantly share code, notes, and snippets.

@KronicDeth
Created May 24, 2015 19:50
Show Gist options
  • Save KronicDeth/de735172ed885ebe19ca to your computer and use it in GitHub Desktop.
Save KronicDeth/de735172ed885ebe19ca to your computer and use it in GitHub Desktop.
%% Every time the parser sees a (unquote_splicing())
%% it assumes that a block is being spliced, wrapping
%% the splicing in a __block__. But in the stab clause,
%% we can have (unquote_splicing(1,2,3)) -> :ok, in such
%% case, we don't actually want the block, since it is
%% an arg style call. unwrap_splice unwraps the splice
%% from such blocks.
unwrap_splice([{'__block__', [], [{unquote_splicing, _, _}] = Splice}]) ->
Splice;
unwrap_splice(Other) -> Other.
package org.elixir_lang.psi.impl;
import com.ericsson.otp.erlang.*;
import org.elixir_lang.Macro;
public class ElixirPsiImplUtil {
private static final OtpErlangAtom UNQUOTE_SPLICING = new OtpErlangAtom("unquote_splicing");
/**
* Unwraps <code>quote_splicing</code> in stabOperation.
*
* @param quotedArguments base quoted arguments from the noParenthesesArguments or parenthesesArguments
* @return quoted arguments with quote_splicing inside block extracted to just the splice
* @see <a href="https://github.com/elixir-lang/elixir/blob/de39bbaca277002797e52ffbde617ace06233a2b/lib/elixir/src/elixir_parser.yrl#L704-L714"><code>unwrap_splice</code></a>
* @see <a href="https://github.com/elixir-lang/elixir/blob/de39bbaca277002797e52ffbde617ace06233a2b/lib/elixir/src/elixir_parser.yrl#L276-L281"><code>unwrap_splice</code> in <code>stab_expr</code></a>
*/
private static OtpErlangObject[] unwrapSplice(OtpErlangObject[] quotedArguments) {
OtpErlangObject[] unwrapped = quotedArguments;
// [_]
if (quotedArguments.length == 1) {
OtpErlangObject quotedArgument = quotedArguments[0];
// [{:__block__, _, _}]
if (Macro.isBlock(quotedArgument)) {
OtpErlangTuple expression = (OtpErlangTuple) quotedArgument;
OtpErlangObject blockArgument = expression.elementAt(2);
// [{:__block__, _, blockArgument} when is_list(blockArgument)
if (blockArgument instanceof OtpErlangList) {
OtpErlangList blockArgumentList = (OtpErlangList) blockArgument;
// [{:__block__, _, [_]}]
if (blockArgumentList.arity() == 1) {
OtpErlangObject blockArgumentListElement = blockArgumentList.elementAt(0);
// [{:__block__, _, [{_, _, _}]}]
if (Macro.isExpression(blockArgumentListElement)) {
OtpErlangTuple blockArgumentExpression = (OtpErlangTuple) blockArgumentListElement;
OtpErlangObject blockArgumentReceiver = blockArgumentExpression.elementAt(0);
// [{:__block__, _, [{:unquote_splicing, _, _}]
if (blockArgumentReceiver.equals(UNQUOTE_SPLICING)) {
unwrapped = blockArgumentList.elements();
}
}
}
}
}
}
return unwrapped;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment