test: add some snapshot tests for export type

This commit is contained in:
rvcas 2024-04-04 17:03:22 -04:00 committed by Lucas
parent 5cb1e23008
commit 5fc338a1eb
6 changed files with 250 additions and 5 deletions

View File

@ -38,11 +38,6 @@ impl Export {
generator: &mut CodeGenerator, generator: &mut CodeGenerator,
modules: &CheckedModules, modules: &CheckedModules,
) -> Result<Export, blueprint::Error> { ) -> Result<Export, blueprint::Error> {
let program = generator
.generate_raw(&func.body, &func.arguments, &module.name)
.to_debruijn()
.unwrap();
let mut definitions = Definitions::new(); let mut definitions = Definitions::new();
let parameters = func let parameters = func
@ -69,6 +64,11 @@ impl Export {
}) })
.collect::<Result<_, _>>()?; .collect::<Result<_, _>>()?;
let program = generator
.generate_raw(&func.body, &func.arguments, &module.name)
.to_debruijn()
.unwrap();
Ok(Export { Ok(Export {
name: format!("{}.{}", &module.name, &func.name), name: format!("{}.{}", &module.name, &func.name),
doc: func.doc.clone(), doc: func.doc.clone(),
@ -78,3 +78,106 @@ impl Export {
}) })
} }
} }
#[cfg(test)]
mod tests {
use super::{CheckedModules, Export};
use crate::tests::TestProject;
use aiken_lang::{
self,
ast::{TraceLevel, Tracing},
};
macro_rules! assert_export {
($code:expr) => {
let mut project = TestProject::new();
let modules = CheckedModules::singleton(project.check(project.parse(indoc::indoc! { $code })));
let mut generator = project.new_generator(
Tracing::All(TraceLevel::Verbose),
);
let (module, func) = modules
.functions()
.next()
.expect("source code did no yield any exports");
let export = Export::from_function(func, module, &mut generator, &modules);
match export {
Err(e) => insta::with_settings!({
description => concat!("Code:\n\n", indoc::indoc! { $code }),
omit_expression => true
}, {
insta::assert_debug_snapshot!(e);
}),
Ok(validator) => insta::with_settings!({
description => concat!("Code:\n\n", indoc::indoc! { $code }),
omit_expression => true
}, {
insta::assert_json_snapshot!(validator);
}),
};
};
}
#[test]
fn basic_export() {
assert_export!(
r#"
pub fn add(a: Int, b: Int) -> Int {
a + b
}
"#
);
}
#[test]
fn illegal_opaque_type() {
assert_export!(
r#"
pub opaque type Thing {
a: Int
}
pub fn add(a: Thing, b: Int) -> Int {
a.a + b
}
"#
);
}
#[test]
fn recursive_types() {
assert_export!(
r#"
pub type Foo<a> {
Empty
Bar(a, Foo<a>)
}
pub fn add(a: Foo<Int>, b: Foo<Int>) -> Int {
when (a, b) is {
(Empty, Empty) -> 0
(Bar(x, y), Bar(c, d)) -> x + c + add(y, d)
(Empty, Bar(c, d)) -> c + add(Empty, d)
(Bar(x, y), Empty) -> x + add(y, Empty)
}
}
"#
);
}
#[test]
fn cannot_export_generics() {
assert_export!(
r#"
pub fn add(_a: a, _b: b) -> Bool {
True
}
"#
);
}
}

View File

