mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-23 23:23:50 +03:00
add circuit type parsing up to type checking
This commit is contained in:
parent
3882ec2425
commit
993b86e8c7
@ -36,4 +36,3 @@ impl fmt::Display for MemberAccess {
|
||||
write!(f, "{}.{}", self.inner, self.name)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,4 +38,3 @@ impl fmt::Display for StaticAccess {
|
||||
write!(f, "{}::{}", self.inner, self.name)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,4 +53,4 @@ impl fmt::Display for Circuit {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.format(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,4 +60,4 @@ impl fmt::Display for CircuitMember {
|
||||
CircuitMember::CircuitFunction(ref function) => write!(f, "{}", function),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,4 +18,4 @@ pub mod circuit;
|
||||
pub use circuit::*;
|
||||
|
||||
pub mod circuit_member;
|
||||
pub use circuit_member::*;
|
||||
pub use circuit_member::*;
|
||||
|
@ -45,4 +45,3 @@ impl fmt::Display for AccessExpression {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,25 +44,26 @@ pub use unary::*;
|
||||
mod value;
|
||||
pub use value::*;
|
||||
|
||||
|
||||
/// Expression that evaluates to a value.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Expression {
|
||||
/// An identifier expression.
|
||||
Identifier(Identifier),
|
||||
/// A literal expression.
|
||||
Value(ValueExpression),
|
||||
/// A binary expression, e.g., `42 + 24`.
|
||||
Binary(BinaryExpression),
|
||||
/// An unary expression.
|
||||
Unary(UnaryExpression),
|
||||
/// A ternary conditional expression `cond ? if_expr : else_expr`.
|
||||
Ternary(TernaryExpression),
|
||||
/// A call expression, e.g., `my_fun(args)`.
|
||||
Call(CallExpression),
|
||||
/// An expression constructing a structure like `Foo { bar: 42, baz }`.
|
||||
CircuitInit(CircuitInitExpression),
|
||||
/// An expression of type "error".
|
||||
/// Will result in a compile error eventually.
|
||||
Err(ErrExpression),
|
||||
/// An identifier expression.
|
||||
Identifier(Identifier),
|
||||
/// A ternary conditional expression `cond ? if_expr : else_expr`.
|
||||
Ternary(TernaryExpression),
|
||||
/// An unary expression.
|
||||
Unary(UnaryExpression),
|
||||
/// A literal expression.
|
||||
Value(ValueExpression),
|
||||
}
|
||||
|
||||
impl Node for Expression {
|
||||
@ -75,6 +76,7 @@ impl Node for Expression {
|
||||
Unary(n) => n.span(),
|
||||
Ternary(n) => n.span(),
|
||||
Call(n) => n.span(),
|
||||
CircuitInit(n) => n.span(),
|
||||
Err(n) => n.span(),
|
||||
}
|
||||
}
|
||||
@ -88,6 +90,7 @@ impl Node for Expression {
|
||||
Unary(n) => n.set_span(span),
|
||||
Ternary(n) => n.set_span(span),
|
||||
Call(n) => n.set_span(span),
|
||||
CircuitInit(n) => n.set_span(span),
|
||||
Err(n) => n.set_span(span),
|
||||
}
|
||||
}
|
||||
@ -103,6 +106,7 @@ impl fmt::Display for Expression {
|
||||
Unary(n) => n.fmt(f),
|
||||
Ternary(n) => n.fmt(f),
|
||||
Call(n) => n.fmt(f),
|
||||
CircuitInit(n) => n.fmt(f),
|
||||
Err(n) => n.fmt(f),
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
|
||||
Expression::Unary(unary) => Expression::Unary(self.reduce_unary(unary)?),
|
||||
Expression::Ternary(ternary) => Expression::Ternary(self.reduce_ternary(ternary)?),
|
||||
Expression::Call(call) => Expression::Call(self.reduce_call(call)?),
|
||||
Expression::CircuitInit(circuit_init) => Expression::CircuitInit(self.reduce_circuit_init(circuit_init)?),
|
||||
Expression::Err(s) => Expression::Err(s.clone()),
|
||||
};
|
||||
|
||||
@ -257,13 +258,19 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
|
||||
}
|
||||
|
||||
let mut functions = IndexMap::new();
|
||||
let mut circuits = IndexMap::new();
|
||||
for (name, function) in program.functions.iter() {
|
||||
functions.insert(*name, self.reduce_function(function)?);
|
||||
}
|
||||
for (name, circuit) in program.circuits.iter() {
|
||||
circuits.insert(*name, self.reduce_circuit(circuit)?);
|
||||
}
|
||||
|
||||
self.reducer.reduce_program(program, inputs, functions)
|
||||
self.reducer.reduce_program(program, inputs, functions, circuits)
|
||||
}
|
||||
|
||||
// Functions
|
||||
|
||||
pub fn reduce_function_input_variable(
|
||||
&mut self,
|
||||
variable: &FunctionInputVariable,
|
||||
@ -299,4 +306,62 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
|
||||
self.reducer
|
||||
.reduce_function(function, identifier, inputs, output, block)
|
||||
}
|
||||
|
||||
// Circuits
|
||||
|
||||
pub fn reduce_circuit_variable_initializer(
|
||||
&mut self,
|
||||
variable: &CircuitVariableInitializer,
|
||||
) -> Result<CircuitVariableInitializer> {
|
||||
let identifier = self.reduce_identifier(&variable.identifier)?;
|
||||
let expression = variable
|
||||
.expression
|
||||
.as_ref()
|
||||
.map(|expr| self.reduce_expression(expr))
|
||||
.transpose()?;
|
||||
|
||||
self.reducer
|
||||
.reduce_circuit_variable_initializer(variable, identifier, expression)
|
||||
}
|
||||
|
||||
pub fn reduce_circuit_init(&mut self, circuit_init: &CircuitInitExpression) -> Result<CircuitInitExpression> {
|
||||
let name = self.reduce_identifier(&circuit_init.name)?;
|
||||
|
||||
let mut members = vec![];
|
||||
for member in circuit_init.members.iter() {
|
||||
members.push(self.reduce_circuit_variable_initializer(member)?);
|
||||
}
|
||||
|
||||
self.reducer.reduce_circuit_init(circuit_init, name, members)
|
||||
}
|
||||
|
||||
pub fn reduce_circuit_member(&mut self, circuit_member: &CircuitMember) -> Result<CircuitMember> {
|
||||
let new = match circuit_member {
|
||||
CircuitMember::CircuitConst(identifier, type_, value) => CircuitMember::CircuitConst(
|
||||
self.reduce_identifier(identifier)?,
|
||||
self.reduce_type(type_, &identifier.span)?,
|
||||
self.reduce_expression(value)?,
|
||||
),
|
||||
CircuitMember::CircuitVariable(identifier, type_) => CircuitMember::CircuitVariable(
|
||||
self.reduce_identifier(identifier)?,
|
||||
self.reduce_type(type_, &identifier.span)?,
|
||||
),
|
||||
CircuitMember::CircuitFunction(function) => {
|
||||
CircuitMember::CircuitFunction(Box::new(self.reduce_function(function)?))
|
||||
}
|
||||
};
|
||||
|
||||
self.reducer.reduce_circuit_member(circuit_member, new)
|
||||
}
|
||||
|
||||
pub fn reduce_circuit(&mut self, circuit: &Circuit) -> Result<Circuit> {
|
||||
let circuit_name = self.reduce_identifier(&circuit.circuit_name)?;
|
||||
|
||||
let mut members = vec![];
|
||||
for member in circuit.members.iter() {
|
||||
members.push(self.reduce_circuit_member(member)?);
|
||||
}
|
||||
|
||||
self.reducer.reduce_circuit(circuit, circuit_name, members)
|
||||
}
|
||||
}
|
||||
|
@ -246,11 +246,13 @@ pub trait ReconstructingReducer {
|
||||
program: &Program,
|
||||
expected_input: Vec<FunctionInput>,
|
||||
functions: IndexMap<Identifier, Function>,
|
||||
circuits: IndexMap<Identifier, Circuit>,
|
||||
) -> Result<Program> {
|
||||
Ok(Program {
|
||||
name: program.name.clone(),
|
||||
expected_input,
|
||||
functions,
|
||||
circuits,
|
||||
})
|
||||
}
|
||||
|
||||
@ -294,4 +296,39 @@ pub trait ReconstructingReducer {
|
||||
span: function.span,
|
||||
})
|
||||
}
|
||||
|
||||
fn reduce_circuit_variable_initializer(
|
||||
&mut self,
|
||||
_variable: &CircuitVariableInitializer,
|
||||
identifier: Identifier,
|
||||
expression: Option<Expression>,
|
||||
) -> Result<CircuitVariableInitializer> {
|
||||
Ok(CircuitVariableInitializer { identifier, expression })
|
||||
}
|
||||
|
||||
fn reduce_circuit_init(
|
||||
&mut self,
|
||||
circuit_init: &CircuitInitExpression,
|
||||
name: Identifier,
|
||||
members: Vec<CircuitVariableInitializer>,
|
||||
) -> Result<CircuitInitExpression> {
|
||||
Ok(CircuitInitExpression {
|
||||
name,
|
||||
members,
|
||||
span: circuit_init.span.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
fn reduce_circuit_member(&mut self, _circuit_member: &CircuitMember, new: CircuitMember) -> Result<CircuitMember> {
|
||||
Ok(new)
|
||||
}
|
||||
|
||||
fn reduce_circuit(
|
||||
&mut self,
|
||||
_circuit: &Circuit,
|
||||
circuit_name: Identifier,
|
||||
members: Vec<CircuitMember>,
|
||||
) -> Result<Circuit> {
|
||||
Ok(Circuit { circuit_name, members })
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,10 @@ pub trait ExpressionVisitor<'a> {
|
||||
fn visit_err(&mut self, _input: &'a ErrExpression) -> VisitResult {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_circuit_init(&mut self, _input: &'a CircuitInitExpression) -> VisitResult {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait StatementVisitor<'a> {
|
||||
@ -105,4 +109,8 @@ pub trait ProgramVisitor<'a> {
|
||||
fn visit_function(&mut self, _input: &'a Function) -> VisitResult {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_circuit(&mut self, _input: &'a Circuit) -> VisitResult {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ pub trait ExpressionVisitorDirector<'a>: VisitorDirector<'a> {
|
||||
Expression::Unary(expr) => self.visit_unary(expr, additional),
|
||||
Expression::Ternary(expr) => self.visit_ternary(expr, additional),
|
||||
Expression::Call(expr) => self.visit_call(expr, additional),
|
||||
Expression::CircuitInit(expr) => self.visit_circuit_init(expr, additional),
|
||||
Expression::Err(expr) => self.visit_err(expr, additional),
|
||||
};
|
||||
}
|
||||
@ -99,6 +100,21 @@ pub trait ExpressionVisitorDirector<'a>: VisitorDirector<'a> {
|
||||
None
|
||||
}
|
||||
|
||||
fn visit_circuit_init(
|
||||
&mut self,
|
||||
input: &'a CircuitInitExpression,
|
||||
additional: &Self::AdditionalInput,
|
||||
) -> Option<Self::Output> {
|
||||
if let VisitResult::VisitChildren = self.visitor_ref().visit_circuit_init(input) {
|
||||
input.members.iter().for_each(|member| {
|
||||
if let Some(expr) = &member.expression {
|
||||
self.visit_expression(expr, additional);
|
||||
}
|
||||
});
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn visit_err(&mut self, input: &'a ErrExpression, _additional: &Self::AdditionalInput) -> Option<Self::Output> {
|
||||
self.visitor_ref().visit_err(input);
|
||||
None
|
||||
@ -184,6 +200,7 @@ pub trait ProgramVisitorDirector<'a>: VisitorDirector<'a> + StatementVisitorDire
|
||||
.functions
|
||||
.values()
|
||||
.for_each(|function| self.visit_function(function));
|
||||
input.circuits.values().for_each(|circuit| self.visit_circuit(circuit));
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,4 +209,20 @@ pub trait ProgramVisitorDirector<'a>: VisitorDirector<'a> + StatementVisitorDire
|
||||
self.visit_block(&input.block);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_circuit(&mut self, input: &'a Circuit) {
|
||||
if let VisitResult::VisitChildren = self.visitor_ref().visit_circuit(input) {
|
||||
input.members.iter().for_each(|member| {
|
||||
match member {
|
||||
CircuitMember::CircuitConst(_, _, expr) => {
|
||||
self.visit_expression(expr, &Default::default());
|
||||
}
|
||||
CircuitMember::CircuitFunction(func) => {
|
||||
self.visit_function(func);
|
||||
}
|
||||
CircuitMember::CircuitVariable(_, _) => {}
|
||||
};
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
//! A Leo program consists of import, circuit, and function definitions.
|
||||
//! Each defined type consists of ast statements and expressions.
|
||||
|
||||
use crate::{Function, FunctionInput, Identifier};
|
||||
use crate::{Circuit, Function, FunctionInput, Identifier};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -32,8 +32,10 @@ pub struct Program {
|
||||
/// Expected main function inputs.
|
||||
/// Empty after parsing.
|
||||
pub expected_input: Vec<FunctionInput>,
|
||||
/// A map from function names to their definitions.
|
||||
/// A map from function names to function definitions.
|
||||
pub functions: IndexMap<Identifier, Function>,
|
||||
/// A map from circuit names to circuit definitions.
|
||||
pub circuits: IndexMap<Identifier, Circuit>,
|
||||
}
|
||||
|
||||
impl AsRef<Program> for Program {
|
||||
@ -59,6 +61,7 @@ impl Program {
|
||||
name,
|
||||
expected_input: vec![],
|
||||
functions: IndexMap::new(),
|
||||
circuits: IndexMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,8 +92,8 @@ impl<'a> ParserContext<'a> {
|
||||
&self.token.token == tok
|
||||
}
|
||||
|
||||
/// Removes the next token if it exists and returns it, or [None] if
|
||||
/// the next token does not exist.
|
||||
/// Returns `true` if the next token is equal to the given token.
|
||||
/// Advances the parser to the next token.
|
||||
pub(super) fn eat(&mut self, token: &Token) -> bool {
|
||||
self.check(token).then(|| self.bump()).is_some()
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
use super::*;
|
||||
|
||||
use leo_errors::{ParserError, Result};
|
||||
use leo_span::sym;
|
||||
|
||||
const INT_TYPES: &[Token] = &[
|
||||
Token::I8,
|
||||
@ -374,6 +375,29 @@ impl ParserContext<'_> {
|
||||
Some(Ok(gt))
|
||||
}
|
||||
|
||||
/// Returns an [`Expression`] AST node if the next tokens represent a
|
||||
/// circuit initialization expression.
|
||||
pub fn parse_circuit_expression(&mut self, identifier: Identifier) -> Result<Expression> {
|
||||
let (members, _, span) = self.parse_list(Delimiter::Brace, Some(Token::Comma), |p| {
|
||||
let expression = if p.eat(&Token::Colon) {
|
||||
// Parse individual circuit variable declarations.
|
||||
Some(p.parse_expression()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Some(CircuitVariableInitializer {
|
||||
identifier: p.expect_ident()?,
|
||||
expression,
|
||||
}))
|
||||
})?;
|
||||
Ok(Expression::CircuitInit(CircuitInitExpression {
|
||||
span: &identifier.span + &span,
|
||||
name: identifier,
|
||||
members,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Returns an [`Expression`] AST node if the next token is a primary expression:
|
||||
/// - Literals: field, group, unsigned integer, signed integer, boolean, address
|
||||
/// - Aggregate types: array, tuple
|
||||
@ -425,7 +449,22 @@ impl ParserContext<'_> {
|
||||
Token::StaticString(value) => Expression::Value(ValueExpression::String(value, span)),
|
||||
Token::Ident(name) => {
|
||||
let ident = Identifier { name, span };
|
||||
Expression::Identifier(ident)
|
||||
if !self.disallow_circuit_construction && self.eat(&Token::LeftCurly) {
|
||||
self.parse_circuit_expression(ident)?
|
||||
} else {
|
||||
Expression::Identifier(ident)
|
||||
}
|
||||
}
|
||||
Token::SelfUpper => {
|
||||
let ident = Identifier {
|
||||
name: sym::SelfUpper,
|
||||
span,
|
||||
};
|
||||
if !self.disallow_circuit_construction && self.eat(&Token::LeftCurly) {
|
||||
self.parse_circuit_expression(ident)?
|
||||
} else {
|
||||
Expression::Identifier(ident)
|
||||
}
|
||||
}
|
||||
t if crate::type_::TYPE_TOKENS.contains(&t) => Expression::Identifier(Identifier {
|
||||
name: t.keyword_to_symbol().unwrap(),
|
||||
|
@ -23,19 +23,25 @@ impl ParserContext<'_> {
|
||||
/// Returns a [`Program`] AST if all tokens can be consumed and represent a valid Leo program.
|
||||
pub fn parse_program(&mut self) -> Result<Program> {
|
||||
let mut functions = IndexMap::new();
|
||||
let mut circuits = IndexMap::new();
|
||||
|
||||
while self.has_next() {
|
||||
match &self.token.token {
|
||||
Token::Circuit => {
|
||||
let (id, circuit) = self.parse_circuit()?;
|
||||
circuits.insert(id, circuit);
|
||||
}
|
||||
Token::Const if self.peek_is_function() => {
|
||||
let (id, function) = self.parse_function()?;
|
||||
functions.insert(id, function);
|
||||
}
|
||||
Token::Ident(sym::test) => return Err(ParserError::test_function(self.token.span).into()),
|
||||
// Const functions share the first token with the global Const.
|
||||
Token::Const if self.peek_is_function() => {
|
||||
let (id, function) = self.parse_function_declaration()?;
|
||||
functions.insert(id, function);
|
||||
}
|
||||
Token::Function => {
|
||||
let (id, function) = self.parse_function_declaration()?;
|
||||
let (id, function) = self.parse_function()?;
|
||||
functions.insert(id, function);
|
||||
}
|
||||
|
||||
_ => return Err(Self::unexpected_item(&self.token).into()),
|
||||
}
|
||||
}
|
||||
@ -43,13 +49,16 @@ impl ParserContext<'_> {
|
||||
name: String::new(),
|
||||
expected_input: Vec::new(),
|
||||
functions,
|
||||
circuits,
|
||||
})
|
||||
}
|
||||
|
||||
fn unexpected_item(token: &SpannedToken) -> ParserError {
|
||||
ParserError::unexpected(
|
||||
&token.token,
|
||||
[Token::Function, Token::Ident(sym::test)]
|
||||
[Token::Function,
|
||||
Token::Circuit,
|
||||
Token::Ident(sym::test)]
|
||||
.iter()
|
||||
.map(|x| format!("'{}'", x))
|
||||
.collect::<Vec<_>>()
|
||||
@ -58,6 +67,121 @@ impl ParserContext<'_> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a [`CircuitMember`] AST node if the next tokens represent a circuit member variable
|
||||
/// or circuit member function or circuit member constant.
|
||||
pub fn parse_circuit_declaration(&mut self) -> Result<Vec<CircuitMember>> {
|
||||
let mut members = Vec::new();
|
||||
|
||||
let (mut semi_colons, mut commas) = (false, false);
|
||||
|
||||
while self.eat(&Token::RightCurly) {
|
||||
members.push(if self.peek_is_function() {
|
||||
// function
|
||||
self.parse_member_function_declaration()?
|
||||
} else if self.eat(&Token::Static) {
|
||||
// static const
|
||||
self.parse_const_member_variable_declaration()?
|
||||
} else {
|
||||
// variable
|
||||
let variable = self.parse_member_variable_declaration()?;
|
||||
|
||||
if self.eat(&Token::Semicolon) {
|
||||
if commas {
|
||||
self.emit_err(ParserError::mixed_commas_and_semicolons(self.token.span));
|
||||
}
|
||||
semi_colons = true;
|
||||
}
|
||||
|
||||
if self.eat(&Token::Comma) {
|
||||
if semi_colons {
|
||||
self.emit_err(ParserError::mixed_commas_and_semicolons(self.token.span));
|
||||
}
|
||||
commas = true;
|
||||
}
|
||||
|
||||
variable
|
||||
});
|
||||
}
|
||||
|
||||
self.ban_mixed_member_order(&members);
|
||||
|
||||
Ok(members)
|
||||
}
|
||||
|
||||
/// Emits errors if order isn't `consts variables functions`.
|
||||
fn ban_mixed_member_order(&self, members: &[CircuitMember]) {
|
||||
let mut had_var = false;
|
||||
let mut had_fun = false;
|
||||
for member in members {
|
||||
match member {
|
||||
CircuitMember::CircuitConst(id, _, e) if had_var => {
|
||||
self.emit_err(ParserError::member_const_after_var(id.span() + e.span()));
|
||||
}
|
||||
CircuitMember::CircuitConst(id, _, e) if had_fun => {
|
||||
self.emit_err(ParserError::member_const_after_fun(id.span() + e.span()));
|
||||
}
|
||||
CircuitMember::CircuitVariable(id, _) if had_fun => {
|
||||
self.emit_err(ParserError::member_var_after_fun(id.span()));
|
||||
}
|
||||
CircuitMember::CircuitConst(..) => {}
|
||||
CircuitMember::CircuitVariable(..) => had_var = true,
|
||||
CircuitMember::CircuitFunction(..) => had_fun = true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses `IDENT: TYPE`.
|
||||
fn parse_typed_field_name(&mut self) -> Result<(Identifier, Type)> {
|
||||
let name = self.expect_ident()?;
|
||||
self.expect(&Token::Colon)?;
|
||||
let type_ = self.parse_all_types()?.0;
|
||||
|
||||
Ok((name, type_))
|
||||
}
|
||||
|
||||
/// Returns a [`CircuitMember`] AST node if the next tokens represent a circuit member static constant.
|
||||
pub fn parse_const_member_variable_declaration(&mut self) -> Result<CircuitMember> {
|
||||
self.expect(&Token::Static)?;
|
||||
self.expect(&Token::Const)?;
|
||||
|
||||
// `IDENT: TYPE = EXPR`:
|
||||
let (name, type_) = self.parse_typed_field_name()?;
|
||||
self.expect(&Token::Assign)?;
|
||||
let expr = self.parse_expression()?;
|
||||
|
||||
self.expect(&Token::Semicolon)?;
|
||||
|
||||
Ok(CircuitMember::CircuitConst(name, type_, expr))
|
||||
}
|
||||
|
||||
/// Returns a [`CircuitMember`] AST node if the next tokens represent a circuit member variable.
|
||||
pub fn parse_member_variable_declaration(&mut self) -> Result<CircuitMember> {
|
||||
let (name, type_) = self.parse_typed_field_name()?;
|
||||
|
||||
Ok(CircuitMember::CircuitVariable(name, type_))
|
||||
}
|
||||
|
||||
/// Returns a [`CircuitMember`] AST node if the next tokens represent a circuit member function.
|
||||
pub fn parse_member_function_declaration(&mut self) -> Result<CircuitMember> {
|
||||
if self.peek_is_function() {
|
||||
let function = self.parse_function()?;
|
||||
Ok(CircuitMember::CircuitFunction(Box::new(function.1)))
|
||||
} else {
|
||||
return Err(Self::unexpected_item(&self.token).into());
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an [`(Identifier, Function)`] ast node if the next tokens represent a circuit declaration.
|
||||
pub(super) fn parse_circuit(&mut self) -> Result<(Identifier, Circuit)> {
|
||||
self.expect(&Token::Circuit)?;
|
||||
let circuit_name = self.expect_ident()?;
|
||||
|
||||
self.expect(&Token::LeftCurly)?;
|
||||
let members = self.parse_circuit_declaration()?;
|
||||
|
||||
Ok((circuit_name.clone(), Circuit { circuit_name, members }))
|
||||
}
|
||||
|
||||
/// Returns a [`ParamMode`] AST node if the next tokens represent a function parameter mode.
|
||||
pub(super) fn parse_function_parameter_mode(&mut self) -> Result<ParamMode> {
|
||||
let public = self.eat(&Token::Public).then(|| self.prev_token.span);
|
||||
@ -106,7 +230,7 @@ impl ParserContext<'_> {
|
||||
|
||||
/// Returns an [`(Identifier, Function)`] AST node if the next tokens represent a function name
|
||||
/// and function definition.
|
||||
fn parse_function_declaration(&mut self) -> Result<(Identifier, Function)> {
|
||||
fn parse_function(&mut self) -> Result<(Identifier, Function)> {
|
||||
// Parse `function IDENT`.
|
||||
let start = self.expect(&Token::Function)?;
|
||||
let name = self.expect_ident()?;
|
||||
|
@ -87,8 +87,10 @@ pub enum Token {
|
||||
U32,
|
||||
U64,
|
||||
U128,
|
||||
SelfUpper,
|
||||
|
||||
// Regular Keywords
|
||||
Circuit,
|
||||
Console,
|
||||
/// Const variable and a const function.
|
||||
Const,
|
||||
@ -103,6 +105,8 @@ pub enum Token {
|
||||
/// For public inputs.
|
||||
Public,
|
||||
Return,
|
||||
SelfLower,
|
||||
Static,
|
||||
|
||||
// Meta Tokens
|
||||
Eof,
|
||||
@ -115,6 +119,7 @@ pub enum Token {
|
||||
pub const KEYWORD_TOKENS: &[Token] = &[
|
||||
Token::Address,
|
||||
Token::Bool,
|
||||
Token::Circuit,
|
||||
Token::Console,
|
||||
Token::Const,
|
||||
Token::Constant,
|
||||
@ -134,7 +139,10 @@ pub const KEYWORD_TOKENS: &[Token] = &[
|
||||
Token::Let,
|
||||
Token::Public,
|
||||
Token::Return,
|
||||
Token::SelfLower,
|
||||
Token::SelfUpper,
|
||||
Token::Scalar,
|
||||
Token::Static,
|
||||
Token::String,
|
||||
Token::True,
|
||||
Token::U8,
|
||||
@ -155,6 +163,7 @@ impl Token {
|
||||
Some(match self {
|
||||
Token::Address => sym::address,
|
||||
Token::Bool => sym::bool,
|
||||
Token::Circuit => sym::circuit,
|
||||
Token::Console => sym::console,
|
||||
Token::Const => sym::Const,
|
||||
Token::Constant => sym::Constant,
|
||||
@ -175,6 +184,9 @@ impl Token {
|
||||
Token::Public => sym::Public,
|
||||
Token::Return => sym::Return,
|
||||
Token::Scalar => sym::scalar,
|
||||
Token::SelfLower => sym::SelfLower,
|
||||
Token::SelfUpper => sym::SelfUpper,
|
||||
Token::Static => sym::Static,
|
||||
Token::String => sym::string,
|
||||
Token::True => sym::True,
|
||||
Token::U8 => sym::u8,
|
||||
@ -251,7 +263,9 @@ impl fmt::Display for Token {
|
||||
U32 => write!(f, "u32"),
|
||||
U64 => write!(f, "u64"),
|
||||
U128 => write!(f, "u128"),
|
||||
SelfUpper => write!(f, "Self"),
|
||||
|
||||
Circuit => write!(f, "circuit"),
|
||||
Console => write!(f, "console"),
|
||||
Const => write!(f, "const"),
|
||||
Constant => write!(f, "constant"),
|
||||
@ -261,8 +275,10 @@ impl fmt::Display for Token {
|
||||
If => write!(f, "if"),
|
||||
In => write!(f, "in"),
|
||||
Let => write!(f, "let"),
|
||||
SelfLower => write!(f, "self"),
|
||||
Public => write!(f, "public"),
|
||||
Return => write!(f, "return"),
|
||||
Static => write!(f, "static"),
|
||||
Eof => write!(f, "<eof>"),
|
||||
}
|
||||
}
|
||||
|
@ -48,13 +48,14 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
||||
fn visit_expression(&mut self, input: &'a Expression, expected: &Self::AdditionalInput) -> Option<Self::Output> {
|
||||
if let VisitResult::VisitChildren = self.visitor.visit_expression(input) {
|
||||
return match input {
|
||||
Expression::Identifier(expr) => self.visit_identifier(expr, expected),
|
||||
Expression::Value(expr) => self.visit_value(expr, expected),
|
||||
Expression::Binary(expr) => self.visit_binary(expr, expected),
|
||||
Expression::Unary(expr) => self.visit_unary(expr, expected),
|
||||
Expression::Ternary(expr) => self.visit_ternary(expr, expected),
|
||||
Expression::Call(expr) => self.visit_call(expr, expected),
|
||||
Expression::CircuitInit(expr) => self.visit_circuit_init(expr, expected),
|
||||
Expression::Err(expr) => self.visit_err(expr, expected),
|
||||
Expression::Identifier(expr) => self.visit_identifier(expr, expected),
|
||||
Expression::Ternary(expr) => self.visit_ternary(expr, expected),
|
||||
Expression::Unary(expr) => self.visit_unary(expr, expected),
|
||||
Expression::Value(expr) => self.visit_value(expr, expected),
|
||||
};
|
||||
}
|
||||
|
||||
@ -535,4 +536,8 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
||||
expr => self.visit_expression(expr, expected),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_circuit_init(&mut self, input: &'a CircuitInitExpression, additional: &Self::AdditionalInput) -> Option<Self::Output> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -53,4 +53,11 @@ impl<'a> ProgramVisitorDirector<'a> for Director<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_circuit(&mut self, input: &'a Circuit) {
|
||||
todo!()
|
||||
// if let VisitResult::VisitChildren = self.visitor_ref().visit_function(input) {
|
||||
// self.
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
@ -180,6 +180,7 @@ symbols! {
|
||||
// general keywords
|
||||
AlwaysConst,
|
||||
assert,
|
||||
circuit,
|
||||
Class: "class",
|
||||
context,
|
||||
CoreFunction,
|
||||
@ -198,6 +199,9 @@ symbols! {
|
||||
prelude,
|
||||
Public,
|
||||
Return: "return",
|
||||
SelfLower: "self",
|
||||
SelfUpper: "Self",
|
||||
Static: "static",
|
||||
Star: "*",
|
||||
std,
|
||||
Struct: "struct",
|
||||
|
Loading…
Reference in New Issue
Block a user