From 1721c3945bc318520c7a3f098126b5737bb809c4 Mon Sep 17 00:00:00 2001 From: Kasey White Date: Mon, 9 Jan 2023 01:44:51 -0500 Subject: [PATCH] Refactors: Add test 40 refactor how we get data type from type Call contains type now to handle certain record cases --- crates/aiken-lang/src/air.rs | 38 ++---- crates/aiken-lang/src/builder.rs | 12 +- crates/aiken-lang/src/uplc.rs | 138 +++++++-------------- examples/acceptance_tests/040/aiken.lock | 5 + examples/acceptance_tests/040/aiken.toml | 2 + examples/acceptance_tests/040/lib/tests.ak | 16 +++ 6 files changed, 88 insertions(+), 123 deletions(-) create mode 100644 examples/acceptance_tests/040/aiken.lock create mode 100644 examples/acceptance_tests/040/aiken.toml create mode 100644 examples/acceptance_tests/040/lib/tests.ak diff --git a/crates/aiken-lang/src/air.rs b/crates/aiken-lang/src/air.rs index fd490d18..163c4f4d 100644 --- a/crates/aiken-lang/src/air.rs +++ b/crates/aiken-lang/src/air.rs @@ -3,7 +3,7 @@ use std::{collections::HashSet, sync::Arc}; use uplc::builtins::DefaultFunction; use crate::{ - ast::{AssignmentKind, BinOp, UnOp}, + ast::{BinOp, UnOp}, tipo::{Type, ValueConstructor}, }; @@ -59,6 +59,7 @@ pub enum Air { Call { scope: Vec, count: usize, + tipo: Arc, }, Builtin { @@ -77,7 +78,10 @@ pub enum Air { Assignment { scope: Vec, name: String, - kind: AssignmentKind, + }, + + Assert { + scope: Vec, }, DefineFunc { @@ -89,27 +93,6 @@ pub enum Air { variant_name: String, }, - DefineConst { - scope: Vec, - func_name: String, - module_name: String, - count: usize, - }, - - DefineConstrFields { - scope: Vec, - func_name: String, - module_name: String, - count: usize, - }, - - DefineConstrFieldAccess { - scope: Vec, - func_name: String, - module_name: String, - count: usize, - }, - Lam { scope: Vec, name: String, @@ -224,10 +207,6 @@ pub enum Air { tipo: Arc, }, - Record { - scope: Vec, - }, - RecordUpdate { scope: Vec, highest_index: usize, @@ -261,10 +240,8 @@ impl Air { | Air::Builtin { scope, .. } | Air::BinOp { scope, .. } | Air::Assignment { scope, .. } + | Air::Assert { scope } | Air::DefineFunc { scope, .. } - | Air::DefineConst { scope, .. } - | Air::DefineConstrFields { scope, .. } - | Air::DefineConstrFieldAccess { scope, .. } | Air::Lam { scope, .. } | Air::When { scope, .. } | Air::Clause { scope, .. } @@ -281,7 +258,6 @@ impl Air { | Air::Tuple { scope, .. } | Air::Todo { scope, .. } | Air::ErrorTerm { scope, .. } - | Air::Record { scope, .. } | Air::RecordUpdate { scope, .. } | Air::UnOp { scope, .. } | Air::Trace { scope, .. } diff --git a/crates/aiken-lang/src/builder.rs b/crates/aiken-lang/src/builder.rs index 8b891f43..27581398 100644 --- a/crates/aiken-lang/src/builder.rs +++ b/crates/aiken-lang/src/builder.rs @@ -1123,6 +1123,15 @@ pub fn monomorphize( } // TODO check on assignment if type is needed Air::Assignment { .. } => {} + Air::Call { scope, count, tipo } => { + if tipo.is_generic() { + let mut tipo = tipo.clone(); + find_generics_to_replace(&mut tipo, &generic_types); + + new_air[index] = Air::Call { scope, count, tipo }; + needs_variant = true; + } + } Air::When { scope, tipo, @@ -1445,10 +1454,11 @@ pub fn handle_recursion_ir( let current_call = recursion_ir[index - 1].clone(); match current_call { - Air::Call { scope, count } => { + Air::Call { scope, count, tipo } => { recursion_ir[index - 1] = Air::Call { scope, count: count + 1, + tipo, } } _ => unreachable!(), diff --git a/crates/aiken-lang/src/uplc.rs b/crates/aiken-lang/src/uplc.rs index 52aac5ec..673eed99 100644 --- a/crates/aiken-lang/src/uplc.rs +++ b/crates/aiken-lang/src/uplc.rs @@ -1,10 +1,10 @@ use std::{ collections::{HashMap, HashSet}, - ops::Deref, sync::Arc, vec, }; +use crate::tipo::TypeVar; use indexmap::IndexMap; use itertools::Itertools; use uplc::{ @@ -23,7 +23,7 @@ use uplc::{ use crate::{ air::Air, ast::{ - ArgName, AssignmentKind, BinOp, Clause, Pattern, Span, TypedArg, TypedDataType, + ArgName, AssignmentKind, BinOp, Clause, DataType, Pattern, Span, TypedArg, TypedDataType, TypedFunction, UnOp, }, builder::{ @@ -207,10 +207,13 @@ impl<'a> CodeGenerator<'a> { self.build_ir(tail, ir_stack, scope); } } - TypedExpr::Call { fun, args, .. } => { + TypedExpr::Call { + fun, args, tipo, .. + } => { ir_stack.push(Air::Call { scope: scope.clone(), count: args.len(), + tipo: tipo.clone(), }); let mut scope_fun = scope.clone(); scope_fun.push(self.id_gen.next()); @@ -811,22 +814,7 @@ impl<'a> CodeGenerator<'a> { } // find data type definition - let data_type_key = match tipo { - Type::Fn { ret, .. } => match ret.as_ref() { - Type::App { module, name, .. } => DataTypeKey { - module_name: module.clone(), - defined_type: name.clone(), - }, - _ => unreachable!(), - }, - Type::App { module, name, .. } => DataTypeKey { - module_name: module.clone(), - defined_type: name.clone(), - }, - _ => unreachable!(), - }; - - let data_type = self.data_types.get(&data_type_key).unwrap(); + let data_type = self.lookup_data_type_by_tipo(tipo).unwrap(); let (index, _) = data_type .constructors @@ -1002,22 +990,8 @@ impl<'a> CodeGenerator<'a> { tipo, .. } => { - let data_type_key = match tipo.as_ref() { - Type::Fn { ret, .. } => match &**ret { - Type::App { module, name, .. } => DataTypeKey { - module_name: module.clone(), - defined_type: name.clone(), - }, - _ => unreachable!(), - }, - Type::App { module, name, .. } => DataTypeKey { - module_name: module.clone(), - defined_type: name.clone(), - }, - _ => unreachable!(), - }; + let data_type = self.lookup_data_type_by_tipo(tipo).unwrap(); - let data_type = self.data_types.get(&data_type_key).unwrap(); let (_, constructor_type) = data_type .constructors .iter() @@ -1027,9 +1001,7 @@ impl<'a> CodeGenerator<'a> { let mut nested_pattern = vec![]; if *is_record { let field_map = match constructor { - tipo::PatternConstructor::Record { field_map, .. } => { - field_map.clone().unwrap() - } + PatternConstructor::Record { field_map, .. } => field_map.clone().unwrap(), }; let mut type_map: HashMap> = HashMap::new(); @@ -1336,22 +1308,7 @@ impl<'a> CodeGenerator<'a> { } => { let id = self.id_gen.next(); let constr_var_name = format!("{constr_name}_{id}"); - let data_type_key = match tipo.as_ref() { - Type::Fn { ret, .. } => match &**ret { - Type::App { module, name, .. } => DataTypeKey { - module_name: module.clone(), - defined_type: name.clone(), - }, - _ => unreachable!(), - }, - Type::App { module, name, .. } => DataTypeKey { - module_name: module.clone(), - defined_type: name.clone(), - }, - _ => unreachable!(), - }; - - let data_type = self.data_types.get(&data_type_key).unwrap(); + let data_type = self.lookup_data_type_by_tipo(tipo).unwrap(); if data_type.constructors.len() > 1 { pattern_vec.push(Air::ClauseGuard { @@ -1441,7 +1398,6 @@ impl<'a> CodeGenerator<'a> { Pattern::Var { name, .. } => { pattern_vec.push(Air::Assignment { name: name.clone(), - kind, scope, }); @@ -1549,22 +1505,7 @@ impl<'a> CodeGenerator<'a> { tipo, .. } => { - let data_type_key = match tipo.as_ref() { - Type::Fn { ret, .. } => match &**ret { - Type::App { module, name, .. } => DataTypeKey { - module_name: module.clone(), - defined_type: name.clone(), - }, - _ => unreachable!(), - }, - Type::App { module, name, .. } => DataTypeKey { - module_name: module.clone(), - defined_type: name.clone(), - }, - _ => unreachable!(), - }; - - let data_type = self.data_types.get(&data_type_key).unwrap(); + let data_type = self.lookup_data_type_by_tipo(tipo).unwrap(); let (_, constructor_type) = data_type .constructors .iter() @@ -2299,29 +2240,14 @@ impl<'a> CodeGenerator<'a> { arity, .. } => { - let data_type_key = match &*constructor.tipo { - Type::App { module, name, .. } => DataTypeKey { - module_name: module.to_string(), - defined_type: name.to_string(), - }, - Type::Fn { ret, .. } => match ret.deref() { - Type::App { module, name, .. } => DataTypeKey { - module_name: module.to_string(), - defined_type: name.to_string(), - }, - _ => unreachable!(), - }, - Type::Var { .. } => todo!(), - Type::Tuple { .. } => todo!(), - }; - if constructor.tipo.is_bool() { arg_stack .push(Term::Constant(UplcConstant::Bool(constr_name == "True"))); } else if constructor.tipo.is_void() { arg_stack.push(Term::Constant(UplcConstant::Unit)); } else { - let data_type = self.data_types.get(&data_type_key).unwrap(); + let data_type = + self.lookup_data_type_by_tipo(&constructor.tipo).unwrap(); let (constr_index, _) = data_type .constructors @@ -3033,6 +2959,9 @@ impl<'a> CodeGenerator<'a> { arg_stack.push(term); } + Air::Assert { .. } => { + todo!() + } Air::DefineFunc { func_name, params, @@ -3115,9 +3044,6 @@ impl<'a> CodeGenerator<'a> { arg_stack.push(term); } } - Air::DefineConst { .. } => todo!(), - Air::DefineConstrFields { .. } => todo!(), - Air::DefineConstrFieldAccess { .. } => todo!(), Air::Lam { name, .. } => { let arg = arg_stack.pop().unwrap(); @@ -3708,7 +3634,6 @@ impl<'a> CodeGenerator<'a> { arg_stack.push(term); } - Air::Record { .. } => todo!(), Air::RecordUpdate { highest_index, indices, @@ -4177,4 +4102,35 @@ impl<'a> CodeGenerator<'a> { } } } + + fn lookup_data_type_by_tipo(&self, tipo: &Type) -> Option<&&DataType>> { + match tipo { + Type::Fn { ret, .. } => match ret.as_ref() { + Type::App { module, name, .. } => { + let data_type_key = DataTypeKey { + module_name: module.clone(), + defined_type: name.clone(), + }; + self.data_types.get(&data_type_key) + } + _ => unreachable!(), + }, + Type::App { module, name, .. } => { + let data_type_key = DataTypeKey { + module_name: module.clone(), + defined_type: name.clone(), + }; + + self.data_types.get(&data_type_key) + } + Type::Var { tipo } => { + if let TypeVar::Link { tipo } = &*tipo.borrow() { + self.lookup_data_type_by_tipo(tipo) + } else { + None + } + } + _ => None, + } + } } diff --git a/examples/acceptance_tests/040/aiken.lock b/examples/acceptance_tests/040/aiken.lock new file mode 100644 index 00000000..3a78b1e7 --- /dev/null +++ b/examples/acceptance_tests/040/aiken.lock @@ -0,0 +1,5 @@ +# This file was generated by Aiken +# You typically do not need to edit this file + +requirements = [] +packages = [] diff --git a/examples/acceptance_tests/040/aiken.toml b/examples/acceptance_tests/040/aiken.toml new file mode 100644 index 00000000..dbb3240d --- /dev/null +++ b/examples/acceptance_tests/040/aiken.toml @@ -0,0 +1,2 @@ +name = "aiken-lang/acceptance_test_039" +version = "0.0.0" diff --git a/examples/acceptance_tests/040/lib/tests.ak b/examples/acceptance_tests/040/lib/tests.ak new file mode 100644 index 00000000..f13c4e76 --- /dev/null +++ b/examples/acceptance_tests/040/lib/tests.ak @@ -0,0 +1,16 @@ + + + +pub type Car{ + Honda { remote_connect: ByteArray, owner: ByteArray, wheels: Int} + Ford { remote_connect: ByteArray, owner: ByteArray, wheels: Int, truck_bed_limit: Int } +} + + + +test update_owner1(){ + let initial_car: Data = Ford{remote_connect: #[], owner: #[], wheels: 4, truck_bed_limit: 10000} + assert Ford{ owner, ..} = initial_car + owner == #[] + +}