Skip to main content

November 2022

Week of 2022-11-28​

  • πŸ“’ We support the True and False keywords as expressions.

  • πŸ“’ A new alias declaration is supported which allows defining local parameter values. This will eventually subsume type aliases and other things as it gets built out.

  • πŸ“’ We now have end-to-end execution of Mojo files using the kgen tool! Functions exported with @export can be executed.

  • πŸ“’ We have try-except-else and raise statements and implicit error propagation! The error semantics are that def can raise by default, but fn must explicitly declare raising with a @raises decorator. Stub out basic Error type.

  • The & sigil for by-ref arguments is now specified after the identifier. Postfix works better for ref and move operators on the expression side because it chains an mentally associates correctly: thing.method().result^. We don't do that yet, but align param decl syntax to it so that things won't be odd looking when we do. In practice this looks like:

    def mutate_argument(a&: index):
        a = 25

Week of 2022-11-21​

  • πŸ“’ The magic index type is gone. Long live __mlir_type.index.

  • Implement parameter substitution into parametric __mlir_type decls. This allows us to define parametric opaque MLIR types with exposed parameters using a new "placeholder" attribute. This allows us to expose the power of the KGEN type parametric system directly into Mojo.

  • πŸ“’ Fully-parametric custom types can now be defined and work in Mojo, bringing together a lot of the recent work. We can write the SIMD type directly as a wrapper around the KGEN type, for example:

    struct SIMD[dt: __mlir_type.`!kgen.dtype`, nelts: __mlir_type.index]:
        var value:
          __mlir_type.`!pop.simd<#lit<placeholder index>,
                                 #lit<placeholder !kgen.dtype>>`[nelts, dt]
    
        fn __add__(self, rhs: SIMD[dt, nelts]) -> SIMD[dt, nelts]:
            return __mlir_op.`pop.add`(self.value, rhs.value)

Week of 2022-11-14​

  • πŸ“’ Implement a magic __mlir_type declaration that can be used to access any MLIR type. E.g. __mlir_type.f64.

  • πŸ“’ Add an fn declaration. These are like def declarations, but are more strict in a few ways: they require type annotations on arguments, don't allow implicit variable declarations in their body, and make their arguments rvalues instead of lvalues.

  • Implemented Swift-style backtick identifiers, which are useful for code migration where names may collide with new keywords.

  • πŸ“’ A new __include directive has been added that performs source-level textual includes. This is temporary until we have an import model.

  • Implement IR generation for arithmetic operators like + and * in terms of the __add__ and __mul__ methods.

  • πŸ“’ Added support for break and continue statements, as well as early returns inside loops and conditionals!

  • πŸ“’ Implemented augmented assignment operators, like += and @=.

  • πŸ“’ Mojo now has access to generating any MLIR operations (without regions) with a new __mlir_op magic declaration. We can start to build out the language's builtin types with this:

    struct Int:
        var value: __mlir_type.index
    
        fn __add__(self, rhs: Int) -> Int:
            return __mlir_op.`index.add`(self.value, rhs.value)

    Attributes can be attached to the declaration with subscript [] syntax, and an explicit result type can be specified with a special _type attribute if it cannot be inferred. Attributes can be accessed via the __mlir_attr magic decl:

    __mlir_op.`index.cmp`[
        _type: __mlir_type.i1,
        pred: __mlir_attr.`#index<cmp_predicate slt>`
    ](lhs, rhs)
  • Improved diagnostics emissions with ranges! Now errors highlight the whole section of code and not just the first character.

Week of 2022-11-07​

  • Implemented the @interface and @implements decorators, which provide access to KGEN generator interfaces. A function marked as an @interface has no body, but it can be implemented by multiple other functions.

    @interface
    def add(lhs: index, rhs: index):
    
    @implements(add)
    def normal_add(lhs: index, rhs: index) -> index:
        return lhs + rhs
    
    @implements(add)
    def slow_add(lhs: index, rhs: index) -> index:
        wait(1000)
        return normal_add(lhs, rhs)
  • πŸ“’ Support for static struct methods and initializer syntax has been added. Initializing a struct with Foo() calls an implicitly static __new__ method. This method should be used instead of __init__ inside structs.

    struct Foo:
        var value: index
    
        def __new__() -> Foo:
            var result: Foo
            result.value = Foo.return_a_number() # static method!
            return result
    
        @staticmethod
        def return_a_number() -> index:
            return 42
  • πŸ“’ Full by-ref argument support. It's now possible to define in-place operators like __iadd__ and functions like swap(x, y) correctly.

  • πŸ“’ Implemented support for field extract from rvalues, like x.value where x is not an lvalue (var declaration or by-ref function argument).

Was this page helpful?