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

goto/jump/label support #298

Open
ukanuk opened this issue Jun 22, 2023 · 1 comment
Open

goto/jump/label support #298

ukanuk opened this issue Jun 22, 2023 · 1 comment

Comments

@ukanuk
Copy link

ukanuk commented Jun 22, 2023

Is your feature request related to a problem? Please describe.
Goto/label statements are available in C++, Visual Basic, and other languages, too. I work with the FANUC TP language which unfortunately does not have good support for more sophisticated control structures and therefore goto/label statements are often more readable.

Describe the solution you'd like
A unique word or number allows goto statements and associated labels to be associated with each other. Matchup should highlight this association, and vim should let me jump between them with %. Note there can be multiple goto statements but only one label; with multiple goto statements, % should cycle through all the goto's and the label similar to how it cycles through an if-elseif-elseif-else-endif statement.

Describe alternatives you've considered
The best I've come up so far is this (for FANUC TP language), but it only highlights previous matches when I select the final LBL. It will not find the final label when I select initial JMP LBL statements. It works as expected for multiline IF statements and FOR loops (note FANUC TP also supports single-line IF statements, where if the result is true then it executes the following instruction which is JMP in this sample code).

let b:match_ignorecase = 1
let b:match_words = '\<IF\>.*:\<ELSE\>.*:\<ENDIF\>.*,'
  \ . '\<FOR\>.*:\<ENDFOR\>.*,'
  \ . 'LBL\[\(\d\+\):LBL\[\1'

Additional context
Goto/label statements in C++ https://en.cppreference.com/w/cpp/language/goto

#include <iostream>
 
struct Object
{
    // non-trivial destructor
    ~Object() { [std::cout](https://en.cppreference.com/w/cpp/io/cout) << 'd'; }
};
 
struct Trivial
{
    double d1;
    double d2;
}; // trivial ctor and dtor
 
int main()
{
    int a = 10;
 
    // loop using goto
label:
    Object obj;
    [std::cout](https://en.cppreference.com/w/cpp/io/cout) << a << ' ';
    a -= 2;
 
    if (a != 0)
        goto label;  // jumps out of scope of obj, calls obj destructor
    [std::cout](https://en.cppreference.com/w/cpp/io/cout) << '\n';
 
    // goto can be used to efficiently leave a multi-level (nested) loops
    for (int x = 0; x < 3; ++x)
        for (int y = 0; y < 3; ++y)
        {
            [std::cout](https://en.cppreference.com/w/cpp/io/cout) << '(' << x << ',' << y << ") " << '\n';
            if (x + y >= 3)
                goto endloop;
        }
 
endloop:
    [std::cout](https://en.cppreference.com/w/cpp/io/cout) << '\n';
 
    goto label2; // jumps into the scope of n and t
 
    [[maybe_unused]] int n; // no initializer
 
    [[maybe_unused]] Trivial t; // trivial ctor/dtor, no initializer
 
//  int x = 1;   // error: has initializer
//  Object obj2; // error: non-trivial dtor
 
label2:
    {
        Object obj3;
        goto label3; // jumps forward, out of scope of obj3
    }
 
label3:
    [std::cout](https://en.cppreference.com/w/cpp/io/cout) << '\n';
}

Goto/label statements in Visual Basic https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/goto-statement

Sub GoToStatementDemo()
        Dim number As Integer = 1
        Dim sampleString As String
        ' Evaluate number and branch to appropriate label.
        If number = 1 Then GoTo Line1 Else GoTo Line2
Line1:
        sampleString = "Number equals 1"
        GoTo LastLine
Line2:
        ' The following statement never gets executed because number = 1.
        sampleString = "Number equals 2"
LastLine:
        ' Write "Number equals 1" in the Debug window.
        Debug.WriteLine(sampleString)
    End Sub

JMP/LBL statements in FANUC TP sample code with valid syntax (yes, including the hardcoded line numbers starting partway through). Syntax is already mostly supported by https://github.com/KnoP-01/vim-tp, but I opened an issue with that project to improve matchup support.

/PROG  JMOVE
/ATTR
OWNER		= MNEDITOR;
COMMENT		= "";
PROG_SIZE	= 202;
CREATE		= DATE 23-06-22  TIME 09:24:12;
MODIFIED	= DATE 23-06-22  TIME 09:24:20;
FILE_NAME	= ;
VERSION		= 0;
LINE_COUNT	= 1;
MEMORY_SIZE	= 570;
PROTECT		= READ_WRITE;
TCD:  STACK_SIZE	= 0,
      TASK_PRIORITY	= 50,
      TIME_SLICE	= 0,
      BUSY_LAMP_OFF	= 0,
      ABORT_REQUEST	= 0,
      PAUSE_REQUEST	= 0;
DEFAULT_GROUP	= 1,*,*,*,*;
CONTROL_CODE	= 00000000 00000000;
LOCAL_REGISTERS	= 0,0,0;
/APPL
  SPOT Welding Equipment Number : 1 ;
/MN
   1:  !******************** ;
   2:  !MAIN SEQUENCE ;
   3:   ;
   4:  LBL[11:Main process] ;
   5:  !Do stuff ;
   6:   ;
   7:  !Error if timeout waiting for END ;
   8:  LBL[12] ;
   9:  WAIT (DI[1105:SIGNAL END]=ON) TIMEOUT,LBL[91] ;
  10:   ;
  11:  ! Good result = skip to end ;
  12:  LBL[13] ;
  13:  IF (DI[1118:RESULT GOOD]),JMP LBL[19] ;
  14:   ;
  15:  ! End of process cleanup ;
  16:  IF (GO[30:POSITION]<>0) THEN ;
  17:  FOR R[1]=1 TO 5 ;
  18:  !Do stuff ;
  19:  !Wait for input 1114 else error ;
  20:  LBL[17] ;
  21:  WAIT (DI[1114:PARTIAL POSITION]) TIMEOUT,LBL[92] ;
  22:  ENDFOR ;
  23:  ELSE ;
  24:  !Wait for positon=0 else error ;
  25:  LBL[18] ;
  26:  WAIT (DI[1113:HOME POSITION]) TIMEOUT,LBL[93] ;
  27:  ENDIF ;
  28:   ;
  29:  !End program normally ;
  30:  LBL[19:END PROCESS] ;
  31:  END ;
  32:   ;
  33:  !******************** ;
  34:  !ERROR HANDLING ;
  35:   ;
  36:  LBL[91:ERROR0] ;
  37:  LBL[92:ERROR1] ;
  38:  !Do error handling, then restart ;
  39:  JMP LBL[11] ;
  40:   ;
  41:  LBL[93:ERROR2] ;
  42:  !Do error handling, then resume ;
  43:  JMP LBL[12] ;
/POS
/END
@ukanuk
Copy link
Author

ukanuk commented Jun 24, 2023

Simplified FANUC TP example:

LBL[11:Main process] ;
WAIT (DI[1105:SIGNAL END]=ON) TIMEOUT,LBL[91] ;
WAIT (DI[1106:SIGNAL START]=OFF) TIMEOUT,LBL[91] ;
LBL[12] ;
IF (DI[1118:RESULT GOOD]),JMP LBL[19] ;
WAIT (DI[1114:PARTIAL POSITION]) TIMEOUT,LBL[92] ;
WAIT (DI[1113:HOME POSITION]) TIMEOUT,LBL[93] ;
LBL[19:END PROCESS] ;
END ;
LBL[91:ERROR0] ;
LBL[92:ERROR1] ;
JMP LBL[11] ;
LBL[93:ERROR2] ;
JMP LBL[12] ;

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