Skip to content

Commit

Permalink
Merge pull request #43 from AntChainOpenLabs/support_tuple
Browse files Browse the repository at this point in the history
feature: support tuple type
  • Loading branch information
i-zhen authored Jan 29, 2024
2 parents 979c6e0 + eb2c415 commit cb07903
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 13 deletions.
8 changes: 8 additions & 0 deletions smart_ir/src/ir/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,14 @@ impl Type {
Type::Builtin(BuiltinType::MapIter)
}

pub fn tuple(types: Vec<Type>) -> Type {
let mut tuple_ele = vec![];
for _ty in types {
tuple_ele.push(_ty);
}
Type::Tuple(Rc::new(tuple_ele))
}

pub const fn storage_path() -> Type {
Type::Builtin(BuiltinType::StoragePath)
}
Expand Down
30 changes: 24 additions & 6 deletions yul_to_ir/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions yul_to_ir/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,13 @@ pub struct FunctionDefinition {
pub returns: Vec<TypedIdentifier>,
}

#[derive(Debug, Clone)]
pub struct FunctionDeclaration {
pub name: Identifier,
pub params: Vec<TypedIdentifier>,
pub returns: Vec<TypedIdentifier>,
}

pub type TypedIdentifierList = Vec<TypedIdentifier>;

#[derive(Debug, Clone)]
Expand Down
3 changes: 2 additions & 1 deletion yul_to_ir/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{cell::RefCell, rc::Rc};
use indexmap::IndexMap;
use smart_ir::ir::{builder::IdentifierId, cfg::Type};

use crate::ast::Object;
use crate::ast::{FunctionDeclaration, Object};

pub const WORD_SIZE: usize = 256 / 8;
pub const WORD_TY: Type = Type::u256();
Expand All @@ -32,6 +32,7 @@ pub struct Yul2IRContext {
pub return_data_id: RefCell<IdentifierId>,
pub current_module_name: RefCell<String>,
pub current_contract_name: RefCell<String>,
pub current_func_decls: RefCell<IndexMap<String, FunctionDeclaration>>,
}

