diff --git a/compiler/ast/src/expressions/literal.rs b/compiler/ast/src/expressions/literal.rs index 481dafc1db..ff6de5cfe9 100644 --- a/compiler/ast/src/expressions/literal.rs +++ b/compiler/ast/src/expressions/literal.rs @@ -32,6 +32,11 @@ pub enum Literal { /// A group literal, either product or affine. /// For example, `42group` or `(12, 52)group`. Group(Box), + /// 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`. I8(String, #[serde(with = "leo_span::span_json")] Span), /// 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), /// A 128-bit signed integer literal, e.g., `42i128`. 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`. U8(String, #[serde(with = "leo_span::span_json")] Span), /// A 16-bit unsigned integer literal, e.g., `42u16`. diff --git a/compiler/ast/src/statements/iteration.rs b/compiler/ast/src/statements/iteration.rs index 5e699f5f5a..185dc0cf13 100644 --- a/compiler/ast/src/statements/iteration.rs +++ b/compiler/ast/src/statements/iteration.rs @@ -19,6 +19,7 @@ use crate::{Block, Expression, Identifier, Node, Type, Value}; use leo_span::Span; use serde::{Deserialize, Serialize}; +use std::cell::RefCell; use std::fmt; /// A bounded `for` loop statement `for variable in start .. =? stop block`. @@ -32,12 +33,12 @@ pub struct IterationStatement { pub start: Expression, /// The concrete value of `start`. #[serde(skip)] - pub start_value: Box>, + pub start_value: RefCell>, /// The end of the iteration, possibly `inclusive`. pub stop: Expression, /// The concrete value of `stop`. #[serde(skip)] - pub stop_value: Box>, + pub stop_value: RefCell>, /// Whether `stop` is inclusive or not. /// Signified with `=` when parsing. pub inclusive: bool, diff --git a/compiler/ast/src/value/mod.rs b/compiler/ast/src/value/mod.rs index 7c533a40ed..5b4e77da5b 100644 --- a/compiler/ast/src/value/mod.rs +++ b/compiler/ast/src/value/mod.rs @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -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 indexmap::IndexMap; @@ -833,6 +833,32 @@ impl From<&Value> for Type { } } +// TODO: Consider making this `Option` 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::().unwrap(), span.clone()), + Literal::I16(string, span) => Self::I16(string.parse::().unwrap(), span.clone()), + Literal::I32(string, span) => Self::I32(string.parse::().unwrap(), span.clone()), + Literal::I64(string, span) => Self::I64(string.parse::().unwrap(), span.clone()), + Literal::I128(string, span) => Self::I128(string.parse::().unwrap(), span.clone()), + Literal::U8(string, span) => Self::U8(string.parse::().unwrap(), span.clone()), + Literal::U16(string, span) => Self::U16(string.parse::().unwrap(), span.clone()), + Literal::U32(string, span) => Self::U32(string.parse::().unwrap(), span.clone()), + Literal::U64(string, span) => Self::U64(string.parse::().unwrap(), span.clone()), + Literal::U128(string, span) => Self::U128(string.parse::().unwrap(), span.clone()), + } + } +} + // impl From for Literal { // fn from(v: Value) -> Self { // use Value::*; diff --git a/compiler/passes/src/type_checker/check_statements.rs b/compiler/passes/src/type_checker/check_statements.rs index 8dd52e0a30..413ec99da5 100644 --- a/compiler/passes/src/type_checker/check_statements.rs +++ b/compiler/passes/src/type_checker/check_statements.rs @@ -134,7 +134,18 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> { self.symbol_table = RefCell::new(prev_st); 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); + + // 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) {