Skip to content

Verified: Ladder Diagram

Each claim the Ladder Diagram page makes, with the tests that prove it in the last green CI run: 31 of 31 verified. The claims live in docs/claims/ladder.yaml.

Last green CI run 16 Oct 2026, 14:48 UTC on c7618d3 · all runtime claims

LD-001 verified

A .ld file's rungs compile and run; a normally-open contact passes power when its tag is TRUE and a normally-closed contact (/Tag) when it is FALSE.

where the docs say so

LD-002 verified

A rising-edge contact (+Tag) passes one scan of power on Tag's 0 to 1 transition and a falling-edge contact (-Tag) one scan on 1 to 0.

where the docs say so

  • pass TestConformance/ld-coils/+ contact passes one scan on the rise, - contact one scan on the fall in lang/conformance
  • pass TestEdgeContactOneShot in lang/ld

LD-003 verified

A parallel branch [ a | b ] is the OR of its legs; each leg is a series and branches nest.

where the docs say so

  • pass TestRungShapes in lang/ld
  • pass TestConformance/ld-coils/nested branch, bare leg passes at once in lang/conformance
  • pass TestConformance/ld-coils/nested branch, FB leg is Q false at PT-1ms, true at PT, drop resets in lang/conformance

LD-004 verified

A function contact such as EQ(P101_Mode, 0) passes power when the call returns TRUE; a leading / negates any BOOL term, including a function call or an accessor chain such as /t1.Q.

where the docs say so

  • pass TestNegatedFunctionContact in lang/ld
  • pass TestFunctionContactExpressionArgs in lang/ld
  • pass TestConformance/ld-coils/negated function contact passes power when the call returns FALSE in lang/conformance
  • pass TestFunctionContactPassesPowerWhenTrue in lang/ld

LD-005 verified

A block in the rung is driven by power on its power-in pin and power continues from its power-out pin; every other pin is named in the parentheses, with => capturing an output pin (BOOL or not) into a variable.

where the docs say so

  • pass TestTranspileRungs in lang/ld
  • pass TestLadderFunctionBlockRuns in lang/ld
  • pass TestLadderOutputBinding in lang/ld
  • pass TestConformance/ld-coils/FB-only rung (no coil) still runs, its outputs read elsewhere in lang/conformance

LD-006 verified

An output coil ( Tag ) assigns Tag the rung condition every scan; a set coil ( S Tag ) latches Tag := Tag OR condition; a reset coil ( R Tag ) unlatches Tag := Tag AND NOT condition.

where the docs say so

  • pass TestConformance/ld-coils/S coil latches, R coil unlatches, R wins a same-scan tie in lang/conformance
  • pass TestTranspileRungs in lang/ld

LD-007 verified

A P coil is TRUE for exactly one scan when the rung condition rises; an N coil for one scan when it falls; a condition already TRUE on the first scan counts as a rising edge.

where the docs say so

  • pass TestConformance/ld-coils/P coil is TRUE for exactly one scan on the rising edge in lang/conformance
  • pass TestConformance/ld-coils/first scan with A already TRUE counts as a rising edge in lang/conformance
  • pass TestConformance/ld-coils/N coil is TRUE for exactly one scan on the falling edge in lang/conformance

LD-008 verified

Contacts and coils take accessor references, so array elements and struct members address directly (Levels[2], PIT_001.VALUE).

where the docs say so · Array-element contact and coil (Levels[1] ( Levels[2] )) and an instance-array element; struct members as contact and coil (M.Cmd ( M.Running )) are run in the VAR_IN_OUT test. TestBitAccessInLadder was dropped: integer bit access is a different feature.

  • pass TestTranspileRungs in lang/ld
  • pass TestFBInstanceArrayInLadder in lang/ld
  • pass TestLadderFunctionBlockInOutStructPin in lang/ld

LD-009 verified

A rung header carries a (* ... *) comment, and full-line // comments inside the block are diagram notes.

where the docs say so

  • pass TestLadderComments in lang/ld
  • pass TestRungHeaderMultilineComment in lang/ld
  • pass TestRungHeaderCommentWithAsterisks in lang/ld

LD-010 verified

Series elements AND together and branch legs OR, so [ Start | Run ] /Stop ( Run ) compiles to Run := AND(OR(Start, Run), NOT Stop) (the seal-in).

where the docs say so

  • pass TestTranspileRungs in lang/ld

LD-011 verified

