diff --git a/Cargo.lock b/Cargo.lock index b70139f7..a3ec426c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,6 +149,8 @@ dependencies = [ "clap", "combine", "hex", + "strum", + "strum_macros", ] [[package]] @@ -199,12 +201,37 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rustversion" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" + [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strum" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96acfc1b70604b8b2f1ffa4c57e59176c7dbb05d556c71ecd2f5498a1dee7f8" + +[[package]] +name = "strum_macros" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "syn" version = "1.0.92" diff --git a/Cargo.toml b/Cargo.toml index 3118c9ee..b951c6c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,5 @@ anyhow = "1.0.57" clap = { version = "3.1.14", features = ["derive"] } combine = "4.6.4" hex = "0.4.3" +strum = "0.24.0" +strum_macros = "0.24.0" diff --git a/src/ast.rs b/src/ast.rs index 707b9b7b..258922e1 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,3 +1,5 @@ +use strum_macros::EnumString; + #[derive(Debug)] pub struct Program { pub version: String, @@ -27,7 +29,7 @@ pub enum Term { // tag: 6 Error(Box), // tag: 7 - // Builtin + Builtin(DefaultFunction), } #[derive(Debug, Clone)] @@ -46,3 +48,78 @@ pub enum Constant { // tag: 5 Bool(bool), } + +#[derive(Debug, Clone, EnumString)] +pub enum DefaultFunction { + // Integer functions + AddInteger, + SubtractInteger, + MultiplyInteger, + DivideInteger, + QuotientInteger, + RemainderInteger, + ModInteger, + EqualsInteger, + LessThanInteger, + LessThanEqualsInteger, + // ByteString functions + AppendByteString, + ConsByteString, + SliceByteString, + LengthOfByteString, + IndexByteString, + EqualsByteString, + LessThanByteString, + LessThanEqualsByteString, + // Cryptography and hash functions + Sha2_256, + Sha3_256, + Blake2b_256, + VerifySignature, + VerifyEcdsaSecp256k1Signature, + VerifySchnorrSecp256k1Signature, + // String functions + AppendString, + EqualsString, + EncodeUtf8, + DecodeUtf8, + // Bool function + IfThenElse, + // Unit function + ChooseUnit, + // Tracing function + Trace, + // Pairs functions + FstPair, + SndPair, + // List functions + ChooseList, + MkCons, + HeadList, + TailList, + NullList, + // Data functions + // It is convenient to have a "choosing" function for a data type that has more than two + // constructors to get pattern matching over it and we may end up having multiple such data + // types, hence we include the name of the data type as a suffix. + ChooseData, + ConstrData, + MapData, + ListData, + IData, + BData, + UnConstrData, + UnMapData, + UnListData, + UnIData, + UnBData, + EqualsData, + SerialiseData, + // Misc constructors + // Constructors that we need for constructing e.g. Data. Polymorphic builtin + // constructors are often problematic (See note [Representable built-in + // functions over polymorphic built-in types]) + MkPairData, + MkNilData, + MkNilPairData, +} diff --git a/src/parser.rs b/src/parser.rs index 5c09f10d..fe4096f5 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use combine::{ attempt, between, choice, many1, parser::char::{alpha_num, digit, hex_digit, space, spaces, string}, @@ -6,7 +8,7 @@ use combine::{ token, EasyParser, ParseError, Parser, Stream, }; -use crate::ast::{Constant, Program, Term}; +use crate::ast::{Constant, DefaultFunction, Program, Term}; pub fn program(src: &str) -> anyhow::Result { let mut parser = program_(); @@ -136,7 +138,31 @@ where ) } -fn constant() -> impl Parser +pub fn builtin() -> impl Parser +where + Input: Stream, + Input::Error: ParseError, +{ + string("builtin") + .with(skip_many1(space())) + .with(many1(alpha_num())) + .map(|builtin_name: String| { + Term::Builtin(DefaultFunction::from_str(&builtin_name).unwrap()) + }) +} + +pub fn error() -> impl Parser +where + Input: Stream, + Input::Error: ParseError, +{ + string("error") + .with(skip_many1(space())) + .with(term_()) + .map(|term| Term::Error(Box::new(term))) +} + +pub fn constant() -> impl Parser where Input: Stream, Input::Error: ParseError,