feat(bls): aiken level g1 and g2 literals
This commit is contained in:
parent
90aea6476a
commit
3675762c3e
|
@ -82,6 +82,7 @@ dependencies = [
|
||||||
name = "aiken-lang"
|
name = "aiken-lang"
|
||||||
version = "1.0.20-alpha"
|
version = "1.0.20-alpha"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"blst",
|
||||||
"chumsky",
|
"chumsky",
|
||||||
"hex",
|
"hex",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
|
|
@ -27,6 +27,7 @@ vec1 = "1.10.1"
|
||||||
uplc = { path = '../uplc', version = "1.0.20-alpha" }
|
uplc = { path = '../uplc', version = "1.0.20-alpha" }
|
||||||
num-bigint = "0.4.3"
|
num-bigint = "0.4.3"
|
||||||
petgraph = "0.6.3"
|
petgraph = "0.6.3"
|
||||||
|
blst = "0.3.11"
|
||||||
|
|
||||||
[target.'cfg(not(target_family="wasm"))'.dependencies]
|
[target.'cfg(not(target_family="wasm"))'.dependencies]
|
||||||
chumsky = "0.9.2"
|
chumsky = "0.9.2"
|
||||||
|
|
|
@ -11,6 +11,7 @@ use std::{
|
||||||
ops::Range,
|
ops::Range,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
use uplc::machine::runtime::Compressable;
|
||||||
use vec1::Vec1;
|
use vec1::Vec1;
|
||||||
|
|
||||||
pub const CAPTURE_VARIABLE: &str = "_capture";
|
pub const CAPTURE_VARIABLE: &str = "_capture";
|
||||||
|
@ -492,6 +493,12 @@ pub enum Constant {
|
||||||
bytes: Vec<u8>,
|
bytes: Vec<u8>,
|
||||||
preferred_format: ByteArrayFormatPreference,
|
preferred_format: ByteArrayFormatPreference,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
CurvePoint {
|
||||||
|
location: Span,
|
||||||
|
point: Curve,
|
||||||
|
preferred_format: ByteArrayFormatPreference,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Constant {
|
impl Constant {
|
||||||
|
@ -500,6 +507,10 @@ impl Constant {
|
||||||
Constant::Int { .. } => builtins::int(),
|
Constant::Int { .. } => builtins::int(),
|
||||||
Constant::String { .. } => builtins::string(),
|
Constant::String { .. } => builtins::string(),
|
||||||
Constant::ByteArray { .. } => builtins::byte_array(),
|
Constant::ByteArray { .. } => builtins::byte_array(),
|
||||||
|
Constant::CurvePoint { point, .. } => match point {
|
||||||
|
Curve::Bls12_381(Bls12_381Point::G1(_)) => builtins::g1_element(),
|
||||||
|
Curve::Bls12_381(Bls12_381Point::G2(_)) => builtins::g2_element(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,7 +518,8 @@ impl Constant {
|
||||||
match self {
|
match self {
|
||||||
Constant::Int { location, .. }
|
Constant::Int { location, .. }
|
||||||
| Constant::String { location, .. }
|
| Constant::String { location, .. }
|
||||||
| Constant::ByteArray { location, .. } => *location,
|
| Constant::ByteArray { location, .. }
|
||||||
|
| Constant::CurvePoint { location, .. } => *location,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -997,6 +1009,78 @@ pub enum ByteArrayFormatPreference {
|
||||||
Utf8String,
|
Utf8String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
|
||||||
|
pub enum CurveType {
|
||||||
|
Bls12_381(Bls12_381PointType),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for CurveType {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
CurveType::Bls12_381(point) => write!(f, "<Bls12_381, {point}>"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<&Curve> for CurveType {
|
||||||
|
fn from(value: &Curve) -> Self {
|
||||||
|
match value {
|
||||||
|
Curve::Bls12_381(point) => CurveType::Bls12_381(point.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
|
||||||
|
pub enum Bls12_381PointType {
|
||||||
|
G1,
|
||||||
|
G2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&Bls12_381Point> for Bls12_381PointType {
|
||||||
|
fn from(value: &Bls12_381Point) -> Self {
|
||||||
|
match value {
|
||||||
|
Bls12_381Point::G1(_) => Bls12_381PointType::G1,
|
||||||
|
Bls12_381Point::G2(_) => Bls12_381PointType::G2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Bls12_381PointType {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Bls12_381PointType::G1 => write!(f, "G1"),
|
||||||
|
Bls12_381PointType::G2 => write!(f, "G2"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
|
||||||
|
pub enum Curve {
|
||||||
|
Bls12_381(Bls12_381Point),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Curve {
|
||||||
|
pub fn compress(&self) -> Vec<u8> {
|
||||||
|
match self {
|
||||||
|
Curve::Bls12_381(point) => match point {
|
||||||
|
Bls12_381Point::G1(g1) => g1.compress(),
|
||||||
|
Bls12_381Point::G2(g2) => g2.compress(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
|
||||||
|
pub enum Bls12_381Point {
|
||||||
|
G1(blst::blst_p1),
|
||||||
|
G2(blst::blst_p2),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Bls12_381Point {
|
||||||
|
fn default() -> Self {
|
||||||
|
Bls12_381Point::G1(Default::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
|
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
|
||||||
pub enum AssignmentKind {
|
pub enum AssignmentKind {
|
||||||
Let,
|
Let,
|
||||||
|
|
|
@ -4,7 +4,7 @@ use vec1::Vec1;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
self, Annotation, Arg, AssignmentKind, BinOp, ByteArrayFormatPreference, CallArg,
|
self, Annotation, Arg, AssignmentKind, BinOp, ByteArrayFormatPreference, CallArg, Curve,
|
||||||
DefinitionLocation, IfBranch, Located, LogicalOpChainKind, ParsedCallArg, Pattern,
|
DefinitionLocation, IfBranch, Located, LogicalOpChainKind, ParsedCallArg, Pattern,
|
||||||
RecordUpdateSpread, Span, TraceKind, TypedClause, TypedRecordUpdateArg, UnOp,
|
RecordUpdateSpread, Span, TraceKind, TypedClause, TypedRecordUpdateArg, UnOp,
|
||||||
UntypedClause, UntypedRecordUpdateArg,
|
UntypedClause, UntypedRecordUpdateArg,
|
||||||
|
@ -34,6 +34,12 @@ pub enum TypedExpr {
|
||||||
bytes: Vec<u8>,
|
bytes: Vec<u8>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
CurvePoint {
|
||||||
|
location: Span,
|
||||||
|
tipo: Rc<Type>,
|
||||||
|
point: Curve,
|
||||||
|
},
|
||||||
|
|
||||||
Sequence {
|
Sequence {
|
||||||
location: Span,
|
location: Span,
|
||||||
expressions: Vec<Self>,
|
expressions: Vec<Self>,
|
||||||
|
@ -186,7 +192,8 @@ impl TypedExpr {
|
||||||
| Self::Assignment { tipo, .. }
|
| Self::Assignment { tipo, .. }
|
||||||
| Self::ModuleSelect { tipo, .. }
|
| Self::ModuleSelect { tipo, .. }
|
||||||
| Self::RecordAccess { tipo, .. }
|
| Self::RecordAccess { tipo, .. }
|
||||||
| Self::RecordUpdate { tipo, .. } => tipo.clone(),
|
| Self::RecordUpdate { tipo, .. }
|
||||||
|
| Self::CurvePoint { tipo, .. } => tipo.clone(),
|
||||||
Self::Pipeline { expressions, .. } | Self::Sequence { expressions, .. } => {
|
Self::Pipeline { expressions, .. } | Self::Sequence { expressions, .. } => {
|
||||||
expressions.last().map(TypedExpr::tipo).unwrap_or_else(void)
|
expressions.last().map(TypedExpr::tipo).unwrap_or_else(void)
|
||||||
}
|
}
|
||||||
|
@ -227,7 +234,8 @@ impl TypedExpr {
|
||||||
| TypedExpr::ByteArray { .. }
|
| TypedExpr::ByteArray { .. }
|
||||||
| TypedExpr::Assignment { .. }
|
| TypedExpr::Assignment { .. }
|
||||||
| TypedExpr::TupleIndex { .. }
|
| TypedExpr::TupleIndex { .. }
|
||||||
| TypedExpr::RecordAccess { .. } => None,
|
| TypedExpr::RecordAccess { .. }
|
||||||
|
| TypedExpr::CurvePoint { .. } => None,
|
||||||
TypedExpr::If { .. } => None,
|
TypedExpr::If { .. } => None,
|
||||||
|
|
||||||
// TODO: test
|
// TODO: test
|
||||||
|
@ -269,7 +277,8 @@ impl TypedExpr {
|
||||||
| Self::TupleIndex { location, .. }
|
| Self::TupleIndex { location, .. }
|
||||||
| Self::ModuleSelect { location, .. }
|
| Self::ModuleSelect { location, .. }
|
||||||
| Self::RecordAccess { location, .. }
|
| Self::RecordAccess { location, .. }
|
||||||
| Self::RecordUpdate { location, .. } => *location,
|
| Self::RecordUpdate { location, .. }
|
||||||
|
| Self::CurvePoint { location, .. } => *location,
|
||||||
|
|
||||||
Self::If { branches, .. } => branches.first().body.type_defining_location(),
|
Self::If { branches, .. } => branches.first().body.type_defining_location(),
|
||||||
|
|
||||||
|
@ -306,7 +315,8 @@ impl TypedExpr {
|
||||||
| Self::TupleIndex { location, .. }
|
| Self::TupleIndex { location, .. }
|
||||||
| Self::ModuleSelect { location, .. }
|
| Self::ModuleSelect { location, .. }
|
||||||
| Self::RecordAccess { location, .. }
|
| Self::RecordAccess { location, .. }
|
||||||
| Self::RecordUpdate { location, .. } => *location,
|
| Self::RecordUpdate { location, .. }
|
||||||
|
| Self::CurvePoint { location, .. } => *location,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +333,8 @@ impl TypedExpr {
|
||||||
| TypedExpr::UInt { .. }
|
| TypedExpr::UInt { .. }
|
||||||
| TypedExpr::String { .. }
|
| TypedExpr::String { .. }
|
||||||
| TypedExpr::ByteArray { .. }
|
| TypedExpr::ByteArray { .. }
|
||||||
| TypedExpr::ModuleSelect { .. } => Some(Located::Expression(self)),
|
| TypedExpr::ModuleSelect { .. }
|
||||||
|
| TypedExpr::CurvePoint { .. } => Some(Located::Expression(self)),
|
||||||
|
|
||||||
TypedExpr::Trace { text, then, .. } => text
|
TypedExpr::Trace { text, then, .. } => text
|
||||||
.find_node(byte_index)
|
.find_node(byte_index)
|
||||||
|
@ -472,6 +483,12 @@ pub enum UntypedExpr {
|
||||||
preferred_format: ByteArrayFormatPreference,
|
preferred_format: ByteArrayFormatPreference,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
CurvePoint {
|
||||||
|
location: Span,
|
||||||
|
point: Curve,
|
||||||
|
preferred_format: ByteArrayFormatPreference,
|
||||||
|
},
|
||||||
|
|
||||||
PipeLine {
|
PipeLine {
|
||||||
expressions: Vec1<Self>,
|
expressions: Vec1<Self>,
|
||||||
one_liner: bool,
|
one_liner: bool,
|
||||||
|
@ -733,7 +750,8 @@ impl UntypedExpr {
|
||||||
| Self::RecordUpdate { location, .. }
|
| Self::RecordUpdate { location, .. }
|
||||||
| Self::UnOp { location, .. }
|
| Self::UnOp { location, .. }
|
||||||
| Self::LogicalOpChain { location, .. }
|
| Self::LogicalOpChain { location, .. }
|
||||||
| Self::If { location, .. } => *location,
|
| Self::If { location, .. }
|
||||||
|
| Self::CurvePoint { location, .. } => *location,
|
||||||
Self::Sequence {
|
Self::Sequence {
|
||||||
location,
|
location,
|
||||||
expressions,
|
expressions,
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
Annotation, Arg, ArgName, AssignmentKind, BinOp, ByteArrayFormatPreference, CallArg,
|
Annotation, Arg, ArgName, AssignmentKind, BinOp, ByteArrayFormatPreference, CallArg,
|
||||||
ClauseGuard, Constant, DataType, Definition, Function, IfBranch, LogicalOpChainKind,
|
ClauseGuard, Constant, CurveType, DataType, Definition, Function, IfBranch,
|
||||||
ModuleConstant, Pattern, RecordConstructor, RecordConstructorArg, RecordUpdateSpread, Span,
|
LogicalOpChainKind, ModuleConstant, Pattern, RecordConstructor, RecordConstructorArg,
|
||||||
TraceKind, TypeAlias, TypedArg, UnOp, UnqualifiedImport, UntypedArg, UntypedClause,
|
RecordUpdateSpread, Span, TraceKind, TypeAlias, TypedArg, UnOp, UnqualifiedImport,
|
||||||
UntypedClauseGuard, UntypedDefinition, UntypedFunction, UntypedModule, UntypedPattern,
|
UntypedArg, UntypedClause, UntypedClauseGuard, UntypedDefinition, UntypedFunction,
|
||||||
UntypedRecordUpdateArg, Use, Validator, CAPTURE_VARIABLE,
|
UntypedModule, UntypedPattern, UntypedRecordUpdateArg, Use, Validator, CAPTURE_VARIABLE,
|
||||||
},
|
},
|
||||||
docvec,
|
docvec,
|
||||||
expr::{FnStyle, UntypedExpr, DEFAULT_ERROR_STR, DEFAULT_TODO_STR},
|
expr::{FnStyle, UntypedExpr, DEFAULT_ERROR_STR, DEFAULT_TODO_STR},
|
||||||
|
@ -352,7 +352,12 @@ impl<'comments> Formatter<'comments> {
|
||||||
bytes,
|
bytes,
|
||||||
preferred_format,
|
preferred_format,
|
||||||
..
|
..
|
||||||
} => self.bytearray(bytes, preferred_format),
|
} => self.bytearray(bytes, None, preferred_format),
|
||||||
|
Constant::CurvePoint {
|
||||||
|
point,
|
||||||
|
preferred_format,
|
||||||
|
..
|
||||||
|
} => self.bytearray(&point.compress(), Some(point.into()), preferred_format),
|
||||||
Constant::Int { value, base, .. } => self.int(value, base),
|
Constant::Int { value, base, .. } => self.int(value, base),
|
||||||
Constant::String { value, .. } => self.string(value),
|
Constant::String { value, .. } => self.string(value),
|
||||||
}
|
}
|
||||||
|
@ -676,17 +681,24 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
pub fn bytearray<'a>(
|
pub fn bytearray<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
bytes: &'a [u8],
|
bytes: &[u8],
|
||||||
|
curve: Option<CurveType>,
|
||||||
preferred_format: &ByteArrayFormatPreference,
|
preferred_format: &ByteArrayFormatPreference,
|
||||||
) -> Document<'a> {
|
) -> Document<'a> {
|
||||||
match preferred_format {
|
match preferred_format {
|
||||||
ByteArrayFormatPreference::HexadecimalString => "#"
|
ByteArrayFormatPreference::HexadecimalString => "#"
|
||||||
.to_doc()
|
.to_doc()
|
||||||
|
.append(Document::String(
|
||||||
|
curve.map(|c| c.to_string()).unwrap_or_default(),
|
||||||
|
))
|
||||||
.append("\"")
|
.append("\"")
|
||||||
.append(Document::String(hex::encode(bytes)))
|
.append(Document::String(hex::encode(bytes)))
|
||||||
.append("\""),
|
.append("\""),
|
||||||
ByteArrayFormatPreference::ArrayOfBytes(Base::Decimal { .. }) => "#"
|
ByteArrayFormatPreference::ArrayOfBytes(Base::Decimal { .. }) => "#"
|
||||||
.to_doc()
|
.to_doc()
|
||||||
|
.append(Document::String(
|
||||||
|
curve.map(|c| c.to_string()).unwrap_or_default(),
|
||||||
|
))
|
||||||
.append(
|
.append(
|
||||||
flex_break("[", "[")
|
flex_break("[", "[")
|
||||||
.append(join(bytes.iter().map(|b| b.to_doc()), break_(",", ", ")))
|
.append(join(bytes.iter().map(|b| b.to_doc()), break_(",", ", ")))
|
||||||
|
@ -697,6 +709,9 @@ impl<'comments> Formatter<'comments> {
|
||||||
.group(),
|
.group(),
|
||||||
ByteArrayFormatPreference::ArrayOfBytes(Base::Hexadecimal) => "#"
|
ByteArrayFormatPreference::ArrayOfBytes(Base::Hexadecimal) => "#"
|
||||||
.to_doc()
|
.to_doc()
|
||||||
|
.append(Document::String(
|
||||||
|
curve.map(|c| c.to_string()).unwrap_or_default(),
|
||||||
|
))
|
||||||
.append(
|
.append(
|
||||||
flex_break("[", "[")
|
flex_break("[", "[")
|
||||||
.append(join(
|
.append(join(
|
||||||
|
@ -771,7 +786,13 @@ impl<'comments> Formatter<'comments> {
|
||||||
bytes,
|
bytes,
|
||||||
preferred_format,
|
preferred_format,
|
||||||
..
|
..
|
||||||
} => self.bytearray(bytes, preferred_format),
|
} => self.bytearray(bytes, None, preferred_format),
|
||||||
|
|
||||||
|
UntypedExpr::CurvePoint {
|
||||||
|
point,
|
||||||
|
preferred_format,
|
||||||
|
..
|
||||||
|
} => self.bytearray(&point.compress(), Some(point.into()), preferred_format),
|
||||||
|
|
||||||
UntypedExpr::If {
|
UntypedExpr::If {
|
||||||
branches,
|
branches,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use chumsky::prelude::*;
|
use chumsky::prelude::*;
|
||||||
|
use uplc::machine::runtime::Compressable;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast,
|
ast,
|
||||||
|
@ -45,14 +46,37 @@ pub fn value() -> impl Parser<Token, ast::Constant, Error = ParseError> {
|
||||||
base,
|
base,
|
||||||
});
|
});
|
||||||
|
|
||||||
let constant_bytearray_parser =
|
let constant_bytearray_parser = literal::bytearray(
|
||||||
literal::bytearray(
|
|bytes, preferred_format, curve, location, emit| match curve {
|
||||||
|bytes, preferred_format, location| ast::Constant::ByteArray {
|
Some(curve @ ast::CurveType::Bls12_381(point)) => {
|
||||||
|
let point = match point {
|
||||||
|
ast::Bls12_381PointType::G1 => {
|
||||||
|
blst::blst_p1::uncompress(&bytes).map(ast::Bls12_381Point::G1)
|
||||||
|
}
|
||||||
|
ast::Bls12_381PointType::G2 => {
|
||||||
|
blst::blst_p2::uncompress(&bytes).map(ast::Bls12_381Point::G2)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let point = point.unwrap_or_else(|_err| {
|
||||||
|
emit(ParseError::point_not_on_curve(curve, location));
|
||||||
|
|
||||||
|
ast::Bls12_381Point::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
ast::Constant::CurvePoint {
|
||||||
|
location,
|
||||||
|
point: ast::Curve::Bls12_381(point),
|
||||||
|
preferred_format,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => ast::Constant::ByteArray {
|
||||||
location,
|
location,
|
||||||
bytes,
|
bytes,
|
||||||
preferred_format,
|
preferred_format,
|
||||||
},
|
},
|
||||||
);
|
},
|
||||||
|
);
|
||||||
|
|
||||||
choice((
|
choice((
|
||||||
constant_string_parser,
|
constant_string_parser,
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use crate::{ast::Span, parser::token::Token};
|
use crate::{
|
||||||
|
ast::{CurveType, Span},
|
||||||
|
parser::token::Token,
|
||||||
|
};
|
||||||
use indoc::formatdoc;
|
use indoc::formatdoc;
|
||||||
use miette::Diagnostic;
|
use miette::Diagnostic;
|
||||||
use owo_colors::{OwoColorize, Stream::Stdout};
|
use owo_colors::{OwoColorize, Stream::Stdout};
|
||||||
|
@ -46,6 +49,32 @@ impl ParseError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn point_not_on_curve(curve: CurveType, span: Span) -> Self {
|
||||||
|
Self {
|
||||||
|
kind: ErrorKind::PointNotOnCurve { curve },
|
||||||
|
span,
|
||||||
|
while_parsing: None,
|
||||||
|
expected: HashSet::new(),
|
||||||
|
label: Some("out off curve"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unknown_point_curve(curve: String, point: Option<String>, span: Span) -> Self {
|
||||||
|
let label = if point.is_some() {
|
||||||
|
Some("unknown curve")
|
||||||
|
} else {
|
||||||
|
Some("unknown point")
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
kind: ErrorKind::UnknownCurvePoint { curve, point },
|
||||||
|
span,
|
||||||
|
while_parsing: None,
|
||||||
|
expected: HashSet::new(),
|
||||||
|
label,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn malformed_base16_string_literal(span: Span) -> Self {
|
pub fn malformed_base16_string_literal(span: Span) -> Self {
|
||||||
Self {
|
Self {
|
||||||
kind: ErrorKind::MalformedBase16StringLiteral,
|
kind: ErrorKind::MalformedBase16StringLiteral,
|
||||||
|
@ -134,6 +163,15 @@ pub enum ErrorKind {
|
||||||
hint: Option<String>,
|
hint: Option<String>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
#[error("I tripped over a {}", fmt_curve_type(.curve))]
|
||||||
|
PointNotOnCurve { curve: CurveType },
|
||||||
|
|
||||||
|
#[error("I tripped over a {}", fmt_unknown_curve(.curve, .point))]
|
||||||
|
UnknownCurvePoint {
|
||||||
|
curve: String,
|
||||||
|
point: Option<String>,
|
||||||
|
},
|
||||||
|
|
||||||
#[error("I tripped over a malformed hexadecimal digits.")]
|
#[error("I tripped over a malformed hexadecimal digits.")]
|
||||||
#[diagnostic(help("{}", formatdoc! {
|
#[diagnostic(help("{}", formatdoc! {
|
||||||
r#"When numbers starts with '0x', they are treated as hexadecimal numbers. Thus, only digits from 0-9 or letter from a-f (or A-F) can be used following a '0x' number declaration. Plus, hexadecimal digits always go by pairs, so the total number of digits must be even (not counting leading zeros)."#
|
r#"When numbers starts with '0x', they are treated as hexadecimal numbers. Thus, only digits from 0-9 or letter from a-f (or A-F) can be used following a '0x' number declaration. Plus, hexadecimal digits always go by pairs, so the total number of digits must be even (not counting leading zeros)."#
|
||||||
|
@ -186,6 +224,32 @@ pub enum ErrorKind {
|
||||||
InvalidWhenClause,
|
InvalidWhenClause,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fmt_curve_type(curve: &CurveType) -> String {
|
||||||
|
match curve {
|
||||||
|
CurveType::Bls12_381(point) => {
|
||||||
|
format!("{point} point that is not in the bls12_381 curve")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fmt_unknown_curve(curve: &String, point: &Option<String>) -> String {
|
||||||
|
match point {
|
||||||
|
Some(point) => {
|
||||||
|
format!(
|
||||||
|
"{} which is an unknown point for curve {}",
|
||||||
|
point.if_supports_color(Stdout, |s| s.purple()),
|
||||||
|
curve.if_supports_color(Stdout, |s| s.purple()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
format!(
|
||||||
|
"{} which is an unknown curve",
|
||||||
|
curve.if_supports_color(Stdout, |s| s.purple())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Diagnostic, thiserror::Error)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Diagnostic, thiserror::Error)]
|
||||||
pub enum Pattern {
|
pub enum Pattern {
|
||||||
#[error("I found an unexpected char '{0:?}'.")]
|
#[error("I found an unexpected char '{0:?}'.")]
|
||||||
|
|
|
@ -1,13 +1,43 @@
|
||||||
use chumsky::prelude::*;
|
use chumsky::prelude::*;
|
||||||
|
use uplc::machine::runtime::Compressable;
|
||||||
|
|
||||||
use crate::parser::{error::ParseError, expr::UntypedExpr, literal::bytearray, token::Token};
|
use crate::{
|
||||||
|
ast,
|
||||||
|
parser::{error::ParseError, expr::UntypedExpr, literal::bytearray, token::Token},
|
||||||
|
};
|
||||||
|
|
||||||
pub fn parser() -> impl Parser<Token, UntypedExpr, Error = ParseError> {
|
pub fn parser() -> impl Parser<Token, UntypedExpr, Error = ParseError> {
|
||||||
bytearray(|bytes, preferred_format, location| UntypedExpr::ByteArray {
|
bytearray(
|
||||||
location,
|
|bytes, preferred_format, curve, location, emit| match curve {
|
||||||
bytes,
|
Some(curve @ ast::CurveType::Bls12_381(point)) => {
|
||||||
preferred_format,
|
let point = match point {
|
||||||
})
|
ast::Bls12_381PointType::G1 => {
|
||||||
|
blst::blst_p1::uncompress(&bytes).map(ast::Bls12_381Point::G1)
|
||||||
|
}
|
||||||
|
ast::Bls12_381PointType::G2 => {
|
||||||
|
blst::blst_p2::uncompress(&bytes).map(ast::Bls12_381Point::G2)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let point = point.unwrap_or_else(|_err| {
|
||||||
|
emit(ParseError::point_not_on_curve(curve, location));
|
||||||
|
|
||||||
|
ast::Bls12_381Point::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
UntypedExpr::CurvePoint {
|
||||||
|
location,
|
||||||
|
point: ast::Curve::Bls12_381(point),
|
||||||
|
preferred_format,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => UntypedExpr::ByteArray {
|
||||||
|
location,
|
||||||
|
bytes,
|
||||||
|
preferred_format,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -9,16 +9,70 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parser<A>(
|
pub fn parser<A>(
|
||||||
into: impl Fn(Vec<u8>, ast::ByteArrayFormatPreference, ast::Span) -> A,
|
into: impl Fn(
|
||||||
|
Vec<u8>,
|
||||||
|
ast::ByteArrayFormatPreference,
|
||||||
|
Option<ast::CurveType>,
|
||||||
|
ast::Span,
|
||||||
|
&mut dyn FnMut(ParseError),
|
||||||
|
) -> A,
|
||||||
) -> impl Parser<Token, A, Error = ParseError> {
|
) -> impl Parser<Token, A, Error = ParseError> {
|
||||||
choice((array_of_bytes(), hex_string(), utf8_string()))
|
choice((
|
||||||
.map_with_span(move |(preferred_format, bytes), span| into(bytes, preferred_format, span))
|
array_of_bytes(),
|
||||||
|
hex_string(),
|
||||||
|
utf8_string().map(|(p, b)| (None, p, b)),
|
||||||
|
))
|
||||||
|
.validate(move |(curve, preferred_format, bytes), span, emit| {
|
||||||
|
into(bytes, preferred_format, curve, span, emit)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_of_bytes(
|
fn curve_point() -> impl Parser<Token, ast::CurveType, Error = ParseError> {
|
||||||
) -> impl Parser<Token, (ast::ByteArrayFormatPreference, Vec<u8>), Error = ParseError> {
|
just(Token::Less)
|
||||||
|
.ignore_then(select! {Token::UpName {name} => name})
|
||||||
|
.then_ignore(just(Token::Comma))
|
||||||
|
.then(select! {Token::UpName {name} => name})
|
||||||
|
.then_ignore(just(Token::Greater))
|
||||||
|
.validate(
|
||||||
|
|(curve_type, point_type), span, emit| match curve_type.as_str() {
|
||||||
|
"Bls12_381" => {
|
||||||
|
let point = match point_type.as_str() {
|
||||||
|
"G1" => ast::Bls12_381PointType::G1,
|
||||||
|
"G2" => ast::Bls12_381PointType::G2,
|
||||||
|
_ => {
|
||||||
|
emit(ParseError::unknown_point_curve(
|
||||||
|
curve_type,
|
||||||
|
Some(point_type),
|
||||||
|
span,
|
||||||
|
));
|
||||||
|
|
||||||
|
ast::Bls12_381PointType::G1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ast::CurveType::Bls12_381(point)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
emit(ParseError::unknown_point_curve(curve_type, None, span));
|
||||||
|
|
||||||
|
ast::CurveType::Bls12_381(ast::Bls12_381PointType::G1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn array_of_bytes() -> impl Parser<
|
||||||
|
Token,
|
||||||
|
(
|
||||||
|
Option<ast::CurveType>,
|
||||||
|
ast::ByteArrayFormatPreference,
|
||||||
|
Vec<u8>,
|
||||||
|
),
|
||||||
|
Error = ParseError,
|
||||||
|
> {
|
||||||
just(Token::Hash)
|
just(Token::Hash)
|
||||||
.ignore_then(
|
.ignore_then(curve_point().or_not())
|
||||||
|
.then(
|
||||||
select! {Token::Int {value, base, ..} => (value, base)}
|
select! {Token::Int {value, base, ..} => (value, base)}
|
||||||
.validate(|(value, base), span, emit| {
|
.validate(|(value, base), span, emit| {
|
||||||
let byte: u8 = match value.parse() {
|
let byte: u8 = match value.parse() {
|
||||||
|
@ -38,7 +92,7 @@ pub fn array_of_bytes(
|
||||||
.allow_trailing()
|
.allow_trailing()
|
||||||
.delimited_by(just(Token::LeftSquare), just(Token::RightSquare)),
|
.delimited_by(just(Token::LeftSquare), just(Token::RightSquare)),
|
||||||
)
|
)
|
||||||
.validate(|bytes, span, emit| {
|
.validate(|(curve, bytes), span, emit| {
|
||||||
let base = bytes.iter().try_fold(None, |acc, (_, base)| match acc {
|
let base = bytes.iter().try_fold(None, |acc, (_, base)| match acc {
|
||||||
None => Ok(Some(base)),
|
None => Ok(Some(base)),
|
||||||
Some(previous_base) if previous_base == base => Ok(Some(base)),
|
Some(previous_base) if previous_base == base => Ok(Some(base)),
|
||||||
|
@ -58,15 +112,33 @@ pub fn array_of_bytes(
|
||||||
Ok(Some(base)) => *base,
|
Ok(Some(base)) => *base,
|
||||||
};
|
};
|
||||||
|
|
||||||
(bytes.into_iter().map(|(b, _)| b).collect::<Vec<u8>>(), base)
|
(
|
||||||
|
curve,
|
||||||
|
bytes.into_iter().map(|(b, _)| b).collect::<Vec<u8>>(),
|
||||||
|
base,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.map(|(curve, bytes, base)| {
|
||||||
|
(
|
||||||
|
curve,
|
||||||
|
ast::ByteArrayFormatPreference::ArrayOfBytes(base),
|
||||||
|
bytes,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.map(|(bytes, base)| (ast::ByteArrayFormatPreference::ArrayOfBytes(base), bytes))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hex_string(
|
pub fn hex_string() -> impl Parser<
|
||||||
) -> impl Parser<Token, (ast::ByteArrayFormatPreference, Vec<u8>), Error = ParseError> {
|
Token,
|
||||||
|
(
|
||||||
|
Option<ast::CurveType>,
|
||||||
|
ast::ByteArrayFormatPreference,
|
||||||
|
Vec<u8>,
|
||||||
|
),
|
||||||
|
Error = ParseError,
|
||||||
|
> {
|
||||||
just(Token::Hash)
|
just(Token::Hash)
|
||||||
.ignore_then(
|
.ignore_then(curve_point().or_not())
|
||||||
|
.then(
|
||||||
select! {Token::ByteString {value} => value}.validate(|value, span, emit| {
|
select! {Token::ByteString {value} => value}.validate(|value, span, emit| {
|
||||||
match hex::decode(value) {
|
match hex::decode(value) {
|
||||||
Ok(bytes) => bytes,
|
Ok(bytes) => bytes,
|
||||||
|
@ -77,7 +149,13 @@ pub fn hex_string(
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.map(|token| (ast::ByteArrayFormatPreference::HexadecimalString, token))
|
.map(|(curve, token)| {
|
||||||
|
(
|
||||||
|
curve,
|
||||||
|
ast::ByteArrayFormatPreference::HexadecimalString,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn utf8_string(
|
pub fn utf8_string(
|
||||||
|
|
|
@ -3,13 +3,13 @@ use vec1::Vec1;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
Annotation, Arg, ArgName, AssignmentKind, BinOp, ByteArrayFormatPreference, CallArg,
|
Annotation, Arg, ArgName, AssignmentKind, BinOp, Bls12_381Point, ByteArrayFormatPreference,
|
||||||
ClauseGuard, Constant, IfBranch, LogicalOpChainKind, RecordUpdateSpread, Span, TraceKind,
|
CallArg, ClauseGuard, Constant, Curve, IfBranch, LogicalOpChainKind, RecordUpdateSpread,
|
||||||
Tracing, TypedArg, TypedCallArg, TypedClause, TypedClauseGuard, TypedIfBranch,
|
Span, TraceKind, Tracing, TypedArg, TypedCallArg, TypedClause, TypedClauseGuard,
|
||||||
TypedPattern, TypedRecordUpdateArg, UnOp, UntypedArg, UntypedClause, UntypedClauseGuard,
|
TypedIfBranch, TypedPattern, TypedRecordUpdateArg, UnOp, UntypedArg, UntypedClause,
|
||||||
UntypedIfBranch, UntypedPattern, UntypedRecordUpdateArg,
|
UntypedClauseGuard, UntypedIfBranch, UntypedPattern, UntypedRecordUpdateArg,
|
||||||
},
|
},
|
||||||
builtins::{bool, byte_array, function, int, list, string, tuple},
|
builtins::{bool, byte_array, function, g1_element, g2_element, int, list, string, tuple},
|
||||||
expr::{FnStyle, TypedExpr, UntypedExpr},
|
expr::{FnStyle, TypedExpr, UntypedExpr},
|
||||||
format,
|
format,
|
||||||
tipo::fields::FieldMap,
|
tipo::fields::FieldMap,
|
||||||
|
@ -321,6 +321,10 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
location,
|
location,
|
||||||
} => self.infer_bytearray(bytes, preferred_format, location),
|
} => self.infer_bytearray(bytes, preferred_format, location),
|
||||||
|
|
||||||
|
UntypedExpr::CurvePoint {
|
||||||
|
location, point, ..
|
||||||
|
} => self.infer_curve_point(point, location),
|
||||||
|
|
||||||
UntypedExpr::RecordUpdate {
|
UntypedExpr::RecordUpdate {
|
||||||
location,
|
location,
|
||||||
constructor,
|
constructor,
|
||||||
|
@ -363,6 +367,21 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn infer_curve_point(&mut self, curve: Curve, location: Span) -> Result<TypedExpr, Error> {
|
||||||
|
let tipo = match curve {
|
||||||
|
Curve::Bls12_381(point) => match point {
|
||||||
|
Bls12_381Point::G1(_) => g1_element(),
|
||||||
|
Bls12_381Point::G2(_) => g2_element(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(TypedExpr::CurvePoint {
|
||||||
|
location,
|
||||||
|
point: curve,
|
||||||
|
tipo,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn infer_trace_if_false(
|
fn infer_trace_if_false(
|
||||||
&mut self,
|
&mut self,
|
||||||
value: UntypedExpr,
|
value: UntypedExpr,
|
||||||
|
@ -1345,6 +1364,15 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
preferred_format,
|
preferred_format,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Constant::CurvePoint {
|
||||||
|
location,
|
||||||
|
point,
|
||||||
|
preferred_format,
|
||||||
|
} => Ok(Constant::CurvePoint {
|
||||||
|
location,
|
||||||
|
point,
|
||||||
|
preferred_format,
|
||||||
|
}),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
// Check type annotation is accurate.
|
// Check type annotation is accurate.
|
||||||
|
@ -2000,7 +2028,8 @@ fn assert_no_assignment(expr: &UntypedExpr) -> Result<(), Error> {
|
||||||
| UntypedExpr::Var { .. }
|
| UntypedExpr::Var { .. }
|
||||||
| UntypedExpr::LogicalOpChain { .. }
|
| UntypedExpr::LogicalOpChain { .. }
|
||||||
| UntypedExpr::TraceIfFalse { .. }
|
| UntypedExpr::TraceIfFalse { .. }
|
||||||
| UntypedExpr::When { .. } => Ok(()),
|
| UntypedExpr::When { .. }
|
||||||
|
| UntypedExpr::CurvePoint { .. } => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn assert_assignment(expr: &UntypedExpr) -> Result<(), Error> {
|
fn assert_assignment(expr: &UntypedExpr) -> Result<(), Error> {
|
||||||
|
|
Loading…
Reference in New Issue