Skip to content

Commit 3cbe2b9

Browse files
committed
Continued working on support for C static_assert statement
1 parent d6b3649 commit 3cbe2b9

File tree

5 files changed

+107
-6
lines changed

5 files changed

+107
-6
lines changed

src/asg/expr/kind.rs

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ pub enum ExprKind {
4646
InterpreterSyscall(InterpreterSyscallKind, Vec<Expr>),
4747
Break,
4848
Continue,
49+
StaticAssert(Box<TypedExpr>, Option<String>),
4950
}
5051

5152
// Make sure ExprKind doesn't accidentally become huge

src/c/translate/eval.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::c::{
66
use num_bigint::BigInt;
77
use num_traits::Zero;
88

9+
// NOTE: Should this combined with the delayed version that can happen during lowering?
910
pub fn evaluate_to_const_integer(expr: &Expr) -> Result<BigInt, ParseError> {
1011
match &expr.kind {
1112
ExprKind::Integer(integer) => {

src/lower/error.rs

+8
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub enum LowerErrorKind {
5353
CannotUseTraitDirectly {
5454
name: String,
5555
},
56+
StaticAssertFailed(Option<String>),
5657
Other {
5758
message: String,
5859
},
@@ -124,6 +125,13 @@ impl Display for LowerErrorKind {
124125
LowerErrorKind::CannotUseTraitDirectly { name } => {
125126
write!(f, "Cannot use trait '{}' directly", name)
126127
}
128+
LowerErrorKind::StaticAssertFailed(message) => {
129+
if let Some(message) = message {
130+
write!(f, "static_assert failed: {}", message)
131+
} else {
132+
write!(f, "static_assert failed!")
133+
}
134+
}
127135
LowerErrorKind::Other { message } => {
128136
write!(f, "{}", message)
129137
}

src/lower/expr/mod.rs

+84
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ use crate::{
1414
NumericMode, SignOrIndeterminate, StructLiteral, UnaryMathOperation, VariableStorageKey,
1515
},
1616
ast::{FloatSize, IntegerBits, IntegerRigidity},
17+
data_units::BitUnits,
1718
ir::{self, Break, IntegerSign, Literal, OverflowOperator, Value, ValueReference},
1819
lower::structure::mono,
1920
resolve::PolyCatalog,
2021
};
2122
use call::{lower_expr_call, lower_expr_poly_call};
23+
use num::{BigInt, FromPrimitive};
2224
use short_circuit::lower_short_circuiting_binary_operation;
2325

2426
pub fn lower_expr(
@@ -559,6 +561,88 @@ pub fn lower_expr(
559561

560562
Ok(ir::Value::Literal(Literal::Void))
561563
}
564+
ExprKind::StaticAssert(condition, message) => {
565+
// TODO: How would this to make sense in generic functions?
566+
// It would need access to polymorphs if used, so would only
567+
// be able to do it when lowering (here).
568+
// But if the condition doen't depend at all on polymorphs,
569+
// then ideally we would evaluate it only once regardless
570+
// of how many instances of the generic function are instatiated.
571+
// (including zero)
572+
573+
let evaluated = evaluate_const_integer_expr(builder, ir_module, &condition.expr, asg)?;
574+
575+
if evaluated.is_zero() {
576+
return Err(LowerErrorKind::StaticAssertFailed(message.clone()).at(expr.source));
577+
}
578+
579+
Ok(ir::Value::Literal(Literal::Void))
580+
}
581+
}
582+
}
583+
584+
#[derive(Clone, Debug)]
585+
pub struct EvaluatedConstInteger {
586+
pub signed: bool,
587+
pub bits: BitUnits,
588+
pub value: BigInt,
589+
}
590+
591+
impl EvaluatedConstInteger {
592+
pub fn is_zero(&self) -> bool {
593+
self.value == BigInt::ZERO
594+
}
595+
}
596+
597+
// NOTE: Should this be combined with the version that can happen at C parse-time?
598+
pub fn evaluate_const_integer_expr(
599+
builder: &mut Builder,
600+
ir_module: &ir::Module,
601+
condition: &asg::Expr,
602+
asg: &Asg,
603+
) -> Result<EvaluatedConstInteger, LowerError> {
604+
match &condition.kind {
605+
ExprKind::BooleanLiteral(value) => Ok(EvaluatedConstInteger {
606+
signed: false,
607+
bits: BitUnits::of(1),
608+
value: BigInt::from_u8(*value as u8).unwrap(),
609+
}),
610+
ExprKind::IntegerLiteral(_)
611+
| ExprKind::IntegerKnown(_)
612+
| ExprKind::EnumMemberLiteral(_) => todo!(),
613+
ExprKind::ResolvedNamedExpression(inner) => {
614+
evaluate_const_integer_expr(builder, ir_module, inner, asg)
615+
}
616+
ExprKind::Variable(_)
617+
| ExprKind::GlobalVariable(_)
618+
| ExprKind::FloatingLiteral(_, _)
619+
| ExprKind::String(_)
620+
| ExprKind::NullTerminatedString(_)
621+
| ExprKind::Null
622+
| ExprKind::Call(_)
623+
| ExprKind::PolyCall(_)
624+
| ExprKind::DeclareAssign(_)
625+
| ExprKind::BasicBinaryOperation(_) => todo!(),
626+
ExprKind::ShortCircuitingBinaryOperation(_) => todo!(),
627+
ExprKind::IntegerCast(_) => todo!(),
628+
ExprKind::IntegerExtend(_) => todo!(),
629+
ExprKind::IntegerTruncate(_) => todo!(),
630+
ExprKind::FloatExtend(_)
631+
| ExprKind::FloatToInteger(_)
632+
| ExprKind::IntegerToFloat(_)
633+
| ExprKind::Member(_)
634+
| ExprKind::StructLiteral(_)
635+
| ExprKind::UnaryMathOperation(_) => todo!(),
636+
ExprKind::Dereference(_) | ExprKind::AddressOf(_) | ExprKind::Conditional(_) => todo!(),
637+
ExprKind::While(_) | ExprKind::ArrayAccess(_) | ExprKind::Zeroed(_) => todo!(),
638+
ExprKind::SizeOf(_)
639+
| ExprKind::InterpreterSyscall(_, _)
640+
| ExprKind::Break
641+
| ExprKind::Continue
642+
| ExprKind::StaticAssert(_, _) => Err(LowerError::other(
643+
"Expected constant integer expression",
644+
condition.source,
645+
)),
562646
}
563647
}
564648

src/resolve/expr/mod.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -512,12 +512,19 @@ pub fn resolve_expr(
512512

513513
return Ok(inner);
514514
}
515-
ast::ExprKind::StaticAssert(_condition, _message) => {
516-
todo!(
517-
"resolve_expr - static_assert - {:?} {:?}",
518-
_condition,
519-
_message
520-
)
515+
ast::ExprKind::StaticAssert(condition, message) => {
516+
let condition = resolve_expr(
517+
ctx,
518+
condition,
519+
None,
520+
Initialized::Require,
521+
ResolveExprMode::RequireValue,
522+
)?;
523+
524+
return Ok(TypedExpr::new(
525+
asg::TypeKind::Void.at(ast_expr.source),
526+
ExprKind::StaticAssert(Box::new(condition), message.clone()).at(ast_expr.source),
527+
));
521528
}
522529
}?;
523530

0 commit comments

Comments
 (0)