Skip to content

Releases: mica-lang/mica

0.8.0 – `let`, tuples, and patterns

30 Oct 21:34
242849b
Compare
Choose a tag to compare

#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

29 Jan 14:22
Compare
Choose a tag to compare

This release introduces string iterators into the API.

  • String.bytes/0 - iterates over individual bytes in a string (yields Number)
  • String.chars/0 - iterates over Unicode codepoints in a string (yields String)
  • String.code_points/0 - same as String.chars/0, but yields Number
  • String.lines/0 - iterates over LF or CRLF separated lines in the string (yields String)
  • String.split/1 - splits the string into substrings using a separator, going from the left (yields String)
  • String.rsplit/1 - splits the string into substrings using a separator, going from the right (yields String)

0.7.0 – Better handling of user data

31 Oct 21:53
Compare
Choose a tag to compare

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.
    • If you've only ever used the high-level ForeignFunction API, this does not affect you.
  • Breaking: Errors in mica::ll are now prefixed with Language - mica::ll::error::{ErrorKind, Error} are now mica::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 trait IntoValue, together with the new functions Value::new and Engine::create_value. The latter can be used to create user data values.

And now for the exciting stuff!

  • It is now possible to accept Cloneable UserData 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 is TypeBuilder::add_static, from which you can return any type implementing UserData.

And probably a bunch of stuff I forgot about.

0.6.0 – Big restructuring

27 Oct 21:30
Compare
Choose a tag to compare

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, and mica-std are now consolidated into the singular mica crate.
    • mica-language is available under mica::ll, with ll 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 under mica::corelib.
      • Following the rename, mica::StandardLibrary was renamed to mica::CoreLibrary.
      • The std-io feature was removed because it was largely unimplemented.
  • Breaking: Engine initialization has been simplified to just Engine::new(). This loads the default core library mica::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 a u16 parameter count rather than impl 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 into BareMaybeVarargs and BareExactArgs to let us specify non-varargs functions explicitly.
  • Internal change: the giant macro in mica::hl for generating ForeignFunction 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

26 Sep 20:53
Compare
Choose a tag to compare
  • #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 like func name() = nil, where nil is the return value of the function. This value can be any expression.
    • Function expressions follow, and also use this new syntax. func () end becomes func () = nil.
    • Refer to the language documentation for more details.
  • #89 Postfix impl [docs]
    • The impl operator, which used to be spelled like impl 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 becomes struct Example impl end
  • #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 with while.
    • 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 and CountDown, 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.

0.4.0 – Data structures

10 Jun 11:46
Compare
Choose a tag to compare

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.
  • #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 \\.
  • #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
      
  • #60 List and Dict 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>.

Refer to the language documentation for details and usage examples.

0.3.0 – Optimizations

03 Apr 19:31
Compare
Choose a tag to compare

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 Dropping and Cloneing 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 own Gc<T> instead of Rust's Rc<T> is used.
    • There's now a Gc type in Mica's standard library, for controlling the GC's operation.
  • #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

28 Mar 11:33
Compare
Choose a tag to compare

This release adds user-defined types, including structs with implementations, into the language. Refer to the language reference for more information.