Skip to content

Commit 49de311

Browse files
committed
Add support for ForLoop and If expressions; enhance expression handling in AST
1 parent 2fe647d commit 49de311

File tree

3 files changed

+104
-11
lines changed

3 files changed

+104
-11
lines changed

sdk/src/ast/build.rs

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use super::{
1212
contract::Contract,
1313
custom_type::{CustomType, EnumType, StructType, Type},
1414
expression::{
15-
Array, Assign, BinEx, Binary, Break, Cast, ConstBlock, EBlock, Expression, FunctionCall,
16-
Identifier, MemberAccess, MethodCall, Reference,
15+
Array, Assign, BinEx, Binary, Break, Cast, ConstBlock, EBlock, Expression, ForLoop,
16+
FunctionCall, Identifier, If, MemberAccess, MethodCall, Reference,
1717
},
1818
statement::{Block, Statement},
1919
};
@@ -254,20 +254,54 @@ pub(crate) fn build_block_statement(
254254
}))
255255
}
256256

257-
pub(crate) fn build_eblock_expression(block: &Rc<Block>) -> Expression {
258-
let id = Uuid::new_v4().as_u128();
257+
pub(crate) fn build_eblock_expression(block: &Rc<Block>, id: u128) -> Expression {
259258
Expression::EBlock(Rc::new(EBlock {
260259
id,
261260
location: block.location.clone(),
262261
block: block.clone(),
263262
}))
264263
}
265264

266-
pub(crate) fn build_const_block_expression(block: &Rc<Block>) -> Expression {
267-
let id = Uuid::new_v4().as_u128();
265+
pub(crate) fn build_const_block_expression(block: &Rc<Block>, id: u128) -> Expression {
268266
Expression::Const(Rc::new(ConstBlock {
269267
id,
270268
location: block.location.clone(),
271269
block: block.clone(),
272270
}))
273271
}
272+
273+
pub(crate) fn build_for_loop_expression(
274+
codebase: &mut Codebase<OpenState>,
275+
for_loop: &syn::ExprForLoop,
276+
block: &Rc<Block>,
277+
id: u128,
278+
) -> Expression {
279+
let expression = codebase.build_expression(&for_loop.expr, id, false);
280+
Expression::ForLoop(Rc::new(ForLoop {
281+
id,
282+
location: location!(for_loop),
283+
expression,
284+
block: block.clone(),
285+
}))
286+
}
287+
288+
pub(crate) fn build_if_expression(
289+
codebase: &mut Codebase<OpenState>,
290+
if_expr: &syn::ExprIf,
291+
then_branch: Rc<Block>,
292+
id: u128,
293+
) -> Expression {
294+
let condition = codebase.build_expression(&if_expr.cond, id, false);
295+
let else_branch = if let Some((_, else_expr)) = &if_expr.else_branch {
296+
Some(codebase.build_expression(else_expr, id, false))
297+
} else {
298+
None
299+
};
300+
Expression::If(Rc::new(If {
301+
id,
302+
location: location!(if_expr),
303+
condition,
304+
then_branch,
305+
else_branch,
306+
}))
307+
}

sdk/src/ast/expression.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ pub enum Expression {
2020
Closure(Rc<Closure>),
2121
Const(Rc<ConstBlock>),
2222
Continue(Rc<Continue>),
23+
ForLoop(Rc<ForLoop>),
2324
FunctionCall(Rc<FunctionCall>),
25+
If(Rc<If>),
2426
MethodCall(Rc<MethodCall>),
2527
MemberAccess(Rc<MemberAccess>),
2628
Reference(Rc<Reference>),
@@ -41,7 +43,9 @@ impl Expression {
4143
Expression::Closure(c) => c.id,
4244
Expression::Const(c) => c.id,
4345
Expression::Continue(c) => c.id,
46+
Expression::ForLoop(f) => f.id,
4447
Expression::FunctionCall(f) => f.id,
48+
Expression::If(i) => i.id,
4549
Expression::MethodCall(m) => m.id,
4650
Expression::MemberAccess(m) => m.id,
4751
Expression::Reference(r) => r.id,
@@ -62,7 +66,9 @@ impl Expression {
6266
Expression::Closure(c) => c.location.clone(),
6367
Expression::Const(c) => c.location.clone(),
6468
Expression::Continue(c) => c.location.clone(),
69+
Expression::ForLoop(f) => f.location.clone(),
6570
Expression::FunctionCall(f) => f.location.clone(),
71+
Expression::If(i) => i.location.clone(),
6672
Expression::MethodCall(m) => m.location.clone(),
6773
Expression::MemberAccess(m) => m.location.clone(),
6874
Expression::Reference(r) => r.location.clone(),
@@ -407,6 +413,25 @@ pub struct Continue {
407413
pub location: Location,
408414
}
409415

416+
#[node_location]
417+
#[derive(serde::Serialize, serde::Deserialize)]
418+
pub struct ForLoop {
419+
pub id: u128,
420+
pub location: Location,
421+
pub expression: Expression,
422+
pub block: Rc<Block>,
423+
}
424+
425+
#[node_location]
426+
#[derive(serde::Serialize, serde::Deserialize)]
427+
pub struct If {
428+
pub id: u128,
429+
pub location: Location,
430+
pub condition: Expression,
431+
pub then_branch: Rc<Block>,
432+
pub else_branch: Option<Expression>,
433+
}
434+
410435
#[cfg(test)]
411436
mod function_call_tests {
412437
use super::*;

sdk/src/codebase.rs

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ use crate::build::{
66
build_array_expression, build_assign_expresison, build_binary_expression,
77
build_block_statement, build_break_expression, build_cast_expression,
88
build_const_block_expression, build_contract, build_eblock_expression, build_enum_custom_type,
9-
build_identifier, build_member_access_expression, build_method_call_expression,
10-
build_reference_expression, build_struct_custom_type,
9+
build_for_loop_expression, build_identifier, build_if_expression,
10+
build_member_access_expression, build_method_call_expression, build_reference_expression,
11+
build_struct_custom_type,
1112
};
1213
use crate::custom_type::Type;
1314
use crate::errors::SDKErr;
@@ -322,10 +323,11 @@ impl Codebase<OpenState> {
322323
break_expr
323324
}
324325
syn::Expr::Block(block_expr) => {
326+
let id = Uuid::new_v4().as_u128();
325327
let block_statement = build_block_statement(self, &block_expr.block);
326-
self.add_node(NodeKind::Statement(block_statement.clone()), parent_id);
328+
self.add_node(NodeKind::Statement(block_statement.clone()), id);
327329
let block = match block_statement {
328-
Statement::Block(block) => build_eblock_expression(&block),
330+
Statement::Block(block) => build_eblock_expression(&block, id),
329331
_ => Expression::Empty,
330332
};
331333
self.add_node(
@@ -396,7 +398,7 @@ impl Codebase<OpenState> {
396398
let block_statement = build_block_statement(self, &expr_const.block);
397399
self.add_node(NodeKind::Statement(block_statement.clone()), id);
398400
let const_block = match block_statement {
399-
Statement::Block(block) => build_const_block_expression(&block),
401+
Statement::Block(block) => build_const_block_expression(&block, id),
400402
_ => Expression::Empty,
401403
};
402404
self.add_node(
@@ -416,6 +418,22 @@ impl Codebase<OpenState> {
416418
);
417419
cont_expr
418420
}
421+
syn::Expr::ForLoop(expr_forloop) => {
422+
let id = Uuid::new_v4().as_u128();
423+
let block_statement = build_block_statement(self, &expr_forloop.body);
424+
self.add_node(NodeKind::Statement(block_statement.clone()), id);
425+
let for_loop = match block_statement {
426+
Statement::Block(block) => {
427+
build_for_loop_expression(self, expr_forloop, &block, id)
428+
}
429+
_ => Expression::Empty,
430+
};
431+
self.add_node(
432+
NodeKind::Statement(Statement::Expression(for_loop.clone())),
433+
parent_id,
434+
);
435+
for_loop
436+
}
419437
syn::Expr::Field(field_expr) => {
420438
let reference = build_member_access_expression(self, field_expr, is_tried);
421439
self.add_node(
@@ -424,6 +442,22 @@ impl Codebase<OpenState> {
424442
);
425443
reference
426444
}
445+
syn::Expr::If(expr_if) => {
446+
let id = Uuid::new_v4().as_u128();
447+
let then_block = build_block_statement(self, &expr_if.then_branch);
448+
self.add_node(NodeKind::Statement(then_block.clone()), id);
449+
match then_block {
450+
Statement::Block(block) => {
451+
let if_expr = build_if_expression(self, expr_if, block.clone(), id);
452+
self.add_node(
453+
NodeKind::Statement(Statement::Expression(if_expr.clone())),
454+
parent_id,
455+
);
456+
if_expr
457+
}
458+
_ => Expression::Empty,
459+
}
460+
}
427461
syn::Expr::Try(expr_try) => self.build_expression(&expr_try.expr, parent_id, true),
428462
syn::Expr::MethodCall(method_call) => {
429463
let method_call = build_method_call_expression(self, method_call, is_tried);

0 commit comments

Comments
 (0)