Enabling Dialects and Features¶
IronPLC aims to let you take code from another PLC environment and use it
without changes. To support this, IronPLC uses dialects — named presets
that select the IEC 61131-3 edition and a default set of extensions.
Individual --allow-* flags provide fine-grained control on top of the
selected dialect.
Supported Dialects¶
- iec61131-3-ed2 (default)
Strict IEC 61131-3:2003 (Edition 2). No extensions are enabled. This is the default when no dialect is specified.
Enables: nothing beyond strict IEC 61131-3 (no extensions).
- iec61131-3-ed3
Strict IEC 61131-3:2013 (Edition 3). Enables Edition 3 keywords including LTIME, LDATE, LTIME_OF_DAY, LDATE_AND_TIME, REF_TO, REF, and NULL. No extensions.
Enables:
--allow-long-time-typesand--allow-ref-to(the Edition 3 keywords), plus--allow-partial-access-syntax.- rusty
RuSTy-compatible dialect. Uses Edition 2 as a base (so Edition 3 type names like LDT remain available as identifiers) and enables REF_TO support together with the extensions that RuSTy accepts (listed below).
Enables:
--allow-c-style-comments,--allow-missing-semicolon,--allow-top-level-var-global,--allow-constant-type-params,--allow-empty-var-blocks,--allow-time-as-function-name,--allow-ref-to,--allow-ref-arithmetic,--allow-ref-stack-variables,--allow-ref-type-punning,--allow-int-to-bool-initializer,--allow-sizeof,--allow-system-uptime-global,--allow-cross-family-widening,--allow-partial-access-syntax,--allow-pragmas,--allow-short-circuit-operators,--allow-mixed-located-var-declarations,--allow-constant-initializer-expressions,--allow-bit-string-case-labels,--allow-paren-string-length,--allow-struct-initializer-expressions, and--allow-fb-inheritance.- codesys
CODESYS-compatible dialect. Uses Edition 2 as a base and enables the long-time-type keywords (LTIME, LDT, etc.) and REF_TO together with the extensions that the CODESYS IDE accepts. The implicit __SYSTEM_UP_TIME globals are not pre-bound under this dialect, since they are an IronPLC runtime convention rather than a CODESYS feature.
Enables:
--allow-c-style-comments,--allow-missing-semicolon,--allow-top-level-var-global,--allow-constant-type-params,--allow-empty-var-blocks,--allow-time-as-function-name,--allow-long-time-types,--allow-ref-to,--allow-reference-to,--allow-ref-arithmetic,--allow-ref-stack-variables,--allow-ref-type-punning,--allow-int-to-bool-initializer,--allow-sizeof,--allow-cross-family-widening,--allow-partial-access-syntax,--allow-pragmas,--allow-short-circuit-operators,--allow-mixed-located-var-declarations,--allow-constant-initializer-expressions,--allow-bit-string-case-labels,--allow-paren-string-length,--allow-struct-initializer-expressions, and--allow-fb-inheritance.- twincat
Beckhoff TwinCAT-compatible dialect. TwinCAT 3 is built on the CODESYS V3 runtime, so it uses an Edition 2 base and enables the long-time-type keywords (LTIME, LDT, etc.) along with the extensions TwinCAT shares with CODESYS, such as curly-brace pragmas, C-style comments, and the
AND_THENshort-circuit operator. Unlikecodesys, it does not enable theREF_TO/REF()/NULLreference extensions: TwinCAT spells referencesREFERENCE TO(bound withREF=), which this dialect enables instead via--allow-reference-to. (Pointer types —POINTER TOwithADR()— are not parsed yet.) As withcodesys, the implicit __SYSTEM_UP_TIME globals are not pre-bound, since they are an IronPLC runtime convention rather than a TwinCAT feature.Enables:
--allow-c-style-comments,--allow-missing-semicolon,--allow-top-level-var-global,--allow-constant-type-params,--allow-empty-var-blocks,--allow-time-as-function-name,--allow-long-time-types,--allow-reference-to,--allow-int-to-bool-initializer,--allow-sizeof,--allow-cross-family-widening,--allow-partial-access-syntax,--allow-pragmas,--allow-short-circuit-operators,--allow-mixed-located-var-declarations,--allow-constant-initializer-expressions,--allow-bit-string-case-labels,--allow-paren-string-length,--allow-struct-initializer-expressions, and--allow-fb-inheritance.
Editions are additive — enabling a later edition includes all features from earlier editions.
See Edition Support for a complete list of features that require a specific edition.
Tip
Run ironplcc dialects to see which features each dialect enables.
How to Select a Dialect¶
Command Line¶
Pass the --dialect flag when running ironplcc:
ironplcc check --dialect rusty main.st
ironplcc check --dialect iec61131-3-ed3 main.st
See ironplcc for all compiler options.
Visual Studio Code¶
Set the ironplc.dialect setting:
Open (or on macOS).
Search for
ironplc.Change Dialect to the desired value (e.g.,
rustyoriec61131-3-ed3).
Or add it directly to your settings.json:
{
"ironplc.dialect": "rusty"
}
See Settings Reference for all extension settings.
Enabling Specific Features¶
Individual --allow-* flags can be combined with any dialect to enable
additional features on top of the dialect’s defaults. Flags can only enable
features — they never disable features that a dialect already includes. To see
which flags a dialect already enables by default, see Supported Dialects.
--allow-c-style-commentsAllow C-style comments (
//line comments and/* */block comments). These are not part of the IEC 61131-3 standard but are supported by many PLC environments.--allow-missing-semicolonAllow missing semicolons after keyword statements like
END_IFandEND_STRUCT. Also allows aCASEbranch with no statements at all (a label that falls straight through to the next label,ELSE, orEND_CASE) – strict IEC 61131-3 only allows this via an explicit empty statement (5: ;); this fills in the dropped;.--allow-top-level-var-globalAllow
VAR_GLOBALdeclarations at the top level of a file, outside of aCONFIGURATIONblock. See Variable Scope.--allow-constant-type-paramsAllow constant references in type parameters such as array bounds and string lengths (e.g.,
ARRAY[1..MY_CONST] OF INTorSTRING[MY_CONST]). See Array Types.--allow-empty-var-blocksAllow empty variable blocks (
VAR END_VAR,VAR_INPUT END_VAR, etc.). Some PLC environments permit variable blocks with no declarations.--allow-time-as-function-nameAllow
TIMEto be used as a function name (e.g.,TIME()). Required for OSCAT compatibility whereTIME()reads the PLC system clock.--allow-long-time-typesAllow the IEC 61131-3:2013 long-time-type keywords LTIME, LDATE, LTIME_OF_DAY (
LTOD), and LDATE_AND_TIME (LDT). Without this flag those words remain available as ordinary identifiers, so Edition 2 code may use them as names.--allow-ref-toAllow
REF_TO,REF(), andNULLsyntax (standardized in IEC 61131-3:2013) without enabling the rest of Edition 3. This is useful when you need references but want to keep Edition 2 keyword handling for the rest of your code. See Reference Types.--allow-reference-toAllow the Beckhoff TwinCAT / CODESYS
REFERENCE TOreference type and theREF=binding operator. This is the TwinCAT/CODESYS-facing alternative to--allow-ref-to: the two describe the same underlying reference but with different surface syntax. The compiler does not restrict flag combinations, so--allow-ref-toand--allow-reference-tomay be set at once. See Reference Types.--allow-ref-arithmeticAllow arithmetic (
+,-) and ordering comparisons (<,>,<=,>=) onREF_TOtypes. By default, only=and<>are permitted on references.--allow-ref-stack-variablesAllow
REF()on stack-allocated variables (VAR_TEMPand functionVAR_INPUT/VAR_OUTPUT). Required for OSCAT patterns where the reference does not escape the call.--allow-ref-type-punningAllow assigning between
REF_TOtypes of different base types (type punning), such as reinterpreting the bits of aREALthrough aREF_TO DWORD.--allow-int-to-bool-initializerAllow integer literals
0and1asBOOLvariable initializers (e.g.,debug : BOOL := 0;). The compiler rewrites0toFALSEand1toTRUE. This is a universal extension supported by CoDeSys, TwinCAT, RuSTy, and virtually every PLC runtime.--allow-sizeofAllow the
SIZEOF()operator that returns the size in bytes of a variable or type. This is an extension supported by CODESYS, TwinCAT, and RuSTy. See SIZEOF.--allow-system-uptime-globalExpose
__SYSTEM_UP_TIME(TIME) and__SYSTEM_UP_LTIME(LTIME) as implicitVAR_GLOBALvalues holding the VM’s monotonic uptime. This is an IronPLC runtime convention.--allow-cross-family-wideningAllow implicit widening between bit-string and integer type families. For example, passing a
BYTEvariable where anINTparameter is expected, or passing a bare integer literal0where aBYTEparameter is expected. This is an extension supported by CODESYS, TwinCAT, and RuSTy.--allow-partial-access-syntaxAllow IEC 61131-3:2013 partial-access bit syntax
.%Xn(e.g.,myByte.%X3to access bit 3 of aBYTE). Semantically equivalent to the short form.n. Byte/word/dword/lword partial access (.%Bn,.%Wn,.%Dn,.%Ln) is not yet supported.--allow-pragmasAllow curly-brace pragmas such as
{attribute 'qualified_only'}and{attribute 'strict'}. These are CODESYS-core syntax (documented by CODESYS itself, and inherited by any IDE built on the CODESYS V3 runtime, including Beckhoff TwinCAT and Schneider Electric Machine Expert). A pragma is parsed and discarded like a comment — its contents are not yet interpreted. Pragmas do not nest; an unclosed{still produces a parse error.--allow-short-circuit-operatorsAllow the
AND_THENshort-circuit boolean operator, a Beckhoff/CODESYS extension. Unlike plainAND(which always evaluates both operands),AND_THENonly evaluates its right operand when the left operand isTRUE— commonly used to guard a dereference (ptr <> 0 AND_THEN ptr^ = 99).ironplcc checkfully supportsAND_THEN(parsing, type-checking, and round-tripping through plc2plc with its spelling preserved — it is not normalized toAND, since the short-circuit behavior is a real, externally-visible difference in TwinCAT/CODESYS). Codegen (ironplcc compile) does not yet implement the short-circuit evaluation this operator requires and refuses to compile it (problem P9999) rather than silently emitting eager (behaviorally incorrect) bytecode.--allow-mixed-located-var-declarationsAllow an
AT-located variable (complete address likeAT %IX0.0, or incomplete/wildcard address likeAT %I*) inside an otherwise plainVAR/VAR_INPUT/VAR_OUTPUTblock, instead of requiring located variables to live in their own dedicated block. The IEC 61131-3 standard requires located and plain variables to be declared in separate blocks; real CODESYS/TwinCAT code commonly mixes them. Without this flag, mixing produces problem P4036. A block containing only located variables is unaffected by this flag — it is standard syntax and always allowed.--allow-constant-initializer-expressionsAllow a
VARinitializer to be a constant expression — arithmetic between literals and/or references to declaredCONSTANTvariables (e.g.scaled : LREAL := SCALE*4.0;) — rather than only a bare literal. The IEC 61131-3 standard’s initializer grammar permits only literals in this position; this extension folds the expression to a literal at compile time. Using this form without the flag produces P4037; if the expression does not fully reduce to a constant (e.g. it references a non-CONSTANTvariable), it produces P4038.--allow-bit-string-case-labelsAllow a hex, binary, or octal bit-string literal (e.g.
16#D012,2#1010,8#17) as aCASElabel. The IEC 61131-3 standard grammar for a case label permits only a subrange, a decimalsigned_integer, or an enumerated value; radix-prefixed literals are separate productions the standard does not include here. Real TwinCAT/CODESYS code uses them. Without this flag, such a label produces P4041. A plain decimal label (5:) is standard syntax and is always allowed.--allow-paren-string-lengthAllow a string type’s maximum length to be delimited with parentheses (
STRING(255),WSTRING(100)) in addition to the standard square brackets (STRING[255]). The IEC 61131-3 standard grammar declares a string length only with brackets; the parenthesis form is a dialect extension. Without this flag, the parenthesis form produces P4042. The bracket form is standard syntax and is always allowed, and the delimiters must match (STRING[255)is always a syntax error). The renderer normalizes the parenthesis form to brackets.--allow-struct-initializer-expressionsAllow a general (non-constant) expression — such as a pointer dereference plus member access (
pDevice^.Delta) — as the value in a structured or call-style initializer’sname := valuepairs (e.g.tonDelta : TON := (PT := pDevice^.Delta);). The IEC 61131-3 standard grammar for a structured initializer value permits only a constant, enumerated value, array initializer, or nested structure initializer; a value computed at instantiation time is an extension used by TwinCAT/CODESYS. Without this flag, such a value produces P4043. A constant value is standard syntax and is always allowed.--allow-fb-inheritanceAllow function-block inheritance syntax:
EXTENDS/IMPLEMENTS/ABSTRACTonFUNCTION_BLOCKdeclarations, andINTERFACEdeclarations. These are parsed and theEXTENDS/IMPLEMENTS/INTERFACEnames are recognized as valid types, but inheritance, interface dispatch, method/property declarations, and abstract-instantiation checking are not yet semantically supported — using them produces problem P9999 rather than a parse error. Enabled by--dialect=rustyand--dialect=codesys.
Pass the flag when running ironplcc:
ironplcc check --allow-c-style-comments --allow-empty-var-blocks main.st
Or combine with a dialect:
ironplcc check --dialect iec61131-3-ed3 --allow-c-style-comments main.st
See ironplcc for all compiler options.