Skip to content

Releases: qatlang/qat

v0.7.0 - Const Generics, Regions, Pattern Matching Updates, bool

03 Feb 16:11
26d09ba
Compare
Choose a tag to compare
  • 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 created
    region 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 and match blocks to emit only the branches that will be executed.
  • If else case is not present in match 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 to Json. 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 the Identifier datatype. This concept is integrated in the entire codebase now.
  • New EntityOverview system used for IDE integration. Added IR::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 to fs::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 for default, none, signed & unsigned integers has been updated to be compatible with future and maybe datatypes
  • Compiler version is set in llvm::Module instances using llvm::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 the qat 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

29 Nov 12:44
26d09ba
Compare
Choose a tag to compare
  • 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 to cstring. 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 returned
  • heap'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

22 Nov 09:31
26d09ba
Compare
Choose a tag to compare
  • 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?]
  • 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 is str{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 in say'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 by new 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

24 Oct 18:43
26d09ba
Compare
Choose a tag to compare
  • 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 and future keywords have been added. The future 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

15 Oct 18:13
26d09ba
Compare
Choose a tag to compare
  • 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

30 Sep 10:29
26d09ba
Compare
Choose a tag to compare
  • 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 and continue 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 for choice types. Complete expression support is work in progress.
  • Heap allocation and memory management via heap'get, heap'grow and heap'put