aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md1
-rw-r--r--docs/assembly.rst40
2 files changed, 15 insertions, 26 deletions
diff --git a/Changelog.md b/Changelog.md
index b2e080a0..23de7dcd 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -8,6 +8,7 @@ Features:
* Inline Assembly: Present proper error message when not supplying enough arguments to a functional
instruction.
* Inline Assembly: introduce ``keccak256`` as an opcode. ``sha3`` is still a valid alias.
+ * Inline Assembly: ``for`` and ``switch`` statements.
Bugfixes:
* Fixed crash concerning non-callable types.
diff --git a/docs/assembly.rst b/docs/assembly.rst
index 394fc9f5..7ef41483 100644
--- a/docs/assembly.rst
+++ b/docs/assembly.rst
@@ -28,11 +28,8 @@ arising when writing manual assembly by the following features:
* access to external variables: ``function f(uint x) { assembly { x := sub(x, 1) } }``
* labels: ``let x := 10 repeat: x := sub(x, 1) jumpi(repeat, eq(x, 0))``
* loops: ``for { let i := 0 } lt(i, x) { i := add(i, 1) } { y := mul(2, y) }``
-* switch statements: ``switch x case 0: { y := mul(x, 2) } default: { y := 0 }``
-* function calls: ``function f(x) -> y { switch x case 0: { y := 1 } default: { y := mul(x, f(sub(x, 1))) } }``
-
-.. note::
- Of the above, loops, function calls and switch statements are not yet implemented.
+* switch statements: ``switch x case 0 { y := mul(x, 2) } default { y := 0 }``
+* function calls: ``function f(x) -> y { switch x case 0 { y := 1 } default { y := mul(x, f(sub(x, 1))) } }``
We now want to describe the inline assembly language in detail.
@@ -501,9 +498,6 @@ is performed by replacing the variable's value on the stack by the new value.
Switch
------
-.. note::
- Switch is not yet implemented.
-
You can use a switch statement as a very basic version of "if/else".
It takes the value of an expression and compares it to several constants.
The branch corresponding to the matching constant is taken. Contrary to the
@@ -516,10 +510,10 @@ case called ``default``.
assembly {
let x := 0
switch calldataload(4)
- case 0: {
+ case 0 {
x := calldataload(0x24)
}
- default: {
+ default {
x := calldataload(0x44)
}
sstore(0, div(x, 2))
@@ -531,13 +525,10 @@ case does require them.
Loops
-----
-.. note::
- Loops are not yet implemented.
-
Assembly supports a simple for-style loop. For-style loops have
a header containing an initializing part, a condition and a post-iteration
part. The condition has to be a functional-style expression, while
-the other two can also be blocks. If the initializing part is a block that
+the other two are blocks. If the initializing part
declares any variables, the scope of these variables is extended into the
body (including the condition and the post-iteration part).
@@ -555,9 +546,6 @@ The following example computes the sum of an area in memory.
Functions
---------
-.. note::
- Functions are not yet implemented.
-
Assembly allows the definition of low-level functions. These take their
arguments (and a return PC) from the stack and also put the results onto the
stack. Calling a function looks the same way as executing a functional-style
@@ -569,7 +557,7 @@ defined outside of that function. There is no explicit ``return``
statement.
If you call a function that returns multiple values, you have to assign
-them to a tuple using ``(a, b) := f(x)`` or ``let (a, b) := f(x)``.
+them to a tuple using ``a, b := f(x)`` or ``let a, b := f(x)``.
The following example implements the power function by square-and-multiply.
@@ -578,12 +566,12 @@ The following example implements the power function by square-and-multiply.
assembly {
function power(base, exponent) -> result {
switch exponent
- 0: { result := 1 }
- 1: { result := base }
- default: {
+ case 0 { result := 1 }
+ case 1 { result := base }
+ default {
result := power(mul(base, base), div(exponent, 2))
switch mod(exponent, 2)
- 1: { result := mul(base, result) }
+ case 1 { result := mul(base, result) }
}
}
}
@@ -703,13 +691,13 @@ The following assembly will be generated::
mstore(0x40, 0x60) // store the "free memory pointer"
// function dispatcher
switch div(calldataload(0), exp(2, 226))
- case 0xb3de648b: {
+ case 0xb3de648b {
let (r) = f(calldataload(4))
let ret := $allocate(0x20)
mstore(ret, r)
return(ret, 0x20)
}
- default: { revert(0, 0) }
+ default { revert(0, 0) }
// memory allocator
function $allocate(size) -> pos {
pos := mload(0x40)
@@ -860,8 +848,8 @@ Grammar::
AssemblyAssignment = '=:' Identifier
LabelDefinition = Identifier ':'
AssemblySwitch = 'switch' FunctionalAssemblyExpression AssemblyCase*
- ( 'default' ':' AssemblyBlock )?
- AssemblyCase = 'case' FunctionalAssemblyExpression ':' AssemblyBlock
+ ( 'default' AssemblyBlock )?
+ AssemblyCase = 'case' FunctionalAssemblyExpression AssemblyBlock
AssemblyFunctionDefinition = 'function' Identifier '(' IdentifierList? ')'
( '->' '(' IdentifierList ')' )? AssemblyBlock
AssemblyFor = 'for' ( AssemblyBlock | FunctionalAssemblyExpression)