上一章我們已經簡單介紹了Solidity語言的基本概念及特點,在瞭解Solidity的基礎知識及用法後,我們可以嘗試在Remix、JIDE等編譯器上嘗試編寫一些簡單的智慧合約,以此來更好地熟悉開發智慧合約所需的環境及基礎。那麼今天,我們將在這裡更詳細地講解一些Solidity語言的語法。
首先來講解一下Solidity語言中的原始檔對映。它作為AST輸出的一部分,各個編譯器會提供AST中節點對應的原始碼範圍。可用於檢測AST靜態程式碼,分析錯誤,也可用於高亮本地變數以及對應的除錯工具。編譯器也能生成從位元組碼到指令原始碼之間的範圍對映,這在靜態分析工具中佔據著重要地位,在位元組碼級別中的分析,可在除錯工具中顯示對應的程式碼位置,同時也支援斷點操作。
接下來,讓我們一起來了解一下屬於Solidity語言特有的性質。Solidity有著一些獨特的語法,函式型別。在Solidity語言中,函式型別可以作為本地變數,也就是說,在使用var 時,可以給var賦予不同的函式。
而Solidity語言還有著兩個非常有意思的內部機制:清理變數(Cleaning Up Variables)與優化(The Optimizer)。
contract FunctionSelector {
function select(bool useB, uint x) returns (uint z) {
var f = a;
if (useB) f = b;
return f(x);
}
function a(uint x) returns (uint z) {
return x * x;
}
function b(uint x) returns (uint z) {
return 2 * x;
}
}
複製程式碼
清理變數(Cleaning Up Variables):在Solidity中,當一個值的佔用位數小於32個位元組,其中無用的位將會被清除。Solidity編譯器可在因無用的資料而產生任何副作用之前就將這些無用的資料清除,例如,在向記憶體寫入一個值之前,不需要的位元組位需要先清除掉,因為沒有用到的記憶體位也可能被用於計算雜湊值,也可能會作為訊息呼叫作為資料儲存。同樣,在storage中儲存的無用位元組位也需處理,否則會帶來一些負面影響。 另外,後續操作的不正確也會產生副作用,我們是不會主動的去處理無用位元組位的。Solidity編譯器會在輸入資料載入到棧上後對這些無用位元組位進行相應處理。不同的無效值有著不一樣的處理規則:
優化(The Optimizer):Solidity的優化基於彙編,也就是說,Solidity可以被其他的程式語言使用。編譯器在JUMP和JUMPDEST處拆分基本的指令序列為一個個的基本塊。在這些程式碼塊中,所有的指令都將被分析。所有的對棧,記憶體或儲存的操作被記錄成由指令及其引數組成的一個個表示式,而這些表示式又會指向另一個表示式。核心目的是找到一些表示式在任何輸入的情況下都恆等,然後將它們組合成一個表示式類。優化器首先嚐試在一系列已知的表示式中,找出一些全新的表示式。如果找不到,表示式通過一些簡單的原則進行簡化。流程最後,會有一個表示式處於棧頂,並且有一系列的對記憶體或儲存的修改。這些資訊與基本塊存在一起以方便地對他們進行連線。此外,關於棧,儲存和記憶體配置的資訊會傳遞到下一個塊。如果我們知道所有JUMP和JUMPI指令的目標,我們就可以構建程式的完整的控制流程圖。在最後一步中,每個塊中的程式碼都將重新生成。在某個塊結束時,將生成棧上表示式的依賴樹,不在依賴樹上的操作會被處理。在我們原始程式碼中想要應用的對記憶體、儲存想要的修改順序的程式碼就生成出來了(被丟棄的修改被判定為完全不需要的),最終,生成了所有的需要在棧上存在的值。
這些步驟應用於每個基本的塊,如果新生成的程式碼更小,將會替換現有的程式碼。如果一個塊處於分析期間時在JUMPI處分裂,條件被證實為一個常量,JUMPI將可以基於常量值被替換掉,比如下述程式碼:
var x = 7;
data[7] = 9;
if (data[x] != x + 2)
return 2;
else
return 1;
複製程式碼
簡化的程式碼可以被編譯為:
data[7] = 9;
return 1;
複製程式碼
Solidity的完整語法,敬請期待後續文章。
部分資料來源:http://www.tryblockchain.org/