1
1
package edu .cmu .cs .obsidian .codegen
2
2
3
3
import edu .cmu .cs .obsidian .CompilerOptions
4
- import edu .cmu .cs .obsidian .codegen .LiteralKind .LiteralKind
5
4
6
5
import java .io .{File , FileWriter }
7
6
import java .nio .file .{Files , Path , Paths }
@@ -17,7 +16,6 @@ import scala.collection.immutable.Map
17
16
object CodeGenYul extends CodeGenerator {
18
17
19
18
// TODO improve this temporary symbol table
20
- var tempSymbolTable : Map [String , Int ] = Map () // map from field identifiers to index in storage
21
19
var tempTableIdx : Int = 0 // counter indicating the next available slot in the table
22
20
var stateIdx : Int = - 1 // whether or not there is a state
23
21
var stateEnumMapping : Map [String , Int ] = Map () // map from state name to an enum value
@@ -156,7 +154,6 @@ object CodeGenYul extends CodeGenerator {
156
154
def translateField (f : Field ): Seq [YulStatement ] = {
157
155
// Reserve a slot in the storage by assigning a index in the symbol table
158
156
// since field declaration has not yet be assigned, there is no need to do sstore
159
- tempSymbolTable += f.name -> tempTableIdx
160
157
tempTableIdx += 1
161
158
Seq () // TODO: do we really mean to always return the empty sequence?
162
159
}
@@ -198,7 +195,6 @@ object CodeGenYul extends CodeGenerator {
198
195
}
199
196
}
200
197
201
-
202
198
Seq (FunctionDefinition (
203
199
transaction.name, // TODO rename transaction name (by adding prefix/suffix)
204
200
transaction.args.map(v => TypedName (v.varName, mapObsTypeToABI(v.typIn.toString))),
@@ -222,46 +218,55 @@ object CodeGenYul extends CodeGenerator {
222
218
case Some (retVarName) =>
223
219
val temp_id = nextTemp()
224
220
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 ()
226
225
case None => assert(assertion = false , " error: returning an expression from a transaction without a return type" )
227
226
Seq ()
228
227
}
229
228
case Assignment (assignTo, e) =>
230
229
assignTo match {
231
230
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)
245
239
Seq ()
246
240
}
247
241
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) +:
253
256
scrutinee_yul :+
254
- edu.cmu.cs.obsidian.codegen.Switch (id ,
257
+ edu.cmu.cs.obsidian.codegen.Switch (id_scrutinee ,
255
258
Seq (
256
259
Case (boollit(true ), Block (pos_yul)),
257
260
Case (boollit(false ), Block (neg_yul))))
258
261
case e : Expression => translateExpr(nextTemp(), e, contractName, checkedTable)
259
262
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))
262
264
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)
265
270
case VariableDeclWithSpec (typIn, typOut, varName) =>
266
271
assert(assertion = false , s " TODO: translateStatement unimplemented for ${s.toString}" )
267
272
Seq ()
@@ -271,9 +276,18 @@ object CodeGenYul extends CodeGenerator {
271
276
case Revert (maybeExpr) =>
272
277
assert(assertion = false , s " TODO: translateStatement unimplemented for ${s.toString}" )
273
278
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))
277
291
case IfInState (e, ePerm, typeState, s1, s2) =>
278
292
assert(assertion = false , s " TODO: translateStatement unimplemented for ${s.toString}" )
279
293
Seq ()
@@ -325,7 +339,7 @@ object CodeGenYul extends CodeGenerator {
325
339
case e : AtomicExpression =>
326
340
e match {
327
341
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
329
343
case NumLiteral (n) =>
330
344
Seq (assign1(retvar, intlit(n)))
331
345
case StringLiteral (value) =>
0 commit comments