November 2022
Week of 2022-11-28
-
📢 We support the
TrueandFalsekeywords as expressions. -
📢 A new
aliasdeclaration 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
kgentool! Functions exported with@exportcan be executed. -
📢 We have try-except-else and
raisestatements and implicit error propagation! The error semantics are thatdefcan raise by default, butfnmust explicitly declare raising with a@raisesdecorator. Stub out basicErrortype. -
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
indextype is gone. Long live__mlir_type.index. -
Implement parameter substitution into parametric
__mlir_typedecls. 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_typedeclaration that can be used to access any MLIR type. E.g.__mlir_type.f64. -
📢 Add an
fndeclaration. These are likedefdeclarations, 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
__includedirective has been added that performs source-level textual includes. This is temporary until we have animportmodel. -
Implement IR generation for arithmetic operators like
+and*in terms of the__add__and__mul__methods. -
📢 Added support for
breakandcontinuestatements, 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_opmagic 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_typeattribute if it cannot be inferred. Attributes can be accessed via the__mlir_attrmagic 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
@interfaceand@implementsdecorators, which provide access to KGEN generator interfaces. A function marked as an@interfacehas 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 likeswap(x, y)correctly. -
📢 Implemented support for field extract from rvalues, like
x.valuewherexis not an lvalue (vardeclaration or by-ref function argument).