diff options
25 files changed, 228 insertions, 13 deletions
diff --git a/AGENTS/CONVENTIONS.md b/AGENTS/CONVENTIONS.md index 83e73e2..87a95b7 100644 --- a/AGENTS/CONVENTIONS.md +++ b/AGENTS/CONVENTIONS.md @@ -97,7 +97,9 @@ and INPUT STRING buffers — declared in `SetupExternalFunctions`, never fetched bare `getFunction("malloc")`. **One symbol namespace, one table.** `Symbols` (name → `SymbolInfo{Storage, -TypeName, IsArray, ConstantValue, ScopeID}`) in CodeGen is the only symbol table. +TypeName, IsArray, ConstantValue, ScopeID, IsReference}`) in CodeGen is the 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`). A non-null ConstantValue denotes a read-only CONSTANT with no Storage. Read it through `emitExpr`; all writable/address-taking paths must reject it through `requireWritable`. Register variables through `registerSymbol()` (parameters are diff --git a/AGENTS/PITFALLS.md b/AGENTS/PITFALLS.md index ec5d034..6ef422b 100644 --- a/AGENTS/PITFALLS.md +++ b/AGENTS/PITFALLS.md @@ -87,6 +87,14 @@ test programs. `this.Method(...)`; unqualified calls remain global. Parameters and local declarations shadowing fields warn without failing compilation. Method-only classes are allowed; empty classes and array fields remain unsupported. + PROCEDURE NEW is an ordinary case-insensitive member, also called automatically + after zero initialization by DECLARE and assignment-only keyword NEW. Fields and + array elements recursively require parameterless construction before the outer NEW. + Class variables and BYVAL class parameters use reference slots: keyword NEW rebinds + them, while ordinary assignment copies into their current object. Fields, array + elements, BYREF, this and pointer dereferences receive a value copy from NEW; + the temporary allocation leaks. Old address-of pointers retain the previous object. + Private access and ordinary argument checks apply to automatic construction too. - **Exception extensions.** TRY requires exactly one parameterless CATCH and ENDTRY. Bare THROW raises a new anonymous exception even inside CATCH; there is @@ -114,8 +122,8 @@ SET types (`SET`/`DEFINE` are reserved with dedicated errors), random files (OPENFILE...FOR RANDOM/SEEK/GETRECORD/PUTRECORD — TYPE is done, so these are unblocked now; the RANDOM keyword is reserved and gives a dedicated parse error), DATE, string escape sequences, -array-typed record fields, whole-array RETURN, class constructors/destructors, -NEW and class inheritance. Compiler fixtures now live in `tests/` (see TESTING.md). +array-typed record fields, whole-array RETURN, destructors/DELETE +and class inheritance (INHERITS/SUPER). Compiler fixtures now live in `tests/` (see TESTING.md). Nightly CI runs the compiler suites, packaged EMBEDDED smoke checks and existing plugin tests. The initial standard conflicts and missing diagnostic locations are fixed on Linux. diff --git a/AGENTS/SUBSYSTEMS.md b/AGENTS/SUBSYSTEMS.md index b21386d..1d13c57 100644 --- a/AGENTS/SUBSYSTEMS.md +++ b/AGENTS/SUBSYSTEMS.md @@ -78,8 +78,22 @@ FunctionGen binds field aliases and `this` to the incoming receiver storage befo binding explicit parameters. CodeGen saves/restores `CurrentClass` around each function body; unqualified calls still resolve globally. Local declarations and parameters may shadow fields with a source-line warning; `this.Field` remains -explicit. `this` cannot be redeclared within methods. Constructors and language-level -inheritance remain unsupported. +explicit. `this` cannot be redeclared within methods. `TypeInfo::IsClass` distinguishes +classes from records without changing their shared LLVM representation. + +`ConstructorGen.cc` emits recursive field construction in declaration order followed +by the ordinary NEW method, sharing `emitMethodCall` access checks, argument +marshalling and exception-aware calls. DECLARE zeroes its original storage on every +execution; arrays loop over all flat elements and default-construct each one. +Constructor argument lists are class-only, and field/array defaults require a +parameterless NEW. Explicit NEW method calls do not reconstruct fields. +`SymbolInfo::IsReference` marks a pointer slot for declared class variables and BYVAL +class parameters; `symbolAddress` loads their current object address for all value, +lvalue, address-of, receiver and BYREF paths. Field aliases, this and BYREF parameters +bind addresses directly. Assignment-only `NewExprAST` uses checked MemoryHandler +allocation (at least one byte for method-only classes), zero initialization and +construction, then rebinds reference slots or copies into other destinations. Ordinary assignment always copies. Heap lifetimes +remain unmanaged; destructors, DELETE and INHERITS/SUPER are unsupported. **Runtime checks** (`RuntimeCheck`): array bounds, file misuse, enum ranges, null dereferences and array-parameter bounds contracts are checked at their emit sites. @@ -123,4 +137,4 @@ malloc/realloc buffer per line and strips one trailing `\r`; fopen modes are tex nothing is declared or emitted eagerly. Helper bodies are built with the *shared* Builder (RuntimeCheck emits through the same one), saving/restoring the insert block. -**Explicit memory** (`MemoryHandler`): lazily emits internal allocation/find/release/resize helpers and a linked list of live allocation start addresses. Only explicit MALLOC/REALLOC allocations enter the list; STRING/ARRAY internals retain their existing ownership. FREE validates non-null addresses, unlinks and frees the tracking node, releases the block and returns the original address. Zero-byte allocation returns null. REALLOC validates non-null addresses before its zero-size release path; null behaves as MALLOC. Positive-size resizing updates the node only after success, leaving the old block and record intact on failure. Node allocation precedes the user allocation; if the latter fails, its node is freed before the diagnostic and anonymous throw. Helpers use RuntimeCheck and ExceptionHandler, including source-line arguments and per-function unwind preparation. Sizes accept INTEGER and C integers and convert to native size_t. Address reuse can make stale aliases indistinguishable from current allocations; dereferences are not checked against this list. +**Explicit memory** (`MemoryHandler`): lazily emits internal allocation/find/release/resize helpers and a linked list of live allocation start addresses. Explicit MALLOC/REALLOC and keyword NEW allocations enter the list; STRING/ARRAY internals retain their existing ownership. FREE validates non-null addresses, unlinks and frees the tracking node, releases the block and returns the original address. Zero-byte allocation returns null. REALLOC validates non-null addresses before its zero-size release path; null behaves as MALLOC. Positive-size resizing updates the node only after success, leaving the old block and record intact on failure. Node allocation precedes the user allocation; if the latter fails, its node is freed before the diagnostic and anonymous throw. Helpers use RuntimeCheck and ExceptionHandler, including source-line arguments and per-function unwind preparation. Sizes accept INTEGER and C integers and convert to native size_t. Address reuse can make stale aliases indistinguishable from current allocations; dereferences are not checked against this list. diff --git a/doc/language/keyword/cpsc-keyword-class.7.md b/doc/language/keyword/cpsc-keyword-class.7.md index faa84df..f0d2e12 100644 --- a/doc/language/keyword/cpsc-keyword-class.7.md +++ b/doc/language/keyword/cpsc-keyword-class.7.md @@ -2,7 +2,7 @@ # NAME -cpsc-keyword-class, cpsc-keyword-public, cpsc-keyword-private, cpsc-keyword-endclass - define a class with fields and methods +cpsc-keyword-class, cpsc-keyword-public, cpsc-keyword-private, cpsc-keyword-endclass, cpsc-keyword-new - define a class with fields and methods # SYNOPSIS @@ -10,6 +10,9 @@ cpsc-keyword-class, cpsc-keyword-public, cpsc-keyword-private, cpsc-keyword-endc CLASS name PUBLIC publicField : type PRIVATE privateField : type + PUBLIC PROCEDURE NEW(parameters) + statements + ENDPROCEDURE PUBLIC PROCEDURE method(parameters) statements ENDPROCEDURE @@ -17,6 +20,8 @@ CLASS name RETURN expression ENDFUNCTION ENDCLASS +DECLARE object : ClassName(arguments) +object <- NEW ClassName(arguments) ``` # DESCRIPTION @@ -29,22 +34,32 @@ Within a method, bare field names refer to the current object's fields. The comp Parameters and local variables, arrays, or constants may shadow fields; this produces a warning with the source line and does not prevent compilation. The local name takes precedence; `this.Field` continues to access the field. The name `this` cannot be a class member or a method parameter or local declaration. -Classes retain record value semantics: zero initialization, whole-value copying, arrays, pointers, and ordinary function/procedure parameters. Methods modify the receiver's storage. The object reference `this` may be read, returned, or passed as an object, including BYREF to a procedure; `this <- Other` copies Other into the current object without rebinding the reference. PRIVATE fields still initialize and copy with the whole value. Constructors, destructors, NEW, INHERITS, and array fields are unsupported. +Classes retain record value semantics: zero initialization, whole-value copying, arrays, pointers, and ordinary function/procedure parameters. Methods modify the receiver's storage. The object reference `this` may be read, returned, or passed as an object, including BYREF to a procedure; `this <- Other` copies Other into the current object without rebinding the reference. PRIVATE fields still initialize and copy with the whole value. + +A constructor is a PROCEDURE named NEW, following guide section 10.2. It may be PUBLIC or PRIVATE; FUNCTION NEW and global PROCEDURE NEW are errors. Member names are case insensitive, so New and new also name the constructor. Only one NEW is allowed per class. Explicit `Object.NEW(arguments)`, `CALL Object.NEW(arguments)` and `this.NEW(arguments)` behave like ordinary member calls and may be repeated; they do not zero the object or reconstruct its fields. + +`DECLARE Object : ClassName`, `DECLARE Object : ClassName()` and `DECLARE Object : ClassName(arguments)` zero the object's storage, construct its fields recursively in declaration order, then call its NEW procedure. These automatic DECLARE, field and array calls are compiler extensions. Array elements and class-valued fields in records or classes use parameterless construction, before the enclosing constructor runs. A required constructor argument cannot be omitted; supplying arguments to a class without NEW is an error. Empty parentheses are allowed for a class without NEW. Constructor arguments after ARRAY OF are unsupported. A declaration executed again, such as inside a loop, zeroes and constructs its original storage again. + +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 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. + +When Target is a declared class variable, including a function local or BYVAL parameter, NEW rebinds that variable to the heap object. No `^` dereference is needed to access it. Address-of, BYREF calls and method calls use its current object. Pointers taken before rebinding continue to refer to the previous object. Ordinary `A <- B` remains a value copy into A's current object and does not rebind A. BYVAL parameters copy the caller's value and can rebind independently. + +For an array element, field (including a bare field inside a method), BYREF parameter, this, or pointer dereference, NEW constructs a heap object and copies its value into the existing target. That temporary allocation is retained. There is no automatic reclamation, destructor or DELETE support; INHERITS, SUPER and array fields remain unsupported. # EXAMPLE ```text CLASS Counter PRIVATE Value : INTEGER - PUBLIC PROCEDURE Set(Number : INTEGER) + PUBLIC PROCEDURE NEW(Number : INTEGER) this.Value <- Number ENDPROCEDURE FUNCTION Get() RETURNS INTEGER RETURN Value ENDFUNCTION ENDCLASS -DECLARE Item : Counter -Item.Set(3) +DECLARE Item : Counter(3) +Item <- NEW Counter(5) OUTPUT Item.Get() ``` diff --git a/doc/language/keyword/cpsc-keyword-declare.7.md b/doc/language/keyword/cpsc-keyword-declare.7.md index 0fd5cf3..428a934 100644 --- a/doc/language/keyword/cpsc-keyword-declare.7.md +++ b/doc/language/keyword/cpsc-keyword-declare.7.md @@ -19,6 +19,8 @@ C_INT, C_CHAR, C_STRING and C_DOUBLE are native C aliases for int, char, char* a ARRAY bounds are inclusive and may be expressions; multiple ranges create multiple dimensions. Access elements with `name[index, ...]`. Bounds are checked at run time; an invalid index throws an exception that TRY/CATCH can handle. Whole-array assignment is unsupported. Declare arrays before using them; arrays declared inside a control-flow block stay in that block. +For class variables, an optional argument list after the type supplies constructor arguments, such as `DECLARE Item : Counter(3)`. Declarations zero storage and automatically construct class fields and array elements before calling the outer constructor. See [cpsc-keyword-class(7)](cpsc-keyword-class.7.md) for construction and NEW rebinding rules. + # EXAMPLE ```text diff --git a/include/cps/MemoryHandler.h b/include/cps/MemoryHandler.h index ded838b..2768ebe 100644 --- a/include/cps/MemoryHandler.h +++ b/include/cps/MemoryHandler.h @@ -8,7 +8,7 @@ class TypeSystem; class RuntimeCheck; class ExceptionHandler; -// Only explicit memory builtins own entries in this runtime's allocation list. +// Explicit memory builtins and keyword NEW own entries in this allocation list. // Internal STRING/ARRAY storage retains its existing lifetime rules. class MemoryHandler { llvm::LLVMContext &Context; diff --git a/lib/CodeGen/ConstructorGen.cc b/lib/CodeGen/ConstructorGen.cc index f726590..99f21df 100644 --- a/lib/CodeGen/ConstructorGen.cc +++ b/lib/CodeGen/ConstructorGen.cc @@ -62,6 +62,10 @@ void CodeGen::emitAssignment(const LValueInfo &Target, ExprAST *Expr, const Symb } Value *Size = Builder->CreateIntCast(Types->getSizeOfConstant(Class->LLVMType), Type::getIntNTy(*TheContext, sizeof(std::size_t) * CHAR_BIT), false); + // Method-only classes have zero-sized LLVM structs but still need + // a non-null object address (MALLOC(0) deliberately returns null). + Size = Builder->CreateSelect(Builder->CreateICmpEQ(Size, ConstantInt::get(Size->getType(), 0)), + ConstantInt::get(Size->getType(), 1), Size); Value *Object = Memory->emitAllocate(Size, New->getLine()); Builder->CreateStore(Types->getZeroValue(Class->Name), Object); if (!emitConstruct(Class->Name, Object, New->getArgs(), New->getLine())) return; diff --git a/plugin/syntaxes/cie-pseudocode.tmLanguage.json b/plugin/syntaxes/cie-pseudocode.tmLanguage.json index 191eec2..6cdd586 100644 --- a/plugin/syntaxes/cie-pseudocode.tmLanguage.json +++ b/plugin/syntaxes/cie-pseudocode.tmLanguage.json @@ -21,7 +21,7 @@ "name": "keyword.control.throw.cpp" }, { - "match": "(?<!\\w)(?:IF|THEN|ELSE|ENDIF|WHILE|DO|ENDWHILE|REPEAT|UNTIL|FOR|TO|STEP|NEXT|RETURN|CALL)(?!\\w)", + "match": "(?<!\\w)(?:IF|THEN|ELSE|ENDIF|WHILE|DO|ENDWHILE|REPEAT|UNTIL|FOR|TO|STEP|NEXT|RETURN|CALL|NEW)(?!\\w)", "name": "keyword.control.cie-pseudocode" }, { diff --git a/tests/i/class-heap-new/expected.txt b/tests/i/class-heap-new/expected.txt index 37e731a..27bf128 100644 --- a/tests/i/class-heap-new/expected.txt +++ b/tests/i/class-heap-new/expected.txt @@ -14,3 +14,12 @@ declare caught new caught loop:1 loop:1 +failed rebind:71,71 +nested heap:80,1 +first +second +outer +first +second +outer +method only:99 diff --git a/tests/i/class-heap-new/notes.md b/tests/i/class-heap-new/notes.md index 3a6435c..a395599 100644 --- a/tests/i/class-heap-new/notes.md +++ b/tests/i/class-heap-new/notes.md @@ -3,3 +3,7 @@ Human review: pending. Expected output was independently traced by AI. Project semantics extend guide section 10.2. Each Box constructor sets Value to 1. Rebinding A preserves the old stack object's 7 while the new object becomes 9. Ordinary A <- B copies 4 into the current heap object, leaving B and the old stack object independent. BYVAL copies 4, then independently rebinds and changes its local object to 20. BYREF NEW copies 1 into A's current object, observed through CurrentA. Replacing this likewise copies into that same object; explicit Reset calls the ordinary constructor method. Array-element, field, bare field alias and pointer-dereference NEW assignments preserve their destination addresses and copy 1. Named's argument is 42. Failing throws in both DECLARE and heap construction, reaching the surrounding catches. Loop DECLARE restores its original stack object and constructs it on every iteration, so the previous heap object's 99 is never printed. + +Fragile's failed constructor leaves Stable bound to its original object, whose Value remains 71 through both names. Heap construction of Holder constructs its Box field as 1 while the old Holder's field remains 80 through Field. Ordered prints first, second, outer for stack and heap construction, proving field declaration order before the enclosing constructor. PrivateFactory's unused Build method checks that same-class access permits private automatic and explicit construction. + +A method-only Marker class has no fields, but heap NEW must still provide a non-null object address so a pointer receiver can call Get and print 99. diff --git a/tests/i/class-heap-new/program.cps b/tests/i/class-heap-new/program.cps index 7b8363f..aff248a 100644 --- a/tests/i/class-heap-new/program.cps +++ b/tests/i/class-heap-new/program.cps @@ -98,3 +98,68 @@ FOR Index <- 1 TO 2 Local <- NEW Box Local.Value <- 99 NEXT Index +CLASS Fragile + Value : INTEGER + PROCEDURE NEW(Fail : BOOLEAN) + Value <- 70 + IF Fail THEN + THROW + ENDIF + ENDPROCEDURE +ENDCLASS +TYPE FragilePointer = ^Fragile +DECLARE Stable : Fragile(FALSE) +DECLARE Original : FragilePointer +Original <- ^Stable +Stable.Value <- 71 +TRY + Stable <- NEW Fragile(TRUE) +CATCH + OUTPUT "failed rebind:", Stable.Value, ",", Original^.Value +ENDTRY +H.Item.Value <- 80 +H <- NEW Holder() +OUTPUT "nested heap:", Field^.Value, ",", H.Item.Value +CLASS OrderedFirst + PROCEDURE NEW() + OUTPUT "first" + ENDPROCEDURE +ENDCLASS +CLASS OrderedSecond + PROCEDURE NEW() + OUTPUT "second" + ENDPROCEDURE +ENDCLASS +CLASS Ordered + First : OrderedFirst + Second : OrderedSecond + PROCEDURE NEW() + OUTPUT "outer" + ENDPROCEDURE +ENDCLASS +DECLARE Order : Ordered +Order <- NEW Ordered +CLASS PrivateFactory + Value : INTEGER + PRIVATE PROCEDURE NEW() + Value <- 1 + ENDPROCEDURE + PROCEDURE Build() + DECLARE Local : PrivateFactory + Local <- NEW PrivateFactory + Local.NEW() + ENDPROCEDURE +ENDCLASS +CLASS Marker + PROCEDURE NEW() + ENDPROCEDURE + FUNCTION Get() RETURNS INTEGER + RETURN 99 + ENDFUNCTION +ENDCLASS +TYPE MarkerPointer = ^Marker +DECLARE M : Marker +DECLARE MarkerAddress : MarkerPointer +M <- NEW Marker +MarkerAddress <- ^M +OUTPUT "method only:", MarkerAddress^.Get() diff --git a/tests/iii/class-constructor-array-args-error/case.json b/tests/iii/class-constructor-array-args-error/case.json new file mode 100644 index 0000000..6677de3 --- /dev/null +++ b/tests/iii/class-constructor-array-args-error/case.json @@ -0,0 +1,8 @@ +{ + "errors": [ + { + "reason": "Unexpected token", + "line": 5 + } + ] +} diff --git a/tests/iii/class-constructor-array-args-error/program.cps b/tests/iii/class-constructor-array-args-error/program.cps new file mode 100644 index 0000000..d3c7369 --- /dev/null +++ b/tests/iii/class-constructor-array-args-error/program.cps @@ -0,0 +1,5 @@ +CLASS Box + PROCEDURE NEW(Number : INTEGER) + ENDPROCEDURE +ENDCLASS +DECLARE Items : ARRAY[1:2] OF Box(1) diff --git a/tests/iii/class-constructor-duplicate-error/case.json b/tests/iii/class-constructor-duplicate-error/case.json new file mode 100644 index 0000000..f26c170 --- /dev/null +++ b/tests/iii/class-constructor-duplicate-error/case.json @@ -0,0 +1,8 @@ +{ + "errors": [ + { + "reason": "Duplicate member new in class Box", + "line": 4 + } + ] +} diff --git a/tests/iii/class-constructor-duplicate-error/program.cps b/tests/iii/class-constructor-duplicate-error/program.cps new file mode 100644 index 0000000..0782c5e --- /dev/null +++ b/tests/iii/class-constructor-duplicate-error/program.cps @@ -0,0 +1,6 @@ +CLASS Box + PROCEDURE NEW() + ENDPROCEDURE + PROCEDURE new(Number : INTEGER) + ENDPROCEDURE +ENDCLASS diff --git a/tests/iii/class-constructor-expression-error/case.json b/tests/iii/class-constructor-expression-error/case.json new file mode 100644 index 0000000..3055433 --- /dev/null +++ b/tests/iii/class-constructor-expression-error/case.json @@ -0,0 +1,8 @@ +{ + "errors": [ + { + "reason": "NEW is only allowed on the right of an assignment", + "line": 4 + } + ] +} diff --git a/tests/iii/class-constructor-expression-error/program.cps b/tests/iii/class-constructor-expression-error/program.cps new file mode 100644 index 0000000..67addd5 --- /dev/null +++ b/tests/iii/class-constructor-expression-error/program.cps @@ -0,0 +1,4 @@ +CLASS Box + Value : INTEGER +ENDCLASS +OUTPUT NEW Box() diff --git a/tests/iii/class-constructor-function-error/case.json b/tests/iii/class-constructor-function-error/case.json new file mode 100644 index 0000000..f654a51 --- /dev/null +++ b/tests/iii/class-constructor-function-error/case.json @@ -0,0 +1,8 @@ +{ + "errors": [ + { + "reason": "constructor NEW must be a PROCEDURE", + "line": 2 + } + ] +} diff --git a/tests/iii/class-constructor-function-error/program.cps b/tests/iii/class-constructor-function-error/program.cps new file mode 100644 index 0000000..1daa9fe --- /dev/null +++ b/tests/iii/class-constructor-function-error/program.cps @@ -0,0 +1,5 @@ +CLASS Box + FUNCTION NEW() RETURNS INTEGER + RETURN 1 + ENDFUNCTION +ENDCLASS diff --git a/tests/iii/class-constructor-global-error/case.json b/tests/iii/class-constructor-global-error/case.json new file mode 100644 index 0000000..818dfca --- /dev/null +++ b/tests/iii/class-constructor-global-error/case.json @@ -0,0 +1,8 @@ +{ + "errors": [ + { + "reason": "constructor NEW is only allowed in a CLASS", + "line": 1 + } + ] +} diff --git a/tests/iii/class-constructor-global-error/program.cps b/tests/iii/class-constructor-global-error/program.cps new file mode 100644 index 0000000..4ba097a --- /dev/null +++ b/tests/iii/class-constructor-global-error/program.cps @@ -0,0 +1,2 @@ +PROCEDURE NEW() +ENDPROCEDURE diff --git a/tests/iii/class-constructor-nested-new-error/case.json b/tests/iii/class-constructor-nested-new-error/case.json new file mode 100644 index 0000000..414816c --- /dev/null +++ b/tests/iii/class-constructor-nested-new-error/case.json @@ -0,0 +1,8 @@ +{ + "errors": [ + { + "reason": "NEW is only allowed on the right of an assignment", + "line": 5 + } + ] +} diff --git a/tests/iii/class-constructor-nested-new-error/program.cps b/tests/iii/class-constructor-nested-new-error/program.cps new file mode 100644 index 0000000..b0bd349 --- /dev/null +++ b/tests/iii/class-constructor-nested-new-error/program.cps @@ -0,0 +1,5 @@ +CLASS Box + PROCEDURE NEW(Other : Box) + ENDPROCEDURE +ENDCLASS +DECLARE Item : Box(NEW Box) diff --git a/tests/iii/class-new-errors/case.json b/tests/iii/class-new-errors/case.json index 8ce52ed..7f33ffd 100644 --- a/tests/iii/class-new-errors/case.json +++ b/tests/iii/class-new-errors/case.json @@ -27,6 +27,18 @@ { "reason": "NEW target must have type Hidden", "line": 26 + }, + { + "reason": "Cannot access private method NEW of type Hidden", + "line": 28 + }, + { + "reason": "has no constructor NEW", + "line": 30 + }, + { + "reason": "Cannot coerce value of LLVM type to target type INTEGER", + "line": 31 } ] } diff --git a/tests/iii/class-new-errors/program.cps b/tests/iii/class-new-errors/program.cps index 3a9e9c2..78db102 100644 --- a/tests/iii/class-new-errors/program.cps +++ b/tests/iii/class-new-errors/program.cps @@ -24,3 +24,8 @@ B <- NEW Box(1) R <- NEW Required R <- NEW Required() B <- NEW Hidden +PROCEDURE Forbidden(Target : Hidden) + Target <- NEW Hidden() +ENDPROCEDURE +B <- NEW Box("bad") +R <- NEW Required("bad") |
