CLL - whilei/ethereumproject-wiki GitHub Wiki
The purpose of ECLL is to provide a language that will be simple and friendly for users to write contracts in, but at the same time easily and efficiently compile into Ethereum script code. ECLL abstracts away concepts like pointers, direct memory access and jumping in favor of a more traditional syntax of conditionals, loops, arrays and variables. Function support, including first-class-function support, will be left to a future more powerful, but less efficient, language that will be denoted EHLL ("Ethereum High Level Language")
The specification will be in three parts. The first part will define the language as an abstract syntax tree, formalized using LISP-style S-expression syntax, the second part will provide specifications for what each operation does, and the third will show how the AST is to be rendered in text.
An expression is defined as follows:
- A number is an expression
- A variable name is an expression
-
("arr" a b)is an expression, whereaandbare expressions. This is the equivalent of C'sa[b]. -
(OP a b)is an expression, whereOPis in the set(+ - * / % s/ s% ^ < > <= >= ==) -
(OP a)is an expression, whereais in the set(- !) - The special values
tx.datan,tx.value,tx.sender,contract.address,block.number,block.difficulty,block.timestamp,block.parenthashandblock.basefeeare expressions -
("pseudo" a b)is an expression, whereais a pseudoarray andbis an expression -
("fun" a b...)is an expression, whereais a returning function andb...contains the valid number of arguments
A pseudofunction is defined as follows:
-
block.contract_storageis a pseudofunction
A pseudoarray is defined as follows:
-
tx.dataandcontract.storageare pseudoarrays -
("pfun" a b...)whereais a pseudofunction andb...contains the valid number of arguments is a pseudoarray
contract.storage is a mutable pseudoarray, and the other two are immutable pseudoarrays.
A returning function is defined as follows:
-
block.account_balance,sha256,sha3,ripemd160,ecvalidare returning functions -
arrayis a returning function
A multireturning function is defined as follows:
-
ecsignandecrecoverare multireturning functions
A multiexpression is defined as follows:
-
("mfun" a b...)whereais a multireturning function andb...contains the valid number of arguments is a multiexpression
An acting function is defined as follows:
-
mktxis an acting function
A left-hand-side expression is defined as follows:
- A variable is a left-hand-side expression.
-
("arr" a b)is a left-hand-side expression, whereais a left-hand-side expression andbis an expression. -
("pseudo" a b)is a left-hand-side expression, whereais a mutable pseudoarray andbis an expression.
A statement is defined as follows:
-
("afun" a b...)whereais an acting function andb...contains the valid number of arguments is a statement -
("set" a b)whereais a left-hand-side expression andbis an expression is a statement -
("mset" a... b)wherea...is a list of left-hand-side expressions with the valid number of arguments andbis a multiexpression is a statement -
("seq" a...)wherea...are statements -
("if" a b)whereais an expression andbis a statement -
("if" a1 b1 "elif" a2 b2 "elif" a3 b3 ...)whereakare expressions andbkare statements -
("if" a1 b1 "elif" a2 b2 "elif" a3 b3 ... "else" c)whereakare expressions andbkandcare statements -
("while" a b)whereais an expression andbis a statement "exit"
Pre-compilation, if there are n variables, each variable will be assigned an index in [0,n-1]. Let ind(x) be the index of variable x, and let M[x] be the contract memory at index x
In the context of a right-hand-side expression:
- Arithmetic works in the obvious way.
(* (+ 3 5) (+ 4 8)), for example, returns 96. -
a && bis a shortcut for!(!(a) + !(b)) -
a || bis a shortcut for!(!(a + b)) - A variable
xshould becomeM[ind(x)] -
("arr" a b)returnsM[M[ind(a)]+b] -
tx.datanreturns the number of data fields in the transaction -
("pseudo" "tx.data" i)returns the ith data field in the transaction or zero ifi >= tx.datan -
tx.sender,tx.value,block.basefee,block.difficulty,block.timestamp,block.parenthashandcontract.addressreturn the obvious values. -
("pseudo "contract.storage" i)returns the contract storage at indexi. -
("fun" "block.account_balance" a)returns the balance of addressa -
("pseudo" ("pfun" "block.contract_storage" a) b)returns the contract storage of accountaat indexb -
("mfun" "ecsign" hash key)returns thev,r,striple from the signature -
("mfun" "ecrcover" h v r s)returns thex,ypublic key -
("mfun" "sha256" len arr)returns the SHA256 hash of the string of lengthlenstarting fromM[ind(arr)].sha3andripemd160work similarly -
("fun" "array")returns2^160 + M[2^256 - 1]and setsM[2^256 - 1] <- 2^160 + M[2^256 - 1]
In the context of a left-hand-side expression:
- A variable
xreturnsind(x) -
("arr" a b)returnsa + bwhereaandbhave already been evaluated -
("pseudo" a b)returns an object which, if set, modifies the value of the pseudoarray referent at indexatobinstead of doing a memory set
In the context of a statement:
-
("afun" "mktx" dest value dn ds)creates a transaction sendingvalueether todestwithdndata fields starting fromM[ind(ds)] -
("set" a b)setsM[a] <- bwhereaandbhave already been evaluated -
("mset" a... b)sequentially sets the memory index at each of the values ina...to a value from the multiexpressionb -
("if" a b),("while" a b)and derivatives will work as they do in other languages
- Arithmetic is done using infix notation using the C++ operator precedence:
^then* / % s/ s%then+ -then< <= > >=then==then&&then||. That is to say, arithmetic formulas will behave as they normally do; for example,(+ (* 3 5) (* x y))would be (3 * 5 + x * y) and(* (+ 3 5) (+ x y))would be((3 + 5) * (x + y)) -
("arr" a b)and("pseudo" a b)will both be represented asa[b] -
("fun" a b...),("mfun" a b...),("afun" a b...)and("pfun" a...)will all be represented asa(b1,b2, ... ,bn) - Multiexpressions will be represented as
a1, a2, ... an -
("set" a b)and("mset a... b)will be represented asa = banda1, a2 ... ,an = b, respectively. -
("seq" a...)consists of each of the statements on their own separate line -
("if" a b)and("while" a b)will be represented as in Python, using the keyword directly followed by the expression foraand the indented statement forb - Values can be represented either as integers or inside string quotes, in which case they will be treated as hexadecimal
-
exitexits.
Examples:
Factorial:
x = 1
n = 1
while x < 10:
n = n * x
x = x + 1
Fibonacci sequence:
a = array()
a[0] = 1
a[1] = 1
i = 2
while i < 70:
a[i] = a[i-1] + a[i-2]
i = i + 1
mktx("0676d13c8d2cf5e9e988cc3b5f6dfb5a6a3938fa",a[69],70,a)
A real example - simple forwarding contract to create a transferable account:
if tx.value < tx.basefee * 200:
exit
else:
a = contract.storage[2^256 - 1]
if !(tx.sender == a) && (tx.sender > 0):
exit
if tx.data[0] == 2^160:
contract.storage[2^256 - 1] = tx.data[1]
else:
if a == 0:
contract.storage[2^256 - 1] = tx.sender
o = array()
i = 0
while i < tx.datan - 1:
o[i] = tx.data[i+1]
i = i + 1
mktx(tx.data[0],tx.value - tx.basefee * 250,i,o)
-
("seq" a...)is implemented by separating the statements with semicolons. Newlines are ignored. -
("if" a b)and("while" a b)will be represented as in C++, storingainside brackets andbinside curly brackets
The AST is used as the code directly, with the minor modification that ("fun" a b...), ("pfun" a b...) and ("mfun" a b...) are replaced with (a b...).