Skip to content

Commit

Permalink
index trait working at LHS
Browse files Browse the repository at this point in the history
  • Loading branch information
xunilrj committed Aug 8, 2024
1 parent 589d3b9 commit 7d5a89f
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 213 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -209,54 +209,83 @@ fn type_check_slice(
_type_arguments: &[TypeArgument],
span: Span,
) -> Result<(ty::TyIntrinsicFunctionKind, TypeId), ErrorEmitted> {
if arguments.len() != 3 {
return Err(handler.emit_err(CompileError::IntrinsicIncorrectNumArgs {
name: kind.to_string(),
expected: 3,
span,
}));
}

// if arguments.len() != 3 {
// return Err(handler.emit_err(CompileError::IntrinsicIncorrectNumArgs {
// name: kind.to_string(),
// expected: 3,
// span,
// }));
// }
//
let type_engine = ctx.engines.te();
let engines = ctx.engines();

// start index argument
let start_type = type_engine.insert(
let uint64 = type_engine.insert(
engines,
TypeInfo::UnsignedInteger(IntegerBits::SixtyFour),
None,
);
let start_ty_expr = {

// check first argument
let first_argument_span = arguments[0].span.clone();
let first_argument_type = type_engine.insert(engines, TypeInfo::Unknown, None);
let first_argument_ty_expr = {
let ctx = ctx
.by_ref()
.with_help_text("")
.with_type_annotation(first_argument_type);
ty::TyExpression::type_check(handler, ctx, &arguments[0])?
};

// start index argument
let start_ty_expr = if let Some(v) = arguments.get(1) {
let start_type = type_engine.insert(
engines,
TypeInfo::UnsignedInteger(IntegerBits::SixtyFour),
None,
);

let ctx = ctx
.by_ref()
.with_help_text("")
.with_type_annotation(start_type);
ty::TyExpression::type_check(handler, ctx, &arguments[1])?
} else {
ty::TyExpression {
expression: ty::TyExpressionVariant::Literal(Literal::U64(0)),
return_type: uint64,
span: Span::dummy(),
}
};

// end index argument
let end_type = type_engine.insert(
engines,
TypeInfo::UnsignedInteger(IntegerBits::SixtyFour),
None,
);
let end_ty_expr = {
let end_ty_expr = if let Some(v) = arguments.get(2) {
let end_type = type_engine.insert(
engines,
TypeInfo::UnsignedInteger(IntegerBits::SixtyFour),
None,
);
let ctx = ctx
.by_ref()
.with_help_text("")
.with_type_annotation(end_type);
ty::TyExpression::type_check(handler, ctx, &arguments[2])?
};
} else {
let len = match &*type_engine.get(first_argument_ty_expr.return_type) {
TypeInfo::Ref {
referenced_type, ..
} => match &*type_engine.get(referenced_type.type_id) {
TypeInfo::Array(_, len) => len.val(),
x => unreachable!("{x:?}"),
},
_ => unreachable!(),
};

// check first argument
let first_argument_span = arguments[0].span.clone();
let first_argument_type = type_engine.insert(engines, TypeInfo::Unknown, None);
let first_argument_ty_expr = {
let ctx = ctx
.by_ref()
.with_help_text("")
.with_type_annotation(first_argument_type);
ty::TyExpression::type_check(handler, ctx, &arguments[0])?
ty::TyExpression {
expression: ty::TyExpressionVariant::Literal(Literal::U64(len as u64)),
return_type: uint64,
span: Span::dummy(),
}
};

// statically check start and end, if possible
Expand Down
91 changes: 73 additions & 18 deletions sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2506,6 +2506,31 @@ fn expr_to_expression(
Ok(expression)
}

fn fn_call_index_mut(
name: &'static str,
op_span: Span,
span: Span,
args: &[Expression],
) -> Result<Expression, ErrorEmitted> {
let call_path_binding = TypeBinding {
inner: CallPath {
prefixes: vec![],
suffix: Ident::new_with_override(name.into(), op_span.clone()),
is_absolute: true,
},
type_arguments: TypeArgs::Regular(vec![]),
span: op_span,
};
Ok(Expression {
kind: ExpressionKind::FunctionApplication(Box::new(FunctionApplicationExpression {
call_path_binding,
resolved_call_path_binding: None,
arguments: args.to_vec(),
})),
span,
})
}

fn op_call(
name: &'static str,
op_span: Span,
Expand Down Expand Up @@ -4441,24 +4466,54 @@ fn assignable_to_expression(
kind: ExpressionKind::Variable(name),
span,
},
ElementAccess::Index { target, arg } => Expression {
kind: ExpressionKind::ArrayIndex(ArrayIndexExpression {
prefix: Box::new(element_access_to_expression(
context,
handler,
engines,
*target,
span.clone(),
)?),
index: Box::new(expr_to_expression(
context,
handler,
engines,
*arg.into_inner(),
)?),
}),
span,
},
ElementAccess::Index { target, arg } => {
let target =
element_access_to_expression(context, handler, engines, *target, span.clone())?;
let target = Expression {
kind: ExpressionKind::IntrinsicFunction(IntrinsicFunctionExpression {
name: Ident::new_no_span("__slice".to_string()),
kind_binding: TypeBinding {
inner: Intrinsic::Slice,
type_arguments: TypeArgs::Regular(vec![]),
span: Span::dummy(),
},
arguments: vec![Expression {
kind: ExpressionKind::Ref(RefExpression {
to_mutable_value: true,
value: Box::new(target),
}),
span: span.clone(),
}],
}),
span: span.clone(),
};

let arg = expr_to_expression(context, handler, engines, *arg.inner)?;
let call =
fn_call_index_mut("index_mut", arg.span(), span.clone(), &vec![target, arg])?;
Expression {
kind: ExpressionKind::Deref(Box::new(call)),
span,
}
}
// ElementAccess::Index { target, arg } => Expression {
// kind: ExpressionKind::ArrayIndex(ArrayIndexExpression {
// prefix: Box::new(element_access_to_expression(
// context,
// handler,
// engines,
// *target,
// span.clone(),
// )?),
// index: Box::new(expr_to_expression(
// context,
// handler,
// engines,
// *arg.into_inner(),
// )?),
// }),
// span,
// },
ElementAccess::FieldProjection { target, name, .. } => {
let mut idents = vec![&name];
let mut base = &*target;
Expand Down
48 changes: 48 additions & 0 deletions sway-lib-core/src/ops.sw
Original file line number Diff line number Diff line change
Expand Up @@ -1258,3 +1258,51 @@ pub fn ok_str_eq() {
assert("" != "a");
assert("a" != "b");
}

// Index
pub trait Index<T> {
type Output;
fn index(self, index: T) -> &Self::Output;
}

pub trait IndexMut<T> {
type Output;
fn index_mut(self, index: T) -> &mut Self::Output;
}

impl<T> Index<u64> for &__slice[T] {
type Output = T;

fn index(self, index: u64) -> &Self::Output {
if index >= self.len() {
__revert(999);
}
__elem_at(self, index)
}
}

impl<T> Index<u64> for &mut __slice[T] {
type Output = T;

fn index(self, index: u64) -> &Self::Output {
if index >= self.len() {
__revert(999);
}
__elem_at(self, index)
}
}

impl<T> IndexMut<u64> for &mut __slice[T] {
type Output = T;

fn index_mut(self, index: u64) -> &mut T {
if index >= self.len() {
__revert(999);
}
__elem_at(self, index)
}
}

pub fn index_mut<T>(target: &mut __slice[T], index: u64) -> &mut T {
target.index_mut(index)
}
Loading

0 comments on commit 7d5a89f

Please sign in to comment.