ProvableHQ / leo

🦁 The Leo Programming Language. A Programming Language for Formally Verified, Zero-Knowledge Applications
https://leo-lang.org/
GNU General Public License v3.0
4.79k stars 635 forks source link

[Proposal] Type Casting Implementation #600

Open Protryon opened 3 years ago

Protryon commented 3 years ago

💥 Proposal

Context

See issue #438 .

What It Is

This proposal includes explicit upcasting and downcasting for integer type values with Rust-like syntax.

Syntax

type_cast_expression := primary_expression "as" type_ref
primary_expression := <prior definition of primary expression> | type_cast_expression

Rust-like syntax was chosen over C-like syntax to keep the parser logic as simple as possible, and avoid extra semantic ambiguity at AST level.

Explicit Cast Semantics

A given type_cast_expression is valid if:

  1. The target type and source type are both integers.

Downcasting will be evaluated with C-like bit truncation. Upcasting will be evaluated with normal unsigned/signed respective extension. Signedness casting will not modify the underlying bits at all, just coerce the type represented at asg/compiler level. (manifested in snarkos as moving bit gadgets between, for example, Uint8 -> Int8)

Upcasting bit extensions will be calculated BEFORE a signedness transformation if both are performed.

Examples:

let k: u32 = 5i32 as u32;
let m: u16 = 5u32 as u16;
let n: u16 = 5i32 as u16;
let n: u16 = -5i32 as u16;
let n: i8 = 255u16 as i8;

Implications

Possible Derivative Proposals

howardwu commented 3 years ago

@Protryon I think we should make all implicit upcasting explicit. In implementing a cryptographic primitive in Leo, it could be risky to support implicit upcasting. For the purposes of Leo, language safety matters a lot, and I realize this case would tradeoff ease-of-use for that slightly, but I do believe it's preferred

collinc97 commented 3 years ago

@Protryon I think we should make all implicit upcasting explicit. In implementing a cryptographic primitive in Leo, it could be risky to support implicit upcasting. For the purposes of Leo, language safety matters a lot, and I realize this case would tradeoff ease-of-use for that slightly, but I do believe it's preferred

I agree with Howard - use explicit syntax when upcasting. As a supporting data point, if we mirror the rust type casting syntax I expect developers familiar with rust to gravitate towards explicit casting for everything .

Protryon commented 3 years ago

@collinc97 @howardwu Implicit upcasting has been removed.

acoglio commented 3 years ago

The proposal looks good to me, and I agree with the explicitness of casting.

But to elaborate on the latter point a bit, I believe that:

bendyarm commented 3 years ago

One common operation people will want to do is to multiply two N-bit unsigned integers to get a single 2N-bit unsigned integer. Does this proposal handle that? I could see something like

function something (a: u8, b: u8) -> ...
   let c: u16 = (a * b) as u16;
   ...
bendyarm commented 3 years ago

When we discussed this proposal in meetings, I remember we also discussed overflow issues. Is this the right issue for that or do we need a separate issue? Right now, overflows are errors. But modular arithmetic in the integer types would be a nice feature. Maybe there could be two forms of the arithmetic operators on integers, strict and modular. E.g., let z = x mod+ y would discard an overflow.

acoglio commented 3 years ago

@Protryon I have a few questions about the current implementation:

Protryon commented 3 years ago
  1. Yes. integer -> integer only.
  2. yes, yes, yes, yes, yes, yes, yes
  3. not at the moment
  4. There are no implicit conversions, similar to rust.