- Fixed up calls to `getBuiltInType(...)` which now require some `Container` to pivot on. We now pass in the `Program`
- Fixed up unittests which used `getModule()`, for such uni-modular tests we just use `program.getModules()[0]` now
- When getting the type root everything on the `Program` rather than `tc.getModule()`. We therefore now use the `tc.getProgram()` in its place. This updates the `sizeOf_Literalize(string typeName)` method.
DGen
- `emit()` has been updated to enumerate all `Module[]` of the given `Program` and then calls the respecitve `emit(...)` methods with a (`File`, `Module`) which contains the file which emitting should be written to and also the `Module` being emitted.
- At the end of `emit()` we then try to find the `Module` which contains a function named `main` and then set that as the entrypoint. If such a `main` function cannot be found we then go and do a check whether or not the `dgen:emit_entrypoint_test` configuration option is `true`, if so we then try emit a testing entrypoint and assume that the tst uses only one `Module` (this is something to be cleaned up later; as in all tests should have a `main` method).
- Implemented `findEntrypoint(ref Module mainModule, ref Function mainFunc)` which does as the name implies and finds the containing `Module` which has a `Function` named `"main"` and if so sets both ref arguments and returns `true`, otherwise they are left unset and `false` is returned
- `emitHeaderComment(...)`, `emitStaticAllocations(...)`, `emitFunctionPrototypes(...)`, `emitFunctionDefinitions(...)`, `emitFunctionPrototype(...)`, `emitFunctionDefinition(...)`, `emitCodeQueue(...)`, `emitStdint(...)`, `emitEntrypoint(...)`, `emitTestingEntrypoint(...)` now takes in `File modOut` and `Module mod`
- Note the above have not YET been updated to select correct code queues, static init. queues and `emitEntrypoint(...)` has not yet been implemented
- Updated `emitTestingEntrypoint(...)` to check using the incoming `Module`'s name
- `finalize()` will now compile all sources files, then it will link all generated object files together; optionally cleaning up all but the final genersted excutable at the end
CollidingNameException
- Fixed up name generation (we now anchor on the `Program`)
- Fixed up how we detect if a module's name is in use. We now will check and ensure it doesn't match ANY of the modules contained within the `Program`
DNode
- Implemented `forceName(string)` to set the `name` field forcefully
- The `generate()` method now calls `generalPass(Module, Context)` on each of the `Program`'s `Module`s. We then get an array of `DNode[]` from them. After this we then create a root `DNode` to represent the program and then we make it `needs(DNode)` each `Module` `DNode` created previously.
DNodeGenerator
- When processing `VariableExpression` in `expressionPass(Expression exp, Context context)`, if we get a `Function` being referred to in the expression, then we now set the `Context`'s `Container` still to the `Module` containing the function's definition, _however_ we use a method from the resolver to ensure it is the correct module (because we are now using a multi-module setup).
- We have always set the **root** `Module` when entering `generalPass(Container c, Context context)` and processing a `Function` but, as with the last change mentioned above, we need to find that containing `Module` correctly. Therefore we use a method from the `Resolver` to do that.
- If called with `ScopeType.LOCAL` then the name will be generated in an absolute sense, however the module name will be stripped from the path
- For example `simple_module.a.b` would become `a.b` and then be mapped to `a_b`
- Fixed wrong variable name in `map(Entity item, ScopeType type)`
HashMapper
- Implemented `map(Entity item, ScopeType type)` for `ScopeType.GLOBAL`
- `ScopeType.LOCAL` is yet to be implemented
- Added some future code for `emit()` which will enumerate all `Module`(s) available in the current `Program` and then do an emit step per-each of them and have those go to the correct `File`(s)
- Added a comment for `finalize()` of which indicates where we should link all generated object files for all the modules. After this we should then link this against each other and generate an executable.
- Added seperate stage to _create_ the `main.o` and then only later link with the intent of making an executable.
- This is BETTER because it means we could treat everything in the same way (nevermind a `main` or library)
- Added `-c` to ONLY compile but do NOT attempt to link and make an executable. If we try this it looks for a `main` symbol to satisfy the `_start` for linux-ld
- Updated the build instructions for being able to statically link against the library
- Playing with a way to build library objects without immediately linking
- I am then also seeing how to link it to an application which `_start_` can find its `main` symbol
* Created brsnch
* Created brsnch (removed placeholder)
* Lexer
- Added tab handling for the presence such as spaces would be in.
- Added unit tests for the new tab processing
- Resolved issues where whitepsace was allowed before and or after the
'.' character
- Renamed isSpliter to isSplitter
- Some Code styling
* Check
- Added two new `SymbolType`s for comments
- `SINGLE_LINE_COMMENT` (for `//`) and `MULTI_LINE_COMMENT` (for `/*`)
* Parser
- Added a bogus `parseComment()` which returns nothing, prints out the comment, consumes the `Token` and returns
- `parseStatement()` now supports `parseComment()` whenever a single-line or multi-line comment is detected
* Parser
- Fixed token consumption code in `parseComment()`
* BasicLexer
- Fixed style mishaps
* ArrLexer
- Implemented dummy lexer
* Parser
- Added some comment related functions (for testing)
- Added `pushComment(Token)`, `hasCommentsOnStack() and `getCommentCount()`
- `parseComment()` now pushes the current comment-based `Token` onto the comment-stack
- Added a comment stack
Unit tests
- Added testing for various examples of comment-type `Token`s
* Lexer
- Replaced the characters with Enumerated type
- Working Comment lexing, single and multiline
- Working escape codes for strings
- Working Signage and Size Encoder indicators
- Removed floatMode in favour of float lexing function
- Added doComment for the comment lexing instead of comment mode
- Added doEscapeCode for escape codes in string
Testing
- Added unit tests for comments
- Added unit tests numerical encoders
- Added unit tests numerical encoders
TODO
- ADD unit tests for all valid escape sequences and some invalid
* Lexer
- Removed stringMode in favour of soString
TODO
- Decide on miltiline strings, currently not supported
* Parser
- Test comments which appear at a non-Module but rather statement lavel
* Parser
- Changed to using `BasicLexer` for comment tests now seeing as it is now implemented therein
* Basic
- Added `roll()` and `shourt()` to mark unittests
* Basic
- `shout()` now adds line number to print out
* Lexer rewrite
- flush
- underscores in numbers
- escape codes
- character escapes
- bug fixes
* Basic
- Fixed `shourt(int)`
* Basic
- Remved crashing (on purpose_ unittest
* Resolved bug where isSplitter evaluated to true every time
* Basic
- Removed `goggaWithLineInfo(...)`
* Basic
- Updated `shout()` to remove rolling
- Removed `roll()`
- Added function and module name as well
* Basic
- Documented `shout()`
* Lexer Done and 100% coverage
* LexerSymbols
- Documented
- Formatted
* Lexer (module)
- Added `LS` alias
- Added `isOperator(char c)`, `isSplitter(char c)`, `isNumericalEncoder_Size(char character)`, `isNumericalEncoder_Signage(char character)` and `isValidEscape_String(char character)`
* BasicLexer
- Documented constructor `hasToken()`, `performLex()`, `doIdentOrPath()`, `doChar()`, `doString()`, `doComment()`, `doEscapeCode()`, `doNumber()`, `doEncoder()`, `doFloat()`, `flush()`, `buildAdvance()`, `improvedAdvance()`, `advanceLine()`, `isOperator(char)`, `isSplitter(char)`, `isValidDotPrecede(char character)`, `isNumericalEncoder(char character)`, `isNumericalEncoder_Size(char character)`, `isNumericalEncoder_Signage(char character)` and `isValidEscape_String(char character)`
- Tried reformatting some of `doChar()`, `doString()`, `flush()`, `buildAdvance()`, `improvedAdvance()`, `advanceLine()`, `isOperator(char)`, `isSplitter(char)`
* Basic
- Removed `LS` alias
Lexer
- Made `LS` alias public
* BasicLexer
- Removed methods `isValidEscape_String(char character)`, `isNumericalEncoder_Signage(char character)`, `isNumericalEncoder_Size(char character)`, `isNumericalEncoder(char character)`, `isSplitter(char c)` and ` isOperator(char c)`
Lexer
- Added method `isNumericalEncoder(char character)`
* BasicLexer
- Documented `isValidDotPrecede(char character)`
* Lexer
- Added method `isValidDotPrecede(char character)`
* BasicLexer
- Removed method `isValidDotPrecede(char character)`
* BasicLexer (unittests)
- Documented the unittests
- Fixed formatting
* BasicLexer
- Typo fixes
* BasicLexer (unittests)
- Only compile-in `shourt(...)` when in unittest build mode
* BasicLexer
- Documented `isForward()` and `isBackward()`
- Made `isBackward()` private
---------
Co-authored-by: GMeyer <21568499@sun.ac.za>
Co-authored-by: GMeyer <gustav.meyer1999@gmail.com>
- `getType(Container c, string typeString)` always checks for built in types first and then if one
of such is found it then immediately returns, else does a search. We have now updated that inner
call to `getBuiltInType(TypeChecker, string)` to use the new API which is `getBuiltInType(TypeChecker, Container, string)`
- When processing a `ReturnStmt` and we need to check the return type of the `Function` it is contained within
and the type of its returned `Expression`, we need not call `getBuiltInType(TypeChecker, Containert, string)`, let's
just call `getType(Container, string)` as it does that call for us in any case
- With the above I also anchor it to search for the type based on the `funcContainer` `Container` as that is at the same level as the `ReturnStmt` itself
- Updates for `parentToContainer(Container, Statement[])`:
* We now have a default argument called `allowRecursivePainting` which is set to `true`
by default
* What this does is handle special cases of `Statement`s which are not placed within
a `Container` and therefore can not be reached in a generic way (i.e. `getStatements()` with `Container`
types)
* These special cases are:
1. `Variable`
* Declarations may have a `VariableAssignment` attached to them which has an `Expression`
2. `BinaryOperatorExpression`
* Left and right-hand side operands have `Expression`'s attached to them
3. `VariableAssignmentStdAlone`
* The assignment `Expression`
4. `ReturnStmt`
* It may have an `Expression` in it
5. `FunctionCall`
* We need to process each of its actual arguments, which comes in the form of a `Expression[]`
6. `DiscardStatement`
* This is like a `ReturnStmt` but it always has an `Expression`, therefore we must process it
7. `IfStatement`
* Contains an array of `Branch` (i.e. a `Branch[]`)
8. `WhileLoop`
* Contains a singular `Branch`
9. `ForLoop`
* Contains a singular `Branch`
10. `Branch`
* Contains a condition in the form of an `Expression` and a set of body statements
in the form of a `Statement[]` array
* What we then do for 1-6 (so-called normal cases):
* These we will recurse upon and parent them to the same `Container` that came in in
the original call which was what got us to enter into the cases of 1 to 6.
* What we then do for 7 onwrads (so-called "maintain" cases):
* Notice that each type mentioned in these are all a kind-of `Container`
* We therefore call `parentToContainer(Container, Statement)` not with the incoming
`Container` that came into the call that macthed to one of these cases but
rather to that of this case's container itself
* We do this because we want the scoping to be consistent and that is done by keeping
the ancestry tree as it is expected when multiple calls are done for parenting, for example,
the body `Statement[]` items to their respective `Branch` and then those `Branch[]` to their
`IfStatement`.
* "I said there would be special cases ;)"
Parser (unittests)
- Fixed unittests such that they run by using the `Compiler` object now
- Calling `getModule()` will now return the first `Module` in the `Program`'s list of modules
- Marked `getModule()` for removal
- The constructor now constructs a `Resolver` instance by also passing in the `TypeChecker` itself
- We have updated `dependencyCheck()` to call `checkDefinitionTypes()` on each `Module` of the current `Program`
- We have updated `dependencyCheck()` to call `checkClassInherit()` on each `Module` of the current `Program`
- When handling a `VariableExpression` we look up the `Variable` it referes to, then we must generate a name for it
rooted by its module, we now do this by anchoring at the `this.program` rather than the `modulle`
(what the deprecated `getModule()` would return), this would use the updated `Resolver` code to generate
the name we expect as with the implementation that came before
- When handling a `FunctionCall` we lookup the `Function` it refers to, then we must ask the resolver
to resolve the `Function` by its name using `resolveBest(Container, string)` and this should be best-effort
starting at the `Module` of which the `FunctionCall` is present in. If it happens to be that the `Module`
of the `Function` referred to is outside the provided starting anchor then it will be handled for us, that
is undert the assumption it is `otherModule.myFunc()` being called and present in `otherModule`, compared to
the first case of having `myFunc` being declared in `myModule` of which so is the `myFunc()` `FunctionCall`
statement
- When generating the name of a variable being assigned to for `StaticVariableDeclaration`, we now
anchor at `this.program` instead of `modulle` (the deprecated value returned by `getModule()`)
- Updated `beginCheck()` to now call the `MetaProcessor` with the instance of `this.program` rather than `modulle` (deprecated - as stated before)
- Updated `beginCheck()` such that it now calls `processPseudoEntities()` on each `Module` that is contained
within the current `Program`
- Updated `beginCheck()` such that it now calls `checkContainerCollision()` on each `Module` that is contained
within the current `Program`
- Updated `checkContainerCollision(Container c)` to do the following:
* On each `Entity` we loop over we ensure that it never has a name which matches that of any `Module` that
is stored within our `Program` (exclusivity principle of module names)
* Updated calls to `generateName(Container, Entity)` to use `this.program` as the anchor container (insead
of the deprecated `modulle`)
TypeChecker (unittests)
- Fixed a unittest to not spawn a `TypeChecker` using a `Module` but rather a dummy `Compiler` instance
- Fixed a unittest to not spawn a `TypeChecker` using a `Module` but rather a dummy `Compiler` instance
- Fixed a unittest to not spawn a `TypeChecker` using a `Module` but rather a dummy `Compiler` instance
AND to create a dummy `Program` of which we then add a dummy `Module` to
- Fixed remaining unittests to now use a `Compiler` instance
- Added a `setProgram(Program program)` method
- For now when we finish the call to `parse()` in the `Parser` in `doParse()` we will also add ourselves
to the list of modules. Simply done because as of right now we only add ourselves if we are visited via an
import which implies that you would need a cyclic import ot be visited - which isn't a constraint we obviously
would like to impose upon code writers using TLang. For now we manually add it at the end.
- At the end of `doParse()` call `debugDumpOrds()` on the `Program`
- Added a `getTypeChecker()` method
Compiler (unittests)
- Prints out more information during the exception catch
- Added an assertion that the result from `split(..., ...)` may not be an empty array
- This is an update to the `resolveBest(Container c, string name)` method
- Updated `resolveBest(Container c, string name)` to now include a check for a condition
whereby we pass in a `Container` which is not an `Entity` as well (i.e. it has no name).
The only case whereby this is the case (in our current code) is that of a `Program`
which is purposefully **not** an `Entity` (as I wanted it to be nameless) but it _is_
a `Container`. Therefore we don't want to continue to hit the code below which
does a cast to `Entity` in the form of `containerEntity`, as that would not work
(and the associated assertion would fail).
- What I wanted to accomplish with the two checks is to check if we are given a name
which then directly matches that of a `Module` that is _in_ the provided `Program`,
and in such a case return said `Module`
- Else, we have a case whereby we have `moduleName.<iets>` whereby we then want to
also similarly scan the `Program` for all its modules and then match to the `moduleName`,
as shown in the above example, we then look this `Module` up **but** we don't return yet.
No, what we do is now do a search for the incoming `name` but we _anchor it on_ the found
`Module` to then search therein
- Updated the method `generateName(Container relativeTo, Entity entity)` to have a special case
which is when we pass in a `Container` of which is a `Program`. Because the `Entity` provided
may have been declared in some module at, for example a top-level of the `Module`, we then basically
have no way to know from the top-down where it belongs, _rather_ we must start **at** the `Entity`
itself and then ask the resolver to work its way up to the container of which _is_ a `Module` in
order to find its containing top-level container (i.e. a `Module`). After doing this we then call
the `generateName(Container, Entity)` method with said `Module` and the same `Entity` and return early.
- Some work is being done on `resolveBest(Container c, string name)` but so far no changes have been
necessary (through testing) but many might, so the code added is commented out for now and has no associated
commit message as I am still working on it.
- Added debugging messages to `findContainerOfType(TypeInfo_Class containerType, Statement startingNode)`
- If there is no dot-path but the name matches one of the `Module`s attached to the `Program`, then return it
- This is an update for `resolveBest(Container c, string name)`
- Removed `Module` and replaced it with a `Program`
- Updated constructor to take in a `Program` and a `TypeChecker
- `resolveBest(Container c, string name)` will now loop through every `Module` of the `Program` checking to see if `path[0]` matches the name of any of those modules
- Made it a kind-of `Container`
- Made class final
- Added stub interface implementations
- Added `addStatement(Statement statement)` and `addStatements(Statement[] statements)`
- Added `getStatements()`