Skip to content

Commit

Permalink
Allow declarations without rhs
Browse files Browse the repository at this point in the history
  • Loading branch information
danhper committed Jul 11, 2024
1 parent a0b895d commit dc11574
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 21 deletions.
25 changes: 23 additions & 2 deletions src/interpreter/env.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use futures_util::lock::Mutex;
use solang_parser::pt::{Expression, Identifier};
use std::{
collections::{HashMap, HashSet},
sync::Arc,
Expand All @@ -12,12 +13,12 @@ use alloy::{
signers::{ledger::HDPath, local::PrivateKeySigner, Signature},
transports::http::{Client, Http},
};
use anyhow::{anyhow, Result};
use anyhow::{anyhow, bail, Result};
use coins_ledger::{transports::LedgerAsync, Ledger};

use crate::{interpreter::Config, vendor::ledger_signer::LedgerSigner};

use super::{types::Type, Value};
use super::{evaluate_expression, types::Type, Value};

pub struct Env {
variables: Vec<HashMap<String, Value>>,
Expand Down Expand Up @@ -173,6 +174,26 @@ impl Env {
scope.insert(name.to_string(), value);
}

pub async fn init_variable(
&mut self,
name: &Option<Identifier>,
type_: &Expression,
initializer: &Option<Expression>,
) -> Result<()> {
let id = name.clone().ok_or(anyhow!("invalid declaration"))?.name;
let type_ = match evaluate_expression(self, Box::new(type_.clone())).await? {
Value::TypeObject(t) => t,
v => bail!("invalid type for variable, expected type, got {}", v),
};
let value = if let Some(e) = initializer {
evaluate_expression(self, Box::new(e.clone())).await?
} else {
type_.default_value()?
};
self.set_var(&id, value);
Ok(())
}

fn set_wallet<S>(&mut self, signer: S) -> Result<()>
where
S: TxSigner<Signature> + Send + Sync + 'static,
Expand Down
23 changes: 4 additions & 19 deletions src/interpreter/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,8 @@ pub async fn evaluate_contract_part(
env.set_var(&func.name, Value::Func(Function::UserDefined(func.clone())));
}
ContractPart::VariableDefinition(def) => {
let id = def.name.clone().ok_or(anyhow!("invalid declaration"))?.name;
if let Some(expr) = &def.initializer {
let result = evaluate_expression(env, Box::new(expr.clone())).await?;
env.set_var(&id, result.clone());
} else {
bail!("declarations need rhs")
}
env.init_variable(&def.name, &def.ty, &def.initializer)
.await?;
}
v => bail!("{} not supported", v),
}
Expand Down Expand Up @@ -246,18 +241,8 @@ pub fn evaluate_statement(
}

Statement::VariableDefinition(_, var, expr) => {
let id = var
.name
.clone()
.ok_or(anyhow!("invalid declaration {}", stmt))?
.name;
if let Some(e) = expr {
let result = evaluate_expression(env, Box::new(e.clone())).await?;
env.set_var(&id, result.clone());
Ok(StatementResult::Empty)
} else {
bail!("declarations need rhs")
}
env.init_variable(&var.name, &var.ty, expr).await?;
Ok(StatementResult::Empty)
}
stmt => bail!("statement {:?} not supported", stmt),
}
Expand Down
30 changes: 30 additions & 0 deletions src/interpreter/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,36 @@ impl TryFrom<Type> for DynSolType {
}

impl Type {
pub fn default_value(&self) -> Result<Value> {
let value = match self {
Type::Null => Value::Null,
Type::Address => Value::Addr(Address::ZERO),
Type::Bool => Value::Bool(false),
Type::Int(size) => Value::Int(I256::ZERO, *size),
Type::Uint(size) => Value::Uint(U256::ZERO, *size),
Type::FixBytes(size) => Value::FixBytes(B256::default(), *size),
Type::Bytes => Value::Bytes(vec![]),
Type::String => Value::Str("".to_string()),
Type::Array(_) => Value::Array(vec![]),
Type::FixedArray(t, size) => Value::Array(vec![t.default_value()?; *size]),
Type::NamedTuple(_, fields) => Value::NamedTuple(
"".to_string(),
fields
.iter()
.map(|(k, v)| v.default_value().map(|v_| (k.clone(), v_)))
.collect::<Result<IndexMap<_, _>>>()?,
),
Type::Tuple(types) => Value::Array(
types
.iter()
.map(|t| t.default_value())
.collect::<Result<Vec<_>>>()?,
),
_ => bail!("cannot get default value for type {}", self),
};
Ok(value)
}

pub fn is_int(&self) -> bool {
matches!(self, Type::Int(_) | Type::Uint(_))
}
Expand Down

0 comments on commit dc11574

Please sign in to comment.