mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-23 18:21:38 +03:00
Add check for nested records; fix codegen for circuit nested in record
This commit is contained in:
parent
a26c452de2
commit
da7ff48b11
@ -111,7 +111,7 @@ impl fmt::Display for Type {
|
||||
Type::I32 => write!(f, "i32"),
|
||||
Type::I64 => write!(f, "i64"),
|
||||
Type::I128 => write!(f, "i128"),
|
||||
Type::Identifier(ref variable) => write!(f, "circuit {}", variable),
|
||||
Type::Identifier(ref variable) => write!(f, "{}", variable),
|
||||
Type::Scalar => write!(f, "scalar"),
|
||||
Type::String => write!(f, "string"),
|
||||
Type::U8 => write!(f, "u8"),
|
||||
|
@ -149,7 +149,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
writeln!(
|
||||
output_string,
|
||||
" {} as {}.private;", // todo: CAUTION private record variables only.
|
||||
name, type_,
|
||||
name, type_.to_string().to_lowercase(),
|
||||
)
|
||||
.expect("failed to write to string");
|
||||
}
|
||||
|
@ -121,6 +121,21 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
};
|
||||
check_has_field(sym::owner, Type::Address);
|
||||
check_has_field(sym::gates, Type::U64);
|
||||
|
||||
// Check that the record does not contain another record.
|
||||
for member in input.members.iter() {
|
||||
if let CircuitMember::CircuitVariable(_, Type::Identifier(identifier)) = member {
|
||||
if let Some(circuit) = self.symbol_table.borrow().lookup_circuit(identifier.name) {
|
||||
if circuit.is_record {
|
||||
self.emit_err(TypeCheckerError::record_cannot_contain_record(
|
||||
input.identifier.name,
|
||||
identifier.name,
|
||||
input.span(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure there are no tuple typed members.
|
||||
|
@ -288,4 +288,11 @@ create_messages!(
|
||||
msg: format!("Helper functions cannot have modes associated with their inputs."),
|
||||
help: Some("Consider removing the mode or adding a `@program` annotation to the function.".to_string()),
|
||||
}
|
||||
|
||||
@formatted
|
||||
record_cannot_contain_record {
|
||||
args: (parent_record: impl Display, child_record: impl Display),
|
||||
msg: format!("A record cannot contain another record."),
|
||||
help: Some(format!("Remove the record `{child_record} from `{parent_record}`.")),
|
||||
}
|
||||
);
|
||||
|
35
tests/compiler/records/nested_record.leo
Normal file
35
tests/compiler/records/nested_record.leo
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
*/
|
||||
|
||||
circuit Amount {
|
||||
amount: u64,
|
||||
amt: u64,
|
||||
}
|
||||
|
||||
record Token {
|
||||
// The token owner.
|
||||
owner: address,
|
||||
// The Aleo balance (in gates).
|
||||
gates: u64,
|
||||
// The token amount.
|
||||
amount: Amount,
|
||||
}
|
||||
|
||||
@program
|
||||
function mint(r0: address, r1: u64) -> Token {
|
||||
return Token {
|
||||
owner: r0,
|
||||
gates: 0u64,
|
||||
amount: Amount { amount: r1, amt: r1 },
|
||||
};
|
||||
}
|
||||
|
||||
@program
|
||||
function main(x: address) -> u64 {
|
||||
const c: u64 = 1u64;
|
||||
let t: Token = Token { owner: x, gates: 0u64, amount: Amount { amount: c, amt: c } };
|
||||
|
||||
return t.gates;
|
||||
}
|
22
tests/compiler/records/nested_record_fail.leo
Normal file
22
tests/compiler/records/nested_record_fail.leo
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
*/
|
||||
|
||||
record Foo {
|
||||
// The token owner.
|
||||
owner: address,
|
||||
// The Aleo balance (in gates).
|
||||
gates: u64,
|
||||
// The token amount.
|
||||
amount: u64,
|
||||
}
|
||||
|
||||
record Token {
|
||||
// The token owner.
|
||||
owner: address,
|
||||
// The Aleo balance (in gates).
|
||||
gates: u64,
|
||||
// The token amount.
|
||||
foo: Foo,
|
||||
}
|
9
tests/expectations/compiler/records/nested_record.out
Normal file
9
tests/expectations/compiler/records/nested_record.out
Normal file
@ -0,0 +1,9 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: no input
|
||||
initial_ast: e781700aae47b3e3e6fabae4bc8620588ce4a91c8ed500cd1bfb0005ba92f9a0
|
||||
unrolled_ast: e781700aae47b3e3e6fabae4bc8620588ce4a91c8ed500cd1bfb0005ba92f9a0
|
||||
ssa_ast: fdd24be71c71d34367fdd00465fa80391d89776c49e62ad13bea07385dfeb8f8
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372030]: A record cannot contain another record.\n --> compiler-test:12:1\n |\n 12 | record Token {\n 13 | // The token owner.\n 14 | owner: address,\n 15 | // The Aleo balance (in gates).\n 16 | gates: u64,\n 17 | // The token amount.\n 18 | foo: Foo,\n 19 | }\n | ^\n |\n = Remove the record `Foo from `Token`.\n"
|
Loading…
Reference in New Issue
Block a user