impl Yul2IRContext {
Expand Down
29 changes: 27 additions & 2 deletions yul_to_ir/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,32 @@
use crate::context::Yul2IRContext;
use crate::yul;
use smart_ir::ir::printer::IRPrinter;
#[test]
fn yul_parser_tuple_test() {
let expr = yul::ObjectParser::new().parse(
r#"
object "Token" {
code {
function selector_ret() -> s, z {
s := div(calldataload(0), 0x100000000000000000000000000000000000000000000000000000000)
z := div(calldataload(0), 0x100000000000000000000000000000000000000000000000000000000)
}
function selector_call() {
let a, b := selector_ret()
}
}
}
"#,
).unwrap();
println!("{:?}", expr);
let mut context = Yul2IRContext::new_with_object(expr);
context.transform().unwrap();
let mut p = IRPrinter::new(&context.ir_context);
let mut w = String::new();
p.print_modules(&mut w).unwrap();
println!("{}", w);
}

#[test]
fn yul_parser_erc20_test() {
Expand Down Expand Up @@ -269,9 +295,8 @@ fn yul2ir() {
emitTransfer(from, to, amount)
}
function selector() -> s, z {
function selector() -> s {
s := div(calldataload(0), 0x100000000000000000000000000000000000000000000000000000000)
z := div(calldataload(0), 0x100000000000000000000000000000000000000000000000000000000)
}
function decodeAsAddress(offset) -> v {
Expand Down
96 changes: 92 additions & 4 deletions yul_to_ir/src/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use std::{cell::RefCell, rc::Rc};

use crate::ast::FunctionDeclaration;
use crate::{
ast::{
self, Block, Expression, FunctionCall, FunctionDefinition, Identifier, IfElse,
Expand All @@ -14,6 +15,7 @@ use crate::{
};
use indexmap::IndexMap;
use num_bigint::BigInt;
use smart_ir::ir::cfg::IntLiteral;
use smart_ir::ir::{
builder::{IdentifierId, Label},
cfg::{self, Contract, Expr, Literal, Module, Type},
Expand Down Expand Up @@ -185,9 +187,7 @@ impl Yul2IRContext {
self.parse_ty_name(&var_decl.identifiers[0].type_name),
),
_ => {
return Err(ASTLoweringError {
message: "not support multiple decl".to_string(),
})
return self.walk_tuple_variable_declaration(var_decl);
}
};

Expand All @@ -209,6 +209,69 @@ impl Yul2IRContext {
self.ok_result()
}

fn walk_tuple_variable_declaration(
&self,
var_decl: &crate::ast::VariableDeclaration,
) -> CompileResult {
let mut ret_tys = vec![];
if let Some(value) = &var_decl.value {
ret_tys = match value {
Expression::FunctionCall(func) => {
let func_name = self.current_func_decls.borrow();
let func_decl = func_name.get(&func.id.name).clone();
func_decl.unwrap().returns.clone().into_iter().map(
| x | self.parse_ty_name(&x.type_name)
).collect::<Vec<Type>>()
}
_ => {
vec![]
}
};
}

let ty = cfg::Type::tuple(ret_tys);

let id = self.ir_context.builder.get_ident_id();
self.set_id_type(id, ty.clone());
let init_val = match &var_decl.value {
Some(val) => Some(self.walk_expr(val)?),
None => None,
};

self.ir_context
.builder
.build_declaration(id.clone().into(), init_val, ty);

let id_expr = Expr::Identifier(id);

for (index, i) in var_decl.identifiers.iter().enumerate() {
let _name = i.identifier.name.clone();
let _ty = self.parse_ty_name(&i.type_name);
let _id = self.ir_context.builder.get_ident_id();
self.vars.borrow_mut().insert(_name, _id);
self.set_id_type(_id, _ty.clone());

let instr = self.ir_context.builder.instr_call(
get_intrinsic_func_by_key(IntrinsicFuncName::IR_TUPLE_GET)
.unwrap()
.into(),
vec![
id_expr.clone(),
Expr::Literal(Literal::Int(IntLiteral::I32(index as i32))),
],
cfg::Type::u256(),
);

self.ir_context.builder.build_declaration(
_id.clone().into(),
Some(Expr::Instr(Box::new(instr))),
_ty,
);
}

self.ok_result()
}

fn walk_typed_identifier(&self, typed_id: &crate::ast::TypedIdentifier) -> CompileResult {
self.walk_identifier(&typed_id.identifier);
if let Some(ty) = &typed_id.type_name {
Expand All @@ -232,7 +295,15 @@ impl Yul2IRContext {
}
let module_name = self.current_module_name.borrow().clone();
let contract_name = self.current_contract_name.borrow().clone();
let ret_ty = WORD_TY;
let current_func_decls = self.current_func_decls.borrow();
let mut ret_ty = WORD_TY;
if let Some(func_ret_ty) = current_func_decls.get(&func_name) {
if func_ret_ty.returns.len() > 1 {
ret_ty = Type::tuple(func_ret_ty.returns.clone().into_iter().map(
| x | self.parse_ty_name(&x.type_name)
).collect::<Vec<Type>>());
}
}
let mut args = func_call
.arguments
.iter()
Expand Down Expand Up @@ -433,6 +504,23 @@ impl Yul2IRContext {
functions: IndexMap::new(),
};

for func in object.code.statements.iter().filter(|stmt| match stmt {
crate::ast::Statement::FunctionDefinition(_) => true,
_ => false,
}) {
let mut func_decls = self.current_func_decls.borrow_mut();
if let ast::Statement::FunctionDefinition(func_def) = func {
func_decls.insert(
func_def.name.name.clone(),
FunctionDeclaration {
name: func_def.name.clone(),
params: func_def.params.clone(),
returns: func_def.returns.clone(),
},
);
}
}

for func in object.code.statements.iter().filter(|stmt| match stmt {
crate::ast::Statement::FunctionDefinition(_) => true,
_ => false,
Expand Down

0 comments on commit cb07903

Please sign in to comment.