A rung needs at least one coil, function block or assignment. A block can sit anywhere in the rung, power continuing from its output pin (A t1:TON(PT := T#5S) B ( Lamp ) sets Lamp to t1.Q AND B). Without a coil the rung ends at its last block: A B t1:TON(PT := T#5S) is a complete rung whose output is t1.Q read elsewhere, and anything after that block is an error.

where the docs say so

  • pass TestFBOnlyRung in lang/ld
  • pass TestRungErrors in lang/ld
  • pass TestConformance/ld-coils/FB-only rung (no coil) still runs, its outputs read elsewhere in lang/conformance
  • pass TestConformance/ld-coils/block mid-rung, its Q carries power to the contact and coil after it in lang/conformance

LD-012 verified

Several coils on one rung share one condition, evaluated once and fanned out.

where the docs say so

LD-013 verified

A rung with only a coil is driven by the rail, so ( AlwaysOn ) assigns TRUE.

where the docs say so

LD-014 verified

Rungs evaluate top to bottom within a scan, so a coil written on one rung reads back as a contact on the next rung in the same scan.

where the docs say so

  • pass TestConformance/ld-coils/S coil latches, R coil unlatches, R wins a same-scan tie in lang/conformance
  • pass TestCoilReadsBackOnNextRungSameScan in lang/ld

LD-015 verified

Power is boolean: the six comparisons work as contacts, but a numeric function as a contact (ADD(TempC, 0.0)) is a compile error, not a pass-through.

where the docs say so

  • pass TestCheckRejects/numeric function contact in cmd/naut
  • pass TestSixComparisonsAsContacts in lang/ld

LD-016 verified

Standard blocks use fixed power pins: TON/TOF/TP IN and Q, CTU CU, CTD CD, R_TRIG/F_TRIG CLK, SR S1/Q1, RS S/Q1.

where the docs say so · Each fixture's ladder program drives the block from rung power and reads Q/Q1 as the coil, run against ST; TestLadderRTrigClockIsRungPower puts rung power on R_TRIG's CLK and runs the one-scan pulse.

LD-017 verified

Passing the power pin yourself (t1:TON(IN := x)) is an error, because power owns it.

where the docs say so · The "power pin passed" case of TestRungErrors.

LD-018 verified

Coils assign BOOL only; a timer's elapsed time or a counter's value is stored with the => output binding.

where the docs say so

  • pass TestLadderOutputBinding in lang/ld
  • pass TestConformance/ld-coils/FB-only rung (no coil) still runs, its outputs read elsewhere in lang/conformance
  • pass TestCoilOnNonBoolTargetRefused in lang/ld

LD-019 verified

Any instance output is readable as inst.Pin anywhere, including as a contact, without a => capture.

where the docs say so

  • pass TestLadderFunctionBlockRuns in lang/ld
  • pass TestNegatedFunctionContact in lang/ld

LD-020 verified

Edge contacts and coils get a stable derived instance name (from the rung, the tag and the repeat position) so the edge's retained state survives an unrelated edit.

where the docs say so

  • pass TestEdgeTrigNamesMatchTheCompiler in lang/ld
  • pass TestSwapWarmLadderKeepsEdgeContactMemory in runtime

LD-021 verified

LD transpiles in one hop to the FBD netlist, then to ST, so the built-in vocabulary, user FUNCTIONs and FUNCTION_BLOCKs from library .st files, and arrays/structs through accessors all work in ladder.

where the docs say so

  • pass TestTranspileRungs in lang/ld
  • pass TestLadderCompilesEndToEnd in lang/ld
  • pass TestConformance/st-case-insensitive/a FUNCTION called in another casing computes its result in lang/conformance
  • pass TestLadderLibraryProjectRuns in internal/project
  • pass TestFBInstanceArrayInLadder in lang/ld
  • pass TestLadderFunctionBlockInOutStructPin in lang/ld

LD-022 verified

A user block drops into a rung like a TON: power lands on EN if declared, otherwise the first BOOL VAR_INPUT not bound by name, and continues from ENO or the first BOOL VAR_OUTPUT.

where the docs say so

  • pass TestLadderFunctionBlockPowerPins in lang/ld
  • pass TestLadderLibraryProjectRuns in internal/project
  • pass TestLadderFunctionBlockPowerOutOfENO in lang/ld
  • pass TestLadderPowerSkipsBoundBoolInput in lang/ld

LD-023 verified

Instance state persists across scans, and an online edit carries it by name and type.

where the docs say so · Persistence across scans is run for ladder blocks; TestSwapWarmLadderCarriesRetainedState swaps a .ld program and carries a ladder block's seal-in and TON, a program TON and a CTU.

  • pass TestLadderFunctionBlockRuns in lang/ld
  • pass TestSwapWarmCarriesRetainedState in runtime
  • pass TestSwapWarmLadderCarriesRetainedState in runtime

LD-024 verified

A .ld file may hold FUNCTION_BLOCKs whose bodies are rungs, and a .ld file with no PROGRAM is a project library; two instances are independent with their own state; VAR_* sections including VAR_IN_OUT (a UDT by reference) work.

where the docs say so

LD-025 verified

naut check composes the line maps back through both hops, so a type error in the ST a rung produced reports at that rung's RUNG line.

where the docs say so

  • pass TestLineMap in lang/ld
  • pass TestCheckLandsDiagramErrorsOnSourceLine in cmd/naut

LD-026 verified

Online edits treat .ld as the program source; download, diff against the controller and naut pull move the ladder text itself.

where the docs say so

  • pass TestSwapWarmLadderCarriesRetainedState in runtime
  • pass TestPullMovesLadderText in cmd/naut

LD-027 verified

Jumps and labels (JMP, JMPC, LBL, RET) are not supported.

where the docs say so

LD-028 verified

Master control relay zones (MCR) are not supported.

where the docs say so

LD-029 verified

Negated coils ( /Tag ) are rejected.

where the docs say so

  • pass TestCheckRejects/negated coil in cmd/naut

LD-030 verified

A coil inside a branch, or ahead of a later block, is an error: the output zone is contiguous at the rung's right end.

where the docs say so

  • pass TestRungErrors in lang/ld
  • pass TestCoilZoneIsContiguousAtRightEnd in lang/ld

LD-031 verified

The ladder vocabulary is the IEC built-ins only; vendor instruction sets are not accepted.

where the docs say so · XIC, a Logix instruction, is refused as an unknown function.

  • pass TestCheckRejects/vendor instruction in cmd/naut