aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AGENTS/ARCH/OVERVIEW.md3
-rw-r--r--AGENTS/CONVENTIONS/STRINGS.md51
-rw-r--r--AGENTS/CONVENTIONS/SYMBOLS_AND_ERRORS.md4
-rw-r--r--AGENTS/CONVENTIONS/TEMPLATES_AND_OPERATORS.md9
-rw-r--r--AGENTS/CONVENTIONS/TYPES.md3
-rw-r--r--AGENTS/EXTENDING.md2
-rw-r--r--AGENTS/PITFALLS/exceptions-and-c-interop.md6
-rw-r--r--AGENTS/PITFALLS/modules-and-stdlib.md3
-rw-r--r--AGENTS/PITFALLS/overload-template-operator.md11
-rw-r--r--AGENTS/SUBSYSTEMS/CLASS_LIFETIME.md7
-rw-r--r--AGENTS/SUBSYSTEMS/FUNCTIONS.md7
-rw-r--r--AGENTS/SUBSYSTEMS/STDLIB.md7
-rw-r--r--AGENTS/SUBSYSTEMS/TEMPLATES.md8
-rw-r--r--doc/language/cpsc-language-overview.7.md7
-rw-r--r--doc/language/keyword/cpsc-keyword-c_type.7.md4
-rw-r--r--doc/language/keyword/cpsc-keyword-class.7.md2
-rw-r--r--doc/language/keyword/cpsc-keyword-constant.7.md2
-rw-r--r--doc/language/keyword/cpsc-keyword-implicit.7.md43
-rw-r--r--doc/language/keyword/cpsc-keyword-operator.7.md2
-rw-r--r--doc/language/keyword/cpsc-keyword-overload.7.md6
-rw-r--r--doc/language/keyword/cpsc-keyword-template.7.md4
21 files changed, 129 insertions, 62 deletions
diff --git a/AGENTS/ARCH/OVERVIEW.md b/AGENTS/ARCH/OVERVIEW.md
index ee3fc12..4f2278c 100644
--- a/AGENTS/ARCH/OVERVIEW.md
+++ b/AGENTS/ARCH/OVERVIEW.md
@@ -26,7 +26,8 @@ come from numeric_limits (long double size alone is insufficient). Programs use
the compiler's build ABI; cross-target emission is not implemented. EXTERN "C"
declarations call C functions from INCLUDE_OBJ objects (see [SUBSYSTEMS/EXTERN.md](../SUBSYSTEMS/EXTERN.md)).
CTypeGen handles typed numeric conversions, casts, native arithmetic and I/O.
-Crossing C/pseudocode domains requires a cast, including literals. C arithmetic
+Crossing C/pseudocode domains requires a cast, including numeric literals, except
+for marked IMPLICIT class constructors and the documented text bridges. C arithmetic
uses C++ promotions, except that / always returns pseudocode REAL.
## Language manuals
diff --git a/AGENTS/CONVENTIONS/STRINGS.md b/AGENTS/CONVENTIONS/STRINGS.md
index d07c217..d036fb4 100644
--- a/AGENTS/CONVENTIONS/STRINGS.md
+++ b/AGENTS/CONVENTIONS/STRINGS.md
@@ -2,29 +2,34 @@
Part of [Load-bearing conventions](../CONVENTIONS.md).
-**STRING values use the class machinery.** `string.cps` owns a std::string through an
-internal handle. Ordinary literals construct STRING through NEW(C_STRING); suffixed
-`"text"C` literals produce C_STRING directly. Ordinary literals retain legacy NUL
-truncation. `StringValueGen.cc` bridges construction, C_STR access and file operands;
-INPUT calls READ_INPUT. String functions and all concatenation/comparison operators
-are ordinary library definitions, with exact overload selection. Comparisons use
-case-sensitive byte ordering. A missing STRING class or required bridge method is a
-compile error.
+**Literals are raw C_STRING values.** Both ordinary and C-suffixed double-quoted
+literals emit global text pointers; CONSTANT keeps the same raw type and read-only
+binding. Text operations retain legacy NUL truncation. Single quotes remain CHAR.
+An exact C_STRING overload wins over conversion to STRING.
-**CHAR and STRING convert implicitly.** `emitCoercedExpr` turns a CHAR into a
-one-character STRING (`emitStringFromChar`, STRING.NEW(1, ch)) and a STRING into a CHAR
-(`emitCharFromString`, via the `_LENGTH()` and `C_STR()` bridge methods), so assignment,
-parameter passing and RETURN need no special cases; a length other than 1 is a runtime
-error. `resolveOperator` and `resolveCall` fall back to the STRING overload when an
-exact match is missing and a CHAR is involved (`'a' & 'b'`, `"a" = 'a'`); two CHAR
-operands still compare as CHARs, and CASE converts the CHAR side itself. A converted
-value is a fresh temporary, so `emitAssignment` copies its source (CopySource) only when
-the source type equals the target type. CHAR with INTEGER or BOOLEAN never converts.
+**Automatic construction is opt-in.** `string.cps` owns a std::string through an
+internal handle and declares IMPLICIT NEW(C_STRING) and IMPLICIT NEW(CHAR).
+`TypeCheckGen.cc` shares direct constructor lookup, conversion ranking and emission
+with calls, operators and captured CASE values. Never automatically invoke an
+unmarked constructor, including in a replacement STRING class under -no-std.
+Explicit casts may still use unmarked NEW(C_STRING).
+
+**CHAR compatibility remains.** STRING -> CHAR uses `_LENGTH()` and `C_STR()` and
+checks length 1 at runtime. C_STRING -> CHAR first uses the marked STRING constructor;
+this compatibility bridge ranks below a direct STRING parameter, preserving string
+function selection. Two CHARs compare directly. No path may chain two IMPLICIT NEWs.
+
+**I/O bridges retain STRING behavior.** OUTPUT and file operands convert C_STRING
+through its marked STRING constructor, then use C_STR. INPUT calls READ_INPUT.
+String functions, concatenation and comparisons are ordinary library definitions;
+comparisons use case-sensitive byte ordering. Missing classes or methods diagnose.
**Ownership follows value copies.** STRING constructors/assignment prevent shared
-handles. Records and BYVAL arrays containing STRING recursively copy their
-string-bearing fields/elements; RETURN and temporary cleanup preserve ownership.
-C_STRING casts borrow a STRING buffer or construct an owning STRING copy in the other
-direction. FileHandler owns copied open-file names and frees them on close; READFILE
-buffers are copied into STRING and released. Explicit memory-library allocations remain
-separate from these internal objects.
+handles. Records and BYVAL arrays containing STRING recursively clone owned string
+fields/elements. Converted arguments stay Alive until ownership transfers to the
+callee; failed later arguments release pending values. Converted lvalues are fresh
+objects, never copy sources of a different type. RETURN, discarded values and
+statement temporaries use ordinary class cleanup, including exception exits.
+Explicit C_STRING casts borrow a STRING buffer or construct an owning copy in the
+other direction. FileHandler copies open-file names and releases them on close;
+READFILE copies and releases its buffer. Explicit memory allocations remain separate.
diff --git a/AGENTS/CONVENTIONS/SYMBOLS_AND_ERRORS.md b/AGENTS/CONVENTIONS/SYMBOLS_AND_ERRORS.md
index e21bed1..f382b61 100644
--- a/AGENTS/CONVENTIONS/SYMBOLS_AND_ERRORS.md
+++ b/AGENTS/CONVENTIONS/SYMBOLS_AND_ERRORS.md
@@ -8,8 +8,8 @@ only symbol table.
- Use `symbolAddress` for an object address: class variables and BYVAL class
parameters store their current object address in a reference slot (`IsReference`).
-- Use SymbolInfo::isConstant() for constant checks: scalar literals use
- ConstantValue; owning STRING constants use ReadOnly plus Storage.
+- Use SymbolInfo::isConstant() for constant checks: literals, including raw
+ C_STRING text constants, use ConstantValue and have no writable storage.
- Read values through emitExpr. Writable/address-taking paths reject constants
through requireWritable; internal STRING copy/assignment source bindings may read
their storage.
diff --git a/AGENTS/CONVENTIONS/TEMPLATES_AND_OPERATORS.md b/AGENTS/CONVENTIONS/TEMPLATES_AND_OPERATORS.md
index 79f1a88..675ea3e 100644
--- a/AGENTS/CONVENTIONS/TEMPLATES_AND_OPERATORS.md
+++ b/AGENTS/CONVENTIONS/TEMPLATES_AND_OPERATORS.md
@@ -22,11 +22,13 @@ Part of [Load-bearing conventions](../CONVENTIONS.md). Basic call resolution is
- When multiple definitions share a function/procedure name, every ordinary and
template definition must specify OVERLOAD.
- `resolveCall` computes static argument types/ranks once, then tries exact ordinary,
- non-variadic template and variadic template tiers; an expected result type filters
+ non-variadic template and variadic template tiers, then repeats with permitted
+ BYVAL conversions; an expected result type filters
ordinary candidates, while template tiers still match parameters only. Same-tier ties
are errors.
- Candidate checking must stay silent and must not instantiate speculative class
- types. Explicit arguments pre-bind types without allowing conversions.
+ types. Explicit arguments pre-bind types; substituted scalar BYVAL parameters
+ may then use permitted conversions.
- Instances keep the template owner for diagnostics/library behavior and the first
requester in `VisibilityUnit` for lookup (`value_or(CurrentUnit)`).
- Deferred bodies use the symbol snapshot at the template declaration to preserve
@@ -40,7 +42,8 @@ Part of [Load-bearing conventions](../CONVENTIONS.md). Basic call resolution is
token on PrototypeAST. Canonical names contain a space (`OPERATOR +`,
`Class.OPERATOR AND`) to avoid collisions with ordinary identifiers.
- `OperatorGen.cc` probes visible global and left-class member signatures without
- emitting diagnostics or evaluating operands. Matching is exact; member/global ties
+ emitting diagnostics or evaluating operands. Exact operands and directly supported
+ builtins precede converted overloads; member/global ties
are ambiguous and access is checked only after selection.
- Both getExprTypeInfo and emission must consult this resolver with the expression's
result context before hardcoded builtin result types. A strict context requires the
diff --git a/AGENTS/CONVENTIONS/TYPES.md b/AGENTS/CONVENTIONS/TYPES.md
index 7349ab1..d13773b 100644
--- a/AGENTS/CONVENTIONS/TYPES.md
+++ b/AGENTS/CONVENTIONS/TYPES.md
@@ -18,7 +18,8 @@ C base type and pointer levels independently of the alias `Name`. Use `sameType`
for storage compatibility (including BYREF and array arguments); never equate C
types just because their LLVM types or widths match. CScalar/CPointer values are
handled by CTypeGen, not the legacy representation coercions. Cross-domain
-assignments, arguments and operators require explicit casts, including literals.
+assignments, arguments and operators require explicit casts, including numeric literals,
+except for marked IMPLICIT class constructors and the documented text bridges.
Plain C char uses native signedness; pseudocode CHAR stays unsigned. Numeric
conversions use source signedness, and native floating formats use numeric_limits.
Allocation sizes still use LLVM sizeof; native C type widths use build-compiler
diff --git a/AGENTS/EXTENDING.md b/AGENTS/EXTENDING.md
index dc3be08..a7aeeb0 100644
--- a/AGENTS/EXTENDING.md
+++ b/AGENTS/EXTENDING.md
@@ -80,4 +80,4 @@ also be registered in EmbeddedRunner for static-runtime JIT symbol lookup.
`setupExternalFunctions()` (re-declaring the same symbol in two handlers is fine — it
dedupes by name).
-**Standard-library functions:** define ordinary functions/operators in the appropriate pseudocode-lib/*.cps unit with C ABI helpers in the matching .cc as needed. std.cps imports all public library units. CMake rebuilds and embeds source/object changes; do not add standard-library functions to Builtins.h. Memory allocation functions live in memory.cps/memory.cc; only keyword NEW/DELETE need the MemoryGen bridge. Ordinary string literals need STRING.NEW(C_STRING); the compiler bridges OUTPUT/casts/files through C_STR(), INPUT through READ_INPUT(), and READFILE through assignment from C_STRING.
+**Standard-library functions:** define ordinary functions/operators in the appropriate pseudocode-lib/*.cps unit with C ABI helpers in the matching .cc as needed. std.cps imports all public library units. CMake rebuilds and embeds source/object changes; do not add standard-library functions to Builtins.h. Memory allocation functions live in memory.cps/memory.cc; only keyword NEW/DELETE need the MemoryGen bridge. Double-quoted literals produce C_STRING; STRING contexts require marked IMPLICIT NEW(C_STRING), while CHAR uses marked IMPLICIT NEW(CHAR); the compiler bridges OUTPUT/casts/files through C_STR(), INPUT through READ_INPUT(), and READFILE through assignment from C_STRING.
diff --git a/AGENTS/PITFALLS/exceptions-and-c-interop.md b/AGENTS/PITFALLS/exceptions-and-c-interop.md
index b057d18..0d0f89d 100644
--- a/AGENTS/PITFALLS/exceptions-and-c-interop.md
+++ b/AGENTS/PITFALLS/exceptions-and-c-interop.md
@@ -19,11 +19,11 @@ Part of the [pitfalls index](../PITFALLS.md).
## C type extensions
-- C_STRING is a raw char pointer, not a STRING: explicitly cast to STRING for
- printing or string-library calls.
+- C_STRING is a raw char pointer. A visible IMPLICIT STRING.NEW(C_STRING)
+ permits string-library calls, OUTPUT and file text; an explicit cast also works.
- C aliases share canonical CIdentity; do not use LLVM widths to recover signedness
or nominal type identity. Plain char's signedness is native, unlike pseudocode CHAR.
-- C/pseudocode conversions require casts even for literals. C scalar arithmetic uses
+- Other C/pseudocode conversions require casts, including numeric literals. C scalar arithmetic uses
native promotions, but / always returns REAL.
- Cast aliases must precede their use.
- long double may have padding; sizeof does not identify its floating-point format.
diff --git a/AGENTS/PITFALLS/modules-and-stdlib.md b/AGENTS/PITFALLS/modules-and-stdlib.md
index 5394d78..e43bb78 100644
--- a/AGENTS/PITFALLS/modules-and-stdlib.md
+++ b/AGENTS/PITFALLS/modules-and-stdlib.md
@@ -17,7 +17,8 @@ Part of the [pitfalls index](../PITFALLS.md).
and automatically linked.
- Use -no-std before explicitly supplying a replacement STRING class/library;
otherwise duplicate definitions fail.
- - Ordinary literals require a visible STRING class with NEW(C_STRING).
+ - Double-quoted literals are raw C_STRING. STRING contexts, OUTPUT and file text
+ require a visible STRING class with IMPLICIT NEW(C_STRING), including under -no-std.
- C_TYPE/INCLUDE/EXTERN syntax strings are parser metadata and do not construct
STRING.
- Keyword NEW/DELETE and MALLOC/REALLOC/FREE require memory.cps; -no-std users
diff --git a/AGENTS/PITFALLS/overload-template-operator.md b/AGENTS/PITFALLS/overload-template-operator.md
index 909e5f7..56247ff 100644
--- a/AGENTS/PITFALLS/overload-template-operator.md
+++ b/AGENTS/PITFALLS/overload-template-operator.md
@@ -9,8 +9,9 @@ Part of the [pitfalls index](../PITFALLS.md).
- Count, canonical parameter types, array rank and (for non-VOID definitions) return
type distinguish signatures; a PROCEDURE counts as VOID. BYREF/BYVAL and array
bounds do not.
-- Calls match exact static types, even for a single OVERLOAD definition; ordinary
- functions still coerce arguments. A known expected result type (assignment, BYVAL
+- Calls prefer exact static types, then marked IMPLICIT construction and the
+ existing CHAR/STRING bridge for scalar BYVAL parameters; ordinary functions
+ retain their existing numeric coercions. A known expected result type (assignment, BYVAL
argument, RETURN, condition, subscript, CASE comparison) must match the overload's
return type exactly; `(T) x` only prefers T and otherwise converts. Without a
context, return-only-distinct candidates need one DEFAULT return or remain ambiguous.
@@ -28,7 +29,8 @@ Part of the [pitfalls index](../PITFALLS.md).
- Top-level FUNCTION/PROCEDURE/CLASS only; all template parameters are types, with at
most one final pack.
-- Exact types are required even with explicit arguments (`Max<REAL>(1, 2.5)` fails).
+- Substituted BYVAL parameters allow marked constructors and CHAR/STRING bridges,
+ but numeric widening still fails (`Max<REAL>(1, 2.5)` fails).
Deduction recognizes T and array element T, never the T inside Box<T>.
- When multiple ordinary/template functions share a name, every definition must
specify OVERLOAD; exact ordinary definitions win, then non-variadic templates, then
@@ -55,7 +57,8 @@ Part of the [pitfalls index](../PITFALLS.md).
- Unary/binary operators require OVERLOAD FUNCTION, with supported arity and at least
one record/class/enum operand. Pointer aliases alone do not qualify.
-- Exact matching considers visible globals and left-class members together, and the
+- Exact-first matching considers visible globals and left-class members together,
+ with marked BYVAL construction after directly supported builtins. The
result type joins the match when the context supplies one; ties are errors,
including private/public ties. Without a context, return-only-distinct candidates
need a unique DEFAULT return or remain ambiguous; defaults do not resolve
diff --git a/AGENTS/SUBSYSTEMS/CLASS_LIFETIME.md b/AGENTS/SUBSYSTEMS/CLASS_LIFETIME.md
index 19be0aa..0b12ea1 100644
--- a/AGENTS/SUBSYSTEMS/CLASS_LIFETIME.md
+++ b/AGENTS/SUBSYSTEMS/CLASS_LIFETIME.md
@@ -21,8 +21,9 @@ Part of the [subsystem notes](../SUBSYSTEMS.md). Builds on [classes](CLASSES.md)
- Assignment-only `NewExprAST` uses checked memory-library allocation (at least one byte
for method-only classes), zero initialization and construction, then rebinds
reference slots or copies into other destinations.
-- Ordinary assignment invokes an exact member OPERATOR<- when available, otherwise it
- copies.
+- Ordinary assignment prefers an exact member OPERATOR<-, then permitted BYVAL
+ conversions. Without an operator, a marked converting NEW produces a fresh value;
+ replacing a non-STRING class this way releases its previous value before transfer.
- Heap objects require explicit keyword DELETE; INHERITS/SUPER remain unsupported.
## Destruction
@@ -65,7 +66,7 @@ Part of the [subsystem notes](../SUBSYSTEMS.md). Builds on [classes](CLASSES.md)
before local handlers, while ordinary objects remain function-scoped.
- Function-result method receivers are materialized by the same path as operator
receivers.
-- Assignment first selects an exact member OPERATOR<-; without one, STRING-bearing
+- Assignment first selects a member OPERATOR<- with exact parameters preferred; without one, STRING-bearing
aggregate assignment clones string fields from lvalues or transfers them from rvalues,
releasing the target's old string fields without invoking the enclosing class
destructor; other classes are assigned bitwise.
diff --git a/AGENTS/SUBSYSTEMS/FUNCTIONS.md b/AGENTS/SUBSYSTEMS/FUNCTIONS.md
index 9555f1d..222d4da 100644
--- a/AGENTS/SUBSYSTEMS/FUNCTIONS.md
+++ b/AGENTS/SUBSYSTEMS/FUNCTIONS.md
@@ -27,7 +27,9 @@ internal __cps_main).
- `emitPrototype` records each function's pseudocode signature in a `FuncSig`
overload-set map (`FunctionGen::getOverloads`, filtered by unit visibility).
-- `resolveCall` selects exact static parameter types/ranks for OVERLOAD. When the call
+- `resolveCall` prefers exact static parameter types/ranks for OVERLOAD, then
+ marked constructor conversions for scalar BYVAL parameters. BYREF and arrays
+ remain exact; a single call never chains IMPLICIT constructors. When the call
site has an expected result type, the candidate must also return exactly that type;
a cast only prefers it. Without a context, return-only-distinct candidates use
the unique DEFAULT return, otherwise they are ambiguous. A single ordinary definition keeps implicit conversions.
@@ -57,7 +59,8 @@ internal __cps_main).
- PrototypeAST retains the operator token; FunctionGen validates operand count and
requires a record/class/enum operand.
-- Global signatures and left-class methods share exact-type selection, used by
+- Global signatures and left-class methods share exact-first selection with
+ marked BYVAL construction as fallback, used by
ValueTypeGen and ExpressionGen before builtin operations and filtered by an expected
result type where present. A strict context whose operands match but whose result does
not sets `WrongResult`. Missing candidates leave builtin rules intact; ties are
diff --git a/AGENTS/SUBSYSTEMS/STDLIB.md b/AGENTS/SUBSYSTEMS/STDLIB.md
index 07d0959..138b076 100644
--- a/AGENTS/SUBSYSTEMS/STDLIB.md
+++ b/AGENTS/SUBSYSTEMS/STDLIB.md
@@ -33,8 +33,9 @@ import rules: [CONVENTIONS/EXCEPTIONS_AND_UNITS.md](../CONVENTIONS/EXCEPTIONS_AN
- The STRING class is defined under PP_DEFINE __LIB. Its public internal void*
handle owns std::string. The _string_impl_* C ABI reports __cps_user_line and throws 0 on std::exception.
-- Functions/operators use ordinary resolution; StringValueGen bridges literals, C_STR, C
- conversions and file operands.
-- C_STRING literals have an adjacent uppercase C suffix.
+- Functions/operators use ordinary resolution and marked IMPLICIT NEW(C_STRING)
+ and NEW(CHAR). StringValueGen bridges C_STR, explicit casts, CHAR checks and files.
+- All double-quoted literals are C_STRING; the adjacent uppercase C suffix remains
+ accepted. OUTPUT and file text use the marked STRING constructor.
- STRING INPUT delegates to READ_INPUT (rest of the line, throws at end of input), OUTPUT uses C stdout buffers, and READFILE invokes
assignment from C_STRING then frees its temporary buffer.
diff --git a/AGENTS/SUBSYSTEMS/TEMPLATES.md b/AGENTS/SUBSYSTEMS/TEMPLATES.md
index b80f7ed..ffa011a 100644
--- a/AGENTS/SUBSYSTEMS/TEMPLATES.md
+++ b/AGENTS/SUBSYSTEMS/TEMPLATES.md
@@ -17,12 +17,14 @@ callable lookup.
- `CodeGen::resolveCall` retains ordinary fast paths when no templates exist. Otherwise
it computes static argument types and whole-array ranks once, selecting exact ordinary
definitions (including an expected result type when present) before non-variadic
- templates and then variadic templates. Templates still match only substituted
- parameter types; result contexts do not filter them.
+ templates and then variadic templates, then repeats these tiers with permitted
+ BYVAL conversions. Templates match substituted parameter types; result contexts
+ do not filter them.
- Explicit type arguments pre-bind positional parameters and constrain a pack prefix;
deduction from `T` or array element `T` fills remaining bindings. Composite types such
as `Box<T>` are checked after substitution but do not deduce T.
-- Every position must match exactly and every non-pack type must be bound. Candidate
+- Every non-pack type must be bound; substituted BYVAL positions may use the
+ shared conversion ranks. BYREF and arrays still match exactly. Candidate
failures stay silent; only the final no-match or ambiguity is diagnosed.
- `hasCallable` keeps CALL statement re-resolution aware of templates.
diff --git a/doc/language/cpsc-language-overview.7.md b/doc/language/cpsc-language-overview.7.md
index da4d821..65d1945 100644
--- a/doc/language/cpsc-language-overview.7.md
+++ b/doc/language/cpsc-language-overview.7.md
@@ -14,9 +14,9 @@ User-defined types can overload operators with OVERLOAD FUNCTION OPERATOR; expre
Precedence, from highest to lowest: unary operators, `* / DIV MOD`, `+ - &`, comparisons, AND, OR. Parentheses override precedence.
-Parenthesized type casts, such as (C_INT)Number, have unary precedence. C_INT, C_CHAR, C_STRING and C_DOUBLE are native C aliases; TYPE name = C_TYPE("...") imports other supported C base types and pointers. Conversions between C and pseudocode types must be explicit. These are compiler extensions; see [cpsc-keyword-c_type(7)](keyword/cpsc-keyword-c_type.7.md). EXTERN "C" declares C functions from objects named with INCLUDE_OBJ; see [cpsc-keyword-extern(7)](keyword/cpsc-keyword-extern.7.md).
+Parenthesized type casts, such as (C_INT)Number, have unary precedence. C_INT, C_CHAR, C_STRING and C_DOUBLE are native C aliases; TYPE name = C_TYPE("...") imports other supported C base types and pointers. Conversions between C and pseudocode types require explicit casts except for IMPLICIT class constructors and the text bridges described below. These are compiler extensions; see [cpsc-keyword-c_type(7)](keyword/cpsc-keyword-c_type.7.md). EXTERN "C" declares C functions from objects named with INCLUDE_OBJ; see [cpsc-keyword-extern(7)](keyword/cpsc-keyword-extern.7.md).
-Literals include integers, decimal real numbers, TRUE/FALSE, strings in double quotes, and single-byte characters in single quotes. Negative numbers use unary minus. String and character literals support C++17 simple escapes (`\' \" \? \\ \a \b \f \n \r \t \v`), one to three octal digits, and `\x` followed by hexadecimal digits (byte values only). Unicode escapes `\uXXXX` and `\UXXXXXXXX` encode valid Unicode scalar values as UTF-8 in strings; in CHAR they must be ASCII. Unknown escapes are errors. Ordinary STRING literals retain NUL truncation, so `"a\0b"` is observed as `"a"`. An adjacent uppercase C suffix, as in `"text"C`, produces C_STRING directly. Comments begin with `//` and continue to the end of the line.
+Literals include integers, decimal real numbers, TRUE/FALSE, strings in double quotes, and single-byte characters in single quotes. Negative numbers use unary minus. String and character literals support C++17 simple escapes (`\' \" \? \\ \a \b \f \n \r \t \v`), one to three octal digits, and `\x` followed by hexadecimal digits (byte values only). Unicode escapes `\uXXXX` and `\UXXXXXXXX` encode valid Unicode scalar values as UTF-8 in strings; in CHAR they must be ASCII. Unknown escapes are errors. String literals have type C_STRING and retain NUL truncation in text operations, so `"a\0b"` is observed as `"a"`. An adjacent uppercase C suffix, as in `"text"C`, remains accepted and has the same type. The standard library converts text to STRING through IMPLICIT NEW when needed; see [cpsc-keyword-implicit(7)](keyword/cpsc-keyword-implicit.7.md). Comments begin with `//` and continue to the end of the line.
Declare variables before use. See DECLARE for built-in types and arrays, TYPE for records/enumerations/pointers, and CLASS for public/private fields and methods.
@@ -47,6 +47,7 @@ PP_DEFINE and PP_UNDEF control file-local, case-sensitive preprocessor switches.
- [cpsc-keyword-procedure(7)](keyword/cpsc-keyword-procedure.7.md): define a procedure and parameter modes.
- [cpsc-keyword-operator(7)](keyword/cpsc-keyword-operator.7.md): overload unary and binary operators.
- [cpsc-keyword-overload(7)](keyword/cpsc-keyword-overload.7.md): explicitly overload functions, procedures and constructors.
+- [cpsc-keyword-implicit(7)](keyword/cpsc-keyword-implicit.7.md): permit automatic class construction from one parameter.
- [cpsc-keyword-default(7)](keyword/cpsc-keyword-default.7.md): choose a default return type for an overload.
- [cpsc-keyword-template(7)](keyword/cpsc-keyword-template.7.md): define function, procedure and class templates with type packs.
- [cpsc-keyword-call(7)](keyword/cpsc-keyword-call.7.md): invoke a procedure.
@@ -70,7 +71,7 @@ Closing and auxiliary keywords are documented with their main constructs: PP_UND
# STRING LIBRARY FUNCTIONS
-These ordinary functions and the STRING class come from the embedded standard library, loaded and linked automatically unless **-no-std** is given. Ordinary string literals require a visible STRING class.
+These ordinary functions and the STRING class come from the embedded standard library, loaded and linked automatically unless **-no-std** is given. Using raw text in a STRING context, OUTPUT or file operation requires a visible STRING class with an IMPLICIT NEW(C_STRING) constructor.
- [cpsc-function-length(7)](function/cpsc-function-length.7.md): find a string's length.
- [cpsc-function-mid(7)](function/cpsc-function-mid.7.md): extract part of a string.
diff --git a/doc/language/keyword/cpsc-keyword-c_type.7.md b/doc/language/keyword/cpsc-keyword-c_type.7.md
index beff643..3b8f65c 100644
--- a/doc/language/keyword/cpsc-keyword-c_type.7.md
+++ b/doc/language/keyword/cpsc-keyword-c_type.7.md
@@ -21,9 +21,9 @@ C widths, char signedness and floating-point formats come from the compiler's bu
A cast has unary precedence and converts its following operand. Declare a type alias before using its name in a cast. Numeric, character and boolean values can be explicitly converted between pseudocode and C types. STRING can be cast to char* and back, and C pointer types can be cast to other C pointer types. C void* and original pseudocode pointer types can be explicitly cast to each other. Pointer/integer casts and casts involving pseudocode enums or whole records are unsupported. Casts are values, not assignable locations.
-C/pseudocode assignment, argument passing and mixed arithmetic require an explicit cast, including ordinary literals: use n <- (C_INT)1 and n + (C_INT)1. Different C scalar types use C++ numeric conversions, integer promotions and usual arithmetic conversions. BYREF requires the same type and performs no conversion. Comparisons and logical operations return BOOLEAN. The / operator always performs real division and returns REAL, including with two C integer operands; DIV and MOD accept C integers after promotion. C values used directly as IF/WHILE conditions need a cast to BOOLEAN.
+Except for marked IMPLICIT class constructors and the text bridges below, C/pseudocode assignment, argument passing and mixed arithmetic require an explicit cast, including numeric literals: use n <- (C_INT)1 and n + (C_INT)1. Different C scalar types use C++ numeric conversions, integer promotions and usual arithmetic conversions. BYREF requires the same type and performs no conversion. Comparisons and logical operations return BOOLEAN. The / operator always performs real division and returns REAL, including with two C integer operands; DIV and MOD accept C integers after promotion. C values used directly as IF/WHILE conditions need a cast to BOOLEAN.
-C scalar values support INPUT and OUTPUT. Plain char prints and reads a character; signed char and unsigned char use numeric input/output. _Bool uses the existing TRUE/FALSE output and numeric input. C pointers start null and support prefix ^ for address-of, suffix ^ for dereference, and = or <> between the same C pointer type. Dereferencing null throws; void pointers cannot be dereferenced. Pointer arithmetic and direct pointer INPUT/OUTPUT are unsupported. To print a C string, cast it to STRING. Casting char* to STRING constructs an owning copy; a null char* becomes empty. Casting STRING to char* borrows its buffer until the string changes or is destroyed. A literal such as `"text"C` has type C_STRING without constructing STRING. Pointer validity and writable storage remain the caller's responsibility.
+C scalar values support INPUT and OUTPUT. Plain char prints and reads a character; signed char and unsigned char use numeric input/output. _Bool uses the existing TRUE/FALSE output and numeric input. C pointers start null and support prefix ^ for address-of, suffix ^ for dereference, and = or <> between the same C pointer type. Dereferencing null throws; void pointers cannot be dereferenced. Pointer arithmetic and direct pointer INPUT/OUTPUT are unsupported, except that C_STRING output constructs STRING through its IMPLICIT constructor. Both ordinary and C-suffixed string literals have type C_STRING; they pass directly to C functions and select an exact C_STRING overload ahead of STRING conversion. Casting char* to STRING constructs an owning copy; a null char* becomes empty. Casting STRING to char* borrows its buffer until the string changes or is destroyed. A literal such as `"text"C` has type C_STRING without constructing STRING. Pointer validity and writable storage remain the caller's responsibility.
# EXAMPLE
diff --git a/doc/language/keyword/cpsc-keyword-class.7.md b/doc/language/keyword/cpsc-keyword-class.7.md
index 2a713c0..6d730aa 100644
--- a/doc/language/keyword/cpsc-keyword-class.7.md
+++ b/doc/language/keyword/cpsc-keyword-class.7.md
@@ -40,6 +40,8 @@ A constructor is a PROCEDURE named NEW, following guide section 10.2. It may be
`DECLARE Object : ClassName` zeroes the object's storage and constructs its fields recursively in declaration order; it then calls NEW only when the class has a parameterless NEW. Otherwise the object stays unconstructed until `Object <- NEW ClassName(arguments)` binds it, as in guide section 10.2. `DECLARE Object : ClassName(arguments)` always calls the matching NEW, so `ClassName()` is an error for a class whose NEW requires arguments, and supplying arguments to a class without NEW is an error. These automatic DECLARE, field and array calls are compiler extensions. Array elements and class-valued fields in records or classes follow the plain DECLARE rule, before the enclosing constructor runs. Constructor arguments after ARRAY OF are unsupported. A declaration executed again, such as inside a loop, first destroys its previous live incarnation, then zeroes and constructs its original storage again.
+A single-parameter BYVAL constructor may specify IMPLICIT to allow automatic conversion from its parameter type; see [cpsc-keyword-implicit(7)](cpsc-keyword-implicit.7.md).
+
An `OVERLOAD PROCEDURE NEW(BYREF Other : ClassName)` defines a copy constructor. BYVAL class lvalue arguments and RETURN of class lvalues invoke it; a same-class BYVAL constructor is rejected. Classes without one retain bitwise copying for fields without STRING ownership. Records and BYVAL arrays recursively clone STRING-bearing fields or elements. Other owning class fields retain the existing shallow-copy limitations. Class results transfer ownership directly into BYVAL arguments, RETURN and ordinary assignment without an assignment overload. Discarded results and temporary receivers live until the statement ends, including exception exits. Ordinary user BYREF calls still require bare variables; constructor calls can bind temporaries.
The keyword NEW is allowed only as the complete right side of assignment: `Target <- NEW ClassName`, `Target <- NEW ClassName()` or `Target <- NEW ClassName(arguments)`. Target must have exactly the named class type. NEW requires the memory.cps standard-library unit, imported by default; with **-no-std**, import and supply it explicitly. NEW uses the checked MALLOC allocation path, zeroes storage and constructs fields before calling NEW. A method-only class receives at least one byte of heap storage so its object address is non-null. Allocation failure reports a runtime error and throws; constructor exceptions also propagate to TRY/CATCH. Private constructor access and argument checks follow ordinary member-call rules.
diff --git a/doc/language/keyword/cpsc-keyword-constant.7.md b/doc/language/keyword/cpsc-keyword-constant.7.md
index 55960c5..5f1b9ad 100644
--- a/doc/language/keyword/cpsc-keyword-constant.7.md
+++ b/doc/language/keyword/cpsc-keyword-constant.7.md
@@ -12,7 +12,7 @@ CONSTANT identifier = literal
# DESCRIPTION
-Declare a read-only value whose type is inferred from its literal: INTEGER, REAL, BOOLEAN, CHAR, STRING, or C_STRING for a literal with the C suffix. A negative integer or real literal is allowed. As required by the Cambridge guide, variables, other constants, expressions, casts, and function calls cannot initialize a CONSTANT.
+Declare a read-only value whose type is inferred from its literal: INTEGER, REAL, BOOLEAN, CHAR or C_STRING. Both ordinary and C-suffixed double-quoted literals produce C_STRING; STRING contexts use its IMPLICIT constructor. A negative integer or real literal is allowed. As required by the Cambridge guide, variables, other constants, expressions, casts, and function calls cannot initialize a CONSTANT.
A constant is visible from its declaration to the end of its enclosing block. A top-level constant is also available in functions and procedures defined after its declaration. Functions do not inherit constants from another function or from an enclosing statement block.
diff --git a/doc/language/keyword/cpsc-keyword-implicit.7.md b/doc/language/keyword/cpsc-keyword-implicit.7.md
new file mode 100644
index 0000000..68d7283
--- /dev/null
+++ b/doc/language/keyword/cpsc-keyword-implicit.7.md
@@ -0,0 +1,43 @@
+% CPSC-KEYWORD-IMPLICIT(7)
+
+# NAME
+
+cpsc-keyword-implicit - allow automatic construction of a class value
+
+# SYNOPSIS
+
+```text
+CLASS name
+ [PUBLIC|PRIVATE] [OVERLOAD] IMPLICIT PROCEDURE NEW(value : type)
+ statements
+ ENDPROCEDURE
+ENDCLASS
+```
+
+# DESCRIPTION
+
+IMPLICIT is a compiler extension, absent from the CIE guide. Place it before PROCEDURE NEW, after OVERLOAD when present. The constructor must take exactly one BYVAL parameter, which may omit the BYVAL keyword. BYREF, array and parameter-pack parameters are rejected. Other methods and global functions cannot be IMPLICIT.
+
+A marked constructor allows its parameter type to become the owning class type in assignment, BYVAL argument passing, RETURN and overload selection. The parameter must match the source type directly; equivalent C aliases count as the same type. Conversion does not chain through another IMPLICIT constructor. Unmarked constructors remain available for explicit construction. No standard-library exception grants an unmarked constructor automatic conversion.
+
+Exact parameter matches take priority. If none matches, functions and operators may use implicit construction; competing candidates at the same level are ambiguous. PRIVATE access is checked after selection. BYREF parameters and whole arrays never convert. Existing result-type and DEFAULT selection rules still apply; see [cpsc-keyword-overload(7)](cpsc-keyword-overload.7.md). Directly supported built-in operations precede converted operators.
+
+Double-quoted literals and their CONSTANT values have type C_STRING. The standard library supplies IMPLICIT STRING constructors for C_STRING and CHAR. String functions, comparisons and concatenation therefore retain their normal text behavior. OUTPUT and file operations also bridge raw text through the marked STRING constructor. The older STRING-to-CHAR conversion checks for exactly one character; raw text can use this bridge after constructing STRING, with lower priority than a direct STRING parameter. The adjacent C suffix remains accepted and has the same C_STRING type.
+
+# EXAMPLE
+
+```text
+CLASS Box
+ Value : INTEGER
+ IMPLICIT PROCEDURE NEW(Number : INTEGER)
+ Value <- Number
+ ENDPROCEDURE
+ENDCLASS
+DECLARE Item : Box
+Item <- 42
+OUTPUT Item.Value
+```
+
+# SEE ALSO
+
+[cpsc-keyword-class(7)](cpsc-keyword-class.7.md), [cpsc-keyword-overload(7)](cpsc-keyword-overload.7.md), [cpsc-keyword-operator(7)](cpsc-keyword-operator.7.md), [cpsc-keyword-c_type(7)](cpsc-keyword-c_type.7.md).
diff --git a/doc/language/keyword/cpsc-keyword-operator.7.md b/doc/language/keyword/cpsc-keyword-operator.7.md
index 6c29370..134d3f2 100644
--- a/doc/language/keyword/cpsc-keyword-operator.7.md
+++ b/doc/language/keyword/cpsc-keyword-operator.7.md
@@ -29,7 +29,7 @@ OPERATOR is a compiler extension, absent from the CIE guide. Declare unary and b
Binary operators are `+ - * / DIV MOD & = <> < <= > >= AND OR`. Unary operators are `- NOT`. A global binary definition takes two parameters and a unary definition takes one; at least one parameter must be a record, class or enum. A pointer alias alone does not qualify. A member binary definition takes one explicit parameter and a unary definition takes none; this supplies the left or sole operand. PUBLIC and PRIVATE precede OVERLOAD as for other methods.
-Operands match exact static types, without implicit conversions, following OVERLOAD rules. For example, an INTEGER operand does not match a REAL parameter. Visible global definitions and methods of the left operand's class participate together. The selected method must be accessible: PRIVATE never causes a public fallback. Included units provide operators using the ordinary INCLUDE visibility rules.
+Operands prefer exact static types, following OVERLOAD rules. When no exact candidate or directly supported built-in operation applies, BYVAL operands may use IMPLICIT constructors; see [cpsc-keyword-implicit(7)](cpsc-keyword-implicit.7.md). For example, an INTEGER operand does not match a REAL parameter. Visible global definitions and methods of the left operand's class participate together. The selected method must be accessible: PRIVATE never causes a public fallback. Included units provide operators using the ordinary INCLUDE visibility rules.
Return types also distinguish operator overloads. When the context requires a result type (assignment, RETURN, condition, CASE comparison, subscript and similar positions), only definitions returning exactly that type match; if the operands match but no result does, the error is `No matching overload for OPERATOR +(T, U) returning R`. A cast `(R) expr` only prefers R and otherwise selects by operands before converting. Without an expected result type, such as OUTPUT or an operand of another operator, a unique operand match is selected; definitions that differ only by return type need a `RETURNS DEFAULT type` declaration to avoid ambiguity. DEFAULT follows the same rules as ordinary functions and does not resolve global/member operator ties; see [cpsc-keyword-default(7)](cpsc-keyword-default.7.md).
diff --git a/doc/language/keyword/cpsc-keyword-overload.7.md b/doc/language/keyword/cpsc-keyword-overload.7.md
index 1f7a0a4..bfd4ece 100644
--- a/doc/language/keyword/cpsc-keyword-overload.7.md
+++ b/doc/language/keyword/cpsc-keyword-overload.7.md
@@ -22,11 +22,11 @@ ENDCLASS
# DESCRIPTION
-OVERLOAD is a compiler extension, absent from the CIE guide. Put it immediately before FUNCTION or PROCEDURE, after PUBLIC or PRIVATE when an access keyword is present. OVERLOAD is reserved. Every definition sharing a case-insensitive name must specify OVERLOAD. Global functions, procedures, class methods and NEW constructors support it; MAIN and built-in functions do not.
+OVERLOAD is a compiler extension, absent from the CIE guide. Put it before FUNCTION or PROCEDURE, after PUBLIC or PRIVATE when an access keyword is present. An implicit constructor places IMPLICIT between OVERLOAD and PROCEDURE. OVERLOAD is reserved. Every definition sharing a case-insensitive name must specify OVERLOAD. Global functions, procedures, class methods and NEW constructors support it; MAIN and built-in functions do not.
Signatures differ by parameter count, parameter types, array rank, or return type. BYREF versus BYVAL and declared array bounds do not distinguish signatures. A PROCEDURE counts as returning VOID, so it can coexist with a FUNCTION having the same parameter list; a call that cannot determine a result type is then ambiguous unless the function specifies a DEFAULT return. Nominal user types remain distinct; equivalent native C type aliases identify the same type.
-Calls require an exact match to the arguments' static types. No implicit conversion is used to select an overload, even when only one OVERLOAD definition exists. Array arguments must be whole array variables with matching element types and rank. After selection, ordinary parameter-mode, array-bound and access checks apply. Functions without OVERLOAD retain their ordinary argument conversions and their implicit result conversions.
+Calls prefer exact static parameter types. If no exact candidate matches, BYVAL parameters may use a single IMPLICIT constructor or the existing CHAR/STRING bridge. Competing converted candidates are ambiguous; numeric widening does not select an overload. See [cpsc-keyword-implicit(7)](cpsc-keyword-implicit.7.md). Array arguments must be whole array variables with matching element types and rank. After selection, ordinary parameter-mode, array-bound and access checks apply. Functions without OVERLOAD retain their ordinary argument conversions and their implicit result conversions.
When the context requires a known result type, the selected overload must return exactly that type. This applies to assignment targets, BYVAL arguments, RETURN values, conditions, FOR bounds, subscripts and CASE comparisons. If the arguments match but no overload returns the required type, the error is `No matching overload for Name(T1, T2) returning T`. A cast `(T) expr` is weaker: it first prefers an overload returning T, then uses ordinary parameter selection and converts the result to T.
@@ -36,7 +36,7 @@ Overloads may be defined in separate input files. A caller sees only its own and
Methods use the same rules, including result-type selection; fields and methods cannot share a name. Constructor calls select NEW by their explicit arguments. DECLARE without arguments, class-valued fields and array elements select a parameterless NEW; if NEW exists but has no matching parameterless overload, compilation fails. PRIVATE checks apply to the selected method or constructor.
-Operator definitions use OVERLOAD FUNCTION OPERATOR followed by the operator symbol or keyword. They support global and member forms with exact operand types; see [cpsc-keyword-operator(7)](cpsc-keyword-operator.7.md).
+Operator definitions use OVERLOAD FUNCTION OPERATOR followed by the operator symbol or keyword. They support global and member forms with exact types preferred over implicit construction; see [cpsc-keyword-operator(7)](cpsc-keyword-operator.7.md).
# EXAMPLE
diff --git a/doc/language/keyword/cpsc-keyword-template.7.md b/doc/language/keyword/cpsc-keyword-template.7.md
index afa9cba..59cf889 100644
--- a/doc/language/keyword/cpsc-keyword-template.7.md
+++ b/doc/language/keyword/cpsc-keyword-template.7.md
@@ -25,11 +25,11 @@ ENDCLASS
TEMPLATE is a compiler extension, absent from the CIE guide. Place it before a top-level FUNCTION, PROCEDURE or CLASS, before OVERLOAD when present. Every template parameter names a type; no typename keyword is needed. Names must be distinct. A single optional type pack, written `Rest...`, must come last. Each concrete use creates and caches an ordinary function or class instance by substituting types into the template body.
-Function calls deduce types from parameters typed `T` or `ARRAY OF T`; bounded array parameters also require matching rank. Deduction does not look inside `Box<T>`. Explicit arguments, as in `Max<REAL>(1.5, 2.0)`, bind types positionally before deduction fills any remaining parameters. All argument types must match exactly, including explicitly bound types: `Max<REAL>(1, 2.5)` is an error. Explicit arguments are forbidden on ordinary functions and builtins. A type used only in RETURNS requires an explicit argument.
+Function calls deduce types from parameters typed `T` or `ARRAY OF T`; bounded array parameters also require matching rank. Deduction does not look inside `Box<T>`. Explicit arguments, as in `Max<REAL>(1.5, 2.0)`, bind types positionally before deduction fills any remaining parameters. Substituted BYVAL parameters may use IMPLICIT constructors or the existing CHAR/STRING bridge; otherwise types must match exactly, including explicitly bound types: `Max<REAL>(1, 2.5)` is an error. Explicit arguments are forbidden on ordinary functions and builtins. A type used only in RETURNS requires an explicit argument.
A final parameter `Others : Rest...` expands into one parameter per pack type, possibly none. It cannot be an ARRAY parameter. Write `Others...` only in argument lists of function or method calls, NEW or DECLARE constructors. A bare pack value is invalid. In type argument lists, `Rest...` forwards the current type pack. Explicit pack arguments constrain a prefix; deduction can supply the remaining types.
-When multiple function or procedure definitions share a name, every definition, including ordinary definitions, must specify OVERLOAD. Selection prefers an exact ordinary definition, then a non-variadic template, then a variadic template. Expected result types filter ordinary definitions but do not participate in template selection, which still matches substituted parameter types only. Two matches at the same level are ambiguous; no further template ordering is performed. Explicit template arguments select only templates. Normal BYREF, array-bound and access checks apply after selection; see [cpsc-keyword-overload(7)](cpsc-keyword-overload.7.md).
+When multiple function or procedure definitions share a name, every definition, including ordinary definitions, must specify OVERLOAD. Selection prefers an exact ordinary definition, then an exact non-variadic template, then an exact variadic template. If none matches, it repeats those levels with permitted implicit conversions. Expected result types filter ordinary definitions but do not participate in template selection, which still matches substituted parameter types only. Two matches at the same level are ambiguous; no further template ordering is performed. Explicit template arguments select only templates. Normal BYREF, array-bound and access checks apply after selection; see [cpsc-keyword-overload(7)](cpsc-keyword-overload.7.md).
Use a class instance such as `Box<INTEGER>` wherever a type name is accepted, including nested instances such as `Box<Box<INTEGER>>`. Supply all class type arguments explicitly; variadic CLASS templates are allowed, and their methods may use the class's pack parameters. Pack fields such as `Values : Rest...` are rejected. Constructors, ownership and destruction follow ordinary CLASS rules. In particular, a declaration without constructor arguments needs a matching parameterless NEW when constructors exist; see [cpsc-keyword-class(7)](cpsc-keyword-class.7.md).