Type checking fills in start/stop values for IterationStatement

This commit is contained in:
Pranav Gaddamadugu 2022-07-11 14:48:53 -07:00
parent 3b76574a78
commit ae13db1d4c
4 changed files with 47 additions and 9 deletions

View File

@ -32,6 +32,11 @@ pub enum Literal {
/// A group literal, either product or affine. /// A group literal, either product or affine.
/// For example, `42group` or `(12, 52)group`. /// For example, `42group` or `(12, 52)group`.
Group(Box<GroupLiteral>), Group(Box<GroupLiteral>),
/// A scalar literal, e.g. `1scalar`.
/// An unsigned number followed by the keyword `scalar`.
Scalar(String, #[serde(with = "leo_span::span_json")] Span),
/// A string literal, e.g., `"foobar"`.
String(String, #[serde(with = "leo_span::span_json")] Span),
/// An 8-bit signed integer literal, e.g., `42i8`. /// An 8-bit signed integer literal, e.g., `42i8`.
I8(String, #[serde(with = "leo_span::span_json")] Span), I8(String, #[serde(with = "leo_span::span_json")] Span),
/// A 16-bit signed integer literal, e.g., `42i16`. /// A 16-bit signed integer literal, e.g., `42i16`.
@ -42,11 +47,6 @@ pub enum Literal {
I64(String, #[serde(with = "leo_span::span_json")] Span), I64(String, #[serde(with = "leo_span::span_json")] Span),
/// A 128-bit signed integer literal, e.g., `42i128`. /// A 128-bit signed integer literal, e.g., `42i128`.
I128(String, #[serde(with = "leo_span::span_json")] Span), I128(String, #[serde(with = "leo_span::span_json")] Span),
/// A scalar literal, e.g. `1scalar`.
/// An unsigned number followed by the keyword `scalar`.
Scalar(String, #[serde(with = "leo_span::span_json")] Span),
/// A string literal, e.g., `"foobar"`.
String(String, #[serde(with = "leo_span::span_json")] Span),
/// A 8-bit unsigned integer literal, e.g., `42u8`. /// A 8-bit unsigned integer literal, e.g., `42u8`.
U8(String, #[serde(with = "leo_span::span_json")] Span), U8(String, #[serde(with = "leo_span::span_json")] Span),
/// A 16-bit unsigned integer literal, e.g., `42u16`. /// A 16-bit unsigned integer literal, e.g., `42u16`.

View File

@ -19,6 +19,7 @@ use crate::{Block, Expression, Identifier, Node, Type, Value};
use leo_span::Span; use leo_span::Span;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::cell::RefCell;
use std::fmt; use std::fmt;
/// A bounded `for` loop statement `for variable in start .. =? stop block`. /// A bounded `for` loop statement `for variable in start .. =? stop block`.
@ -32,12 +33,12 @@ pub struct IterationStatement {
pub start: Expression, pub start: Expression,
/// The concrete value of `start`. /// The concrete value of `start`.
#[serde(skip)] #[serde(skip)]
pub start_value: Box<Option<Value>>, pub start_value: RefCell<Option<Value>>,
/// The end of the iteration, possibly `inclusive`. /// The end of the iteration, possibly `inclusive`.
pub stop: Expression, pub stop: Expression,
/// The concrete value of `stop`. /// The concrete value of `stop`.
#[serde(skip)] #[serde(skip)]
pub stop_value: Box<Option<Value>>, pub stop_value: RefCell<Option<Value>>,
/// Whether `stop` is inclusive or not. /// Whether `stop` is inclusive or not.
/// Signified with `=` when parsing. /// Signified with `=` when parsing.
pub inclusive: bool, pub inclusive: bool,

View File

@ -14,9 +14,9 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{GroupLiteral, Identifier, Type}; use crate::{GroupLiteral, Identifier, Literal, Type};
use leo_errors::{type_name, FlattenError, LeoError, Result}; use leo_errors::{type_name, FlattenError, LeoError, Result, TypeCheckerError};
use leo_span::{Span, Symbol}; use leo_span::{Span, Symbol};
use indexmap::IndexMap; use indexmap::IndexMap;
@ -833,6 +833,32 @@ impl From<&Value> for Type {
} }
} }
// TODO: Consider making this `Option<Value>` instead of `Value`.
impl From<&Literal> for Value {
/// Converts a literal to a value.
/// This should only be invoked on literals that are known to be valid.
fn from(literal: &Literal) -> Self {
match literal {
Literal::Address(string, span) => Self::Address(string.clone(), span.clone()),
Literal::Boolean(bool, span) => Self::Boolean(bool.clone(), span.clone()),
Literal::Field(string, span) => Self::Field(string.clone(), span.clone()),
Literal::Group(group_literal) => Self::Group(group_literal.clone()),
Literal::Scalar(string, span) => Self::Scalar(string.clone(), span.clone()),
Literal::String(string, span) => Self::String(string.clone(), span.clone()),
Literal::I8(string, span) => Self::I8(string.parse::<i8>().unwrap(), span.clone()),
Literal::I16(string, span) => Self::I16(string.parse::<i16>().unwrap(), span.clone()),
Literal::I32(string, span) => Self::I32(string.parse::<i32>().unwrap(), span.clone()),
Literal::I64(string, span) => Self::I64(string.parse::<i64>().unwrap(), span.clone()),
Literal::I128(string, span) => Self::I128(string.parse::<i128>().unwrap(), span.clone()),
Literal::U8(string, span) => Self::U8(string.parse::<u8>().unwrap(), span.clone()),
Literal::U16(string, span) => Self::U16(string.parse::<u16>().unwrap(), span.clone()),
Literal::U32(string, span) => Self::U32(string.parse::<u32>().unwrap(), span.clone()),
Literal::U64(string, span) => Self::U64(string.parse::<u64>().unwrap(), span.clone()),
Literal::U128(string, span) => Self::U128(string.parse::<u128>().unwrap(), span.clone()),
}
}
}
// impl From<Value> for Literal { // impl From<Value> for Literal {
// fn from(v: Value) -> Self { // fn from(v: Value) -> Self {
// use Value::*; // use Value::*;

View File

@ -134,7 +134,18 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
self.symbol_table = RefCell::new(prev_st); self.symbol_table = RefCell::new(prev_st);
self.visit_expression(&input.start, iter_type); self.visit_expression(&input.start, iter_type);
// If `input.start` is a literal, instantiate it as a value.
if let Expression::Literal(literal) = &input.start {
input.start_value.replace(Some(Value::from(literal)));
}
self.visit_expression(&input.stop, iter_type); self.visit_expression(&input.stop, iter_type);
// If `input.stop` is a literal, instantiate it as a value.
if let Expression::Literal(literal) = &input.stop {
input.stop_value.replace(Some(Value::from(literal)));
}
} }
fn visit_console(&mut self, input: &'a ConsoleStatement) { fn visit_console(&mut self, input: &'a ConsoleStatement) {