Skip to content

Commit

Permalink
Represent type(f) correctly in the ast (#1609)
Browse files Browse the repository at this point in the history
This makes the ast correct, and also the following code is now parsed
correctly:
    
            function foo() {
                    type(int);
            }

 `type(enum-type).min` or `type(enum).min` is now supported. 

This fixes all the issues wrt `type(T)`  in the solc tests.

Signed-off-by: Sean Young <[email protected]>
  • Loading branch information
seanyoung authored Dec 16, 2023
1 parent 68b59a4 commit 92a6c6c
Show file tree
Hide file tree
Showing 20 changed files with 561 additions and 346 deletions.
10 changes: 0 additions & 10 deletions src/bin/languageserver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,16 +662,6 @@ impl<'a> Builder<'a> {
},
));
}
ast::Expression::CodeLiteral { loc, .. } => {
self.hovers.push((
loc.file_no(),
HoverEntry {
start: loc.start(),
stop: loc.exclusive_end(),
val: make_code_block("bytes"),
},
));
}
ast::Expression::NumberLiteral { loc, ty, value,.. } => {
if let Type::Enum(id) = ty {
self.references.push((
Expand Down
67 changes: 59 additions & 8 deletions src/codegen/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ use crate::sema::{
use crate::Target;
use num_bigint::{BigInt, Sign};
use num_traits::{FromPrimitive, One, ToPrimitive, Zero};
use solang_parser::pt;
use solang_parser::pt::{CodeLocation, Loc};
use solang_parser::pt::{self, CodeLocation, Loc};
use std::{cmp::Ordering, ops::Mul};

pub fn expression(
Expand Down Expand Up @@ -1006,6 +1005,22 @@ pub fn expression(
} if expr.len() == 1 && ns.target == Target::EVM => {
builtin_evm_gasprice(loc, expr, cfg, contract_no, func, ns, vartab, opt)
}
ast::Expression::Builtin {
loc,
tys,
kind: ast::Builtin::TypeMin | ast::Builtin::TypeMax,
..
} => {
let Ok((_, value)) = eval_const_number(expr, ns, &mut Diagnostics::default()) else {
unreachable!();
};

Expression::NumberLiteral {
loc: *loc,
ty: tys[0].clone(),
value,
}
}
ast::Expression::Builtin {
loc,
tys,
Expand Down Expand Up @@ -1051,7 +1066,6 @@ pub fn expression(
right,
opt,
),
ast::Expression::InterfaceId { loc, contract_no } => interfaceid(ns, *contract_no, loc),
ast::Expression::BoolLiteral { loc, value } => Expression::BoolLiteral {
loc: *loc,
value: *value,
Expand All @@ -1061,9 +1075,6 @@ pub fn expression(
ty: ty.clone(),
value: value.clone(),
},
ast::Expression::CodeLiteral {
loc, contract_no, ..
} => code(loc, *contract_no, ns, opt),
ast::Expression::NumberLiteral { loc, ty, value } => Expression::NumberLiteral {
loc: *loc,
ty: ty.clone(),
Expand Down Expand Up @@ -1145,8 +1156,9 @@ pub fn expression(
ty,
}
}

ast::Expression::List { .. } => unreachable!("List shall not appear in the CFG"),
ast::Expression::TypeOperator { .. } | ast::Expression::List { .. } => {
unreachable!("List and Type Operator shall not appear in the CFG")
}
}
}

Expand Down Expand Up @@ -2238,6 +2250,45 @@ fn expr_builtin(
value: 0.into(),
}
}
ast::Builtin::TypeName => {
let ast::Expression::TypeOperator {
ty: Type::Contract(no),
..
} = &args[0]
else {
unreachable!();
};

let value = ns.contracts[*no].id.name.as_bytes().to_owned();

Expression::BytesLiteral {
loc: *loc,
ty: Type::String,
value,
}
}
ast::Builtin::TypeInterfaceId => {
let ast::Expression::TypeOperator {
ty: Type::Contract(contract_no),
..
} = &args[0]
else {
unreachable!();
};

interfaceid(ns, *contract_no, loc)
}
ast::Builtin::TypeRuntimeCode | ast::Builtin::TypeCreatorCode => {
let ast::Expression::TypeOperator {
ty: Type::Contract(contract_no),
..
} = &args[0]
else {
unreachable!();
};

code(loc, *contract_no, ns, opt)
}
_ => {
let arguments: Vec<Expression> = args
.iter()
Expand Down
3 changes: 0 additions & 3 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ pub(crate) mod dispatch;
pub(crate) mod encoding;
mod events;
mod expression;
mod external_functions;
pub(super) mod polkadot;
mod reaching_definitions;
pub mod revert;
Expand Down Expand Up @@ -196,8 +195,6 @@ fn contract(contract_no: usize, ns: &mut Namespace, opt: &Options) {
let mut cfg_no = 0;
let mut all_cfg = Vec::new();

external_functions::add_external_functions(contract_no, ns);

// all the functions should have a cfg_no assigned, so we can generate call instructions to the correct function
for (_, func_cfg) in ns.contracts[contract_no].all_functions.iter_mut() {
*func_cfg = cfg_no;
Expand Down
62 changes: 35 additions & 27 deletions src/codegen/statements/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,37 +170,45 @@ pub(crate) fn statement(
}
}
Statement::Expression(_, _, expr) => {
if let ast::Expression::Assign { left, right, .. } = &expr {
if should_remove_assignment(left, func, opt, ns) {
let mut params = SideEffectsCheckParameters {
cfg,
contract_no,
func: Some(func),
ns,
vartab,
opt,
};
right.recurse(&mut params, process_side_effects_expressions);

return;
match expr {
ast::Expression::Assign { left, right, .. } => {
if should_remove_assignment(left, func, opt, ns) {
let mut params = SideEffectsCheckParameters {
cfg,
contract_no,
func: Some(func),
ns,
vartab,
opt,
};
right.recurse(&mut params, process_side_effects_expressions);

return;
}
}
} else if let ast::Expression::Builtin { args, .. } = expr {
// When array pop and push are top-level expressions, they can be removed
if should_remove_assignment(expr, func, opt, ns) {
let mut params = SideEffectsCheckParameters {
cfg,
contract_no,
func: Some(func),
ns,
vartab,
opt,
};
for arg in args {
arg.recurse(&mut params, process_side_effects_expressions);
ast::Expression::Builtin { args, .. } => {
// When array pop and push are top-level expressions, they can be removed
if should_remove_assignment(expr, func, opt, ns) {
let mut params = SideEffectsCheckParameters {
cfg,
contract_no,
func: Some(func),
ns,
vartab,
opt,
};
for arg in args {
arg.recurse(&mut params, process_side_effects_expressions);
}

return;
}

}
ast::Expression::TypeOperator { .. } => {
// just a stray type(int), no code to generate
return;
}
_ => (),
}

let _ = expression(expr, cfg, contract_no, Some(func), ns, vartab, opt);
Expand Down
33 changes: 17 additions & 16 deletions src/sema/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,8 @@ pub struct Function {
/// This indexmap stores the accounts this functions needs to be called on Solana
/// The string is the account's name
pub solana_accounts: RefCell<IndexMap<String, SolanaAccount>>,
/// List of contracts this function creates
pub creates: Vec<(pt::Loc, usize)>,
}

/// This struct represents a Solana account. There is no name field, because
Expand Down Expand Up @@ -463,6 +465,7 @@ impl Function {
annotations: ConstructorAnnotations::default(),
mangled_name_contracts: HashSet::new(),
solana_accounts: IndexMap::new().into(),
creates: Vec::new(),
}
}

Expand Down Expand Up @@ -888,12 +891,6 @@ pub enum Expression {
ty: Type,
value: Vec<u8>,
},
CodeLiteral {
loc: pt::Loc,
contract_no: usize,
// runtime code rather than deployer (evm only)
runtime: bool,
},
NumberLiteral {
loc: pt::Loc,
ty: Type,
Expand Down Expand Up @@ -1248,10 +1245,6 @@ pub enum Expression {
kind: Builtin,
args: Vec<Expression>,
},
InterfaceId {
loc: pt::Loc,
contract_no: usize,
},
List {
loc: pt::Loc,
list: Vec<Expression>,
Expand All @@ -1268,6 +1261,10 @@ pub enum Expression {
ty: Type,
event_no: usize,
},
TypeOperator {
loc: pt::Loc,
ty: Type,
},
}

#[derive(PartialEq, Eq, Clone, Default, Debug)]
Expand Down Expand Up @@ -1508,16 +1505,15 @@ impl Recurse for Expression {
}

Expression::NumberLiteral { .. }
| Expression::InterfaceId { .. }
| Expression::InternalFunction { .. }
| Expression::ConstantVariable { .. }
| Expression::StorageVariable { .. }
| Expression::Variable { .. }
| Expression::RationalNumberLiteral { .. }
| Expression::CodeLiteral { .. }
| Expression::BytesLiteral { .. }
| Expression::BoolLiteral { .. }
| Expression::EventSelector { .. } => (),
| Expression::EventSelector { .. }
| Expression::TypeOperator { .. } => (),
}
}
}
Expand All @@ -1528,7 +1524,6 @@ impl CodeLocation for Expression {
match self {
Expression::BoolLiteral { loc, .. }
| Expression::BytesLiteral { loc, .. }
| Expression::CodeLiteral { loc, .. }
| Expression::NumberLiteral { loc, .. }
| Expression::RationalNumberLiteral { loc, .. }
| Expression::StructLiteral { loc, .. }
Expand Down Expand Up @@ -1587,11 +1582,11 @@ impl CodeLocation for Expression {
| Expression::Assign { loc, .. }
| Expression::List { loc, list: _ }
| Expression::FormatString { loc, format: _ }
| Expression::InterfaceId { loc, .. }
| Expression::And { loc, .. }
| Expression::NamedMember { loc, .. }
| Expression::UserDefinedOperator { loc, .. }
| Expression::EventSelector { loc, .. } => *loc,
| Expression::EventSelector { loc, .. }
| Expression::TypeOperator { loc, .. } => *loc,
}
}
}
Expand Down Expand Up @@ -1777,6 +1772,12 @@ pub enum Builtin {
ECRecover,
StringConcat,
BytesConcat,
TypeMin,
TypeMax,
TypeName,
TypeInterfaceId,
TypeRuntimeCode,
TypeCreatorCode,
}

#[derive(PartialEq, Eq, Clone, Debug)]
Expand Down
44 changes: 12 additions & 32 deletions src/sema/dotgraphviz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,26 +293,6 @@ impl Dot {
Some(parent_rel),
);
}
Expression::CodeLiteral {
loc,
contract_no,
runtime,
} => {
let labels = vec![
format!(
"code {}literal contract {}",
if *runtime { "runtime " } else { "" },
ns.contracts[*contract_no].id,
),
ns.loc_to_string(PathDisplay::FullPath, loc),
];

self.add_node(
Node::new("code_literal", labels),
Some(parent),
Some(parent_rel),
);
}
Expression::NumberLiteral { loc, ty, value } => {
let labels = vec![
format!("{} literal: {}", ty.to_string(ns), value),
Expand Down Expand Up @@ -1362,18 +1342,6 @@ impl Dot {
self.add_expression(arg, func, ns, node, format!("arg #{no}"));
}
}
Expression::InterfaceId { loc, contract_no } => {
let labels = vec![
format!("interfaceid contract {}", ns.contracts[*contract_no].id),
ns.loc_to_string(PathDisplay::FullPath, loc),
];

self.add_node(
Node::new("interfaceid", labels),
Some(parent),
Some(parent_rel),
);
}
Expression::UserDefinedOperator {
loc,
oper,
Expand Down Expand Up @@ -1447,6 +1415,18 @@ impl Dot {
Some(parent_rel),
);
}
Expression::TypeOperator { loc, ty } => {
let labels = vec![
format!("type({})", ty.to_string(ns)),
ns.loc_to_string(PathDisplay::FullPath, loc),
];

self.add_node(
Node::new("type_operator", labels),
Some(parent),
Some(parent_rel),
);
}
}
}

Expand Down
Loading

0 comments on commit 92a6c6c

Please sign in to comment.