Releases: mica-lang/mica
0.8.0 – `let`, tuples, and patterns
#129 let
[docs]
A let
keyword was introduced to separate variable declarations from assignments to existing variables. This is to improve local reasoning about code.
# Before:
a = 1
# After:
let a = 1
#22 Tuples and records [docs]
Tuples aggregate values in an ordered, heterogenous, immutable way:
let tuple = (1, 2)
assert(tuple._0 == 1)
assert(tuple._1 == 2)
Tuples can be destructured using let
:
let (x, y) = (1, 2)
assert(x == 1 and y == 2)
Records are similar to tuples, but are unordered:
let position = { x: 1, y: 2 }
assert(position.x == 1)
assert(position.y == 2)
assert(position == { y: 2, x: 1 }) # swapping around the keys - the record is still the same
and can also be destructured with let
expressions:
let { x, y } = player.position
# or rename the fields:
let { x: player_x, y: player_y } = player.position
By default, the record must match exactly. This can be relaxed by specifying a ..
"rest" token at the end:
let { something, .. } = some_library
something(1, 2, 3)
Tuples and records are compared by value.
#148 _
pattern by @grisenti [docs]
_
is now a keyword and is used for discarding values.
let _ = some_function()
print(_) # error
This feature is mostly useful in conjunction with the new tuple and record patterns, to ignore fields:
let (x, _) = (1, 2)
let { x: _, y } = { x: 1, y: 2 }
0.7.1 – String iterators
This release introduces string iterators into the API.
String.bytes/0
- iterates over individual bytes in a string (yieldsNumber
)String.chars/0
- iterates over Unicode codepoints in a string (yieldsString
)String.code_points/0
- same asString.chars/0
, but yieldsNumber
String.lines/0
- iterates over LF or CRLF separated lines in the string (yieldsString
)String.split/1
- splits the string into substrings using a separator, going from the left (yieldsString
)String.rsplit/1
- splits the string into substrings using a separator, going from the right (yieldsString
)
0.7.0 – Better handling of user data
This release once again does not improve on anything within the language itself, but rather aims to improve the capabilities of the Rust API.
- Breaking: Method parameters are now handled differently than function parameters.
- There's a new type
MethodParameterCount
that's used for performing various math on parameter counts, safely.- This type limits parameter counts to fit in a
u8
, to reflect what the VM supports.
- This type limits parameter counts to fit in a
- If you've only ever used the high-level
ForeignFunction
API, this does not affect you.
- There's a new type
- Breaking: Errors in
mica::ll
are now prefixed withLanguage
-mica::ll::error::{ErrorKind, Error}
are nowmica::ll::error::{LanguageErrorKind, LanguageError}
. This reflects what the API looked like pre-0.6.0. - Breaking:
mica::ll
foreign function ABI has changed, and how includes an&Environment
parameter. [docs] - Breaking: Values do not implement
From<T>
anymore; these implementations were replaced with a new traitIntoValue
, together with the new functionsValue::new
andEngine::create_value
. The latter can be used to create user data values.
And now for the exciting stuff!
- It is now possible to accept
Clone
ableUserData
as parameters in functions.- In a future release, this will be extended to references - this is not that release though.
- It is also possible to return any
UserData
from functions.- Breaking: As a result of this change,
TypeBuilder::add_constructor
has been removed. The replacement isTypeBuilder::add_static
, from which you can return any type implementingUserData
.
- Breaking: As a result of this change,
And probably a bunch of stuff I forgot about.
0.6.0 – Big restructuring
This release does not add any new features to the language or the API, but rather aims to refine the existing implementation a bit.
- Breaking:
mica-language
,mica-hl
, andmica-std
are now consolidated into the singularmica
crate.mica-language
is available undermica::ll
, withll
standing for low-level.mica-hl
is reexported at the root of the crate.- The standard library
mica-std
has been renamed to the core library and is available undermica::corelib
.- Following the rename,
mica::StandardLibrary
was renamed tomica::CoreLibrary
. - The
std-io
feature was removed because it was largely unimplemented.
- Following the rename,
- Breaking: Engine initialization has been simplified to just
Engine::new()
. This loads the default core librarymica::corelib::Lib
. - Thanks to the changes above, the documentation now features lots of examples, because you don't need
mica-std
to initialize an engine anymore! - Breaking: It is now impossible to create varargs methods inside of custom types. This was intended to be a feature initially but never got implemented; it can be implemented in a backwards-compatible way so restricting methods to fixed argument counts is only breaking one-way.
- As part of this change, the
TypeBuilder::add_raw_*
family of functions now accepts au16
parameter count rather thanimpl Into<Option<u16>>
. This is still not ideal because methods can only ever accept up to 255 arguments, but it will do for the time being. - Also as part of this change,
mica::ffvariants::Bare
was split intoBareMaybeVarargs
andBareExactArgs
to let us specify non-varargs functions explicitly.
- As part of this change, the
- Internal change: the giant macro in
mica::hl
for generatingForeignFunction
implementations was removed in favor of offline code generation.- For users, this does not introduce a build.rs that would further extend compilation times - the generated code is checked into the repository.
- In fact, our current build.rs was deemed unnecessary and has been removed. It only ever checked for NaN boxing support, which can be done just as well using existing
#[cfg]
directives.
- Style change: Code is now indented with 4 spaces instead of 3. Yes, this includes Mica code.
- The rustfmt.toml is definitely not final and may change in the future, perhaps to remove the unstable feature requirement, or wrap certain things (like struct initialization) more aggressively.
0.5.0 – Traits `for` everyone
- #83 Updated function syntax [docs]
- To resolve ambiguities with allowing to leave the body of a function empty, functions now use a new, shorter syntax.
- Instead of
func name() end
, with the block being implicit, functions are now written likefunc name() = nil
, wherenil
is the return value of the function. This value can be any expression. - Function expressions follow, and also use this new syntax.
func () end
becomesfunc () = nil
. - Refer to the language documentation for more details.
- #89 Postfix
impl
[docs]- The
impl
operator, which used to be spelled likeimpl expr end
, is now spelled postfix:expr impl end
. - This leads to struct definitions reading much more nicely, with the scoping of the newly declared struct being more obvious.
- Example:
impl struct Example end
becomesstruct Example impl end
- The
- #38 Traits [docs]
- Mica now has support for traits (aka interfaces, protocols in other languages.)
- Refer to the language documentation for details.
- #36
for
loops [docs]- Because we now have traits that allow for defining an iterator protocol that won't clash with user methods,
for
loops were introduced as a syntax sugar for iterating values produced by an object withwhile
. - Note that Mica is still in alpha and the iterator protocol may be altered, should the need arise. For instance currently it's impossible to specify an implicit iterator for an object a'la Rust's
FromIterator
. - Currently the standard library has two iterators:
CountUp
andCountDown
, which do exactly what they say on the tin. Iterators over things like dict pairs are not available yet because of limitations in mica-hl.- There's also the question of whether we want to reimplement the string iterators from the Rust standard library, which may introduce soundness bugs, but we'll see.
- Because we now have traits that allow for defining an iterator protocol that won't clash with user methods,
0.4.0 – Data structures
This release introduces a bunch of new literals, and adds some basic data structures.
- #47 Improved number literals [docs]
- Added
\b
,\o
,\x
,\radix:
, and\u'C'
literals for numbers. - Added the ability to use
_
as a digit separator. - Added exponential notation.
- Added
- #8 #46 Improved string literals [docs]
- Added
\r
raw string literals, and\\
long string literals. - Added a bunch of common escape sequences for characters in strings.
- Strings cannot contain embedded line breaks anymore. Use the
\n
escape sequence or a long string literal\\
.
- Added
- #54
struct Name
is now an expression [docs]- This allows for a more concise way of creating and implementing a struct:
impl struct Example # ... end
- This allows for a more concise way of creating and implementing a struct:
- #60
List
andDict
types [list docs] [dict docs]- Lists are a basic data structure for storing values sequentially. In Rust, they're known as
Vec<T>
. - Dicts are another basic data structure for storing unordered key-value pairs. In Rust, they're known as
HashMap<K, V>
.
- Lists are a basic data structure for storing values sequentially. In Rust, they're known as
Refer to the language documentation for details and usage examples.
0.3.0 – Optimizations
This release optimizes the Mica interpreter a ton, and adds the ability to call Mica functions and methods from Rust.
- #20 Sinking assignments
- Assignments that don't result in a value now generate more efficient bytecode than previously.
- Basically, there's now a bunch of instructions for directly popping a value off the stack into a variable without making a copy.
- #21 NaN boxing
- Values inside the VM now take up 8 bytes instead of 24 bytes, which should improve cache efficiency.
- #24 Garbage collection
- This is the big star of the show, and improves performance drastically by reducing branch mispredictions caused by
Drop
ping andClone
ing values. - Thanks to the GC values are now trivially dropped and copied.
mica-hl
has received an overhaul of the value API because of this and NaN boxing, because the implementation of values is now hidden and our ownGc<T>
instead of Rust'sRc<T>
is used.- There's now a
Gc
type in Mica's standard library, for controlling the GC's operation.
- This is the big star of the show, and improves performance drastically by reducing branch mispredictions caused by
- #37 Calling Mica from Rust
Engine
now exposes a bunch of functions that let you call any value the()
call operator can be used on (right now only functions), as well as methods.
- Various smaller fixes and optimizations. In particular, a huge performance regression introduced in 0.2.0 as a result of my desperate attempts to implement reentrancy, has now been fixed.
0.2.0 – Structs
This release adds user-defined types, including structs with implementations, into the language. Refer to the language reference for more information.