Skip to content

Commit bdb7221

Browse files
committed
Allow type declaration after ":" in let / let mut
1 parent c07f856 commit bdb7221

File tree

5 files changed

+92
-11
lines changed

5 files changed

+92
-11
lines changed

src/ast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,9 @@ impl<T> Stmt<T> {
269269
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
270270
pub enum StmtEnum<T> {
271271
/// Let expression, binds variables to exprs.
272-
Let(Pattern<T>, Expr<T>),
272+
Let(Pattern<T>, Option<Type>, Expr<T>),
273273
/// Mutable let expression, bind a single variable to an expr.
274-
LetMut(String, Expr<T>),
274+
LetMut(String, Option<Type>, Expr<T>),
275275
/// Assignment of a (previously as mutable declared) variable.
276276
VarAssign(String, Expr<T>),
277277
/// Assignment of an index in a (mutable) array.

src/check.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -627,12 +627,15 @@ impl UntypedStmt {
627627
) -> Result<TypedStmt, TypeErrors> {
628628
let meta = self.meta;
629629
match &self.inner {
630-
ast::StmtEnum::Let(pattern, binding) => {
630+
ast::StmtEnum::Let(pattern, ty, binding) => {
631631
match binding.type_check(top_level_defs, env, fns, defs) {
632-
Ok(binding) => {
632+
Ok(mut binding) => {
633+
if let Some(ty) = ty {
634+
check_type(&mut binding, ty)?;
635+
}
633636
let pattern =
634637
pattern.type_check(env, fns, defs, Some(binding.ty.clone()))?;
635-
Ok(Stmt::new(StmtEnum::Let(pattern, binding), meta))
638+
Ok(Stmt::new(StmtEnum::Let(pattern, ty.clone(), binding), meta))
636639
}
637640
Err(mut errors) => {
638641
if let Err(e) = pattern.type_check(env, fns, defs, None) {
@@ -642,9 +645,12 @@ impl UntypedStmt {
642645
}
643646
}
644647
}
645-
ast::StmtEnum::LetMut(identifier, binding) => {
648+
ast::StmtEnum::LetMut(identifier, ty, binding) => {
646649
match binding.type_check(top_level_defs, env, fns, defs) {
647650
Ok(mut binding) => {
651+
if let Some(ty) = ty {
652+
check_type(&mut binding, ty)?;
653+
}
648654
if binding.ty == Type::Unsigned(UnsignedNumType::Unspecified)
649655
|| binding.ty == Type::Signed(SignedNumType::Unspecified)
650656
{
@@ -662,7 +668,7 @@ impl UntypedStmt {
662668
(Some(binding.ty.clone()), Mutability::Mutable),
663669
);
664670
Ok(Stmt::new(
665-
StmtEnum::LetMut(identifier.clone(), binding),
671+
StmtEnum::LetMut(identifier.clone(), ty.clone(), binding),
666672
meta,
667673
))
668674
}

src/compile.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -374,13 +374,13 @@ impl TypedStmt {
374374
circuit: &mut CircuitBuilder,
375375
) -> Vec<GateIndex> {
376376
match &self.inner {
377-
StmtEnum::Let(pattern, binding) => {
377+
StmtEnum::Let(pattern, _, binding) => {
378378
let binding = binding.compile(prg, env, circuit);
379379
pattern.compile(&binding, prg, env, circuit);
380380
vec![]
381381
}
382382
StmtEnum::Expr(expr) => expr.compile(prg, env, circuit),
383-
StmtEnum::LetMut(identifier, binding) => {
383+
StmtEnum::LetMut(identifier, _, binding) => {
384384
let binding = binding.compile(prg, env, circuit);
385385
env.let_in_current_scope(identifier.clone(), binding);
386386
vec![]

src/parse.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -390,11 +390,17 @@ impl Parser {
390390
if self.next_matches(&TokenEnum::KeywordMut).is_some() {
391391
// let mut <identifier> = <binding>;
392392
let (identifier, _) = self.expect_identifier()?;
393+
let ty = if self.next_matches(&TokenEnum::Colon).is_some() {
394+
let (ty, _) = self.parse_type()?;
395+
Some(ty)
396+
} else {
397+
None
398+
};
393399
self.expect(&TokenEnum::Eq)?;
394400
if let Ok(binding) = self.parse_expr() {
395401
let meta = join_meta(meta, binding.meta);
396402
self.expect(&TokenEnum::Semicolon)?;
397-
return Ok(Stmt::new(StmtEnum::LetMut(identifier, binding), meta));
403+
return Ok(Stmt::new(StmtEnum::LetMut(identifier, ty, binding), meta));
398404
} else {
399405
self.push_error_for_next(ParseErrorEnum::ExpectedStmt);
400406
self.consume_until_one_of(&[TokenEnum::Semicolon]);
@@ -405,11 +411,17 @@ impl Parser {
405411
} else {
406412
// let <pattern> = <binding>;
407413
let pattern = self.parse_pattern()?;
414+
let ty = if self.next_matches(&TokenEnum::Colon).is_some() {
415+
let (ty, _) = self.parse_type()?;
416+
Some(ty)
417+
} else {
418+
None
419+
};
408420
self.expect(&TokenEnum::Eq)?;
409421
if let Ok(binding) = self.parse_expr() {
410422
let meta = join_meta(meta, binding.meta);
411423
self.expect(&TokenEnum::Semicolon)?;
412-
return Ok(Stmt::new(StmtEnum::Let(pattern, binding), meta));
424+
return Ok(Stmt::new(StmtEnum::Let(pattern, ty, binding), meta));
413425
} else {
414426
self.consume_until_one_of(&[TokenEnum::Semicolon]);
415427
self.expect(&TokenEnum::Semicolon)?;

tests/compile.rs

+63
Original file line numberDiff line numberDiff line change
@@ -2423,3 +2423,66 @@ pub fn main(array: [u16; PARTIES]) -> u16 {
24232423
);
24242424
Ok(())
24252425
}
2426+
2427+
#[test]
2428+
fn type_declaration_in_let() -> Result<(), Error> {
2429+
let prg = "
2430+
pub fn main(a: u16, b: u16) -> u16 {
2431+
let c: u16 = 6;
2432+
a + b + c
2433+
}
2434+
";
2435+
let compiled = compile(prg).map_err(|e| pretty_print(e, prg))?;
2436+
let mut eval = compiled.evaluator();
2437+
eval.set_u16(2);
2438+
eval.set_u16(4);
2439+
let output = eval.run().map_err(|e| pretty_print(e, prg))?;
2440+
assert_eq!(
2441+
u16::try_from(output).map_err(|e| pretty_print(e, prg))?,
2442+
2 + 4 + 6
2443+
);
2444+
Ok(())
2445+
}
2446+
2447+
#[test]
2448+
fn type_declaration_in_let_mut() -> Result<(), Error> {
2449+
let prg = "
2450+
pub fn main(a: u16, b: u16) -> u16 {
2451+
let mut result: u16 = 6;
2452+
result += a + b;
2453+
result
2454+
}
2455+
";
2456+
let compiled = compile(prg).map_err(|e| pretty_print(e, prg))?;
2457+
let mut eval = compiled.evaluator();
2458+
eval.set_u16(2);
2459+
eval.set_u16(4);
2460+
let output = eval.run().map_err(|e| pretty_print(e, prg))?;
2461+
assert_eq!(
2462+
u16::try_from(output).map_err(|e| pretty_print(e, prg))?,
2463+
2 + 4 + 6
2464+
);
2465+
Ok(())
2466+
}
2467+
2468+
#[test]
2469+
fn type_declaration_of_array_in_let_mut() -> Result<(), Error> {
2470+
let prg = "
2471+
pub fn main(a: u16, b: u16) -> u16 {
2472+
let mut result: [u16; 2] = [3, 3];
2473+
result[0] = result[0] + a;
2474+
result[1] = result[1] + b;
2475+
result[0] + result[1]
2476+
}
2477+
";
2478+
let compiled = compile(prg).map_err(|e| pretty_print(e, prg))?;
2479+
let mut eval = compiled.evaluator();
2480+
eval.set_u16(2);
2481+
eval.set_u16(4);
2482+
let output = eval.run().map_err(|e| pretty_print(e, prg))?;
2483+
assert_eq!(
2484+
u16::try_from(output).map_err(|e| pretty_print(e, prg))?,
2485+
2 + 4 + 3 + 3
2486+
);
2487+
Ok(())
2488+
}

0 commit comments

Comments
 (0)