Table of Contents

Namespace Hi.NcParsers.EvaluationSyntaxs.Evaluation

Classes

LocalVariableLookup

Reads Fanuc-style local macro variables (#1-#33) from Vars.Local on the current SyntaxPiece JSON, falling back to the immediately previous block when they share the same MacroFrame id. Self-gates the id range so the evaluator's RuntimeVariableLookups chain can fall through to the next lookup for out-of-range keys.

Two-step lookup (mirrors VolatileVariableLookup): the current block sees writes that FanucMacroCallSyntax stamped at inline time (the call-line argument bindings) and writes that FanucLocalVariableReadingSyntax applied on this block before the lookup runs; the previous block (frame-checked) supplies body-internal writes from the prior block in the same macro frame. Looking past the previous block is unnecessary because the reader carries forward block-by-block within a frame.

Frame isolation via MacroFrame: a previous block whose frame id differs from the current block's is skipped — a macro body's body-internal locals are invisible to the caller after return, and the caller's main-frame locals are invisible inside the macro. M98/M198 subprogram inlining (SubProgramCallSyntax) deliberately does not stamp MacroFrame on its inlined blocks, so the callee inherits the caller's frame and sees the caller's locals — matching real Fanuc M98 semantics.

Stateless and dependency-free — instances are interchangeable.

NcBinaryExpr

Binary operation on two operands. Covers arithmetic (+ - * / / MOD), comparison (EQ NE GT GE LT LE, yielding 1.0 / 0.0), and logical bitwise (AND OR XOR, operands truncated to long).

NcExpr

AST root for a Fanuc Custom Macro B value expression. Concrete leaves and combinators sit alongside NcExpressionParser; walking is the job of NcExpressionEvaluator.

NcExpressionEvaluator

Walks an NcExpr AST and produces an EvalResult. Resolves #nnn via an IVariableLookup; built-in function names are matched case-insensitively against a fixed table.

Phase-1 supports: SIN COS TAN ASIN ACOS ATAN SQRT ABS ROUND FIX FUP LN EXP POW. Trigonometric arguments and results are in degrees, matching Fanuc Custom Macro B convention. Unknown function names surface as UnsupportedFunctionCode; arity mismatches as ArgumentMismatchCode; division / MOD by zero and domain errors (e.g. SQRT[-1]) as MathErrorCode; vacant operands as VacantErrorCode.

Numeric domain & type conventions. All values are IEEE 754 double — there is no separate bool / int type at runtime. Comparison ops (EQ NE GT GE LT LE) yield 1.0 (true) or 0.0 (false), using strict double equality / ordering (NaN compares as IEEE specifies — NaN EQ NaN is 0.0). Logical ops (AND OR XOR) truncate each operand to a 64-bit signed integer (Truncate(double) then cast to long) before applying the bitwise operation; non-finite or out-of-range operands surface MathErrorCode rather than silently wrapping. Truthiness at caller-side IF / WHILE gates is value != 0 — any non-zero value (bit, float, comparator result) is true.

NcExpressionParser

Recursive-descent parser for Fanuc Custom Macro B value expressions. Pure: takes a string, produces an NcExpr AST. Performs no variable lookup and no evaluation.

Grammar (lowest precedence at top):

expr     := or-expr
or-expr  := and-expr (('OR' | 'XOR') and-expr)*
and-expr := cmp-expr ('AND' cmp-expr)*
cmp-expr := add-expr (('EQ' | 'NE' | 'GT' | 'GE' | 'LT' | 'LE') add-expr)*
add-expr := term (('+' | '-') term)*
term     := factor (('*' | '/' | 'MOD') factor)*
factor   := ('+' | '-')? primary
primary  := number
         | '#' integer
         | '#' '[' expr ']'
         | '[' expr ']'
         | ident '[' arglist ']' ('/' '[' expr ']')?
arglist  := expr (',' expr)*

Function names and keyword operators (MOD, EQ NE GT GE LT LE, AND OR XOR) are case-insensitive (SIN = sin, EQ = eq); each keyword requires a non-identifier character on its right boundary so EQ1 is not the EQ operator followed by 1. Whitespace is skipped between tokens. The '/' '[' expr ']' tail captures the dual-bracket form Fanuc uses for ATAN[a]/[b]; non-ATAN callers that happen to use it produce a function with an extra arg, which the evaluator rejects with an arity error.

Operator precedence intentionally puts boolean / logical layers below arithmetic so #1 + 1 GT 0 parses as (#1 + 1) GT 0 and #1 GT 0 AND #2 LT 10 parses as (#1 GT 0) AND (#2 LT 10), matching the Fanuc Custom Macro B spec for IF [..] GOTO / IF [..] THEN / WHILE [..] DO conditions.

NcFunctionExpr

Built-in function call like SIN[x], SQRT[x], ATAN[a]/[b].

NcIndirectVariableExpr

Indirect variable reference #[expr]. The inner expression is evaluated and truncated toward zero to obtain an integer; the lookup key is then Prefix concatenated with that integer (e.g. Prefix="#", computed 124"#124").

NcLiteralExpr

Numeric literal (e.g. 1.5, 15., .5, 1e-3).

NcUnaryExpr

Unary + or - applied to an operand.

NcVariableExpr

Direct variable reference; Key is the raw source token (e.g. "#124") passed verbatim to Get(string).

VolatileVariableLookup

Reads Fanuc-style non-retained common variables (#100-#499) from Vars.Volatile. Self-gates the id range so the evaluator's RuntimeVariableLookups chain can fall through to the next lookup for out-of-range keys.

Single-step lookup: VolatileVariableReadingSyntax already dict-merges every block's Vars.Volatile into the next block, so the entry — if it exists — must be on the current block (when this lookup runs after the reader) or on the immediately previous block (when this lookup runs before the reader on the same block, which is the Fanuc preset's order — evaluator first, reader second). No arbitrary walk-back: such a walk would be defensive overkill given the reader's carry guarantee.

Stateless and dependency-free — instances are interchangeable. Reads stay decoupled from the reader (read side here; write side in the reader).

Structs

EvalResult

Outcome of evaluating an NcExpr. Either a successful numeric value, or a failure with an error code matching the diagnostic catalogue used by reading / evaluator syntaxes.

Interfaces

IRuntimeVariableLookup

Stateless variable lookup that needs per-block runtime context — the current SyntaxPiece node (for Previous traceback into runtime-state sections like MachineCoordinateState / ProgramXyz) and the dependency list (so the lookup can read from sibling dependencies without holding a static reference).

Distinguished from IVariableLookup: that one is for long-lived dependencies that already hold their own data (parameter tables, tool-offset wrappers, retained-variable tables) and need no block context. IRuntimeVariableLookup is for context-sensitive resolutions configured declaratively on RuntimeVariableLookups.

Implementations should be brand-specific (e.g. Fanuc #5001-#5043 position reads) and return null for keys outside their range so the evaluator's chain can fall through to the next lookup.

Implementations are XML-serialised as part of VariableEvaluatorSyntax's round-trip: each impl exposes a static XName, registers itself with Generators, and implements MakeXmlSource(string, string, bool). Since impls are stateless, the typical body is just an empty element carrying the type name; brand identity is restored by XFactory dispatch.

IVariableLookup

Resolves a Custom Macro B variable reference to its current numeric value, or null for vacant (Fanuc <vacant>) and out-of-scope alike.

The key is the raw source token — Fanuc "#124", Heidenhain "Q1", Siemens "R1" — so the interface itself is brand-agnostic. Implementations are typically narrow (one per id range / per brand prefix) and parse the prefix locally; chain them at the call site by trying each in priority order until one returns a non-null value.

A returned null is treated by NcExpressionEvaluator as vacant and surfaces as a Variable--Vacant failure when the value is consumed in arithmetic context.

Enums

NcBinaryOp

Binary operators allowed in Fanuc Custom Macro B value expressions.

NcUnaryOp

Unary operators allowed in Fanuc Custom Macro B value expressions.