use crate::codegen::cfg::{ControlFlowGraph, Instr};
use crate::codegen::expression::expression;
use crate::codegen::interface::EventEmitter;
use crate::codegen::interface::TargetCodegen;
use crate::codegen::targets::soroban::encoding::soroban_encode_arg;
use crate::codegen::vartable::Vartable;
use crate::codegen::{Expression, Options};
use crate::sema::ast::{self, Function, Namespace, Type};
use num_bigint::BigInt;
use solang_parser::pt;
pub(crate) struct SorobanEventEmitter<'a> {
pub(crate) args: &'a [ast::Expression],
pub(crate) ns: &'a Namespace,
pub(crate) event_no: usize,
}
impl EventEmitter for SorobanEventEmitter<'_> {
fn selector(&self, _: usize) -> Vec<u8> {
vec![]
}
fn emit(
&self,
contract_no: usize,
func: &Function,
cfg: &mut ControlFlowGraph,
vartab: &mut Vartable,
opt: &Options,
target: &dyn TargetCodegen,
) {
let event = &self.ns.events[self.event_no];
let mut topics: Vec<Expression> = Vec::new();
let mut data_args: Vec<Expression> = Vec::new();
for (ast_exp, field) in self.args.iter().zip(event.fields.iter()) {
let value = expression(
ast_exp,
cfg,
contract_no,
Some(func),
self.ns,
vartab,
opt,
target,
);
let encoded = soroban_encode_arg(value, cfg, vartab, self.ns);
if field.indexed {
topics.push(encoded);
} else {
data_args.push(encoded);
}
}
let data = data_args
.into_iter()
.next()
.unwrap_or_else(|| Expression::NumberLiteral {
loc: pt::Loc::Codegen,
ty: Type::Uint(64),
value: BigInt::from(0u64),
});
cfg.add(
vartab,
Instr::EmitEvent {
event_no: self.event_no,
data,
topics,
},
);
}
}