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
|
// 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/>.
|
||||||
|
pub mod core_constant;
|
||||||
|
pub use core_constant::*;
|
||||||
|
|
||||||
pub mod integer_type;
|
pub mod integer_type;
|
||||||
pub use integer_type::*;
|
pub use integer_type::*;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
use crate::CodeGenerator;
|
use crate::CodeGenerator;
|
||||||
use leo_ast::{
|
use leo_ast::{
|
||||||
AccessExpression,
|
AccessExpression,
|
||||||
|
AssociatedConstant,
|
||||||
AssociatedFunction,
|
AssociatedFunction,
|
||||||
BinaryExpression,
|
BinaryExpression,
|
||||||
BinaryOperation,
|
BinaryOperation,
|
||||||
@ -233,6 +234,11 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
(member_access_instruction, String::new())
|
(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
|
// Pedersen64::hash() -> hash.ped64
|
||||||
fn visit_associated_function(&mut self, input: &'a AssociatedFunction) -> (String, String) {
|
fn visit_associated_function(&mut self, input: &'a AssociatedFunction) -> (String, String) {
|
||||||
let mut instructions = String::new();
|
let mut instructions = String::new();
|
||||||
@ -337,7 +343,7 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
fn visit_access(&mut self, input: &'a AccessExpression) -> (String, String) {
|
fn visit_access(&mut self, input: &'a AccessExpression) -> (String, String) {
|
||||||
match input {
|
match input {
|
||||||
AccessExpression::Member(access) => self.visit_member_access(access),
|
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::AssociatedFunction(function) => self.visit_associated_function(function),
|
||||||
AccessExpression::Tuple(_) => todo!(), // Tuples are not supported in AVM yet.
|
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
|
None
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
use crate::{CallGraph, StructGraph, SymbolTable};
|
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_errors::{emitter::Handler, TypeCheckerError};
|
||||||
use leo_span::{Span, Symbol};
|
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 `struct` is not a core library struct.
|
||||||
/// Emits an error if the `function` is not supported by the 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> {
|
pub(crate) fn get_core_function_call(&self, struct_: &Type, function: &Identifier) -> Option<CoreFunction> {
|
||||||
|
@ -141,6 +141,9 @@ symbols! {
|
|||||||
sub_wrapped,
|
sub_wrapped,
|
||||||
xor,
|
xor,
|
||||||
|
|
||||||
|
// core constants
|
||||||
|
GEN,
|
||||||
|
|
||||||
// core functions
|
// core functions
|
||||||
BHP256,
|
BHP256,
|
||||||
BHP512,
|
BHP512,
|
||||||
|
@ -163,7 +163,7 @@ create_messages!(
|
|||||||
help: None,
|
help: None,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An invalid access call is made e.g., `bool::MAX`
|
/// An invalid access call is made e.g., `SHA256::hash()
|
||||||
@formatted
|
@formatted
|
||||||
invalid_core_function_call {
|
invalid_core_function_call {
|
||||||
args: (expr: impl Display),
|
args: (expr: impl Display),
|
||||||
@ -594,11 +594,30 @@ create_messages!(
|
|||||||
msg: format!("A finalize block cannot return a value."),
|
msg: format!("A finalize block cannot return a value."),
|
||||||
help: None,
|
help: None,
|
||||||
}
|
}
|
||||||
|
|
||||||
@formatted
|
@formatted
|
||||||
too_many_mappings {
|
too_many_mappings {
|
||||||
args: (max: impl Display),
|
args: (max: impl Display),
|
||||||
msg: format!("The number of mappings exceeds the maximum. snarkVM allows up to {max} mappings within a single program."),
|
msg: format!("The number of mappings exceeds the maximum. snarkVM allows up to {max} mappings within a single program."),
|
||||||
help: None,
|
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 {
|
transition main(a: group) -> group {
|
||||||
// unary
|
// unary
|
||||||
let e: group = a.double(); // 2a
|
let b: group = a.double(); // 2a
|
||||||
let g: group = e.neg(); // -2a
|
let c: group = b.neg(); // -2a
|
||||||
|
|
||||||
// binary
|
// 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