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

emit/__emit operator #180

Merged
merged 6 commits into from
Oct 7, 2017
Merged

emit/__emit operator #180

merged 6 commits into from
Oct 7, 2017

Conversation

VVWVV
Copy link
Contributor

@VVWVV VVWVV commented Aug 19, 2017

This PR implements the emit/__emit operator, a modern alternative for the #emit directive.

Signed-off-by: VVWVV <d0u61ev@gmail.com>
Signed-off-by: VVWVV <d0u61ev@gmail.com>
Signed-off-by: VVWVV <d0u61ev@gmail.com>
@Daniel-Cortez
Copy link
Contributor

Daniel-Cortez commented Aug 19, 2017

Pros and cons of the emit/__emit operator over the #emit directive

➕ As an operator, emit can be used in expressions and marcos.

➕ Argument types are checked by the compiler (e.g. branch instructions like JUMP, JZER, JNZ etc. only take a label name as an argument, otherwise the compiler would issue an error).

➖ Not a part of the Pawn 3.2 standard (?)

Syntax

Single-line:

emit <AMX instruction>

Multiline:

emit { <AMX instruction list> }

There's also the __emit keyword that can be used in cases when emit conflicts with something else in the code.

Single-line syntax:

emit const.pri 1

This kind of syntax is very simple. Only one emit statement per line and one AMX instruction per statement are allowed.
To output more than one instruction, either use multiline syntax (see below) or multiple single-line emit statements:

// Swap `a` and `b`
new a = 4, b = 5;
emit load.s.pri a
emit load.s.alt b
emit stor.s.pri b
emit stor.s.alt a

Multiline syntax:

emit { const.pri 1 }

Multiple instructions in one multiline emit statement are allowed, but with one instruction per line only.

new a = 4, b = 5;
emit {
    load.s.pri a
    load.s.alt b
    stor.s.pri b
    stor.s.alt a
}

To put multiple AMX instructions in one line, put each of them into separate multiline emit statements, one instruction per statement:

new a = 4, b = 5;
emit { load.s.both a b } emit { stor.s.pri b } emit { stor.s.alt a }

Also the multiline emit operator can be used to make expressions. emit expressions return the value contained in the PRI register.

new a = emit { const.pri 1 }; // a = 1

Another example:

printf(
    "Free stack space: %d",
    (emit{lctrl 4}, emit{heap 0}, emit{sub})
);

This can be useful for function-like macros:

#define GetFreeStackSpace() (   \
    emit{lctrl 4},              \
    emit{heap 0},               \
    emit{sub}                   \
)

main()
{
    printf("Free stack/heap space: %d", GetFreeStackSpace()); // The return value is used in `printf()`
    GetFreeStackSpace(); // Can be used like this as well, but gives warning #215.
}

Note that the compiler issues warning #215 ("expression has no effect") in the example above, so you might want to do this in order to suppress it:

stock __tmp_GetFreeStackSpace; // Assignment of the expression result to this
                               // variable should help to suppress warning #215.
#define GetFreeStackSpace() (   \
    __tmp_GetFreeStackSpace =   \
    emit{lctrl 4},              \
    emit{heap 0},               \
    emit{sub}                   \
)

main()
{
    printf("Free stack/heap space: %d", GetFreeStackSpace());
    GetFreeStackSpace();
}

@Y-Less
Copy link
Member

Y-Less commented Aug 19, 2017

This is awesome, but why not stick to emit naming? IMHO it would be much clearer that #emit @emit (in amx_assembly) and emit from this are all related. There is also already __asm in amx_assembly that actually outputs x86 assembly, and asm is more likely to be in use in existing codebases than emit. It would also reduce the number of unique keywords.

@Daniel-Cortez
Copy link
Contributor

Daniel-Cortez commented Aug 19, 2017

This is awesome, but why not stick to emit naming? IMHO it would be much clearer that #emit @emit (in amx_assembly) and emit from this are all related.

Well, that's debatable. In my opinion, emit may cause more confusion with #emit and @emit rather than help by making them all related. I'm not a veteran of the SA-MP community like you, though, so you probably know better.

@Y-Less
Copy link
Member

Y-Less commented Sep 30, 2017

Or __emit, since double-underscore prefixes are meant to be reserved for compiler things only, there's no chance of conflicts with conforming code.

@VVWVV VVWVV changed the title asm operator __emit operator Sep 30, 2017
@VVWVV VVWVV changed the title __emit operator asm operator Oct 1, 2017
@Daniel-Cortez
Copy link
Contributor

Daniel-Cortez commented Oct 1, 2017

The name asm was influenced by the asm operator from C/C++ (well, obviously). Initially the operator was called _asm in order to avoid conflicts, but then we (and by "us" I mean @VVWVV and myself; I was reviewing @VVWVV's code from time to time before making it into this PR) decided to stick to asm for the following reasons:

  1. It's simpler to type (unlike @asm, __asm, __emit etc.)
  2. It's an improvement for the language itself, not for a third-party library where names starting with clunky prefixes like "__" or "@" could be (more or less) acceptable.

Anyway, avoiding conflicts seems reasonable as well, so maybe keeping asm with __asm as a fallback would be the best option? Or emit and __emit if both of the former conflict with something else? That way we could both provide compatibility and not sacrifice the operator's name for third-party code completely.

Also, not sure about that, but maybe we should make a poll or something to determine the best option?

@oscar-broman
Copy link
Contributor

oscar-broman commented Oct 1, 2017

It makes more sense to use emit instead of asm, since the Pawn creators decided to go with #emit and not #asm (or something else).

This PR adds an operator closely related to #emit, so why not name it emit?

Names related to pre-processor directives:
#if - if
#else - else
#elseif - else if
#assert - assert
#define - defined
#warning - #pragma warning
#emit - emit (?)

@Daniel-Cortez
Copy link
Contributor

Ok then, I guess I was wrong about confusion between __emit, #emit and @emit; consistency with directive names makes much more sense.
Also both asm and __asm are already used as macro names in amx_assembly, so, IMHO, using emit and __emit is obviously the best option.

@Y-Less
Copy link
Member

Y-Less commented Oct 6, 2017

@Zeex could you have a look at this (and the other pull requests) please?

Rename `asm` to `emit`, add `__emit` as an alternate keyword.
@VVWVV VVWVV changed the title asm operator emit/__emit operator Oct 6, 2017
@Zeex
Copy link
Contributor

Zeex commented Oct 7, 2017

This seems like a useful thing, thanks for the PR. Nicely done.

@Zeex Zeex merged commit 6e08f46 into pawn-lang:master Oct 7, 2017
@Y-Less Y-Less mentioned this pull request Sep 23, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants