Releases: qatlang/qat
Releases · qatlang/qat
v0.7.0 - Const Generics, Regions, Pattern Matching Updates, bool
- Const Generics is finally here. Now generic parameters can expect either a type or a constant expression. Currently, signed & unsigned integers, booleans, string slices, choice types and arrays of these types can be part of a normal constant expression used in a generic entity. The new type wrapping feature can be used to have a constant expression that holds a type. Currently only the specified types can be part of const generics, but theoretically a value of any type that is const constructible, that has the const equality operator and that is const-convertible to a string slice can be used in const generics. This makes the language so much more powerful. The generics is compile time and "zero cost". There can be a default expression for a const generic parameter, and a default type for a generic type parameter. If all generic parameters have default values, the generic entity can be default instantiated, by providing an empty list of generic parameter values.
type SomeTy'<T = i64, const K :: i32 = 10> { pub a :: T. } main -> i32 () [ new s = SomeTy'<>{ 20_i64 }. new s2 = SomeTy'<i32, 35>{ 40 }. give 0. ]
region
is finally here. Regions provide memory safe pointers without having to deal with lifetime issues. The constructors are called when the data is owned and the destructors are called when the program ends. This uses an arena allocator that requests memory at least as big as PAGE_SIZE, and only makes another request if the current block doesn't have any more unused memory. The memory is deallocated only at the end of the program. Regions are part of the type system. New regions with custom names can be createdregion MyRegion.
- Constant
default
expression. This is primarily intended to be used with const generics, but will also support const construction of types in the future.// Both sentences below results in the same type, in the const-generic example SomeTy'<i32, default>{ 40 }. SomeTy'<i32, 10>{ 40 }.
- Type Wrapping concept has been added.
IR::TypedType
is used to represent/hold another type, which can be used in constant expressions - Modular destruction for all types in the IR, that ensures that no values are left undestroyed.
- Pattern matching for string slices. The comparisons are done inline to prevent additional allocations. Now multiple values can be matched for a match case, for all types supported
- Added
bool
type to the IR, which is a specialisation of the 1-bit unsigned integer type - Conditions provided in if-else is now expected to be of
bool
type - Added
==
and!=
operator for string slices. Also supports constant string slices, that are done in compile time if both strings are constants. - Significant updates for pattern matching to support compile time comparisons and const expressions. This is taken advantage of in
if
-else
andmatch
blocks to emit only the branches that will be executed. - If
else
case is not present inmatch
block, the user is now warned. Previously an errow was thrown - Accessing member fields now has optimisations, mostly for constant values
- Fixed constant issue in global declarations. If the declaration had variability, the exact opposite value was used. This caused crash when the global variable was reassigned.
- AST and IR representation for member functions have been updated so that both core types and mix types can be used in the future. Now only core types can be used.
- Pointers now have region ownership. Pointers of this ownership can be used without checking for lifetime as they are guaranteed to be safe.
- Now tags of loops are checked against other tags and also local values. Previously only existing tags were checked.
- Binary expressions now supports multipointers
- Fixed issue while converting
FileRange
toJson
. Any exception will cause an empty file path to be used in the Json representation. - Entity names and symbols were previously represented using
std::string
, but it is now represented using theIdentifier
datatype. This concept is integrated in the entire codebase now. - New
EntityOverview
system used for IDE integration. AddedIR::Mention
which is used in IDEs for tracking entity references, displaying hover information and providing document links - Added
--export-code-info
option to export metadata about the code, which is meant to be used by IDE tooling - Unified name checking system. Previously name conflict checks were performed independenly for each entity in different parts of the codebase, but now it is done in a unified way
- Fixed issue while creating directories.
fs::create_directory
was used which did not do it recursively, thereby causing problems. The function has been changed tofs::create_directories
- Errors happening during CLI configuration is now reported by
IR::Context
, which makes it easily recognisable by IDEs --keep-llvm
option to prevent deletion of generated llvm files.--export-ast
is now an option instead of a command to be more flexible and useful. The AST files are now exported inside the AST folder in the build directory- CLI display now by default doesn't have colors. In further stages, it is checked if the
--no-colors
option is provided, and the behaviour is changed accordingly - Fixed naming issues while creating llvm equivalents for multipointers
- Updates to support compatibility between pointers with specific ownership and pointers with anonymous ownership. While anonymous pointers cannot be converted to any other type of ownership, the opposite is always possible.
- Removed unnecessary loading for multipointers in the
[ ]
operator - Type Inference has been added to
ast::TernaryExpression
and it supports type inference for signed and unsigned integer literals, null pointers, default expression & none expression. Fixed loading issue for local values - Type inference checks for integer and unsigned integer literals
- Owned pointers are properly freed in return sites of a function. This also happens in the destructor of core types if the member field is an owned pointer
- Optimisation to avoid multiple allocations are now present for owned constructor call. This even works if the type is a
maybe
- Fixed minor issue in conditional branches that the rest block was not linked and was incorrectly placed in the block tree
- Improved binary expression parsing. While parsing a binary expression, the LHS and the binary operator were stored separately, which might cause ordering issues and incorrect access to the expressions. That was a hacky way to maintain parser state. Now, the LHS and the binary operator are stored as one, thereby making the system less fragile
none
expression support type inference. This makes the compiler more user friendly and intuitive. Previously, the type had to be manually provided- Since
future
&maybe
are built-in types, better type inference is required to avoid incorrect errors. Now, type inference fordefault
,none
, signed & unsigned integers has been updated to be compatible withfuture
andmaybe
datatypes - Compiler version is set in
llvm::Module
instances usingllvm::VersionTuple
which is created in the CLI configuration stage - Fixed issue #6 where doing
qat run
command to build and run the executable, did not execute the built binary. - Support for multiple executables is there when you do the command
qat run
IR::Context
stores paths to all executables built by the compiler. This is then used when the executables have to be run, if the user ran theqat run
command- Cleaned up the information displayed when the user ran the
qat version
command - Fixed issue that the logic for
&&
and||
were missing in the parser - If the output directory provided to the compiler did not exits, previously an error was thrown. Now an attempt is made to create the directory, if not possible an error is thrown.
heap
expressions are updated to use multipointers- No more third party output in any compiler stage, besides that of the built executables.
- So many more updates, improvements and additions under the hood...
- Significant changes to the parser logic for expressions. The changes are related to the caching of symbols and expressions.
- Parser logic cleanup - removed a lot of legacy logic that caused old syntax to be still valid. Parsing of expressions is now handled totally
v0.6.1 - Multi-Pointers & Multiple Ownership in constructor call
- Fixed serious issue that the
-static
flag passed to clang for the LLVM IR to machine code compilation, always caused segfaults. The flag has been removed from the compilation command, and since static compilation is the default behaviour, this doesn't change anything - Added multi-pointers. They follow this syntax
#[+ cstring ?] // The + inside means that this is a multi-pointer
- Multi pointers have the length/extent/bound of the pointer stored alongside it. This will be useful in bounds checking in the future.
- Only multi pointers can now be indexed into. That is, of all pointer variants, only multi pointers supports indexing/subscript operator
- Main function now calls module initialisers for all modules that have global variables having non-constant initial value
- The syntax for
main
function has been updated so that the only argument used is a multi pointer with anonymous ownership is used for receiving the arguments, instead of having 2 arguments, one for the count and another for the pointer to the data - The concept of pointer access has been removed from
ast::MemberAccess
&ast::MemberFunctionCall
. Previously, special syntax>-
had to be used for accessing members & calling member functions on pointers of types. Now, the idea is that the pointer have to be dereferenced before doing any of those. - Improved conversion from
str
tocstring
. Previously, if the string was a constant, an extra allocation was made, but now heap'get
now returns a multi pointer with heap ownership, if a count is provided. If not, a normal pointer with heap ownership is returnedheap'grow
now always expects a multi pointer- The
own
syntax in constructor calls now supports owning multiple instances of data. The count has to be provided. The syntax is:
own[5] Hello from (a, b)
v0.6.0 - Built-in Optionals, Pointer Ownership, Filesystem based Libraries and much more
maybe
types are built-in optional types. The syntax for such a type is:maybe i32
, similar to futures- Updated pointer syntax to pave way for data ownership. Currently, 4 types of ownership are supported.
- Parent function/type ownership
#[u64]
- Explicit parent type ownership
#[u64 'type]
& Explicit type ownership#[u64 'type(SomeTy)]
- Heap ownership
#[u64 'heap]
- Anonymous ownership
#[u64?]
- Parent function/type ownership
- Pointers with anonymous ownership are not created like that. The ownership is just understood as anonymous in a context different to that of the owner, if there is no explicit ownership specified, or if there is no explicit ownership that can be specified
- The filesystem based library system has been updated. Previously, if there was a file called
lib.qat
in a folder, that folder was understood as a library. Now, the name of the library has to be prepended to the file, so now as an example, it would be something like this:std.lib.qat
- There are also additional checks to see if the name of the library is a keyword or not. If it is, errors are thrown
bring'member
has been added to make another file/folder a child of the current module- Added
meta'moduleInfo
to provide metadata about the current module in scope. This can be used to add data like external dependencies, library name, output name, author and much more - Added
--static
&--shared
switches to the CLI configuration - give/returns can now have void expressions. Previously the compiler complained if the return type of the function was void, but an expression was provided in the give. Now, it does not throw error if the expression itself is of void type (mostly for function calls)
- Basic support for global declarations. The syntax is identical to that of the local initialiser, however, globals doesn't have the type inference and optimisations you get in local declarations as of now.
- Intialiser expressions for global declarations are now emitted inside the module initialiser function and there is a check to see if the expression is a constant or not. If all initialiser expressions for all globals are constants, then the initialiser function for that module will not be called.
- Updated string slice creation syntax. Previously, it was
str from (buffer, length)
. Now it isstr{buffer, length}
which I think is the better one - Removed temporary path parameter in the CLI config. Added
--target
and--sysroot
parameters, mostly part of a successful attempt to achieve WASI compilation. However,--target
has lots of uses on its own. Mostly cross compilation. Added--release
switch that changes the compiler mode to release, which as of now is mostly useful insay'dbg
- Added
say'only
which doesn't append a newline to the output - Now, if one of the copy assignment operator or copy constructor is defined, the other is also required. Similarly, if one of move assignment operator or move constructor is defined, the other is also required.
let
keyword has been replaced bynew
and now the type for local declaration is specified after the name of the local- Syntax for core type member fields have been changed so that type comes after name. Now the syntax is
fieldName :: u64.
say'dbg
has been added that only prints the output if the program was compiled in debug mode
v0.5.0 - Async functions & methods, Return arguments
- Async functions & member functions have landed in the language. Under the hood, this uses the C
pthread
library. Await is implemented as a conditional loop that uses volatile loads to check the state of the future async
,await
andfuture
keywords have been added. Thefuture
datatype has also landed and despite being one type, this along with the async-await semantics took a lot of effort to finish- Return arguments have landed. This system is currently used by futures to manage the state and the value of the future.
- Return argument is the last argument of a function, that is a reference to stack memory, which can be used to set the return value of the function. The return value of the function will be changed to
void
under the hood. Currently this is implicitly used in async functions. - Give sentence inside async functions sets the future value via the return argument and calls
pthread_exit
v0.4.0 - Default values, File & Folder imports & Modular builds
- Added default values to the language
- Integer literals are now responsive and can adapt to the expected bitwidth in the environment
- Added optimisations to prevent multiple copies in local declaration and assignment
- Files and Folders can now be brought into modules. The import can be named or not. This sets up a basic but powerful import system for the language
- Modules now handle their own compilation and hence this new system can be leveraged to manage customised builds for libraries. The presence of main function will make the output an executable. Otherwise, the library can be built into a shared or static library depending on user configuration. The ability to customise build format is work in progress
- The user is warned about implicit copy and move and is also asked to make it explicit. Making these explicit will not change the behaviour of the code
- Added the dereference operator
#
. This is useful for iterators and similar datatypes - Arbitrary integer bitwidths can now be used only if they are imported into the module. However, there is no system to import integer bitwidths as of now. This is an easy thing to do. I just didn't manage to start working on this
- Added
analyse
command to the cli configuration that will prevent compilation to object files. Only lexing, parsing, LLVM IR generation and analysing is done if this command is used instead of build or run
v0.3.11 - Generics, Polymorphism, RAII, Copy & Move
- Compile-time polymorphism via generic
core
types and generic functions - Runtime polymorphism via
mix
types, aka Discriminated Unions / Tagged Unions / Sum Types - With the addition of constructors and destructors, RAII is officially supported
- Added support for copy and move constructors & assignment operators. Currenly there is support for manual move
- Automatic copy & move are work in progress
- Type definitions are supported. Type definitions and mix types currenly cannot be templated.
- Choice types are added. These are equivalent to enum classes in C++
- Local aliases are supported. This enables the user to bind a value to a name and reuse it in that scope, without reassigning it. Currently this is used inside loops. This is an experimental feature
- Loops can be tagged with a label and then
break
andcontinue
can use that tag to manage the control flow of that specific loop - Pattern matching support for
mix
&choice
types. Expressions are allowed as cases forchoice
types. Complete expression support is work in progress. - Heap allocation and memory management via
heap'get
,heap'grow
andheap'put