Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Index operator using Index trait #6356

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions sway-core/src/language/parsed/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,6 @@ pub enum ExpressionKind {
DelineatedPath(Box<DelineatedPathExpression>),
/// A cast of a hash to an ABI for calling a contract.
AbiCast(Box<AbiCastExpression>),
ArrayIndex(ArrayIndexExpression),
StorageAccess(StorageAccessExpression),
IntrinsicFunction(IntrinsicFunctionExpression),
/// A control flow element which loops continually until some boolean expression evaluates as
Expand Down Expand Up @@ -532,7 +531,6 @@ impl PartialEqWithEngines for ExpressionKind {
lhs.eq(rhs, ctx)
}
(ExpressionKind::AbiCast(lhs), ExpressionKind::AbiCast(rhs)) => lhs.eq(rhs, ctx),
(ExpressionKind::ArrayIndex(lhs), ExpressionKind::ArrayIndex(rhs)) => lhs.eq(rhs, ctx),
(ExpressionKind::StorageAccess(lhs), ExpressionKind::StorageAccess(rhs)) => {
lhs.eq(rhs, ctx)
}
Expand Down
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 arguments.get(1).is_some() {
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 arguments.get(2).is_some() {
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
Original file line number Diff line number Diff line change
Expand Up @@ -324,13 +324,6 @@ impl ty::TyExpression {
ExpressionKind::Array(array_expression) => {
Self::type_check_array(handler, ctx.by_ref(), &array_expression.contents, span)
}
ExpressionKind::ArrayIndex(ArrayIndexExpression { prefix, index }) => {
let ctx = ctx
.by_ref()
.with_type_annotation(type_engine.insert(engines, TypeInfo::Unknown, None))
.with_help_text("");
Self::type_check_array_index(handler, ctx, prefix, index, span)
}
ExpressionKind::StorageAccess(StorageAccessExpression {
namespace_names,
field_names,
Expand Down Expand Up @@ -1883,85 +1876,6 @@ impl ty::TyExpression {
})
}

fn type_check_array_index(
handler: &Handler,
mut ctx: TypeCheckContext,
prefix: &Expression,
index: &Expression,
span: Span,
) -> Result<Self, ErrorEmitted> {
let type_engine = ctx.engines.te();
let engines = ctx.engines();

let mut current_prefix_te = Box::new({
let ctx = ctx
.by_ref()
.with_help_text("")
.with_type_annotation(type_engine.insert(engines, TypeInfo::Unknown, None));

ty::TyExpression::type_check(handler, ctx, prefix)?
});

let mut current_type = type_engine.get_unaliased(current_prefix_te.return_type);

let prefix_type_id = current_prefix_te.return_type;
let prefix_span = current_prefix_te.span.clone();

// Create the prefix part of the final array index expression.
// This might be an expression that directly evaluates to an array type,
// or an arbitrary number of dereferencing expressions where the last one
// dereference to an array type.
//
// We will either hit an array at the end or return an error, so the
// loop cannot be endless.
while !current_type.is_array() {
match &*current_type {
TypeInfo::Ref {
referenced_type, ..
} => {
let referenced_type_id = referenced_type.type_id;

current_prefix_te = Box::new(ty::TyExpression {
expression: ty::TyExpressionVariant::Deref(current_prefix_te),
return_type: referenced_type_id,
span: prefix_span.clone(),
});

current_type = type_engine.get_unaliased(referenced_type_id);
}
TypeInfo::ErrorRecovery(err) => return Err(*err),
_ => {
return Err(handler.emit_err(CompileError::NotIndexable {
actually: engines.help_out(prefix_type_id).to_string(),
span: prefix_span,
}))
}
};
}

let TypeInfo::Array(array_type_argument, _) = &*current_type else {
panic!("The current type must be an array.");
};

let index_te = {
let type_info_u64 = TypeInfo::UnsignedInteger(IntegerBits::SixtyFour);
let ctx = ctx
.with_help_text("Array index must be of type \"u64\".")
.with_type_annotation(type_engine.insert(engines, type_info_u64, None));

ty::TyExpression::type_check(handler, ctx, index)?
};

Ok(ty::TyExpression {
expression: ty::TyExpressionVariant::ArrayIndex {
prefix: current_prefix_te,
index: Box::new(index_te),
},
return_type: array_type_argument.type_id,
span,
})
}

fn type_check_intrinsic_function(
handler: &Handler,
ctx: TypeCheckContext,
Expand Down Expand Up @@ -2224,27 +2138,6 @@ impl ty::TyExpression {
indices.push(ty::ProjectionKind::TupleField { index, index_span });
expr = prefix;
}
ExpressionKind::ArrayIndex(ArrayIndexExpression { prefix, index }) => {
let type_info_u64 = TypeInfo::UnsignedInteger(IntegerBits::SixtyFour);
let ctx = ctx
.by_ref()
.with_help_text("Array index must be of type \"u64\".")
.with_type_annotation(type_engine.insert(
engines,
type_info_u64,
None,
));
let typed_index =
ty::TyExpression::type_check(handler, ctx, index.as_ref())
.unwrap_or_else(|err| {
ty::TyExpression::error(err, span.clone(), engines)
});
indices.push(ty::ProjectionKind::ArrayIndex {
index: Box::new(typed_index),
index_span: index.span(),
});
expr = prefix;
}
_ => {
return Err(
handler.emit_err(CompileError::InvalidExpressionOnLhs { span })
Expand Down
3 changes: 0 additions & 3 deletions sway-core/src/semantic_analysis/node_dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,9 +586,6 @@ impl Dependencies {
.gather_from_iter(array_expression.contents.iter(), |deps, expr| {
deps.gather_from_expr(engines, expr)
}),
ExpressionKind::ArrayIndex(ArrayIndexExpression { prefix, index, .. }) => self
.gather_from_expr(engines, prefix)
.gather_from_expr(engines, index),
ExpressionKind::Struct(struct_expression) => {
let StructExpression {
call_path_binding,
Expand Down
4 changes: 0 additions & 4 deletions sway-core/src/semantic_analysis/symbol_resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,10 +610,6 @@ impl ResolveSymbols for ExpressionKind {
expr.abi_name.resolve_symbols(handler, ctx.by_ref());
expr.address.resolve_symbols(handler, ctx.by_ref());
}
ExpressionKind::ArrayIndex(expr) => {
expr.index.resolve_symbols(handler, ctx.by_ref());
expr.prefix.resolve_symbols(handler, ctx.by_ref());
}
ExpressionKind::StorageAccess(_expr) => {}
ExpressionKind::IntrinsicFunction(expr) => {
expr.arguments
Expand Down
Loading
Loading