diff --git a/ergotree-interpreter/src/eval/coll_append.rs b/ergotree-interpreter/src/eval/coll_append.rs index 7d02792fe..9e0f5a423 100644 --- a/ergotree-interpreter/src/eval/coll_append.rs +++ b/ergotree-interpreter/src/eval/coll_append.rs @@ -111,7 +111,7 @@ mod tests { fn append_byte_array_and_byte() { let byte_coll: Constant = vec![1i8, 2i8].into(); let byte: Expr = Expr::Collection(Collection::new(SType::SByte, vec![3i8.into()]).unwrap()); - let expr: Expr = Expr::Append(Append::new(byte_coll.into(), byte).unwrap()); + let expr: Expr = Expr::Append(Append::new(byte_coll.into(), byte).unwrap().into()); assert_eq!(eval_out_wo_ctx::>(&expr), vec![1i8, 2, 3]); } } diff --git a/ergotree-interpreter/src/eval/expr.rs b/ergotree-interpreter/src/eval/expr.rs index 3439ff78c..8929c2ed2 100644 --- a/ergotree-interpreter/src/eval/expr.rs +++ b/ergotree-interpreter/src/eval/expr.rs @@ -50,7 +50,7 @@ impl Evaluable for Expr { Expr::Upcast(op) => op.eval(env, ctx), Expr::Downcast(op) => op.eval(env, ctx), Expr::If(op) => op.eval(env, ctx), - Expr::Append(op) => op.eval(env, ctx), + Expr::Append(op) => op.expr().eval(env, ctx), Expr::ByIndex(op) => op.eval(env, ctx), Expr::ExtractScriptBytes(op) => op.eval(env, ctx), Expr::SizeOf(op) => op.eval(env, ctx), diff --git a/ergotree-ir/src/mir/expr.rs b/ergotree-ir/src/mir/expr.rs index d75cee57d..7b1943e65 100644 --- a/ergotree-ir/src/mir/expr.rs +++ b/ergotree-ir/src/mir/expr.rs @@ -80,11 +80,14 @@ use derive_more::From; use derive_more::TryInto; use thiserror::Error; +mod source_span; +pub use source_span::*; + #[derive(PartialEq, Eq, Debug, Clone, From, TryInto)] /// Expression in ErgoTree pub enum Expr { /// Append - Concatenation of two collections - Append(Append), + Append(SourceSpanWrapper), /// Constant value Const(Constant), /// Placeholder for a constant @@ -227,7 +230,7 @@ impl Expr { /// Type of the expression pub fn tpe(&self) -> SType { match self { - Expr::Append(ap) => ap.tpe(), + Expr::Append(ap) => ap.expr().tpe(), Expr::Const(v) => v.tpe.clone(), Expr::Collection(v) => v.tpe(), Expr::SubstConstants(v) => v.tpe(), diff --git a/ergotree-ir/src/mir/expr/source_span.rs b/ergotree-ir/src/mir/expr/source_span.rs new file mode 100644 index 000000000..07cac9179 --- /dev/null +++ b/ergotree-ir/src/mir/expr/source_span.rs @@ -0,0 +1,57 @@ +use crate::mir::coll_append::Append; + +use super::Expr; + +/// Source position for the Expr +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct SourceSpan { + /// Start position in the source code + pub start: usize, + /// End position in the source code + pub end: usize, +} + +impl SourceSpan { + /// Empty span + pub fn empty() -> Self { + SourceSpan { start: 0, end: 0 } + } +} + +/// Wrapper for Expr with source position +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct SourceSpanWrapper { + /// Source position + pub source_span: SourceSpan, + /// Wrapped value + pub expr: T, +} + +impl SourceSpanWrapper { + /// Expression + pub fn expr(&self) -> &T { + &self.expr + } +} + +// TODO: can be a macros +impl From for Expr { + fn from(v: Append) -> Self { + Expr::Append(SourceSpanWrapper { + source_span: SourceSpan::empty(), + expr: v, + }) + } +} + +impl From for SourceSpanWrapper { + fn from(v: T) -> Self { + SourceSpanWrapper { + source_span: SourceSpan::empty(), + expr: v, + } + } +} + +// TODO: draft pretty printer and how it's sets source span for every expr +// TODO: draft enriching eval errors with source span and hightlight it in the source code piece diff --git a/ergotree-ir/src/serialization/expr.rs b/ergotree-ir/src/serialization/expr.rs index f4b97ba50..d9fe3355b 100644 --- a/ergotree-ir/src/serialization/expr.rs +++ b/ergotree-ir/src/serialization/expr.rs @@ -222,7 +222,7 @@ impl SigmaSerializable for Expr { } None => c.sigma_serialize(w), }, - Expr::Append(ap) => ap.sigma_serialize_w_opcode(w), + Expr::Append(ap) => ap.expr().sigma_serialize_w_opcode(w), Expr::Fold(op) => op.sigma_serialize_w_opcode(w), Expr::ConstPlaceholder(cp) => cp.sigma_serialize_w_opcode(w), Expr::SubstConstants(s) => s.sigma_serialize_w_opcode(w),