Skip to content

fix(tests): quote the paths in runE2ETestPipeline's g++ command - #226

Open
MatthewReed303 wants to merge 2 commits into
Autonomy-Logic:developmentfrom
MatthewReed303:fix/test-helpers-quote-paths
Open

fix(tests): quote the paths in runE2ETestPipeline's g++ command#226
MatthewReed303 wants to merge 2 commits into
Autonomy-Logic:developmentfrom
MatthewReed303:fix/test-helpers-quote-paths

Conversation

@MatthewReed303

Copy link
Copy Markdown
  • runE2ETestPipeline built its g++ command by join(' ')-ing an argv array into
    a shell string and quoted nothing, so any repo path containing a space
    word-split the -I flags and backgrounded the command at an &.
  • 115 tests across 7 integration files failed for this reason alone on a checkout
    under such a path.
  • Quoted in the same style the neighbouring call sites in this file already use
    (:93, :156, and oscat-gpp-compile.test.ts:185-193). No behaviour change
    where the path has no spaces.

The argv array was joined into a shell string with nothing quoted, so a
repo path containing a space word-split the -I flags and 115 tests failed.
Quoted in the style the neighbouring call sites already use.
…h the runtime

An imported CODESYS library using ANY did not compile: generics existed
nowhere. They are now declarable on a VAR_INPUT of a FUNCTION, FUNCTION_BLOCK
or METHOD — CODESYS's seven names, since ANY_ELEMENTARY, ANY_MAGNITUDE and
ANY_DERIVED classify types without being declarable — and never as an array
element. iec_any.hpp carries the TYPE_CLASS enumeration and the IEC_ANY
descriptor; __SYSTEM.AnyType parses as a qualified type name, gated on that
namespace so a dot after any other type stays an error, and is declarable in
its own right so a block can keep what it was handed.

The analyzer enforces CODESYS's two rules: only a variable may be passed, a
literal or expression having no address; and its type must be one the declared
family accepts. That check earns its place — a concrete parameter is caught by
C++ refusing the assignment, but a REAL handed to an ANY_INT still produces
valid C++, a descriptor stamped TYPE_REAL the block was never written for.

Codegen builds the descriptor at every call shape: function block calls named
and positional, both AST shapes a method call arrives in, and FUNCTION calls.
typeclass comes from the declared type, because the payload cannot tell BYTE
from USINT; pvalue from raw_ptr(); diSize from IEC_SIZEOF. A STRING passed
this way queues a sync_length() flushed after the statement, since the callee
writes the characters but not the cached length. arr[i] and s.field reach a
generic pin too — they are VariableExpressions carrying subscripts, so they
passed the variable guard and then failed a lookup keyed on the variable's own
name.

ARRAY [*] OF T as a VAR_IN_OUT comes with it. The parameter is an ArrayView
carrying the runtime bounds, so it needs no copy back and cannot have one, and
ArrayView gains an unbound default because a function block stores its in-outs
as members before there is an array to point at.

STRING(23) parsed and was then widened to 254 downstream. An inline array
dropped its element's length; a VAR_EXTERNAL widened through toParamTypeRef,
which a parameter may do and a GlobalVar<…>* may not. TypeReference carries
elementMaxLength through the project model, and the three external sites share
one externalTypeRefCpp helper.

The debug dispatch was worse than oversized: its four string ops hard-cast
every string to IECStringVar<254>, so a STRING(23) read its length from past
the end of a 54-byte object and a write constructed 258 bytes into it. The
spare byte in Entry becomes cap, the ops take it, and IECStringView locates
each field from the capacity, with static_asserts pinning the layout at 1, 23
and 254. The table also walks the EXTENDS chain now, so an inherited member is
watchable, carrying the declaring type so memberCppName spells it right.

Three conformance fixes. REAL_TO_INT(2.5) answered 3, because
iec_convert_value used std::round, which rounds halves away from zero;
ties-to-even is written out with floor and fmod, which avr-libc carries.
INSERT('ABC','XY',2) answered 'AXYBC' — it inserted before the P-th character
rather than after it, while DELETE_STR beside it is right to keep pos - 1.
CONTINUE had no token and no parser rule.

Also: raw_ptr() and sync_length() on both string classes so a generic
parameter or a driver reaches the characters and not the forcing wrapper;
force() writes the raw value too, so a forced variable reads as forced through
a descriptor; IEC_SIZEOF reports capacity + 1 rather than the wrapper's size;
IECVar::value_field_offset() with static_asserts that the payload stays first,
since ADR(x) lowers to &(x); a native block can name a structure, enumeration
or function block its own library declares, which only worked across a real
dependency before; and a library's enum members are exported, so a bare
enumerator from one qualifies instead of failing to compile.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant