From twincat-mcp-agent
Use this skill to correctly format ST (Structured Text) logic, operators, and control flow statements. It includes precedence rules, IF/CASE/FOR/WHILE loops syntax, mathematical/bitwise operator rules (MOD, SHL, ADR, BITADR), and the list of reserved IEC keywords.
How this skill is triggered — by the user, by Claude, or both
Slash command
/twincat-mcp-agent:tc-syntax-control-flowThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
| Precedence | Operation | Symbol |
| Precedence | Operation | Symbol |
|---|---|---|
| 1 | Parentheses | (expression) |
| 2 | Function call | FunctionName(params) |
| 3 | Exponentiation | EXPT |
| 4 | Negate / Complement | -, NOT |
| 5 | Multiply, Divide, Modulo | *, /, MOD |
| 6 | Add, Subtract | +, - |
| 7 | Comparison | <, >, <=, >= |
| 8 | Equality | =, <> |
| 9 | Boolean AND | AND |
| 10 | Boolean XOR | XOR |
| 11 | Boolean OR | OR |
Equal-precedence operators are processed left to right.
| Operation | Operators | Example |
|---|---|---|
| Assignment | := | bVar := TRUE; |
| Arithmetic | +, -, *, /, MOD, EXPT | nVal := (nA * nB) MOD 10; |
| Bitwise | AND, OR, XOR, NOT | nFlags := nInput AND 16#FF; |
| Bit Shift | SHL, SHR, ROL, ROR | nResult := SHL(nVal, 2); |
| Comparison | =, <>, >, <, >=, <= | IF nCnt >= 10 THEN ... |
| Selection | SEL, MAX, MIN, LIMIT, MUX | nVal := SEL(bSwitch, 0, 100); |
| Address | ADR, SIZEOF, XSIZEOF, BITADR | pData := ADR(stConfig); |
| Dynamic Memory | __NEW, __DELETE | pFB := __NEW(FB_Dyn); __DELETE(pFB); |
| Type Query | __QUERYINTERFACE, __QUERYPOINTER | Runtime interface/pointer conversion. Returns BOOL. |
| Validation | __ISVALIDREF | bOk := __ISVALIDREF(refVar); |
| Introspection | __VARINFO, __POUNAME, __POSITION | Runtime variable info, POU name, source position. |
MOD is not defined for REAL types (error 4017).ADR is not allowed on bits — use BITADR instead (error 4031).ADR must not be applied to expressions or constants (error 4030).XSIZEOF returns ULINT on 64-bit, UDINT on 32-bit; use __UXINT for portability.__NEW allocates from router memory pool. FBs/DUTs require {attribute 'enable_dynamic_creation'}.IF fTemperature < 0.0 THEN
eState := E_State.FROZEN;
ELSIF fTemperature = 0.0 THEN
eState := E_State.FREEZING;
ELSIF fTemperature > 100.0 THEN
eState := E_State.BOILING;
ELSE
eState := E_State.NORMAL;
END_IF;
Condition must be BOOL expression (error 4253).
CASE nCommandID OF
1: bMotorOn := TRUE;
2: bMotorOn := FALSE;
3, 4: bAlarm := TRUE;
10..20: nSpeed := nCommandID * 10;
ELSE
bFault := TRUE;
END_CASE;
FOR nIndex := 1 TO 100 BY 2 DO
IF aBuffer[nIndex] = 70 THEN
nFound := nIndex;
EXIT;
END_IF;
END_FOR;
BY is optional (defaults to 1).nIdx := 0;
WHILE nIdx <= 100 AND aData[nIdx] <> 70 DO
nIdx := nIdx + 2;
END_WHILE;
Condition must be BOOL (error 4254).
REPEAT
nRetryCount := nRetryCount + 1;
bSuccess := F_TryConnect();
UNTIL bSuccess OR nRetryCount >= 5
END_REPEAT;
Executes at least once. Condition must be BOOL (error 4255).
EXIT — exits innermost loop. Error 4262 if outside a loop.RETURN — exits current POU immediately.| Scope | Description | Notes |
|---|---|---|
VAR_INPUT | Input parameters | Read-only inside POU. |
VAR_OUTPUT | Output parameters | Not allowed in functions (error 3820). |
VAR_IN_OUT | Pass-by-reference | Cannot have initial values (error 3761). Must always be provided (error 4061). |
VAR | Local variables | Static lifetime in FB, temporary in Function. |
VAR_TEMP | Temporary variables | Stack memory, reset every cycle. |
VAR RETAIN | Retained variables | Persisted across power cycles. No effect in functions (warning 1410). |
VAR PERSISTENT | Persistent variables | Persisted across power cycles. |
VAR CONSTANT | Constants | Read-only. Cannot be on direct addresses (error 3726). |
VAR_EXTERNAL | External global ref | Must match a globally declared variable (error 3840). |
VAR_STAT | Static variables | Only exist once even with multiple FB instances. |
VAR_INST | Instance variables in methods | Retained between method calls. Only in methods of FBs. |
VAR_GENERIC CONSTANT | Generic constant | Integer constant defined at instantiation. Requires Build 4026+. |
METHOD MethLast : INT
VAR_INPUT
nVar : INT;
END_VAR
VAR_INST
nLast : INT := 0;
END_VAR
MethLast := nLast;
nLast := nVar;
FUNCTION_BLOCK FB_Buffer
VAR_GENERIC CONSTANT
nMaxLen : UDINT := 1;
END_VAR
VAR
aData : ARRAY[0..nMaxLen-1] OF BYTE;
END_VAR
VAR
fbBuf100 : FB_Buffer<100>;
END_VAR
SUPER^(); (* Call FB body of base class *)
SUPER^.METH_DoIt(); (* Call method of base class *)
THIS^.nVarB := 222; (* Access FB variable shadowed by local *)
F_FunA(fbMyFb := THIS^); (* Pass own instance to function *)
Only usable in methods and function block implementations.
VAR
bInput1 AT %IX0.0 : BOOL; (* Digital input, byte 0, bit 0 *)
nAnalog AT %IW2 : INT; (* Analog input, word 2 *)
bOutput AT %QX0.0 : BOOL; (* Digital output *)
nMemory AT %MW10 : INT; (* Memory word 10 *)
END_VAR
| Prefix | Area |
|---|---|
%I | Input |
%Q | Output |
%M | Memory/Marker |
X | Bit |
BOOL variables allowed on bit addresses (error 3722).Keywords must be written in CAPITALS and cannot be used as variable names.
Control Flow: IF, THEN, ELSIF, ELSE, END_IF, CASE, OF, END_CASE, FOR, TO, BY, DO, END_FOR, WHILE, END_WHILE, REPEAT, UNTIL, END_REPEAT, EXIT, RETURN, CONTINUE
Declarations: VAR, VAR_INPUT, VAR_OUTPUT, VAR_IN_OUT, VAR_GLOBAL, VAR_TEMP, VAR_STAT, VAR_INST, VAR_EXTERNAL, VAR_CONFIG, VAR_GENERIC, END_VAR, CONSTANT, RETAIN, PERSISTENT, AT
POU Types: PROGRAM, END_PROGRAM, FUNCTION, END_FUNCTION, FUNCTION_BLOCK, END_FUNCTION_BLOCK, METHOD, END_METHOD, PROPERTY, END_PROPERTY, ACTION, END_ACTION, INTERFACE, END_INTERFACE
Special (ExST): __NEW, __DELETE, __ISVALIDREF, __QUERYINTERFACE, __QUERYPOINTER, __VARINFO, __POUNAME, __POSITION, __TRY, __CATCH, __FINALLY, __ENDTRY, AND_THEN, OR_ELSE
TON (On-Delay), TOF (Off-Delay), TP (Pulse).R_TRIG (Rising Edge), F_TRIG (Falling Edge).CTU (Count Up), CTD (Count Down), CTUD (Count Up/Down).CONCAT, LEN, LEFT, RIGHT, MID, INSERT, DELETE, REPLACE, FIND.MEMCPY, MEMSET, MEMMOVE (in Tc2_System).ABS, SQRT, SIN, COS, TAN, ASIN, ACOS, ATAN, EXP, LN, LOG.VAR
fbTonDelay : TON;
fbTrigRise : R_TRIG;
END_VAR
fbTonDelay(IN := bStart, PT := T#5S);
IF fbTonDelay.Q THEN
bDelayedStart := TRUE;
END_IF;
fbTrigRise(CLK := bButton);
IF fbTrigRise.Q THEN
nPressCount := nPressCount + 1;
END_IF;
Skips the rest of the current iteration and proceeds with the next loop pass. Valid only inside FOR, WHILE, REPEAT.
FOR i := 1 TO 100 DO
IF aData[i] = 0 THEN
CONTINUE; (* skip zero entries *)
END_IF;
nSum := nSum + aData[i];
END_FOR;
| Operator | Behavior |
|---|---|
AND_THEN | Right operand evaluated only if left operand is TRUE |
OR_ELSE | Right operand evaluated only if left operand is FALSE |
(* Safe pointer dereference using short-circuit *)
IF (pConfig <> 0) AND_THEN (pConfig^.bEnabled) THEN
fbProcess();
END_IF;
Standard AND / OR always evaluate both sides — risky with side effects (warning 1504/1505).
{attribute 'qualified_only'}
{attribute 'strict'}
TYPE E_State : (eIdle, eRun, eStop) END_TYPE
CASE eMyState OF
E_State.eIdle: ...
E_State.eRun: ...
E_State.eStop: ...
END_CASE;
With {attribute 'strict'}, the compiler verifies all enum values are handled (or ELSE is provided).
VAR_GLOBAL
bEStop AT %IX0.0 : BOOL; (* Bit-aligned input *)
nCount AT %MW20 : INT; (* Memory word *)
aBuf AT %MB100 : ARRAY [0..9] OF BYTE; (* INVALID — error 3727 *)
END_VAR
AT %I* and AT %Q* declarations are usually replaced in TwinCAT 3 by link mappings in the System Manager / .tsproj rather than fixed addresses.%M* (marker area) is preserved across cycles but not retained across power cycles unless declared RETAIN.npx claudepluginhub techindustryx/twincat-agent --plugin twincatProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.