From d5d2ba9cd743bfac59910cedbbb352e6d244c383 Mon Sep 17 00:00:00 2001 From: rvcas Date: Mon, 24 Oct 2022 13:30:27 -0400 Subject: [PATCH] feat: start creating aiken/builtin module --- Cargo.lock | 1 + crates/cli/src/project.rs | 1 + crates/lang/Cargo.toml | 1 + crates/lang/src/builtins.rs | 138 +++++++++++++++++++++++++-- crates/lang/src/tipo.rs | 5 +- crates/lang/src/tipo/environment.rs | 12 ++- crates/lang/src/tipo/infer.rs | 3 +- examples/sample/src/sample/syntax.ak | 6 ++ 8 files changed, 150 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e7f4986b..6907b6d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,6 +81,7 @@ dependencies = [ "miette", "pretty_assertions", "thiserror", + "uplc", "vec1", ] diff --git a/crates/cli/src/project.rs b/crates/cli/src/project.rs index 6cbe27fc..7e53bea3 100644 --- a/crates/cli/src/project.rs +++ b/crates/cli/src/project.rs @@ -37,6 +37,7 @@ impl Project { let mut module_types = HashMap::new(); module_types.insert("aiken".to_string(), builtins::prelude(&id_gen)); + module_types.insert("aiken/builtin".to_string(), builtins::plutus()); Project { config, diff --git a/crates/lang/Cargo.toml b/crates/lang/Cargo.toml index f834da6b..29fd52a7 100644 --- a/crates/lang/Cargo.toml +++ b/crates/lang/Cargo.toml @@ -16,6 +16,7 @@ internment = "0.7.0" itertools = "0.10.5" miette = "5.2.0" thiserror = "1.0.37" +uplc = { path = '../uplc', version = "0.0.21" } vec1 = "1.8.0" [dev-dependencies] diff --git a/crates/lang/src/builtins.rs b/crates/lang/src/builtins.rs index 43fea17a..e4cc5de5 100644 --- a/crates/lang/src/builtins.rs +++ b/crates/lang/src/builtins.rs @@ -1,9 +1,11 @@ use std::{cell::RefCell, collections::HashMap, sync::Arc}; +use uplc::builtins::DefaultFunction; + use crate::{ ast::{ModuleKind, Span}, tipo::{ - self, fields::FieldMap, Type, TypeConstructor, TypeVar, ValueConstructor, + fields::FieldMap, Type, TypeConstructor, TypeInfo, TypeVar, ValueConstructor, ValueConstructorVariant, }, IdGenerator, @@ -19,8 +21,8 @@ const STRING: &str = "String"; /// Build a prelude that can be injected /// into a compiler pipeline -pub fn prelude(id_gen: &IdGenerator) -> tipo::TypeInfo { - let mut prelude = tipo::TypeInfo { +pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { + let mut prelude = TypeInfo { name: "aiken".to_string(), package: "".to_string(), kind: ModuleKind::Lib, @@ -36,7 +38,7 @@ pub fn prelude(id_gen: &IdGenerator) -> tipo::TypeInfo { TypeConstructor { parameters: vec![], tipo: int(), - origin: Span::empty(), + location: Span::empty(), module: "".to_string(), public: true, }, @@ -46,7 +48,7 @@ pub fn prelude(id_gen: &IdGenerator) -> tipo::TypeInfo { prelude.types.insert( BYTE_ARRAY.to_string(), TypeConstructor { - origin: Span::empty(), + location: Span::empty(), parameters: vec![], tipo: byte_array(), module: "".to_string(), @@ -93,7 +95,7 @@ pub fn prelude(id_gen: &IdGenerator) -> tipo::TypeInfo { prelude.types.insert( BOOL.to_string(), TypeConstructor { - origin: Span::empty(), + location: Span::empty(), parameters: vec![], tipo: bool(), module: "".to_string(), @@ -106,7 +108,7 @@ pub fn prelude(id_gen: &IdGenerator) -> tipo::TypeInfo { prelude.types.insert( LIST.to_string(), TypeConstructor { - origin: Span::empty(), + location: Span::empty(), parameters: vec![list_parameter.clone()], tipo: list(list_parameter), module: "".to_string(), @@ -118,7 +120,7 @@ pub fn prelude(id_gen: &IdGenerator) -> tipo::TypeInfo { prelude.types.insert( STRING.to_string(), TypeConstructor { - origin: Span::empty(), + location: Span::empty(), parameters: vec![], tipo: string(), module: "".to_string(), @@ -145,7 +147,7 @@ pub fn prelude(id_gen: &IdGenerator) -> tipo::TypeInfo { prelude.types.insert( NIL.to_string(), TypeConstructor { - origin: Span::empty(), + location: Span::empty(), parameters: vec![], tipo: nil(), module: "".to_string(), @@ -160,7 +162,7 @@ pub fn prelude(id_gen: &IdGenerator) -> tipo::TypeInfo { prelude.types.insert( RESULT.to_string(), TypeConstructor { - origin: Span::empty(), + location: Span::empty(), parameters: vec![result_value.clone(), result_error.clone()], tipo: result(result_value, result_error), module: "".to_string(), @@ -210,6 +212,122 @@ pub fn prelude(id_gen: &IdGenerator) -> tipo::TypeInfo { prelude } +pub fn plutus() -> TypeInfo { + let mut plutus = TypeInfo { + name: "aiken/builtin".to_string(), + package: "".to_string(), + kind: ModuleKind::Lib, + types: HashMap::new(), + types_constructors: HashMap::new(), + values: HashMap::new(), + accessors: HashMap::new(), + }; + + plutus.values.insert( + DefaultFunction::AddInteger.to_string(), + DefaultFunction::AddInteger.into(), + ); + + plutus.values.insert( + DefaultFunction::SubtractInteger.to_string(), + DefaultFunction::SubtractInteger.into(), + ); + + plutus.values.insert( + DefaultFunction::MultiplyInteger.to_string(), + DefaultFunction::MultiplyInteger.into(), + ); + + plutus.values.insert( + DefaultFunction::DivideInteger.to_string(), + DefaultFunction::DivideInteger.into(), + ); + + plutus +} + +impl From for ValueConstructor { + fn from(builtin: DefaultFunction) -> Self { + let (tipo, arity) = match builtin { + DefaultFunction::AddInteger + | DefaultFunction::SubtractInteger + | DefaultFunction::MultiplyInteger + | DefaultFunction::DivideInteger + | DefaultFunction::QuotientInteger + | DefaultFunction::RemainderInteger + | DefaultFunction::ModInteger => { + let tipo = function(vec![int(), int()], int()); + + (tipo, 2) + } + + DefaultFunction::EqualsInteger + | DefaultFunction::LessThanInteger + | DefaultFunction::LessThanEqualsInteger => { + let tipo = function(vec![int(), int()], bool()); + + (tipo, 2) + } + DefaultFunction::AppendByteString => todo!(), + DefaultFunction::ConsByteString => todo!(), + DefaultFunction::SliceByteString => todo!(), + DefaultFunction::LengthOfByteString => todo!(), + DefaultFunction::IndexByteString => todo!(), + DefaultFunction::EqualsByteString => todo!(), + DefaultFunction::LessThanByteString => todo!(), + DefaultFunction::LessThanEqualsByteString => todo!(), + DefaultFunction::Sha2_256 => todo!(), + DefaultFunction::Sha3_256 => todo!(), + DefaultFunction::Blake2b_256 => todo!(), + DefaultFunction::VerifyEd25519Signature => todo!(), + DefaultFunction::VerifyEcdsaSecp256k1Signature => todo!(), + DefaultFunction::VerifySchnorrSecp256k1Signature => todo!(), + DefaultFunction::AppendString => todo!(), + DefaultFunction::EqualsString => todo!(), + DefaultFunction::EncodeUtf8 => todo!(), + DefaultFunction::DecodeUtf8 => todo!(), + DefaultFunction::IfThenElse => todo!(), + DefaultFunction::ChooseUnit => todo!(), + DefaultFunction::Trace => todo!(), + DefaultFunction::FstPair => todo!(), + DefaultFunction::SndPair => todo!(), + DefaultFunction::ChooseList => todo!(), + DefaultFunction::MkCons => todo!(), + DefaultFunction::HeadList => todo!(), + DefaultFunction::TailList => todo!(), + DefaultFunction::NullList => todo!(), + DefaultFunction::ChooseData => todo!(), + DefaultFunction::ConstrData => todo!(), + DefaultFunction::MapData => todo!(), + DefaultFunction::ListData => todo!(), + DefaultFunction::IData => todo!(), + DefaultFunction::BData => todo!(), + DefaultFunction::UnConstrData => todo!(), + DefaultFunction::UnMapData => todo!(), + DefaultFunction::UnListData => todo!(), + DefaultFunction::UnIData => todo!(), + DefaultFunction::UnBData => todo!(), + DefaultFunction::EqualsData => todo!(), + DefaultFunction::SerialiseData => todo!(), + DefaultFunction::MkPairData => todo!(), + DefaultFunction::MkNilData => todo!(), + DefaultFunction::MkNilPairData => todo!(), + }; + + ValueConstructor::public( + tipo, + ValueConstructorVariant::ModuleFn { + name: builtin.to_string(), + field_map: None, + module: "".to_string(), + arity, + location: Span::empty(), + builtin: Some(builtin), + }, + ) + } +} + pub fn int() -> Arc { Arc::new(Type::App { public: true, diff --git a/crates/lang/src/tipo.rs b/crates/lang/src/tipo.rs index 25f7f7e7..ce0f4b00 100644 --- a/crates/lang/src/tipo.rs +++ b/crates/lang/src/tipo.rs @@ -1,5 +1,7 @@ use std::{cell::RefCell, collections::HashMap, ops::Deref, sync::Arc}; +use uplc::builtins::DefaultFunction; + use crate::{ ast::{Constant, DefinitionLocation, ModuleKind, Span, TypedConstant}, tipo::fields::FieldMap, @@ -354,6 +356,7 @@ pub enum ValueConstructorVariant { module: String, arity: usize, location: Span, + builtin: Option, }, /// A constructor for a custom type @@ -445,7 +448,7 @@ pub struct TypeInfo { #[derive(Debug, Clone)] pub struct TypeConstructor { pub public: bool, - pub origin: Span, + pub location: Span, pub module: String, pub parameters: Vec>, pub tipo: Arc, diff --git a/crates/lang/src/tipo/environment.rs b/crates/lang/src/tipo/environment.rs index 184a7174..f018b42c 100644 --- a/crates/lang/src/tipo/environment.rs +++ b/crates/lang/src/tipo/environment.rs @@ -224,6 +224,7 @@ impl<'a> Environment<'a> { module: module_name.to_owned(), arity: args.len(), location, + builtin: None, }, }, ); @@ -461,7 +462,7 @@ impl<'a> Environment<'a> { info: TypeConstructor, ) -> Result<(), Error> { let name = type_name.clone(); - let location = info.origin; + let location = info.location; match self.module_types.insert(type_name, info) { None => Ok(()), @@ -469,7 +470,7 @@ impl<'a> Environment<'a> { Some(previous) => Err(Error::DuplicateTypeName { name, location, - previous_location: previous.origin, + previous_location: previous.location, }), } } @@ -720,7 +721,7 @@ impl<'a> Environment<'a> { // Register the unqualified import if it is a type constructor if let Some(typ) = module_info.types.get(name) { let typ_info = TypeConstructor { - origin: *location, + location: *location, ..typ.clone() }; @@ -843,7 +844,7 @@ impl<'a> Environment<'a> { self.insert_type_constructor( name.clone(), TypeConstructor { - origin: *location, + location: *location, module: module.to_owned(), public: *public, parameters, @@ -884,7 +885,7 @@ impl<'a> Environment<'a> { self.insert_type_constructor( name.clone(), TypeConstructor { - origin: *location, + location: *location, module: module.to_owned(), public: *public, parameters, @@ -967,6 +968,7 @@ impl<'a> Environment<'a> { module: module_name.to_owned(), arity: args.len(), location: *location, + builtin: None, }, tipo, ); diff --git a/crates/lang/src/tipo/infer.rs b/crates/lang/src/tipo/infer.rs index 7429a9f2..90dbccec 100644 --- a/crates/lang/src/tipo/infer.rs +++ b/crates/lang/src/tipo/infer.rs @@ -206,6 +206,7 @@ fn infer_definition( module: module_name.to_owned(), arity: args.len(), location, + builtin: None, }; environment.insert_variable(name.clone(), module_fn, tipo.clone()); @@ -422,7 +423,7 @@ fn infer_definition( } fn validate_module_name(name: &str) -> Result<(), Error> { - if name == "aiken" { + if name == "aiken" || name == "aiken/builtin" { return Err(Error::ReservedModuleName { name: name.to_string(), }); diff --git a/examples/sample/src/sample/syntax.ak b/examples/sample/src/sample/syntax.ak index 00bac8d3..283b132e 100644 --- a/examples/sample/src/sample/syntax.ak +++ b/examples/sample/src/sample/syntax.ak @@ -1,7 +1,13 @@ +use aiken/builtin.{addInteger} + pub type ScriptContext { idk: Int } pub fn append(a: ByteArray, b: ByteArray) -> ByteArray { todo +} + +pub fn add(a, b) { + addInteger(a, b) } \ No newline at end of file