* 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`
- 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
* 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
- 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)
* 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`
* 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
- 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`
- 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
- 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
- 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).
* 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
- 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
- `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`