Releases: flax-lang/flax
Housekeeping Release
FFI Escape Control
Mainly a release to fix the CI builds, but we have one new feature; the compile-time interpreter will now refuse to call out to external functions via FFI by default, unless --ffi-escape
is passed on the command line.
This is kinda similar to --shell-escape
used in LaTeX.
Virtual Class Fixes
-
Overriding methods now check for a compatible method (in name and signature) in the base class hierarchy, and will error if none is found
-
Method "compatibility" has been expanded to include covariant return types and contravariant parameter types. Note that this applies only to pointer-to-class types, and not value-of-class types.
More Bugfixes
- Fix instances where typechecking would not terminate when dealing with classes in some hierarchy
- Miscellaneous IRBuilder fixes
- Constructor arguments are now in scope in the superclass call, eg. this is now possible:
class Foo : Bar
{
init(x: int, y: int) : super(x * y) { ... }
}
- Fix issues where methods could not be called on rvalues, eg.
Foo().bar(...)
- Fix dumb issue where omitting optional arguments would hard crash the compiler
Overdue Bugfixes
-
When lexer errors are encountered (missing quotes or invalid tokens), we used to throw a warning:
attempting to lex file while file is already being lexed, stop it
. That happens because we want to print the context, which requires reading the file, which happens to read the tokens, which... etc. etc. We've just fixed it by returning the current state if we request file contents while lexing. -
Types were not usable from imported modules. Anything that required fetching the SST node of a given
fir::Type
would not work if the type in question was defined in an imported module. I guess we didn't have a test case for this, but the main issue was that thetypeDefnMap
of imported modules was not actually copied to the importing module.
Fixed by a small refactor.
The Compiler Can Actually Compile
Patched up the backend stuff on all platforms, and added some code to find the MSVC toolchain on Windows to let us generate exes.
All of the CI environments now test all 3 configurations: JIT with LLVM, Interpreter, and EXE output.
Arguments follow normal (gcc-style) conventions, eg:
$ flaxc foo.flx # produces an executable foo
$ flaxc -o bar foo.flx # produces 'bar'
Of course, -sysroot
should continue to be used.
Optional Argument Improvements
Fixes an issue detailed in the previous release (0.41.0):
Optional arguments in a variadic function must be specified somewhere in the argument list, to prevent the variadic arguments from being "stolen" by the positional parameter (then you get an error about how you must pass the optional argument by name, even though that wasn't your intention).
For example, this:fn qux(x: str, y: int = 3, args: [str: ...]) { ... }Will result in this error:
error: optional argument 'y' must be passed by name at: ultratiny.flx:28:26 | 28 | qux("hello, world!", "hi", "my", "name", "is", "bob", "ross") | ‾‾‾‾
Now, the example above will work "intuitively"; the strings (starting from "hi"
) will be passed as varargs to the function, and y
will have the default value of 3
.
Note that this means if the intention was to pass a value to y
(but you forgot the name), like this: foo("bla", 7, "a", "bunch", "of", "strings")
, the error will now be the failure in casting 7
to str
, because we presume you wanted to pass 7
as a vararg.
We can't have it both ways, but I feel like the new behaviour will be the more helpful error in the majority of cases.
Compile-time If Bugfix
Oops, fixed a bug where the first branch of an #if
had scoping issues where the declarations were not correctly placed at the top-level scope.
Also, there are obvious security implications for being able to #run
arbitrary code at compile-time, eg. #run system("rm -rf /*")
(thanks, sim642), especially from an imported library.
We'll probably disable calling out to external functions during compile time, or have some way to change that (flag, or directive on imports, or something).
Scope Path Goodness
-
export
s andimport
s can now refer to paths, eg.import foo::bar
will look forfoo/bar.flx
.
Exporting a path will simply place the (public) contents of the file into a namespace with the same name. Bits of the newstd
library use this, for exampleclass map
is inmap.flx
, but it exportsstd
-- meaning the definition ofmap
will live instd::
.
Note that importing a string literal is still supported, but they no longer add the extension if missing -- you would need toimport "foo/bar.flx"
! -
Identifier paths (eg
foo::bar
) can now start with::
to refer to the root scope, and include^
to refer to the parent scope. For example:
fn main()
{
let foo = 10
do {
let foo = 20
libc::printf("^::foo = %d!\n", ^::foo) // prints 10!
}
}
-
Implicit method calls (ie. calling a method without doing
self.method(...)
) work again -
Floating point values can now be compared with each other (oops)
FFI-as Redux
Flip the declaration of ffi-as
, because external names might have strange characters (like spaces! or $
or @
or whatever) that are not valid in Flax identifiers. Made more sense to have the Flax-visible name as part of the actual declaration.
Also, made the external name a string literal, for the reasons stated above.