mirror of
https://github.com/AleoHQ/leo.git
synced 2024-11-24 02:42:21 +03:00
implement group::GEN Leo syntax (#2401)
* implement group::GEN Leo syntax * revert unrelated test changes * move new errors to bottom of file to keep previous error codes consistent
This commit is contained in:
parent
369db97edd
commit
42d97d3d89
41
compiler/ast/src/types/core_constant.rs
Normal file
41
compiler/ast/src/types/core_constant.rs
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// 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/>.
|
||||
|
||||
use crate::Type;
|
||||
use leo_span::{sym, Symbol};
|
||||
|
||||
/// A core constant that maps directly to an AVM bytecode constant.
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub enum CoreConstant {
|
||||
GroupGenerator,
|
||||
}
|
||||
|
||||
impl CoreConstant {
|
||||
/// Returns a `CoreConstant` from the given type and constant symbols.
|
||||
pub fn from_symbols(type_: Symbol, constant: Symbol) -> Option<Self> {
|
||||
Some(match (type_, constant) {
|
||||
(sym::group, sym::GEN) => Self::GroupGenerator,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the `Type` of the `CoreConstant`.
|
||||
pub fn to_type(&self) -> Type {
|
||||
match self {
|
||||
Self::GroupGenerator => Type::Group,
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,8 @@
|
||||
|
||||
// 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/>.
|
||||
pub mod core_constant;
|
||||
pub use core_constant::*;
|
||||
|
||||
pub mod integer_type;
|
||||
pub use integer_type::*;
|
||||
|
@ -17,6 +17,7 @@
|
||||
use crate::CodeGenerator;
|
||||
use leo_ast::{
|
||||
AccessExpression,
|
||||
AssociatedConstant,
|
||||
AssociatedFunction,
|
||||
BinaryExpression,
|
||||
BinaryOperation,
|
||||
@ -233,6 +234,11 @@ impl<'a> CodeGenerator<'a> {
|
||||
(member_access_instruction, String::new())
|
||||
}
|
||||
|
||||
// group::GEN -> group::GEN
|
||||
fn visit_associated_constant(&mut self, input: &'a AssociatedConstant) -> (String, String) {
|
||||
(format!("{input}"), String::new())
|
||||
}
|
||||
|
||||
// Pedersen64::hash() -> hash.ped64
|
||||
fn visit_associated_function(&mut self, input: &'a AssociatedFunction) -> (String, String) {
|
||||
let mut instructions = String::new();
|
||||
@ -337,7 +343,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
fn visit_access(&mut self, input: &'a AccessExpression) -> (String, String) {
|
||||
match input {
|
||||
AccessExpression::Member(access) => self.visit_member_access(access),
|
||||
AccessExpression::AssociatedConstant(_) => todo!(), // Associated constants are not supported in AVM yet.
|
||||
AccessExpression::AssociatedConstant(constant) => self.visit_associated_constant(constant),
|
||||
AccessExpression::AssociatedFunction(function) => self.visit_associated_function(function),
|
||||
AccessExpression::Tuple(_) => todo!(), // Tuples are not supported in AVM yet.
|
||||
}
|
||||
|
@ -150,7 +150,19 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
AccessExpression::AssociatedConstant(..) => {} // todo: Add support for associated constants (u8::MAX).
|
||||
AccessExpression::AssociatedConstant(access) => {
|
||||
// Check associated constant type and constant name
|
||||
if let Some(core_constant) = self.get_core_constant(&access.ty, &access.name) {
|
||||
// Check return type if the expected type is known.
|
||||
let return_type = Some(core_constant.to_type());
|
||||
if let Some(expected) = expected {
|
||||
self.assert_type(&return_type, expected, input.span());
|
||||
}
|
||||
return return_type;
|
||||
} else {
|
||||
self.emit_err(TypeCheckerError::invalid_associated_constant(access, access.span))
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use crate::{CallGraph, StructGraph, SymbolTable};
|
||||
|
||||
use leo_ast::{CoreFunction, Identifier, IntegerType, MappingType, Node, Type, Variant};
|
||||
use leo_ast::{CoreConstant, CoreFunction, Identifier, IntegerType, MappingType, Node, Type, Variant};
|
||||
use leo_errors::{emitter::Handler, TypeCheckerError};
|
||||
use leo_span::{Span, Symbol};
|
||||
|
||||
@ -302,6 +302,21 @@ impl<'a> TypeChecker<'a> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Type checks the inputs to an associated constant and returns the expected output type.
|
||||
pub(crate) fn get_core_constant(&self, type_: &Type, constant: &Identifier) -> Option<CoreConstant> {
|
||||
if let Type::Identifier(ident) = type_ {
|
||||
// Lookup core constant
|
||||
match CoreConstant::from_symbols(ident.name, constant.name) {
|
||||
None => {
|
||||
// Not a core constant.
|
||||
self.emit_err(TypeCheckerError::invalid_core_constant(ident.name, constant.name, ident.span()));
|
||||
}
|
||||
Some(core_constant) => return Some(core_constant),
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Emits an error if the `struct` is not a core library struct.
|
||||
/// Emits an error if the `function` is not supported by the struct.
|
||||
pub(crate) fn get_core_function_call(&self, struct_: &Type, function: &Identifier) -> Option<CoreFunction> {
|
||||
|
@ -141,6 +141,9 @@ symbols! {
|
||||
sub_wrapped,
|
||||
xor,
|
||||
|
||||
// core constants
|
||||
GEN,
|
||||
|
||||
// core functions
|
||||
BHP256,
|
||||
BHP512,
|
||||
|
@ -163,7 +163,7 @@ create_messages!(
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// An invalid access call is made e.g., `bool::MAX`
|
||||
/// An invalid access call is made e.g., `SHA256::hash()
|
||||
@formatted
|
||||
invalid_core_function_call {
|
||||
args: (expr: impl Display),
|
||||
@ -594,11 +594,30 @@ create_messages!(
|
||||
msg: format!("A finalize block cannot return a value."),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@formatted
|
||||
too_many_mappings {
|
||||
args: (max: impl Display),
|
||||
msg: format!("The number of mappings exceeds the maximum. snarkVM allows up to {max} mappings within a single program."),
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// A call to an invalid associated constant is made e.g., `bool::MAX`
|
||||
@formatted
|
||||
invalid_associated_constant {
|
||||
args: (expr: impl Display),
|
||||
msg: format!(
|
||||
"{expr} is not a valid associated constant."
|
||||
),
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// For when an invalid core constant is called.
|
||||
@formatted
|
||||
invalid_core_constant {
|
||||
args: (type_: impl Display, constant: impl Display),
|
||||
msg: format! (
|
||||
"{type_}::{constant} is not a valid core constant.",
|
||||
),
|
||||
help: None,
|
||||
}
|
||||
);
|
||||
|
@ -4,13 +4,16 @@ program groups.aleo {
|
||||
|
||||
transition main(a: group) -> group {
|
||||
// unary
|
||||
let e: group = a.double(); // 2a
|
||||
let g: group = e.neg(); // -2a
|
||||
let b: group = a.double(); // 2a
|
||||
let c: group = b.neg(); // -2a
|
||||
|
||||
// binary
|
||||
let j: group = (a * 2scalar).add(g);
|
||||
let d: group = (a * 2scalar).add(c);
|
||||
|
||||
return j;
|
||||
// generator
|
||||
let e: group = group::GEN;
|
||||
|
||||
return d + e;
|
||||
}
|
||||
}
|
||||
|
||||
|
12
tests/expectations/compiler/core/constants/group_gen.out
Normal file
12
tests/expectations/compiler/core/constants/group_gen.out
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_ast: fad70d5af8fae67cf7c511f82d51bbb417bc16c2b082d987d775284981be49bc
|
||||
unrolled_ast: fad70d5af8fae67cf7c511f82d51bbb417bc16c2b082d987d775284981be49bc
|
||||
ssa_ast: 29b1770e006849d42def40fd2291158a0cd21e9db3ecd03bd6bdfdcc6eb43e0a
|
||||
flattened_ast: 64556dacc04129ffd9f1f68074266e924b5804440aaaeb152a8a33b6fbc80228
|
||||
inlined_ast: 64556dacc04129ffd9f1f68074266e924b5804440aaaeb152a8a33b6fbc80228
|
||||
dce_ast: 64556dacc04129ffd9f1f68074266e924b5804440aaaeb152a8a33b6fbc80228
|
||||
bytecode: cd542f776048c64f42b745a4be5ebe93fe7a8638c8d1692d3d774d491cadfe45
|
||||
warnings: ""
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372074]: group::GENERATOR is not a valid core constant.\n --> compiler-test:7:24\n |\n 7 | let a: group = group::GENERATOR;\n | ^^^^^\nError [ETYC0372073]: group::GENERATOR is not a valid associated constant.\n --> compiler-test:7:24\n |\n 7 | let a: group = group::GENERATOR;\n | ^^^^^^^^^^^^^^^^\n"
|
14
tests/tests/compiler/core/constants/group_gen.leo
Normal file
14
tests/tests/compiler/core/constants/group_gen.leo
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
*/
|
||||
|
||||
program test.aleo {
|
||||
transition main(
|
||||
group_value: group,
|
||||
) -> group {
|
||||
let a: group = group::GEN;
|
||||
|
||||
return group_value + a;
|
||||
}
|
||||
}
|
14
tests/tests/compiler/core/constants/group_gen_fail.leo
Normal file
14
tests/tests/compiler/core/constants/group_gen_fail.leo
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
*/
|
||||
|
||||
program test.aleo {
|
||||
transition main(
|
||||
group_value: group,
|
||||
) -> group {
|
||||
let a: group = group::GENERATOR;
|
||||
|
||||
return group_value + a;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user