Skip to content

Commit eba0ad5

Browse files
authored
assignments, local variables, better tests, other bug fixes (#332)
* formatting the test, removing old code * new test case with less going on * updating primops test case to use local vars not fields * scala style, whitespace, a new util function, comments, variable declaration first cut * updating bool literal test to refer to a local rather than a field * no prizes for guessing where i copied this file from * assign instead of declare; removing type annotations from declarations output with a comment about why * whitespace * similar enough case for decls, so might as well * updating ifthenelse test case to use locals not fields, fixing a bug in the output code * adding case for if, since it\'s so similar to ifthenelse * intconst test to locals not fields * removing sstore for local variables * fixing scaladocs * updating simplecall test to not use fields * adding a top level return to simple call so its testable * scala style * whitespace * removing temp symbol table
1 parent 979d4c1 commit eba0ad5

File tree

12 files changed

+142
-72
lines changed

12 files changed

+142
-72
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"gas" : 30000000,
3+
"gasprice" : "0x9184e72a000",
4+
"startingeth" : 5000000,
5+
"numaccts" : 1
6+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
main contract AssignLocalAdd{
2+
transaction assignlocaladd() {
3+
int x;
4+
bool y;
5+
x = 5 + 12;
6+
return;
7+
}
8+
}

resources/tests/GanacheTests/BoolLiteral.obs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
main contract BoolLiteral{
2-
bool x;
3-
42
transaction BoolLiteral () {
3+
bool x;
54
x = true;
65
x = false;
76
}

resources/tests/GanacheTests/If.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"gas" : 30000000,
3+
"gasprice" : "0x9184e72a000",
4+
"startingeth" : 5000000,
5+
"numaccts" : 1
6+
}

resources/tests/GanacheTests/If.obs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
main contract If {
2+
transaction iftest() {
3+
int x;
4+
if (true) {
5+
x = 1;
6+
}
7+
return;
8+
}
9+
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
main contract IfThenElse {
2-
int x;
32
transaction ifthenelse() {
3+
int x;
44
if (true) {
5-
x = 1;
6-
} else {
7-
x = 0;
8-
}
5+
x = 1;
6+
} else {
7+
x = 0;
8+
}
99
return;
1010
}
1111
}

resources/tests/GanacheTests/IntConst.obs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
main contract IntConst{
2-
int x;
32
transaction intconst() {
3+
int x;
44
x = 4;
55
return;
66
}
Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
main contract PrimOps{
2-
int x;
3-
bool y;
4-
52
transaction primops() {
6-
y = true && false;
7-
y = true || false;
3+
int x;
4+
bool y;
5+
6+
y = true && false;
7+
y = true || false;
88

9-
x = 4 + 4;
10-
x = 4 - 4;
11-
x = 4 / 4;
12-
x = 4 * 4;
13-
x = 4 % 4;
9+
x = 4 + 4;
10+
x = 4 - 4;
11+
x = 4 / 4;
12+
x = 4 * 4;
13+
x = 4 % 4;
1414

15-
y = 1 == 2;
16-
y = 1 != 2;
17-
y = 3 > 4;
18-
y = 3 >= 4;
19-
y = 3 < 3;
20-
y = 3 <= 3;
21-
y = 3 != 3;
15+
y = 1 == 2;
16+
y = 1 != 2;
17+
y = 3 > 4;
18+
y = 3 >= 4;
19+
y = 3 < 3;
20+
y = 3 <= 3;
21+
y = 3 != 3;
2222

23-
y = !y;
24-
x = - x;
23+
y = !y;
24+
x = - x;
2525

26-
return;
26+
return;
2727
}
2828
}
Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
main contract SimpleCall{
2-
int x;
3-
transaction updatex() {
4-
x = 4;
5-
return;
2+
transaction val() returns int {
3+
return 4;
64
}
7-
transaction main(){
5+
transaction main() returns int{
6+
int x;
87
x = 9;
9-
updatex();
10-
return;
8+
x = val();
9+
return x;
1110
}
1211
}

src/main/scala/edu/cmu/cs/obsidian/codegen/CodeGenYul.scala

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package edu.cmu.cs.obsidian.codegen
22

33
import edu.cmu.cs.obsidian.CompilerOptions
4-
import edu.cmu.cs.obsidian.codegen.LiteralKind.LiteralKind
54

65
import java.io.{File, FileWriter}
76
import java.nio.file.{Files, Path, Paths}
@@ -17,7 +16,6 @@ import scala.collection.immutable.Map
1716
object CodeGenYul extends CodeGenerator {
1817

1918
// TODO improve this temporary symbol table
20-
var tempSymbolTable: Map[String, Int] = Map() // map from field identifiers to index in storage
2119
var tempTableIdx: Int = 0 // counter indicating the next available slot in the table
2220
var stateIdx: Int = -1 // whether or not there is a state
2321
var stateEnumMapping: Map[String, Int] = Map() // map from state name to an enum value
@@ -156,7 +154,6 @@ object CodeGenYul extends CodeGenerator {
156154
def translateField(f: Field): Seq[YulStatement] = {
157155
// Reserve a slot in the storage by assigning a index in the symbol table
158156
// since field declaration has not yet be assigned, there is no need to do sstore
159-
tempSymbolTable += f.name -> tempTableIdx
160157
tempTableIdx += 1
161158
Seq() // TODO: do we really mean to always return the empty sequence?
162159
}
@@ -198,7 +195,6 @@ object CodeGenYul extends CodeGenerator {
198195
}
199196
}
200197

201-
202198
Seq(FunctionDefinition(
203199
transaction.name, // TODO rename transaction name (by adding prefix/suffix)
204200
transaction.args.map(v => TypedName(v.varName, mapObsTypeToABI(v.typIn.toString))),
@@ -222,46 +218,55 @@ object CodeGenYul extends CodeGenerator {
222218
case Some(retVarName) =>
223219
val temp_id = nextTemp()
224220
val e_yul = translateExpr(temp_id, e, contractName, checkedTable)
225-
decl_0exp(temp_id) +: e_yul :+ assign1(Identifier(retVarName), temp_id) :+ Leave()
221+
decl_0exp(temp_id) +:
222+
e_yul :+
223+
assign1(Identifier(retVarName), temp_id) :+
224+
Leave()
226225
case None => assert(assertion = false, "error: returning an expression from a transaction without a return type")
227226
Seq()
228227
}
229228
case Assignment(assignTo, e) =>
230229
assignTo match {
231230
case ReferenceIdentifier(x) =>
232-
val kind: LiteralKind = e match {
233-
case NumLiteral(_) => LiteralKind.number
234-
case TrueLiteral() => LiteralKind.boolean
235-
case FalseLiteral() => LiteralKind.boolean
236-
case StringLiteral(_) => LiteralKind.string
237-
case _ =>
238-
assert(assertion = false, s"unimplemented assignment case ${assignTo.toString}")
239-
LiteralKind.number
240-
}
241-
Seq(ExpressionStatement(FunctionCall(Identifier("sstore"),
242-
Seq(intlit(tempSymbolTable(x)), Literal(kind, e.toString, kind.toString))))) //todo: this is likely wrong for strings
243-
case e =>
244-
assert(assertion = false, "TODO: translate assignment case" + e.toString)
231+
//todo: easy optimization is to look at e; if it happens to be a literal we can save a temp.
232+
val id = nextTemp()
233+
val e_yul = translateExpr(id, e, contractName, checkedTable)
234+
decl_0exp(id) +:
235+
e_yul :+
236+
assign1(Identifier(x), id)
237+
case _ =>
238+
assert(assertion = false, "trying to assign to non-assignable: " + e.toString)
245239
Seq()
246240
}
247241
case IfThenElse(scrutinee, pos, neg) =>
248-
val id = nextTemp()
249-
val scrutinee_yul: Seq[YulStatement] = translateExpr(id, scrutinee, contractName, checkedTable)
250-
val pos_yul: Seq[YulStatement] = pos.flatMap(s => translateStatement(s, retVar, contractName, checkedTable))
251-
val neg_yul: Seq[YulStatement] = neg.flatMap(s => translateStatement(s, retVar, contractName, checkedTable))
252-
decl_0exp(id) +:
242+
val id_scrutinee: Identifier = nextTemp()
243+
val scrutinee_yul: Seq[YulStatement] = translateExpr(id_scrutinee, scrutinee, contractName, checkedTable)
244+
val pos_yul: Seq[YulStatement] =
245+
pos.flatMap(s => {
246+
val id_s: Identifier = nextTemp()
247+
decl_0exp(id_s) +: translateStatement(s, Some(id_s.name), contractName, checkedTable)
248+
})
249+
val neg_yul: Seq[YulStatement] =
250+
neg.flatMap(s => {
251+
val id_s: Identifier = nextTemp()
252+
decl_0exp(id_s) +: translateStatement(s, Some(id_s.name), contractName, checkedTable)
253+
})
254+
255+
decl_0exp(id_scrutinee) +:
253256
scrutinee_yul :+
254-
edu.cmu.cs.obsidian.codegen.Switch(id,
257+
edu.cmu.cs.obsidian.codegen.Switch(id_scrutinee,
255258
Seq(
256259
Case(boollit(true), Block(pos_yul)),
257260
Case(boollit(false), Block(neg_yul))))
258261
case e: Expression => translateExpr(nextTemp(), e, contractName, checkedTable)
259262
case VariableDecl(typ, varName) =>
260-
assert(assertion = false, s"TODO: translateStatement unimplemented for ${s.toString}")
261-
Seq()
263+
Seq(decl_0exp_t(Identifier(varName), typ))
262264
case VariableDeclWithInit(typ, varName, e) =>
263-
assert(assertion = false, s"TODO: translateStatement unimplemented for ${s.toString}")
264-
Seq()
265+
val id = nextTemp()
266+
val e_yul = translateExpr(id, e, contractName, checkedTable)
267+
decl_0exp(id) +:
268+
e_yul :+
269+
decl_0exp_t_init(Identifier(varName), typ, id)
265270
case VariableDeclWithSpec(typIn, typOut, varName) =>
266271
assert(assertion = false, s"TODO: translateStatement unimplemented for ${s.toString}")
267272
Seq()
@@ -271,9 +276,18 @@ object CodeGenYul extends CodeGenerator {
271276
case Revert(maybeExpr) =>
272277
assert(assertion = false, s"TODO: translateStatement unimplemented for ${s.toString}")
273278
Seq()
274-
case If(eCond, s) =>
275-
assert(assertion = false, s"TODO: translateStatement unimplemented for ${s.toString}")
276-
Seq()
279+
case If(scrutinee, s) =>
280+
val id_scrutinee: Identifier = nextTemp()
281+
val scrutinee_yul: Seq[YulStatement] = translateExpr(id_scrutinee, scrutinee, contractName, checkedTable)
282+
val s_yul: Seq[YulStatement] =
283+
s.flatMap(s => {
284+
val id_s: Identifier = nextTemp()
285+
decl_0exp(id_s) +: translateStatement(s, Some(id_s.name), contractName, checkedTable)
286+
})
287+
288+
decl_0exp(id_scrutinee) +:
289+
scrutinee_yul :+
290+
edu.cmu.cs.obsidian.codegen.If(id_scrutinee, Block(s_yul))
277291
case IfInState(e, ePerm, typeState, s1, s2) =>
278292
assert(assertion = false, s"TODO: translateStatement unimplemented for ${s.toString}")
279293
Seq()
@@ -325,7 +339,7 @@ object CodeGenYul extends CodeGenerator {
325339
case e: AtomicExpression =>
326340
e match {
327341
case ReferenceIdentifier(x) =>
328-
Seq(assign1(retvar, apply("sload", intlit(tempSymbolTable(x)))))
342+
Seq(assign1(retvar, Identifier(x))) //todo: in general this will need to know to look in memory / storage / stack
329343
case NumLiteral(n) =>
330344
Seq(assign1(retvar, intlit(n)))
331345
case StringLiteral(value) =>

0 commit comments

Comments
 (0)