The ^ operator in MiniScript 1.x is left-associative, so 2^3^2 == (2^3)^2 == 64. In virtually every other language with a power operator (including Python, JavaScript, Fortran, Ruby, Haskell, and R), as well as in standard math notation, ^ is right-associative, so 2^3^2 == 2^(3^2) == 512.
The left-associativity of ^ in MiniScript 1.0 was a mistake. In MiniScript 2.0, it will be right-associative, like most other languages. This is a code-breaking change, though not one that will affect most users.
MiniScript 1.0 does not allow things like 4.foo or 3.14.foo, even when foo is defined as an extension method on the number map. You can call such methods on variables (e.g. x.foo), but not on numeric literals. But there's no strong reason to disallow it, and users are occasionally surprised when it doesn't work. So, in 2.0, let's allow it.
See LANGUAGE_CHANGES.md.
function...end function will comprise an expression, not a statement. This just cleans up various odd corners of the syntax. The effect of this expression is still to create a funcRef, with code that is compiled (just once) for whatever's between the keywords, and outer (if needed) assigned to the locals of the function evaluating this expression.
MiniScript documentation has always said that the order of data in a map is undefined. In practice, though, the C# version of MiniScript always returned keys in insertion order, because that is how the underlying Dictionary class works.
In MiniScript 2, we will commit to this behavior: maps return keys in insertion order, and this is true in both the C# and the C++ versions.
FuncRef will get some metadata which can be accessed via a new intrinsic, perhaps like info(@f). This will include:
- name: the text of the expression to the left of
=where the function was defined, if any - note: when the first statement of a function body evaluates to a string constant, it is stored as the note (similar to a Python docstring)
- params: a list of little maps, one for each parameter; each contains
nameanddefault(the actual default value) - sourceLoc: the location of this function definition in the source code
These details will be returned by info as a frozen map.
We'll add one new type to MiniScript, error, which represents a runtime error, and a new err(msg, innerErr=null) intrinsic for creating them. Here are the special rules, given an error e and any type x:
- Global intrinsic
err(msg, e)returns a newerror(let's call ite2) such thate2.message == msg,e2.inner == e, ande2.stackreturns the stack trace at this point. se.err(msg, e)does the same, but also setse2.__isa == se, i.e., it creates a specialization of a more general errorse. The__isachain can be probed with theisaoperator, just like with maps. Note that this.errmethod will terminate if it creates a loop in the__isachain. (newshould also.)e.foo(wherefoois not literallymessage,inner,stack, or__isa) terminates [note 1].- All errors are immutable, so attempting
e.message = rhs, etc. will terminate with a runtime error. e or xevaluates tox.if e thenandwhile eboth terminate.f(e)returnsefor any intrinsic pure functionf[note 2]; functions that affect state (or which don't normally return a result) terminate.- All binary operators except for
isa,==, and!=(so+,-,*,/,%,^,<,<=,>,>=,and) involvingeevaluate toe(or if both operands are errors, evaluate to the first one), as do the unary operators-andnot. e[i]evaluate toe.- Any use of
e.fooore[i]in an lvalue expression terminates.
Note 1: "Terminates" above means that the program is halted, and a new runtime error is displayed, containing e as its inner error. Program code can not catch these; but they are always preventable with proper code.
Note 2: Any function can be written to propagate an argument error, or do something else when sensible; user functions are up to the user.
And here are some ways in which errors are perfectly ordinary:
return esimply returnseto the caller (i.e., ordinaryreturnbehavior, nothing special here).e isa errorevaluates to 1;isawith any other type evaluates to 0.e == xevaluates to 0 (unlessxis, in fact, another reference toe).e != xevaluates to 1 (unlessxis, in fact, another reference toe).@eevaluates toe.x = emakesxanother reference toe.emay be stored in lists and maps (including as map keys).