@ -477,6 +477,20 @@ impl CheckedModules {
items.into_iter() items.into_iter()
} }
pub fn functions(&self) -> impl Iterator<Item = (&CheckedModule, &TypedFunction)> {
let mut items = vec![];
for module in self.0.values() {
for some_definition in module.ast.definitions() {
if let Definition::Fn(def) = some_definition {
items.push((module, def));
}
}
}
items.into_iter()
}
pub fn into_validators(self) -> impl Iterator<Item = CheckedModule> { pub fn into_validators(self) -> impl Iterator<Item = CheckedModule> {
self.0 self.0
.into_values() .into_values()

View File

@ -0,0 +1,28 @@
---
source: crates/aiken-project/src/export.rs
description: "Code:\n\npub fn add(a: Int, b: Int) -> Int {\n a + b\n}\n"
---
{
"name": "test_module.add",
"parameters": [
{
"title": "a",
"schema": {
"$ref": "#/definitions/Int"
}
},
{
"title": "b",
"schema": {
"$ref": "#/definitions/Int"
}
}
],
"compiledCode": "500100002322337000046eb4004dd68009",
"hash": "bcd6700b4dba798a7d19c5769ef3deb21423f8809594a6942860dd1f",
"definitions": {
"Int": {
"dataType": "integer"
}
}
}

View File

@ -0,0 +1,24 @@
---
source: crates/aiken-project/src/export.rs
description: "Code:\n\npub fn add(_a: a, _b: b) -> Bool {\n True\n}\n"
---
Schema {
error: Error {
context: FreeTypeVariable,
breadcrumbs: [
Var {
tipo: RefCell {
value: Generic {
id: 33,
},
},
alias: None,
},
],
},
location: 11..16,
source_code: NamedSource {
name: "",
source: "<redacted>",
,
}

View File

@ -0,0 +1,24 @@
---
source: crates/aiken-project/src/export.rs
description: "Code:\n\npub opaque type Thing {\n a: Int\n}\n\npub fn add(a: Thing, b: Int) -> Int {\n a.a + b\n}\n"
---
Schema {
error: Error {
context: IllegalOpaqueType,
breadcrumbs: [
App {
public: true,
contains_opaque: true,
module: "test_module",
name: "Thing",
args: [],
alias: None,
},
],
},
location: 47..55,
source_code: NamedSource {
name: "",
source: "<redacted>",
,
}

View File

@ -0,0 +1,52 @@
---
source: crates/aiken-project/src/export.rs
description: "Code:\n\npub type Foo<a> {\n Empty\n Bar(a, Foo<a>)\n}\n\npub fn add(a: Foo<Int>, b: Foo<Int>) -> Int {\n when (a, b) is {\n (Empty, Empty) -> 0\n (Bar(x, y), Bar(c, d)) -> x + c + add(y, d)\n (Empty, Bar(c, d)) -> c + add(Empty, d)\n (Bar(x, y), Empty) -> x + add(y, Empty)\n }\n}\n"
---
{
"name": "test_module.add",
"parameters": [
{
"title": "a",
"schema": {
"$ref": "#/definitions/test_module~1Foo$Int"
}
},
{
"title": "b",
"schema": {
"$ref": "#/definitions/test_module~1Foo$Int"
}
}
],
"compiledCode": "5901c3010000323232323222323232323253330083002300937540062a666010600460126ea801052000001001132323232533300b3004300c375400c2646464a66601c600e601e6ea80284c8cdc019b80003375a60240026600c0046024602600260206ea8028010c040c044008dd6980780098069baa006001132533300b3005300c375400c2a666016600860186ea801c4c8cdc01bad300f001330034c103d8798000300f3010001300d375400e00200226466e00dd698070009980118071807800a60103d8798000300c375400a600200244464646464a66601e601260206ea800854ccc03cc024c040dd50018a4000002002264a66601e601060206ea80084c8c8c94ccc048c02cc04cdd500309919b80337000066eb4c058004ccc02c02c008c058c05c004c050dd5003002180a180a8011bad301300130113754004002264a66601e601260206ea800854ccc03cc020c040dd500189919b80375a6026002666010010980103d8798000301330140013011375400600200226466e00dd6980900099980380398091809800a60103d879800030103754002601c004601c00266ec0008004dc3a40046e1d20003006002300600133760004002ae6955ceaab9e5742ae89",
"hash": "4ce96c928b3be798496fca0ec3666d15d09004115df638801715b5e8",
"definitions": {
"Int": {
"dataType": "integer"
},
"test_module/Foo$Int": {
"title": "Foo",
"anyOf": [
{
"title": "Empty",
"dataType": "constructor",
"index": 0,
"fields": []
},
{
"title": "Bar",
"dataType": "constructor",
"index": 1,
"fields": [
{
"$ref": "#/definitions/Int"
},
{
"$ref": "#/definitions/test_module~1Foo$Int"
}
]
}
]
}
}
}