From 5a67f4e3833c2acca4a351f5dd613bc08f04bfc0 Mon Sep 17 00:00:00 2001 From: _ov4 Date: Sun, 18 Oct 2026 06:11:42 +0000 Subject: feat(operators): document overloads and cover remaining operator forms Add fixed cases for every supported operator, imported global and member operators, CASE comparisons, and declared result type errors. Document syntax, exact matching, access rules and temporary receiver lifetimes. Co-Authored-By: Claude Opus 5.5 --- AGENTS/ARCH.md | 1 + AGENTS/CONVENTIONS.md | 17 +++++- AGENTS/PITFALLS.md | 10 +++- AGENTS/SUBSYSTEMS.md | 12 ++++- doc/language/cpsc-language-overview.7.md | 5 +- doc/language/keyword/cpsc-keyword-operator.7.md | 59 +++++++++++++++++++++ doc/language/keyword/cpsc-keyword-overload.7.md | 2 + tests/i/multifile-operators/case.json | 7 +++ tests/i/multifile-operators/expected.txt | 5 ++ tests/i/multifile-operators/notes.md | 7 +++ tests/i/multifile-operators/operators.cps | 4 ++ tests/i/multifile-operators/program.cps | 21 ++++++++ tests/i/multifile-operators/types.cps | 12 +++++ tests/i/operator-kinds/case.json | 1 + tests/i/operator-kinds/expected.txt | 18 +++++++ tests/i/operator-kinds/notes.md | 7 +++ tests/i/operator-kinds/program.cps | 70 +++++++++++++++++++++++++ tests/iii/operator-result-errors/case.json | 20 +++++++ tests/iii/operator-result-errors/notes.md | 3 ++ tests/iii/operator-result-errors/program.cps | 20 +++++++ 20 files changed, 296 insertions(+), 5 deletions(-) create mode 100644 doc/language/keyword/cpsc-keyword-operator.7.md create mode 100644 tests/i/multifile-operators/case.json create mode 100644 tests/i/multifile-operators/expected.txt create mode 100644 tests/i/multifile-operators/notes.md create mode 100644 tests/i/multifile-operators/operators.cps create mode 100644 tests/i/multifile-operators/program.cps create mode 100644 tests/i/multifile-operators/types.cps create mode 100644 tests/i/operator-kinds/case.json create mode 100644 tests/i/operator-kinds/expected.txt create mode 100644 tests/i/operator-kinds/notes.md create mode 100644 tests/i/operator-kinds/program.cps create mode 100644 tests/iii/operator-result-errors/case.json create mode 100644 tests/iii/operator-result-errors/notes.md create mode 100644 tests/iii/operator-result-errors/program.cps diff --git a/AGENTS/ARCH.md b/AGENTS/ARCH.md index 0ffe875..16456e2 100644 --- a/AGENTS/ARCH.md +++ b/AGENTS/ARCH.md @@ -315,6 +315,7 @@ do not modify the real release for local verification. | `lib/Parser/ParserType.cc` | Type names, variable/array/constant declarations, TYPE/ENDTYPE and CLASS/ENDCLASS declarations, shared field and method parsing, SET/DEFINE reserved stubs | | `lib/CodeGen/CodeGen.cc` | Initialization, symbols, call arguments and main() compilation | | `lib/CodeGen/ExpressionGen.cc`, `StatementGen.cc`, `ControlFlowGen.cc` | Expression/statement dispatch and control-flow emission | +| `lib/CodeGen/OperatorGen.cc`, `include/cps/Operator.h` | Exact global/member operator selection, calls and temporary receivers; shared operator spellings | | `lib/CodeGen/GlobalGen.cc` | Primitive GLOBAL declaration and constant-initializer passes | | `lib/CodeGen/ConstantGen.cc` | Literal constants, declaration conflicts and lexical binding restoration | | `lib/CodeGen/ValueTypeGen.cc`, `OutputGen.cc`, `Builtins.h` | Expression typing, coercion/declarations, scalar output and the shared builtin table | diff --git a/AGENTS/CONVENTIONS.md b/AGENTS/CONVENTIONS.md index 5ab7459..d1f018d 100644 --- a/AGENTS/CONVENTIONS.md +++ b/AGENTS/CONVENTIONS.md @@ -83,8 +83,8 @@ pseudocode types *backwards* from LLVM types (`getExprTypeInfo`'s fallback, only explicitly declared pointer types compare addresses. STRING's six comparison operators use `strcmp` in `StringHandler`, dispatched by pseudocode type in CodeGen before ArithmeticHandler. Ordering is case-sensitive byte lexicographic order; -mixed STRING/non-STRING comparisons are errors. Whole-array and record comparisons -remain unsupported. +mixed STRING/non-STRING comparisons are errors. Whole-array comparisons remain unsupported; records/classes require an explicit +operator overload for comparisons. **Strings are malloc'd and never freed — by design.** Every string-producing operation (`&`, MID/LEFT/RIGHT/LCASE/UCASE, NUM_TO_STR, CHR, READFILE, CHAR/number→STRING @@ -152,6 +152,19 @@ declaration spelling for LLVM lookup, independently of call-site casing. Methods `Class.Method` names and a hidden leading receiver address; their FuncSig parameters contain only explicit source parameters. Method prototypes are pre-registered too. +**Operator overloads share static selection.** OPERATOR is a reserved keyword; +`OVERLOAD FUNCTION OPERATOR+(...)` records the 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 are ambiguous and access is checked only after selection. +Both getExprTypeInfo and emission must consult this resolver before hardcoded +builtin result types. Returns may be any supported function result, including +non-BOOLEAN comparisons/logic. emitCoercedExpr rejects implicit STRING to BOOLEAN; +CASE separately requires BOOLEAN comparisons. Operators use shared argument +marshalling and exception-aware calls. Member lvalues keep their original address; +rvalues are materialized and registered for the existing function-scoped cleanup. + **Parameter modes are sticky and BYREF is procedure-only (guide §8.3).** In `(BYREF a : T, b : T)` the `b` is BYREF too; unannotated parameters default to BYVAL (§8.1). A BYREF parameter in a FUNCTION is a parse error. **Array diff --git a/AGENTS/PITFALLS.md b/AGENTS/PITFALLS.md index 3198852..4059767 100644 --- a/AGENTS/PITFALLS.md +++ b/AGENTS/PITFALLS.md @@ -46,7 +46,7 @@ test programs. at any new call site) and internally defaults to INTEGER for unclassified arithmetic expressions; unknown or unmatched calls now diagnose and return nullptr. OUTPUT reports an error for a nullptr result. - **CONSTANT** accepts only literals (including negative numeric literals), never expressions or other names. Constants have lexical block scope and may shadow outer names; bindings hiding constants are restored on block exit too. Functions inherit previously declared constants from their own unit and all visible imported top-level constants. Constants have no writable storage: assignment, INPUT, READFILE targets, FOR variables, BYREF and address-of are rejected. -- **CASE OF** reads its selector once and tests expression labels in source order, with inclusive TO ranges and an optional final OTHERWISE. Label headers occupy their own source line; bodies may begin after the colon or on subsequent lines. Comparisons reuse ordinary operator rules; records and whole arrays are unsupported. +- **CASE OF** reads its selector once and tests expression labels in source order, with inclusive TO ranges and an optional final OTHERWISE. Label headers occupy their own source line; bodies may begin after the colon or on subsequent lines. Comparisons reuse ordinary operator rules; records/classes need BOOLEAN-returning comparison overloads, and whole arrays are unsupported. - The lexer emits no newline tokens; most grammar is keyword-delimited, while CASE uses token line information to recognize labels. Bare `RETURN` is recognized before block terminators and the next CASE label. @@ -93,6 +93,14 @@ test programs. inputs. MAIN and builtins cannot be overloaded. NEW supports overloads; DECLARE, fields and arrays needing default construction require a matching no-argument NEW. Private access is checked after selection, never used to select a public fallback. +- **OPERATOR extension.** Requires OVERLOAD FUNCTION, with supported unary/binary + 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; ties are errors, including private/public ties. Comparison and logic + result types are declared, not assumed BOOLEAN; implicit STRING to BOOLEAN is + rejected. CASE comparisons must return BOOLEAN. AND/OR overloads evaluate both + operands. Temporary member receivers have function-scoped cleanup, not C++ + full-expression lifetimes. Explicit calls use OPERATOR+(a,b) or a.OPERATOR+(b). - **CLASS subset (§10).** `CLASS`/`ENDCLASS`/`PUBLIC`/`PRIVATE` are reserved. CLASS is a top-level record-derived value type with optional per-member access keywords (no DECLARE). Omitting access defaults to public, per the guide. diff --git a/AGENTS/SUBSYSTEMS.md b/AGENTS/SUBSYSTEMS.md index ac31cde..be20bc3 100644 --- a/AGENTS/SUBSYSTEMS.md +++ b/AGENTS/SUBSYSTEMS.md @@ -43,6 +43,16 @@ compile error (no extern is fabricated). Functions inherit visible GLOBAL storag `StmtEmitter` callback, and must restore its own insert point (and the exchanged ArrayTable) afterwards. +**Operator overloads** (`OperatorGen.cc`): 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 +ValueTypeGen and ExpressionGen before builtin operations. Missing candidates leave +builtin rules intact; ties are errors. Member access is checked after selection. +The raw-expression argument-marshalling overload borrows AST pointers for operator +calls; ordinary calls adapt their unique_ptr lists into it. Member receivers use +lvalue storage or a materialized, Alive-tracked temporary. CASE calls the value +entry point with its already captured selector and requires BOOLEAN results. + **EXTERN "C"** (`ExternDeclAST`, `IncludeObjStmtAST`): the parser builds a body-less `PrototypeAST` (IsExternal, IsVariadic, unnamed `argN` params). `FunctionGen::emitExternPrototype` validates C types, records a `FuncSig` with `IsExternal`, the declared `FunctionType` and @@ -71,7 +81,7 @@ constants live in a TypeSystem-owned table, resolved in `emitExpr`'s `VariableExprAST` branch after `Symbols` misses. The lvalue layer (`emitLValue`/`loadFromLValue`) resolves designator chains to `{address, type name}`; `emitCoercedExpr` is the single name-level admission gate; `emitUserKindBinaryOp` -intercepts binary operators ahead of ArithmeticHandler (which, like StringHandler and +intercepts built-in binary operators ahead of ArithmeticHandler (which, like StringHandler and FileHandler, is deliberately ignorant of user kinds). The enum range check after `E ± INTEGER` is the only site that can produce an invalid ordinal — every other producer (constants, same-name copies, zero-init, memset-0 arrays) is valid by diff --git a/doc/language/cpsc-language-overview.7.md b/doc/language/cpsc-language-overview.7.md index 2e2a393..a66ce69 100644 --- a/doc/language/cpsc-language-overview.7.md +++ b/doc/language/cpsc-language-overview.7.md @@ -8,7 +8,9 @@ cpsc-language-overview - supported cpsc pseudocode syntax Keywords are uppercase and case-sensitive. Identifiers, including built-in function names, are case insensitive. Indentation is for readability; blocks use explicit closing keywords. Identifiers begin with a letter and continue with letters, digits, or underscores. -Assign with ASCII `<-`: `Count <- Count + 1`. Compare with `=`, `<>`, `<`, `>`, `<=`, and `>=`. STRING comparisons compare contents, case-sensitively. Use `+`, `-`, `*`, and `/` for arithmetic; `/` always returns REAL. Use `&` to join strings. +Assign with ASCII `<-`: `Count <- Count + 1`. Compare with `=`, `<>`, `<`, `>`, `<=`, and `>=`. Built-in STRING comparisons compare contents, case-sensitively. Use `+`, `-`, `*`, and `/` for arithmetic; built-in `/` always returns REAL. Use `&` to join strings. + +User-defined types can overload operators with OVERLOAD FUNCTION OPERATOR; expressions then use the declared result type. See [cpsc-keyword-operator(7)](keyword/cpsc-keyword-operator.7.md). STRING cannot be implicitly converted to BOOLEAN. Precedence, from highest to lowest: unary operators, `* / DIV MOD`, `+ - &`, comparisons, AND, OR. Parentheses override precedence. @@ -38,6 +40,7 @@ Multi-file builds use the compiler extensions INCLUDE and GLOBAL. Pass every sou - [cpsc-keyword-for(7)](keyword/cpsc-keyword-for.7.md): iterate over an integer range. - [cpsc-keyword-function(7)](keyword/cpsc-keyword-function.7.md): define a function that returns a value. - [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-call(7)](keyword/cpsc-keyword-call.7.md): invoke a procedure. - [cpsc-keyword-openfile(7)](keyword/cpsc-keyword-openfile.7.md): open a text file. diff --git a/doc/language/keyword/cpsc-keyword-operator.7.md b/doc/language/keyword/cpsc-keyword-operator.7.md new file mode 100644 index 0000000..5ba3999 --- /dev/null +++ b/doc/language/keyword/cpsc-keyword-operator.7.md @@ -0,0 +1,59 @@ +% CPSC-KEYWORD-OPERATOR(7) + +# NAME + +cpsc-keyword-operator - overload unary and binary operators + +# SYNOPSIS + +```text +OVERLOAD FUNCTION OPERATOR+(left : T, right : U) RETURNS R + statements +ENDFUNCTION +CLASS T + OVERLOAD FUNCTION OPERATOR+(right : U) RETURNS R + statements + ENDFUNCTION + OVERLOAD FUNCTION OPERATOR-() RETURNS R + statements + ENDFUNCTION +ENDCLASS +``` + +# DESCRIPTION + +OPERATOR is a compiler extension, absent from the CIE guide. Declare operators with OVERLOAD FUNCTION, at top level or inside CLASS. OPERATOR is reserved; whitespace before the operator is optional. Parentheses are required. Parameters and return values follow FUNCTION rules: parameters default to BYVAL, BYREF is forbidden, and omitting RETURNS defaults to INTEGER. Whole-array operands and array results are unsupported. + +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; multiple matching candidates are an error. The selected method must be accessible: PRIVATE never causes a public fallback. Included units provide operators using the ordinary INCLUDE visibility rules. Return types do not distinguish overloads. + +The expression has the selected function's declared return type. Comparisons and logic may return any supported function result type: a comparison returning STRING can be printed or assigned to STRING, but cannot be implicitly used as BOOLEAN. CASE comparisons must return BOOLEAN. A VOID result may be discarded through an explicit call but cannot be used as a value. + +Operators keep their existing precedence, operand count and associativity. Operands are evaluated once, from left to right; overloaded AND and OR evaluate both operands. Operators are independent: defining = does not define <>, and operands are never swapped to find a match. A matching overload takes precedence over the built-in operation; otherwise the existing built-in rules apply. + +Member operators on variables, fields, array elements and pointer dereferences modify the original receiver. Class-valued expressions can also receive operator calls, supporting chains such as `(A + B) + C`. A temporary receiver follows the compiler's existing function-scoped object cleanup rules, rather than C++ full-expression lifetimes. Copies and return values retain the ordinary class value semantics. + +Explicit calls use `OPERATOR+(A, B)` for global definitions and `A.OPERATOR+(B)` for members. They also work as statements, optionally prefixed with CALL, to discard results. As with ordinary method calls, explicit member access on a function result is unsupported. Assignment, indexing, function-call, address-of and dereference operators cannot be overloaded. + +# EXAMPLE + +```text +CLASS Box + Value : INTEGER + OVERLOAD FUNCTION OPERATOR+(Right : INTEGER) RETURNS Box + DECLARE Result : Box + Result.Value <- Value + Right + RETURN Result + ENDFUNCTION +ENDCLASS +DECLARE Item : Box +DECLARE Sum : Box +Item.Value <- 3 +Sum <- (Item + 2) + 4 +OUTPUT Sum.Value +``` + +# SEE ALSO + +[cpsc-keyword-overload(7)](cpsc-keyword-overload.7.md), [cpsc-keyword-function(7)](cpsc-keyword-function.7.md), [cpsc-keyword-class(7)](cpsc-keyword-class.7.md), [cpsc-keyword-include(7)](cpsc-keyword-include.7.md). diff --git a/doc/language/keyword/cpsc-keyword-overload.7.md b/doc/language/keyword/cpsc-keyword-overload.7.md index f7df69f..21ba7b7 100644 --- a/doc/language/keyword/cpsc-keyword-overload.7.md +++ b/doc/language/keyword/cpsc-keyword-overload.7.md @@ -32,6 +32,8 @@ Overloads may be defined in separate input files. A caller sees only its own and Methods use the same rules; 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). + # EXAMPLE ```text diff --git a/tests/i/multifile-operators/case.json b/tests/i/multifile-operators/case.json new file mode 100644 index 0000000..a71b210 --- /dev/null +++ b/tests/i/multifile-operators/case.json @@ -0,0 +1,7 @@ +{ + "sources": [ + "program.cps", + "operators.cps", + "types.cps" + ] +} diff --git a/tests/i/multifile-operators/expected.txt b/tests/i/multifile-operators/expected.txt new file mode 100644 index 0000000..7642205 --- /dev/null +++ b/tests/i/multifile-operators/expected.txt @@ -0,0 +1,5 @@ +5 +FALSE +range +TRUE +8 diff --git a/tests/i/multifile-operators/notes.md b/tests/i/multifile-operators/notes.md new file mode 100644 index 0000000..73263d1 --- /dev/null +++ b/tests/i/multifile-operators/notes.md @@ -0,0 +1,7 @@ +# multifile-operators + +Human review: pending. Expected output was independently traced by AI, not captured from cpsc. + +Basis: INCLUDE and operator overloading are project extensions. + +Trace: program imports the global INTEGER addition and transitively imports Key and its comparison methods. Value 3 plus 2 gives 5; 3 equals 4 is FALSE. CASE first rejects equality with 1, then matches the inclusive range 1 through 4. Array element value 4 equals high, yielding TRUE. Dereferencing the pointer to item then adding 5 gives 8. diff --git a/tests/i/multifile-operators/operators.cps b/tests/i/multifile-operators/operators.cps new file mode 100644 index 0000000..f0c4f05 --- /dev/null +++ b/tests/i/multifile-operators/operators.cps @@ -0,0 +1,4 @@ +INCLUDE "types.cps" +OVERLOAD FUNCTION OPERATOR+(lhs : Key, rhs : INTEGER) RETURNS INTEGER +RETURN lhs.Value + rhs +ENDFUNCTION diff --git a/tests/i/multifile-operators/program.cps b/tests/i/multifile-operators/program.cps new file mode 100644 index 0000000..85eb3ee --- /dev/null +++ b/tests/i/multifile-operators/program.cps @@ -0,0 +1,21 @@ +INCLUDE "operators.cps" +DECLARE item : Key +DECLARE low : Key +DECLARE high : Key +item.Value <- 3 +low.Value <- 1 +high.Value <- 4 +OUTPUT item + 2 +OUTPUT item = high +CASE OF item +low : OUTPUT "wrong" +low TO high : OUTPUT "range" +OTHERWISE : OUTPUT "wrong" +ENDCASE +DECLARE items : ARRAY[1:2] OF Key +items[2].Value <- 4 +OUTPUT items[2] = high +TYPE KeyPointer = ^Key +DECLARE pointer : KeyPointer +pointer <- ^item +OUTPUT pointer^ + 5 diff --git a/tests/i/multifile-operators/types.cps b/tests/i/multifile-operators/types.cps new file mode 100644 index 0000000..9198da4 --- /dev/null +++ b/tests/i/multifile-operators/types.cps @@ -0,0 +1,12 @@ +CLASS Key +Value : INTEGER +OVERLOAD FUNCTION OPERATOR=(rhs : Key) RETURNS BOOLEAN +RETURN Value = rhs.Value +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR>=(rhs : Key) RETURNS BOOLEAN +RETURN Value >= rhs.Value +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR<=(rhs : Key) RETURNS BOOLEAN +RETURN Value <= rhs.Value +ENDFUNCTION +ENDCLASS diff --git a/tests/i/operator-kinds/case.json b/tests/i/operator-kinds/case.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/tests/i/operator-kinds/case.json @@ -0,0 +1 @@ +{} diff --git a/tests/i/operator-kinds/expected.txt b/tests/i/operator-kinds/expected.txt new file mode 100644 index 0000000..3edc836 --- /dev/null +++ b/tests/i/operator-kinds/expected.txt @@ -0,0 +1,18 @@ +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +114 diff --git a/tests/i/operator-kinds/notes.md b/tests/i/operator-kinds/notes.md new file mode 100644 index 0000000..f4d829e --- /dev/null +++ b/tests/i/operator-kinds/notes.md @@ -0,0 +1,7 @@ +# operator-kinds + +Human review: pending. Expected output was independently traced by AI, not captured from cpsc. + +Basis: operator overloading is a project extension. + +Trace: each binary operator on Choice explicitly returns its own marker 101 through 115 in source order. Unary minus returns 116 and NOT returns 117. The explicit AND call returns 114. In particular /, &, comparisons and logic must use the declared INTEGER result, overriding builtin type inference and enum comparisons. diff --git a/tests/i/operator-kinds/program.cps b/tests/i/operator-kinds/program.cps new file mode 100644 index 0000000..b66fa0e --- /dev/null +++ b/tests/i/operator-kinds/program.cps @@ -0,0 +1,70 @@ +TYPE Choice = (First, Second) +OVERLOAD FUNCTION OPERATOR +(lhs : Choice, rhs : Choice) RETURNS INTEGER +RETURN 101 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR -(lhs : Choice, rhs : Choice) RETURNS INTEGER +RETURN 102 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR *(lhs : Choice, rhs : Choice) RETURNS INTEGER +RETURN 103 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR /(lhs : Choice, rhs : Choice) RETURNS INTEGER +RETURN 104 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR DIV(lhs : Choice, rhs : Choice) RETURNS INTEGER +RETURN 105 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR MOD(lhs : Choice, rhs : Choice) RETURNS INTEGER +RETURN 106 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR &(lhs : Choice, rhs : Choice) RETURNS INTEGER +RETURN 107 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR =(lhs : Choice, rhs : Choice) RETURNS INTEGER +RETURN 108 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR <>(lhs : Choice, rhs : Choice) RETURNS INTEGER +RETURN 109 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR <(lhs : Choice, rhs : Choice) RETURNS INTEGER +RETURN 110 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR <=(lhs : Choice, rhs : Choice) RETURNS INTEGER +RETURN 111 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR >(lhs : Choice, rhs : Choice) RETURNS INTEGER +RETURN 112 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR >=(lhs : Choice, rhs : Choice) RETURNS INTEGER +RETURN 113 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR AND(lhs : Choice, rhs : Choice) RETURNS INTEGER +RETURN 114 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR OR(lhs : Choice, rhs : Choice) RETURNS INTEGER +RETURN 115 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR-(value : Choice) RETURNS INTEGER +RETURN 116 +ENDFUNCTION +OVERLOAD FUNCTION OPERATOR NOT(value : Choice) RETURNS INTEGER +RETURN 117 +ENDFUNCTION +OUTPUT First + Second +OUTPUT First - Second +OUTPUT First * Second +OUTPUT First / Second +OUTPUT First DIV Second +OUTPUT First MOD Second +OUTPUT First & Second +OUTPUT First = Second +OUTPUT First <> Second +OUTPUT First < Second +OUTPUT First <= Second +OUTPUT First > Second +OUTPUT First >= Second +OUTPUT First AND Second +OUTPUT First OR Second +OUTPUT -First +OUTPUT NOT Second +OUTPUT OPERATOR AND(First, Second) diff --git a/tests/iii/operator-result-errors/case.json b/tests/iii/operator-result-errors/case.json new file mode 100644 index 0000000..67abec2 --- /dev/null +++ b/tests/iii/operator-result-errors/case.json @@ -0,0 +1,20 @@ +{ + "errors": [ + { + "reason": "Cannot implicitly convert STRING to BOOLEAN", + "line": 8 + }, + { + "reason": "Cannot implicitly convert STRING to BOOLEAN", + "line": 12 + }, + { + "reason": "Cannot implicitly convert STRING to BOOLEAN", + "line": 17 + }, + { + "reason": "CASE comparison must return BOOLEAN", + "line": 19 + } + ] +} diff --git a/tests/iii/operator-result-errors/notes.md b/tests/iii/operator-result-errors/notes.md new file mode 100644 index 0000000..bb407a2 --- /dev/null +++ b/tests/iii/operator-result-errors/notes.md @@ -0,0 +1,3 @@ +# operator-result-errors + +The equality operator returns STRING. Reject that result as an IF condition, BOOLEAN return value, BOOLEAN argument and CASE comparison. diff --git a/tests/iii/operator-result-errors/program.cps b/tests/iii/operator-result-errors/program.cps new file mode 100644 index 0000000..8cf9ede --- /dev/null +++ b/tests/iii/operator-result-errors/program.cps @@ -0,0 +1,20 @@ +CLASS Box +Value : INTEGER +OVERLOAD FUNCTION OPERATOR=(rhs : Box) RETURNS STRING +RETURN "text" +ENDFUNCTION +ENDCLASS +DECLARE item : Box +IF item = item THEN +OUTPUT "wrong" +ENDIF +FUNCTION Bad(value : Box) RETURNS BOOLEAN +RETURN value = value +ENDFUNCTION +FUNCTION NeedBool(flag : BOOLEAN) RETURNS INTEGER +RETURN 0 +ENDFUNCTION +OUTPUT NeedBool(item = item) +CASE OF item +item : OUTPUT "wrong" +ENDCASE -- cgit v1.3.1-4-g156e