Commit Graph

994 Commits

Author SHA1 Message Date
Tristan B. Velloza Kildaire f0b4e62370 Dependency
- Cleaned up
2023-08-16 10:42:07 +02:00
Tristan B. Velloza Kildaire 57a69423dd Dependency
- Refactored code
2023-08-16 10:39:11 +02:00
Tristan B. Velloza Kildaire ac22faa8ed Dependency
- Cleaned up some more
2023-08-16 10:31:35 +02:00
Tristan B. Velloza Kildaire 7735c672cb Dependency
- Removed no-op branch
2023-08-16 10:30:10 +02:00
Tristan B. Velloza Kildaire 30108d2b0b Dependency
- No need to set it here if set above
2023-08-16 10:29:33 +02:00
Tristan B. Velloza Kildaire 15af484586 Revert "Dependency"
This reverts commit 5ddab9dd3d.
2023-08-16 10:28:40 +02:00
Tristan B. Velloza Kildaire 5ddab9dd3d Dependency
- Checking iets (fr)
2023-08-16 10:28:10 +02:00
Tristan B. Velloza Kildaire 2975f0c770 Dependency
- Undid checking-iets
2023-08-16 10:26:04 +02:00
Tristan B. Velloza Kildaire 8b7ce12a9b Dependency
- Checking iets
2023-08-16 10:25:48 +02:00
Tristan B. Velloza Kildaire d083c618ff Dependency
- Removed path-hopper code
2023-08-16 10:20:23 +02:00
Tristan B. Velloza Kildaire 9fb397a947 Dependency
- Don't fetch-and-set context for `bruh` (the entity being referenced)
2023-08-16 10:18:30 +02:00
Tristan B. Velloza Kildaire 084df3fb32 Dependency
- Cleaned up some more, added link to issue regarding context sets
2023-08-16 10:16:36 +02:00
Tristan B. Velloza Kildaire d838d88542 Dependency
- Avoid path hopping by making this beanch constantly `true`
2023-08-16 10:13:16 +02:00
Tristan B. Velloza Kildaire cf27320630 Dependency
- Added some comments
2023-08-16 10:10:13 +02:00
Tristan B. Velloza Kildaire 1b4780d95a Dependency
- Removed crap for `VariableExpression` dependency node generation
- This is a work-in-progress clean up
2023-08-16 10:04:57 +02:00
Tristan B. Velloza Kildaire 3d9bf28f3b Merge branch 'vardec_varass_dependency' of github.com:tbklang/tlang into vardec_varass_dependency 2023-08-14 22:30:26 +02:00
Tristan B. Velloza Kildaire 5e4049ffee
Hotfix/jcli upgrade fix (#25)
* Dub

- Upgraded `jcli` to version `0.25.0-beta.2`

* Dub

- Upgtraded package `jcli` to version `0.25.0-beta.3`

* - Try using latest version of `dmd`
2023-08-14 22:29:52 +02:00
Tristan B. Velloza Kildaire ef29cf018d - Try using latest version of `dmd` 2023-08-14 22:21:46 +02:00
Tristan B. Velloza Kildaire 330d0a2d96 Dub
- Upgtraded package `jcli` to version `0.25.0-beta.3`
2023-08-14 22:12:28 +02:00
Tristan B. Velloza Kildaire e2d54f1cb1 Dub
- Upgraded `jcli` to version `0.25.0-beta.2`
2023-08-10 22:55:44 +02:00
Tristan B. Velloza Kildaire b47a651caf
🧠️ Feature: Universal coercion and type enforcer (#9)
* TypeChecker

- Added `bool isSameType2(Value v1, Value v2, bool attemptCoercion = false)` for future implementation of universal coercion as per #115

* TypeChecker

- Renamed `isSameType2` to `typeEnforce`
- Updated `typeEnforce`'s default parameter documentation from `false` to `attemptCoercion` (as it should have been in the beginning)

* TypeCheckerException

- Save the `TypecheckError` coming in as `errType` and make it available via `getError()`

TypemMismatchException

- Save the original (expected) and attempted types and make them available via `getExpectedType()` and `getATtemptedType()` respectively

* TypeChecker

- Updated `typeEnforce` from taking in `Value v1, Value v2, bool` to `Type t1, Value v2, bool`.
- `typeEnforce()` will now extract the `Type` of `Value v2` and call `isSameType(t1, t2)`, if that fails and coercion is allowed then it is attempted, however if that fails then it causes an exception to be thrown. In the case coercion is not allowed, then a `TypeMismatchException` is thrown

Unit tests

- Tested the new `typeEnforce(Type t1, Value v2, bool)` and it seems to work, both a case of failing matching (coercion disallowed) and working coercion (coercion allowed)

* TypeChecker

- Documented existing unittest for `typeEnforce(Type, Value, bool)`
- Added new unit test for `typeEnforce(Type, Value, bool)` which tests when the types ARE the same

* TypeChecker

- Cleaned up `typeEnforce(Type, Value, bool)`

* TypeChecker

- Added a work-in-progress unit test to test how I would use `typeEnforce(Type t1, Value v2, bool coercion = false)` in practice
- Added TODOs in `attemptCoercion(Type, Type)` where I must add support

* TypeChecker

- Finished the unit test testing out the usage for `typeEnforce(Type, Value, bool coerce = false)`
- Added TODOs to `attemptCoercion(Type, Value)` for the changes required to it

* TypeChecker

- Removed incorrect TODOs from `attemptCoerce(Type, Value)` and updated the message when the coercion fails

Unit tests

- Updated first unit test for `typeEnforce()` to test failing coercion on a non-`LiteralValue` instruction
- Added a unit test where `typeEnforce()` WILL pass as it coerces a `LiteralValue` instruction

* Exceptions (`typechecker`)

- Added new exception type `CoercionException` to be thrown whenever a coercion cannot take place.

* TypeChecker

- Ensure that `attemptCoercion(Type, Value)` only throws instances of `CoercionException`

* Unit tests

- Fixed failing-coercion check by catching the correct exception when it fails `CoercionException` instead of `TypeMismatchException`)

* TypeChecker

- Added documentation for `isSameType(Type t1, Type t2)`

* TypeChecker

- Updated documentation for `isCoercibleRange(Type, Value)`
- Updated `attemptCoercion(Type, Value)` with new documentation and renamed parameters

* Unit tests (typechecker)

- Added comments

* TypeChecker

- Removed now-completed TODO in `typeEnforce(Type t1, Value v2, bool allowCoercion = false)`

* TypeChecker

- Removed unused `typeStatus` variable in `typeEnforce(Type, Value, bool)`

* TypeChecker

- Variable declarations (with assignments) now use the `typeEnforce()` method with coercion allowed in order to do the type checking and coercion changes
- Added a comment explaining a certain branch of `attemptCoercion(Type, Value)`

* TypeChecker

- If the to-type and provided-type are both numerical then use a size-based test

Test cases

- Added two test cases which test `typeEnforce()` on incoming `Value`-based instructions as part of variable declarations

* Test cases

- Fixed negative test case - it MUST have an error and that should be seen as a pass

* TypeChecker (unit tests)

- Disabled invalid unit test (marked for re-writing)
- I should re-write the below. It is now incorrect as I DO ALLOW coercion of non literal-based instructions now - so it fails because it is using an older specification of TLang

* TypeChecker

- Migrated the type checking of standalone variable assignments to using `typeEnforce()`

Test cases

- Added positive and negative test cases

* - Updated `.gitignore`

* Feature/type enforcer cast instr emit (#13)

* TypeChecker

- `typeEnforce()` now will not change the type of `Value`-based instruction `v2` but rather return, on successful coercion set a `ref`-based argument to a new instance of a `CastedValueInstruction`, if coercion fails or was disabled and types mismatched then an exeption is thrown as normal.
- If the types are an exact same match, a-la `isSameType(Type, Type)`, then this `ref` value is set to `v2` (makes programming easy) else we would have no way to know
- `attemptCoerce()` now, to go with the above changes to `typeEnforce()`, returns a `CatsedValueInstruction` to the to-type on successful coercion, else an exception is thrown as usual
- Updated two cases of `typeEnforce()` usage to the new method signature, also now add a sanity check assertion that the types now DO match as they should

* TypeChecker

- We need not set it again, look the value we use when we CALL `typeEnforce()` is that of the `fromInstruction` and if no changes occur we still have it, it is fine - if it changes via the call to `typeEnforce()` via the `ref` based argument thne same old
- No need for us to set it here in the event of no changes, we are writing back the exact same Instruction/object-reference

* TypeChecker (unit tests)

- Upgraded to the new `typeEnforcer()` method signature

* TypeChecker

- Improved documentation for `typeEnforce()`

* TypeChecker

- Added TODO regarding pointer coercion with integers in `Pointer + Integer` case (for pointer airthmetic)

* TypeChecker

- Added a new branch which currently throws an exception as it is unimplememted
- This branch (above) is in `attemptCoercion()` and is to handle the coercion of `Integer` to `Pointer` for pointer arithmetic
- When doing the typechecking/codegen for `BinaryOp`, disable the pointer coercion call to `attemptPointerAriehmeticCoercion()`, instead now make calls in those cases they apply, to `typeEnforce()`

- The above stuff is still broken, not yet implemented.

* TypeChecker

- Cannot use cast as that can return false positives for an all pointer case as all `Pointer`s are `Integer`s
- Added `isPointerType(Type)` to check the above
- Added then also `isIntegralTypeButNotPointer(Type)` which checks for an `Integer` type but excluding if it is a `Pointer`
- Updated the checks in the `BinaryOperator` branch of `typeCheckThing(DNode)` to do this

* TypeChecker

- Need to do the `Pointer` checks first in `attemptCoercion(Type, Value)`

* TypeChecker

- `attemptCoercion(Type, Value)` now returns a `CastedValueInstruction` to cast the `Integer` type to the `Pointer` type

* TypeCHecker

- Catch mis use of type enforcement by using `isIntegralTypeButNotPointer(Type)` and isPointerType`(Type)` for the previous commit

* TypeChecker

- Refresh the types after the potential calls to `typeEnforce(..., ..., ..., ...)`

* Pipeline

- Use `set -e` for `simple_pointer.t` test in emit stage

* Pipelines (emit stage)

- Previous compilation may have succeeded, meaning ./tlang.out never gets updated and exits fine with 0, but we only use the last commands exit status to check for a pass for a test.
- By setting this if COMPILATION fails then we exit with its code and the test status is set via that

* Pipelines

- Removed the `set -e` code as the correct `Exception` now causes a non-zero exit code from the changes made in `varass_vardec_dependency`

* DGen

- Added notice for issue #140

* TypeChecker

- Made `isIntegralTypeButNotPointer(Type)` public
- Made `isPointerType(Type)` public

* Instructions

- `CastedValueInstruction` now is unrelaxed by default but can be set (tis aids in how it can be emitted later for issue #140)

* DGen

- Added some checks for certain conditions whereby pointer coercion requires relaxing the casted operands (coerced operands)

* DGen

- Relax `CastedValueInstruction`(s) when appropriate in `BinaryOpInstr` handling code
- Removed panics

* DGen

- Added relaxation support to the code emitting code for `CastedValueInstruction`

* DGen

- make debug messages for when relaxation occurs for `CastedValueInstruction` emitting more clear

* TypeChecker

- Implemented `biggerOfTheTwo(Integer, Integer)` which determines the biggest of the two `Integer`-based types and returns that one.

* TypeChecker

- Fixed incorrect variable name in `biggerOfTheTwo(Integer, Integer)`

* TypeChecker

- Throw an error in the case where a `BinaryOperatorExpression` occurs with non-`Integer`-based instructions (at least for now)

* TypeChecker

- If both types are `Integral` (but not `Pointer`) then smaller coerces to bigger, if they however are equal then signed coerces to unsigned

* TypeChecker

- Removed now irrelevant comment

* TypeChecker

- Don't throw exception here, rather let the `isSameType(Type, Type)` check handle that
- We still keep the warning we print about missing cases implementation-wise

* TypeChecker

- Fixed explanation

* TypeChecker

- Marked related issue

* TypeChecker

- Implemented ` isStackArrayType(Type typeIn)`
- WIP: Added a check for handling `StackArray -> Pointer` coercion to `attemptCoercion(Type, Value)`

* TypeChecker

- `attemptCoercion(Type, Value)` will now ensure firstly that the `StackArray`'s component type matches that of the `Pointer`'s referred type, if not throw an exception, if so, then return a `CastedValueInstruction`

* TypeChecker

- Print out a debug message when attempting to coerce a `StackArray` to a `Pointer`
- Fixed the error message thrown when a `StackArray` could not be coerced to a `Pointer` due to the component type != ptr's referred type
- `FunctionCall` handling now has the `canCoerceStackArray()` code disabled and uses the `typeEnforce()` method

* TypeChecker

- Type checking code for `FunctionCall`

* TypeCheck

- Completed TODO comment

* TypeChecker

- Added a TODO

* TypeChecker

- Added FIXME where the `typeEnforce()` call need to be made for the `ReturnStmt`'s return expression's type to match or be checked-against the containing `Function`'s

* TypeChecker

- `ReturnStmt` now uses `typeEnforce()`

* Test cases

- Added two new checks for checking the return type of a function and matching a `ReturnStmt`'s expression's type to it

* TypeChecker

- Removed assertion check, rather let the exception thrown handle the error
- Only after we know the finally-parenting `Container` is a `Function` (should we reference `funcContainer`

* Test cases

- Removed explicit cast from `simple_function_recursion_factorial.t`

* TypeChecker

- If we have a `LiteralValue` and a non-`LiteralValue` then coerce the `LiteralValue` towards the non`-LiteralValue` via `typeEnforce()`
- This should allow the correct range checking of literal values within the range of the to-type and not require annoying explicit casts

* Test cases

- Removed now-unneeded explicit casts on literal values in `simple_function_recursion_factorial.t`

* TypeChecker

- Added comment describing the process used
- Removed now-completed TODO

* TypeChecker

- Removed some dead code
- Removed now-completed FIXME/TODO

* TypeChecker

- Removed old type checking code for variable declarations with assignments
- Removed old type checking code for standalone variable assignments
2023-08-10 19:42:11 +02:00
Tristan B. Velloza Kildaire 239832a74a Variable
- When calling `replace(Statement, Statement)`, if we hit the `variableAssignment` replacement check, first check and ensure it is not null`, try
2023-07-26 16:19:49 +02:00
Tristan B. Velloza Kildaire 220e4789c4 DGen
- Added ability to flag whether symbol mapping should occur or not
- By default enable symbol mapping
2023-07-22 18:12:16 +02:00
Tristan B. Velloza Kildaire 5833f9af67 Revert "CodeEmitter"
This reverts commit 75372ee132.
2023-07-22 12:55:26 +02:00
Tristan B. Velloza Kildaire 75372ee132 CodeEmitter
- Added a new parameter to `transform(Instruction)` (now `transform(Instruction, Object)`. `customRules` is an `Object` to be interpreted by the underlying emitter which can change how certain transformations are done when it is in a certain state

DGen

- Uses new `CodeEmitter` API
2023-07-22 00:30:32 +02:00
Tristan B. Velloza Kildaire 4e8fb0a801 TypeCheck
- Undo incorrect FIXME
2023-07-17 23:25:53 +02:00
Tristan B. Velloza Kildaire 6165d5dc6f TypeChecker
- Added a TODO regarding the `ClassStaticNode` handling
2023-07-17 22:53:46 +02:00
Tristan B. Velloza Kildaire 32056803d4 Containers
- Fixed `clone(Container)` implementation for `Struct` whereby it would not parent the newly created copy
2023-07-17 17:07:35 +02:00
Tristan B. Velloza Kildaire 9b55b3dec4 Containers
- `Struct`'s `MCloenable` API adhered to
2023-07-17 17:01:10 +02:00
Tristan B. Velloza Kildaire b09aa3add0 Data
- `Variable` and `VariableAssignment` now uses the new `MCloneable` API
2023-07-17 17:00:34 +02:00
Tristan B. Velloza Kildaire a4bd462d14 Expressions
- Added notes about where parenting must manually be done
2023-07-17 16:57:42 +02:00
Tristan B. Velloza Kildaire 7acb8e6308 Expressions
- `BinaryOperatorExpression`, `CastedExpression` and `IntegerLiteral`  now implements the new `MCloneable` API
2023-07-17 16:56:10 +02:00
Tristan B. Velloza Kildaire 254c5ee6b9 Mcro
- Made `MCloneable`'s `clone()` require a `Container` argument of which the final cloned `Statement` must parent-itself to
2023-07-17 16:51:22 +02:00
Tristan B. Velloza Kildaire 921235ab22 DGen
- If `typeTransform(Type)` is called on an unknown type then print out the type in the error message asx well
2023-07-17 16:35:32 +02:00
Tristan B. Velloza Kildaire a42ec98625 DGen
- If `typeTransform(Type)` fails then the debug text should be in the error coloring
2023-07-17 16:31:49 +02:00
Tristan B. Velloza Kildaire 8a11eabd96
🧠 Feature/Meta: Cloneable (round 1) (#21)
* Data

- Moved AST manipulation imports to the top
- Made `VariableAssignment` cloneable
- Made `Variable` cloneable

* Data

- When trying to `clone()` an `Expression`, do a runtime type check to check if we can (else `null` is used)

* Expressions

- Moved AST-manipulation related import to the top

* Expressions

- `BinaryOperatorExpression` now overrides `clone()` from `MCloneable`

* Expressions

- `IntegerLiteral` now implements `MCloneable`

* Expressions

- `CastedExpression` now implements `clone()` for `MCloneable`

* Containers

- Moved all AST maniuplation-related imports to the top

* Containers

- Made `Struct` support `MCloneable`'s `clone()` method

* Data

- Only clone the `VariableAssignment` if the `Variable` has one

* Containers (unit test)

- Added test which tests the `clone()` on a `Struct`
2023-07-17 16:16:18 +02:00
Tristan B. Velloza Kildaire f1aaaf1088 Expressions
- Made the `Expression` class abstract
- Removed irrelevant TODOs and method
- Removed uneeded constructor

VariableExpression

- Removed unused junk
2023-07-17 15:01:46 +02:00
Tristan B. Velloza Kildaire 2411969955 Data
- Removed unused type `ArgumentList`
2023-07-17 14:41:18 +02:00
Tristan B. Velloza Kildaire 4cae2bb6ce Parser
- Removed now-completed TODO
2023-07-17 10:55:32 +02:00
Tristan B. Velloza Kildaire 0b3a06efde
🐞 Bugfix: expect(string) should throw ParserException atleast (#20)
* Parser

- Removed commented-out code

* Parser

- Removed `isUnitTest` variable and how `expect(string)` relies on it

* Parser

- Now throw a new `ParserException` instead of a `TError` when calling `expect(string)`

* Parser

- Made `expect(string)` not static

* TypeChecker

- Implemented `expect(string)` which throws a `TypeCheckerException` in a similar fashion to `Parser`'s `expect(string)`

* Dependency

- Implemented `expect(string)` which throws a `DependencyException` in a similar fashion to `Parser`'s `expect(string)`

Exceptions (dependency)

- Added enum member `GENERAL_ERROR` to `DependencyError`

* Parser (unit tests)

- Made more specific
2023-07-16 20:33:51 +02:00
Tristan B. Velloza Kildaire fa9399b90d Test cases
- Fixed `simple_function_decls.t` to include the required (but missing) `return` statement
2023-07-16 19:58:40 +02:00
Tristan B. Velloza Kildaire b18efdc76c Tets cases
- Added missing `return` to function `banana` in `simple_functions.t` test case
2023-07-16 19:54:47 +02:00
Tristan B. Velloza Kildaire 352eada94a Parser (unit tests)
- Because this causes `expect(string)` to be called (this unit test) we must catch `TError` as that is what `expect(string)` throws
- We should update this (see #147)
2023-07-16 19:49:13 +02:00
Tristan B. Velloza Kildaire a1443c4c48 Parser (unit tests)
- Updated unit test which was meant to check for a greater number of body statements of the `Function` at question
2023-07-16 19:43:44 +02:00
Tristan B. Velloza Kildaire f8bfd27ece
🐞 Bugfix: Recursively check for return statemen tprescence (#19)
* Parsing

- Added a TODO for where the fix needs to be

* Parser

- Implemented `findOfType(TypeInfo_Class statementType, Container from)` which given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. it will return an array of `Statement` (`Statement[]`) of the matches.
- Implemented `existsWithin(TypeInfo_Class statementType, Container from)` given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. It will return `true` if any matches are found.
- We now will recursively explore the `Function`'s body statements in search of a `ReturnStmt`
2023-07-16 19:21:09 +02:00
Tristan B. Velloza Kildaire ddedc0d806
🐞 Bugfix: Ensure that typed functions contain a return statement (#17)
* Parser

- Added TODO for checking for non-`void` function's return statements

* Parser

- If a `ReturnStmt` is not found after calling `parseFuncDef()`

* Parser

- Added a FIXME comment that needs to be completed soon

* Parser

- Only check that a `ReturnStmt` is present in a function definition when `wantsBody` is true ELSE we'd expect it for `efunc` `extern`'d statements
- Fixed a unit test which had a missing `return <expr>`
- Added a unit test which tests for a function definition with a body with a non-void return type that it DOES fail
- Removed two now-completed TODOs and FIXMEs

Test cases

- Fixed test case in `typecheck/simple_function_call.t` to now include the required `return <expr>` statements
2023-07-16 18:22:56 +02:00
Tristan B. Velloza Kildaire 4c99b56677 TypeChecker
- Fixed the `Function` `Container` resolution for the `ReturnStmt` to now find the nearest `parent` in its parenthood tree which is a `Function`, extract the `Function`'s name and then use that where needed
2023-07-12 09:55:59 +02:00
Tristan B. Velloza Kildaire 3e101ac5f8 Resolution
- Implemented `findContainerOfType(TypeInfo_Class, Statement)` which, given a type-of `Container` and a starting `Statement` (AST node) this will swim upwards to try and find the first matching parent of which is of the given type (exactly, not kind-of).
2023-07-12 09:55:14 +02:00
Tristan B. Velloza Kildaire c0920f2fdb
🐞️ Functions: Expressionless return and enforcing requirement (#7)
* Parser

- Added a TODO in `parseReturn()` for issue #113

* Data

- The `ReturnStmt` now has a default constructor which is for cases where one doesn't want to provide an expression (for expressionless returns)

Parser

- `parseReturn()` now supports expressionless returns

Test cases

- Added `simple_return_expressionless.t` to test expressionless return statement

* Data

- Added a method `hasReturnExpression()` to `ReturnStmt` which returns `true` if the return statement has an expression attached, `false` otherwise

* Dependency

- When processing a `ReturnStmt` only run do dependency generation for the return statement's expression IF it has one

* Instruction

- Made `ReturnInstruction` have a constructor which takes in no `Value` instruction (intended for return expression)
- Added a `hasReturnExpInstr()` to `ReturnInstruction`such that during typechecking/codegen we can check for it

* TypeChecker

- Added a TODO regarding the missing typechecking for `ReturnStmt` typechecking. Added notes on how we'd go about this.
- Fixed crash due to assuming there was always an expression on the stack that could be popped off for generating a `ReturnInstruction` (this is not the case when the return statement is expressionless)

* Tests

- Added a typecheck test for `simple_return_expressionless.t`

* TypeChecker

- Update `isSameType(Type t1, Type t2)` to check if the actual types of both `Type` objects are the same as a last resort
- Added a `NOTE` comment on how `isSameType(Type t1, Type t2)` is implemented

- Added typechecking code for `ReturnStmt` and updated the code generation with it. We now do the following:
    1. We extract the container of the `ReturnStmt` and cast it to a `Function`; if it is not a `Function` we throw an error because you cannot have a `ReturnStmt` appear in a non-`Function` container
    2. We extract the function's name relative to it container (the function's container) for use of it in error messages
    3. Next, we get the return type of the function and do the following:
        a. If the return type is `void`
            i. If the return has an expression we throw an error
            ii. If the return has NO expression we pass typechecking and generate the `ReturnInstr`
        b. If the return type is non-`void`
            i. If the return has an expression we ensure that its type matches that of the function's return type and generate the `ReturnInstr`
            ii. If the return has NO expression we raise an exception as one is expected
    4. If we pass and got here then we set the `ReturnInstr`'s context and `addInstrB(returnInstr)`

* Test cases

- Added test case `simple_return_type.t` which is here to test our return type checking

* - Updated `.gitignore`

* Parser

- Use `lexer` for all `Token`-based operations
2023-07-11 21:43:21 +02:00
Tristan B. Velloza Kildaire c31175bae7 Containers
- Removed redundant import that causes compilation failure on `ldc2`
2023-07-10 20:59:57 +02:00