From dbfb39c89337d799862cc95715f766d0a6ffda29 Mon Sep 17 00:00:00 2001 From: arty Date: Mon, 10 Apr 2023 16:45:49 -0700 Subject: [PATCH 01/75] Isolate just embed --- .../clvm_tools/stages/stage_2/module.rs | 6 + src/compiler/compiler.rs | 8 +- src/compiler/comptypes.rs | 11 +- src/compiler/frontend.rs | 4 +- src/compiler/preprocessor.rs | 167 +++++++++++++++--- src/compiler/sexp.rs | 20 +-- src/tests/classic/run.rs | 118 ++++++++++++- 7 files changed, 294 insertions(+), 40 deletions(-) diff --git a/src/classic/clvm_tools/stages/stage_2/module.rs b/src/classic/clvm_tools/stages/stage_2/module.rs index cbf134365..5585a7368 100644 --- a/src/classic/clvm_tools/stages/stage_2/module.rs +++ b/src/classic/clvm_tools/stages/stage_2/module.rs @@ -20,6 +20,7 @@ use crate::classic::clvm_tools::stages::stage_2::inline::{ formulate_path_selections_for_destructuring, is_at_capture, is_inline_destructure, }; use crate::classic::clvm_tools::stages::stage_2::optimize::optimize_sexp; +use crate::classic::clvm_tools::stages::stage_2::reader::process_embed_file; lazy_static! { pub static ref MAIN_NAME: String = "".to_string(); @@ -340,6 +341,11 @@ fn parse_mod_sexp( macros, run_program.clone(), ) + } else if op == "embed-file".as_bytes() { + let (name, constant) = + process_embed_file(allocator, run_program.clone(), declaration_sexp)?; + constants.insert(name, constant); + Ok(()) } else if namespace.contains(&name) { Err(EvalErr( declaration_sexp, diff --git a/src/compiler/compiler.rs b/src/compiler/compiler.rs index 7639f88b5..2f86d580f 100644 --- a/src/compiler/compiler.rs +++ b/src/compiler/compiler.rs @@ -298,17 +298,17 @@ impl CompilerOpts for DefaultCompilerOpts { &self, inc_from: String, filename: String, - ) -> Result<(String, String), CompileErr> { + ) -> Result<(String, Vec), CompileErr> { if filename == "*macros*" { - return Ok((filename, STANDARD_MACROS.clone())); + return Ok((filename, STANDARD_MACROS.clone().as_bytes().to_vec())); } else if let Some(content) = self.known_dialects.get(&filename) { - return Ok((filename, content.to_string())); + return Ok((filename, content.as_bytes().to_vec())); } for dir in self.include_dirs.iter() { let mut p = PathBuf::from(dir); p.push(filename.clone()); - match fs::read_to_string(p.clone()) { + match fs::read(p.clone()) { Err(_e) => { continue; } diff --git a/src/compiler/comptypes.rs b/src/compiler/comptypes.rs index 0b7b89e1a..799ac4318 100644 --- a/src/compiler/comptypes.rs +++ b/src/compiler/comptypes.rs @@ -228,6 +228,14 @@ pub enum HelperForm { Defun(bool, DefunData), } +/// To what purpose is the file included. +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] +pub enum IncludeProcessType { + Bin, + Hex, + SExpression, +} + /// A description of an include form. Here, records the locations of the various /// parts of the include so they can be marked in the language server and be /// subject to other kind of reporting if desired. @@ -239,6 +247,7 @@ pub struct IncludeDesc { pub nl: Srcloc, /// The relative path to a target or a special directive name. pub name: Vec, + pub kind: Option, } impl IncludeDesc { @@ -357,7 +366,7 @@ pub trait CompilerOpts { &self, inc_from: String, filename: String, - ) -> Result<(String, String), CompileErr>; + ) -> Result<(String, Vec), CompileErr>; /// Given a parsed SExp, compile it as an independent program based on the /// settings given here. The result is bare generated code. diff --git a/src/compiler/frontend.rs b/src/compiler/frontend.rs index 3f8307376..0f4357206 100644 --- a/src/compiler/frontend.rs +++ b/src/compiler/frontend.rs @@ -522,7 +522,7 @@ fn match_op_name_4(pl: &[SExp]) -> Option { nl: ll.clone(), name: name.clone(), args: Rc::new(pl[2].clone()), - body: Rc::new(enlist(l.clone(), tail_list)), + body: Rc::new(enlist(l.clone(), &tail_list)), }) } _ => Some(OpName4Match { @@ -714,7 +714,7 @@ fn frontend_start( let args = Rc::new(x[1].clone()); let body_vec: Vec> = x.iter().skip(2).map(|s| Rc::new(s.clone())).collect(); - let body = Rc::new(enlist(pre_forms[0].loc(), body_vec)); + let body = Rc::new(enlist(pre_forms[0].loc(), &body_vec)); let ls = preprocess(opts.clone(), includes, body)?; return compile_mod_( diff --git a/src/compiler/preprocessor.rs b/src/compiler/preprocessor.rs index 0663a82bd..ed3ae4209 100644 --- a/src/compiler/preprocessor.rs +++ b/src/compiler/preprocessor.rs @@ -1,12 +1,34 @@ use std::borrow::Borrow; +use std::collections::HashMap; use std::rc::Rc; +use clvmr::allocator::Allocator; + +use crate::classic::clvm::__type_compatibility__::{Bytes, BytesFromType}; + +use crate::compiler::cldb::hex_to_modern_sexp; use crate::compiler::compiler::KNOWN_DIALECTS; -use crate::compiler::comptypes::{CompileErr, CompilerOpts, IncludeDesc}; +use crate::compiler::comptypes::{CompileErr, CompilerOpts, IncludeDesc, IncludeProcessType}; +use crate::compiler::runtypes::RunFailure; use crate::compiler::sexp::{decode_string, enlist, parse_sexp, SExp}; use crate::compiler::srcloc::Srcloc; use crate::util::ErrInto; +/// Determines how an included file is used. +/// +/// Basic means that the file contains helper forms to include in the program. +/// Processed means that some kind of processing is done and the result is a named +/// constant. +#[derive(Clone, Debug)] +enum IncludeType { + /// Normal include in chialisp. The code in the target file will join the + /// program being compiled. + Basic(IncludeDesc), + /// The data in the file will be processed in some way and the result will + /// live in a named constant. + Processed(IncludeDesc, IncludeProcessType, Vec), +} + /// Given a specification of an include file, load up the forms inside it and /// return them (or an error if the file couldn't be read or wasn't a list). pub fn process_include( @@ -19,7 +41,7 @@ pub fn process_include( // Because we're also subsequently returning CompileErr later in the pipe, // this needs an explicit err map. - parse_sexp(start_of_file.clone(), content.bytes()) + parse_sexp(start_of_file.clone(), content.iter().copied()) .err_into() .and_then(|x| match x[0].proper_list() { None => Err(CompileErr( @@ -30,6 +52,64 @@ pub fn process_include( }) } +fn compose_defconst(loc: Srcloc, name: &[u8], sexp: Rc) -> Rc { + Rc::new(enlist( + loc.clone(), + &[ + Rc::new(SExp::Atom(loc.clone(), b"defconst".to_vec())), + Rc::new(SExp::Atom(loc.clone(), name.to_vec())), + Rc::new(SExp::Cons( + loc.clone(), + Rc::new(SExp::Atom(loc, vec![1])), + sexp, + )), + ], + )) +} + +fn process_embed( + loc: Srcloc, + opts: Rc, + fname: &str, + kind: IncludeProcessType, + constant_name: &[u8], +) -> Result>, CompileErr> { + let mut allocator = Allocator::new(); + let run_to_compile_err = |e| match e { + RunFailure::RunExn(l, x) => CompileErr( + l, + format!("failed to convert compiled clvm to expression: throw ({x})"), + ), + RunFailure::RunErr(l, e) => CompileErr( + l, + format!("failed to convert compiled clvm to expression: {e}"), + ), + }; + + let (full_name, content) = opts.read_new_file(opts.filename(), fname.to_string())?; + let content = match kind { + IncludeProcessType::Bin => Rc::new(SExp::Atom(loc.clone(), content)), + IncludeProcessType::Hex => hex_to_modern_sexp( + &mut allocator, + &HashMap::new(), + loc.clone(), + &decode_string(&content), + ) + .map_err(run_to_compile_err)?, + IncludeProcessType::SExpression => { + let parsed = parse_sexp(Srcloc::start(&full_name), content.iter().copied()) + .map_err(|e| CompileErr(e.0, e.1))?; + if parsed.len() != 1 { + return Err(CompileErr(loc, format!("More than one form in {fname}"))); + } + + parsed[0].clone() + } + }; + + Ok(vec![compose_defconst(loc, constant_name, content)]) +} + /* Expand include inline in forms */ fn process_pp_form( opts: Rc, @@ -52,7 +132,8 @@ fn process_pp_form( ..desc }); - let parsed = parse_sexp(Srcloc::start(&full_name), content.bytes())?; + let parsed = parse_sexp(Srcloc::start(&full_name), content.iter().copied()) + .map_err(|e| CompileErr(e.0, e.1))?; if parsed.is_empty() { return Ok(()); } @@ -67,27 +148,63 @@ fn process_pp_form( Ok(()) }; - let included: Option = body + let include_type: Option = body .proper_list() .map(|x| x.iter().map(|elt| elt.atomize()).collect()) .map(|x: Vec| { match &x[..] { [SExp::Atom(kw, inc), SExp::Atom(nl, fname)] => { - if "include".as_bytes().to_vec() == *inc { - return Ok(Some(IncludeDesc { + if inc == b"include" { + return Ok(Some(IncludeType::Basic(IncludeDesc { kw: kw.clone(), nl: nl.clone(), + kind: None, name: fname.clone(), - })); + }))); } } - [SExp::Atom(kw, inc), SExp::QuotedString(nl, _, fname)] => { - if "include".as_bytes().to_vec() == *inc { - return Ok(Some(IncludeDesc { - kw: kw.clone(), - nl: nl.clone(), - name: fname.clone(), - })); + + [SExp::Atom(kl, embed_file), SExp::Atom(_, name), SExp::Atom(_, kind), SExp::Atom(nl, fname)] => { + if embed_file == b"embed-file" { + if kind == b"hex" { + return Ok(Some(IncludeType::Processed( + IncludeDesc { + kw: kl.clone(), + nl: nl.clone(), + kind: Some(IncludeProcessType::Hex), + name: fname.clone(), + }, + IncludeProcessType::Hex, + name.clone() + ))); + } else if kind == b"bin" { + return Ok(Some(IncludeType::Processed( + IncludeDesc { + kw: kl.clone(), + nl: nl.clone(), + kind: Some(IncludeProcessType::Bin), + name: fname.clone(), + }, + IncludeProcessType::Bin, + name.clone(), + ))); + } else if kind == b"sexp" { + return Ok(Some(IncludeType::Processed( + IncludeDesc { + kw: kl.clone(), + nl: nl.clone(), + kind: Some(IncludeProcessType::SExpression), + name: fname.clone(), + }, + IncludeProcessType::SExpression, + name.clone(), + ))); + } else { + return Err(CompileErr( + body.loc(), + format!("bad include kind in embed-file {body}") + )); + } } } @@ -98,7 +215,7 @@ fn process_pp_form( // Include is only allowed as a proper form. It's a keyword in // this language. if let SExp::Atom(_, inc) = &x[0] { - if "include".as_bytes().to_vec() == *inc { + if inc == b"include" { return Err(CompileErr( body.loc(), format!("bad tail in include {body}"), @@ -112,11 +229,19 @@ fn process_pp_form( }) .unwrap_or_else(|| Ok(None))?; - if let Some(i) = included { - recurse_dependencies(opts.clone(), includes, i.clone())?; - process_include(opts, i) - } else { - Ok(vec![body]) + match include_type { + Some(IncludeType::Basic(f)) => { + recurse_dependencies(opts.clone(), includes, f.clone())?; + process_include(opts, f) + } + Some(IncludeType::Processed(f, kind, name)) => process_embed( + body.loc(), + opts, + &Bytes::new(Some(BytesFromType::Raw(f.name.to_vec()))).decode(), + kind, + &name, + ), + _ => Ok(vec![body]), } } @@ -155,7 +280,7 @@ fn inject_std_macros(body: Rc) -> SExp { let mut v_clone: Vec> = v.iter().map(|x| Rc::new(x.clone())).collect(); let include_copy: &SExp = include_form.borrow(); v_clone.insert(0, Rc::new(include_copy.clone())); - enlist(body.loc(), v_clone) + enlist(body.loc(), &v_clone) } _ => { let body_clone: &SExp = body.borrow(); diff --git a/src/compiler/sexp.rs b/src/compiler/sexp.rs index 599eea3fe..7b00d2834 100644 --- a/src/compiler/sexp.rs +++ b/src/compiler/sexp.rs @@ -79,13 +79,11 @@ pub fn random_sexp(rng: &mut R, remaining: usize) -> SExp { // list let length = rng.gen_range(1..=remaining); let costs = vec![remaining / length; length]; - enlist( - loc(), - costs - .iter() - .map(|c| Rc::new(random_sexp(rng, *c))) - .collect(), - ) + let collected_list: Vec> = costs + .iter() + .map(|c| Rc::new(random_sexp(rng, *c))) + .collect(); + enlist(loc(), &collected_list) } 1 => { // cons @@ -309,7 +307,7 @@ fn make_atom(l: Srcloc, v: Vec) -> SExp { } } -pub fn enlist(l: Srcloc, v: Vec>) -> SExp { +pub fn enlist(l: Srcloc, v: &[Rc]) -> SExp { let mut result = SExp::Nil(l); for i_reverse in 0..v.len() { let i = v.len() - i_reverse - 1; @@ -622,7 +620,7 @@ fn parse_sexp_step(loc: Srcloc, p: &SExpParseState, this_char: u8) -> SExpParseR list_content.to_vec(), )), (')', SExpParseState::Empty) => emit( - Rc::new(enlist(pl.ext(&loc), list_content.to_vec())), + Rc::new(enlist(pl.clone(), list_content)), SExpParseState::Empty, ), (')', SExpParseState::Bareword(l, t)) => { @@ -630,7 +628,7 @@ fn parse_sexp_step(loc: Srcloc, p: &SExpParseState, this_char: u8) -> SExpParseR let mut updated_list = list_content.to_vec(); updated_list.push(Rc::new(parsed_atom)); emit( - Rc::new(enlist(pl.ext(&loc), updated_list)), + Rc::new(enlist(pl.clone(), &updated_list)), SExpParseState::Empty, ) } @@ -722,7 +720,7 @@ fn parse_sexp_step(loc: Srcloc, p: &SExpParseState, this_char: u8) -> SExpParseR emit(list_content[0].clone(), SExpParseState::Empty) } else { emit( - Rc::new(enlist(pl.ext(&loc), list_content.to_vec())), + Rc::new(enlist(pl.ext(&loc), list_content)), SExpParseState::Empty, ) } diff --git a/src/tests/classic/run.rs b/src/tests/classic/run.rs index 6a849743a..ba86e53ce 100644 --- a/src/tests/classic/run.rs +++ b/src/tests/classic/run.rs @@ -534,6 +534,123 @@ fn test_treehash_constant_embedded_modern_loop() { assert!(result_text.contains("stack limit exceeded")); } +#[test] +fn test_embed_file_2() { + let program = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "(mod () (embed-file testhex hex hex-embed-01.hex) testhex)".to_string(), + ]) + .trim() + .to_string(); + let run_result = do_basic_brun(&vec!["brun".to_string(), program, "()".to_string()]) + .trim() + .to_string(); + assert_eq!(run_result, "(65 66 67)"); +} + +#[test] +fn test_embed_file_4() { + let program = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "(mod () (include *standard-cl-21*) (embed-file testhex hex hex-embed-01.hex) testhex)" + .to_string(), + ]) + .trim() + .to_string(); + let run_result = do_basic_brun(&vec!["brun".to_string(), program, "()".to_string()]) + .trim() + .to_string(); + assert_eq!(run_result, "(65 66 67)"); +} + +#[test] +fn test_embed_file_5() { + let program = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "(mod () (embed-file testsexp sexp embed.sexp) testsexp)".to_string(), + ]) + .trim() + .to_string(); + let run_result = do_basic_brun(&vec!["brun".to_string(), program, "()".to_string()]) + .trim() + .to_string(); + assert_eq!(run_result, "(lsh 24 25)"); +} + +#[test] +fn test_embed_file_6() { + let program = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "(mod () (include *standard-cl-21*) (embed-file testsexp sexp embed.sexp) testsexp)" + .to_string(), + ]) + .trim() + .to_string(); + let run_result = do_basic_brun(&vec!["brun".to_string(), program, "()".to_string()]) + .trim() + .to_string(); + assert_eq!(run_result, "(lsh 24 25)"); +} + +#[test] +fn test_embed_file_7() { + let program = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "(mod () (embed-file hello bin hello.bin) hello)".to_string(), + ]) + .trim() + .to_string(); + let run_result = do_basic_brun(&vec!["brun".to_string(), program, "()".to_string()]) + .trim() + .to_string(); + assert_eq!(run_result, "\"hello\""); +} + +#[test] +fn test_embed_file_8() { + let program = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "(mod () (include *standard-cl-21*) (embed-file hello bin hello.bin) hello)".to_string(), + ]) + .trim() + .to_string(); + let run_result = do_basic_brun(&vec!["brun".to_string(), program, "()".to_string()]) + .trim() + .to_string(); + assert_eq!(run_result, "\"hello\""); +} + +#[test] +fn test_embed_file_9() { + let program = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "(mod () (include *standard-cl-21*) (embed-file hello bin hello.bin) (sha256 (sha256 hello)))".to_string(), + ]) + .trim() + .to_string(); + let run_result = do_basic_brun(&vec!["brun".to_string(), program, "()".to_string()]) + .trim() + .to_string(); + assert_eq!( + run_result, + "0x9595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50" + ); +} + #[test] fn test_num_encoding_just_less_than_5_bytes() { let res = do_basic_run(&vec!["run".to_string(), "4281419728".to_string()]) @@ -747,7 +864,6 @@ fn test_check_tricky_arg_path_random() { ) .unwrap(); let disassembled = disassemble(&mut allocator, converted); - eprintln!("run {} want {} have {}", program, disassembled, res); assert_eq!(disassembled, res); } } From 56edf55bbd79e5ad2f9864753d6b2feda03780bc Mon Sep 17 00:00:00 2001 From: arty Date: Mon, 10 Apr 2023 17:03:42 -0700 Subject: [PATCH 02/75] Ensure new test files are there --- resources/tests/hello.bin | 1 + resources/tests/hex-embed-01.hex | 1 + 2 files changed, 2 insertions(+) create mode 100644 resources/tests/hello.bin create mode 100644 resources/tests/hex-embed-01.hex diff --git a/resources/tests/hello.bin b/resources/tests/hello.bin new file mode 100644 index 000000000..b6fc4c620 --- /dev/null +++ b/resources/tests/hello.bin @@ -0,0 +1 @@ +hello \ No newline at end of file diff --git a/resources/tests/hex-embed-01.hex b/resources/tests/hex-embed-01.hex new file mode 100644 index 000000000..058e339eb --- /dev/null +++ b/resources/tests/hex-embed-01.hex @@ -0,0 +1 @@ +ff41ff42ff4380 \ No newline at end of file From 7678fa6388716d5250e9667ba9c101c6e06b21d2 Mon Sep 17 00:00:00 2001 From: Chris Marslender Date: Fri, 28 Apr 2023 13:51:01 -0500 Subject: [PATCH 03/75] Add nightly upload step --- .github/workflows/build-arm64-wheels.yml | 19 +++++++++++++++++++ .github/workflows/build-m1-wheel.yml | 19 +++++++++++++++++++ .github/workflows/build-test.yml | 20 ++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/.github/workflows/build-arm64-wheels.yml b/.github/workflows/build-arm64-wheels.yml index 60c9d5b1d..10276efbb 100644 --- a/.github/workflows/build-arm64-wheels.yml +++ b/.github/workflows/build-arm64-wheels.yml @@ -75,10 +75,16 @@ jobs: shell: bash run: | unset HAS_SECRET + unset HAS_AWS_SECRET + if [ -n "$SECRET" ]; then HAS_SECRET='true' ; fi echo "HAS_SECRET=${HAS_SECRET}" >>$GITHUB_OUTPUT + + if [ -n "$AWS_SECRET" ]; then HAS_AWS_SECRET='true' ; fi + echo HAS_AWS_SECRET=${HAS_AWS_SECRET} >>$GITHUB_OUTPUT env: SECRET: "${{ secrets.test_pypi_password }}" + AWS_SECRET: "${{ secrets.INSTALLER_UPLOAD_KEY }}" - name: publish (PyPi) if: startsWith(github.event.ref, 'refs/tags') && steps.check_secrets.outputs.HAS_SECRET @@ -99,3 +105,16 @@ jobs: run: | . ./activate twine upload --non-interactive --skip-existing --verbose 'target/wheels/*' + + - name: Publish Nightlies + if: steps.check_secrets.outputs.HAS_AWS_SECRET + env: + AWS_ACCESS_KEY_ID: "${{ secrets.INSTALLER_UPLOAD_KEY }}" + AWS_SECRET_ACCESS_KEY: "${{ secrets.INSTALLER_UPLOAD_SECRET }}" + AWS_REGION: us-west-2 + run: | + FILES=$(find ${{ github.workspace }}/target/wheels -type f -name '*.whl') + while IFS= read -r file; do + filename=$(basename $file) + aws --no-progress s3 cp "$file" "s3://download.chia.net/nightlies/clvm_tools_rs/$filename" + done <<< "$FILES" diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index 87abadb73..23854d9f9 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -100,10 +100,16 @@ jobs: shell: bash run: | unset HAS_SECRET + unset HAS_AWS_SECRET + if [ -n "$SECRET" ]; then HAS_SECRET='true' ; fi echo "HAS_SECRET=${HAS_SECRET}" >>$GITHUB_OUTPUT + + if [ -n "$AWS_SECRET" ]; then HAS_AWS_SECRET='true' ; fi + echo HAS_AWS_SECRET=${HAS_AWS_SECRET} >>$GITHUB_OUTPUT env: SECRET: "${{ secrets.test_pypi_password }}" + AWS_SECRET: "${{ secrets.INSTALLER_UPLOAD_KEY }}" - name: Install twine run: arch -arm64 pip install twine @@ -124,3 +130,16 @@ jobs: TWINE_NON_INTERACTIVE: 1 TWINE_PASSWORD: ${{ secrets.test_pypi_password }} run: arch -arm64 twine upload --non-interactive --skip-existing --verbose 'target/wheels/*' + + - name: Publish Nightlies + if: steps.check_secrets.outputs.HAS_AWS_SECRET + env: + AWS_ACCESS_KEY_ID: "${{ secrets.INSTALLER_UPLOAD_KEY }}" + AWS_SECRET_ACCESS_KEY: "${{ secrets.INSTALLER_UPLOAD_SECRET }}" + AWS_REGION: us-west-2 + run: | + FILES=$(find ${{ github.workspace }}/target/wheels -type f -name '*.whl') + while IFS= read -r file; do + filename=$(basename $file) + aws --no-progress s3 cp "$file" "s3://download.chia.net/nightlies/clvm_tools_rs/$filename" + done <<< "$FILES" diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 08d7f1a70..d6697bca5 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -205,10 +205,17 @@ jobs: shell: bash run: | unset HAS_SECRET + unset HAS_AWS_SECRET + if [ -n "$SECRET" ]; then HAS_SECRET='true' ; fi echo "HAS_SECRET=${HAS_SECRET}" >>$GITHUB_OUTPUT + + if [ -n "$AWS_SECRET" ]; then HAS_AWS_SECRET='true' ; fi + echo HAS_AWS_SECRET=${HAS_AWS_SECRET} >>$GITHUB_OUTPUT + env: SECRET: "${{ secrets.test_pypi_password }}" + AWS_SECRET: "${{ secrets.INSTALLER_UPLOAD_KEY }}" - name: publish (PyPi) if: startsWith(github.event.ref, 'refs/tags') && steps.check_secrets.outputs.HAS_SECRET @@ -227,6 +234,19 @@ jobs: TWINE_PASSWORD: ${{ secrets.test_pypi_password }} run: twine upload --non-interactive --skip-existing --verbose 'target/wheels/*' + - name: Publish Nightlies + if: steps.check_secrets.outputs.HAS_AWS_SECRET + env: + AWS_ACCESS_KEY_ID: "${{ secrets.INSTALLER_UPLOAD_KEY }}" + AWS_SECRET_ACCESS_KEY: "${{ secrets.INSTALLER_UPLOAD_SECRET }}" + AWS_REGION: us-west-2 + run: | + FILES=$(find ${{ github.workspace }}/target/wheels -type f -name '*.whl') + while IFS= read -r file; do + filename=$(basename $file) + aws --no-progress s3 cp "$file" "s3://download.chia.net/nightlies/clvm_tools_rs/$filename" + done <<< "$FILES" + fmt: runs-on: ubuntu-20.04 name: cargo fmt From 5a713d3f3fd8bc8dde5b0bc7004f43d6c0d2b83c Mon Sep 17 00:00:00 2001 From: Chris Marslender Date: Fri, 28 Apr 2023 14:37:59 -0500 Subject: [PATCH 04/75] Fix shell for windows compat and directory needs hyphens for pip normalization --- .github/workflows/build-arm64-wheels.yml | 2 +- .github/workflows/build-m1-wheel.yml | 2 +- .github/workflows/build-test.yml | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-arm64-wheels.yml b/.github/workflows/build-arm64-wheels.yml index 10276efbb..8acb32d32 100644 --- a/.github/workflows/build-arm64-wheels.yml +++ b/.github/workflows/build-arm64-wheels.yml @@ -116,5 +116,5 @@ jobs: FILES=$(find ${{ github.workspace }}/target/wheels -type f -name '*.whl') while IFS= read -r file; do filename=$(basename $file) - aws --no-progress s3 cp "$file" "s3://download.chia.net/nightlies/clvm_tools_rs/$filename" + aws --no-progress s3 cp "$file" "s3://download.chia.net/nightlies/clvm-tools-rs/$filename" done <<< "$FILES" diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index 23854d9f9..aa24504b0 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -141,5 +141,5 @@ jobs: FILES=$(find ${{ github.workspace }}/target/wheels -type f -name '*.whl') while IFS= read -r file; do filename=$(basename $file) - aws --no-progress s3 cp "$file" "s3://download.chia.net/nightlies/clvm_tools_rs/$filename" + aws --no-progress s3 cp "$file" "s3://download.chia.net/nightlies/clvm-tools-rs/$filename" done <<< "$FILES" diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index d6697bca5..61605e85a 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -236,6 +236,7 @@ jobs: - name: Publish Nightlies if: steps.check_secrets.outputs.HAS_AWS_SECRET + shell: bash env: AWS_ACCESS_KEY_ID: "${{ secrets.INSTALLER_UPLOAD_KEY }}" AWS_SECRET_ACCESS_KEY: "${{ secrets.INSTALLER_UPLOAD_SECRET }}" @@ -244,7 +245,7 @@ jobs: FILES=$(find ${{ github.workspace }}/target/wheels -type f -name '*.whl') while IFS= read -r file; do filename=$(basename $file) - aws --no-progress s3 cp "$file" "s3://download.chia.net/nightlies/clvm_tools_rs/$filename" + aws --no-progress s3 cp "$file" "s3://download.chia.net/nightlies/clvm-tools-rs/$filename" done <<< "$FILES" fmt: From b2fe8d4f5316ad5aa2cda018abcf6c2be49bbed4 Mon Sep 17 00:00:00 2001 From: Chris Marslender Date: Fri, 28 Apr 2023 16:42:57 -0500 Subject: [PATCH 05/75] Try working dir for windows find issues --- .github/workflows/build-test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 61605e85a..aeaf9c4e2 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -237,12 +237,13 @@ jobs: - name: Publish Nightlies if: steps.check_secrets.outputs.HAS_AWS_SECRET shell: bash + working-directory: ./target/wheels env: AWS_ACCESS_KEY_ID: "${{ secrets.INSTALLER_UPLOAD_KEY }}" AWS_SECRET_ACCESS_KEY: "${{ secrets.INSTALLER_UPLOAD_SECRET }}" AWS_REGION: us-west-2 run: | - FILES=$(find ${{ github.workspace }}/target/wheels -type f -name '*.whl') + FILES=$(find . -type f -name '*.whl') while IFS= read -r file; do filename=$(basename $file) aws --no-progress s3 cp "$file" "s3://download.chia.net/nightlies/clvm-tools-rs/$filename" From fb84709de435daec493133f73a200552c20c8de5 Mon Sep 17 00:00:00 2001 From: Chris Marslender Date: Mon, 1 May 2023 10:25:44 -0500 Subject: [PATCH 06/75] Only publish nightly artifacts on the `nightly` branch --- .github/workflows/build-arm64-wheels.yml | 3 ++- .github/workflows/build-m1-wheel.yml | 3 ++- .github/workflows/build-test.yml | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-arm64-wheels.yml b/.github/workflows/build-arm64-wheels.yml index 8acb32d32..0da03a96b 100644 --- a/.github/workflows/build-arm64-wheels.yml +++ b/.github/workflows/build-arm64-wheels.yml @@ -5,6 +5,7 @@ on: branches: - main - dev + - nightly tags: - '**' pull_request: @@ -107,7 +108,7 @@ jobs: twine upload --non-interactive --skip-existing --verbose 'target/wheels/*' - name: Publish Nightlies - if: steps.check_secrets.outputs.HAS_AWS_SECRET + if: steps.check_secrets.outputs.HAS_AWS_SECRET && github.ref == 'refs/heads/nightly' env: AWS_ACCESS_KEY_ID: "${{ secrets.INSTALLER_UPLOAD_KEY }}" AWS_SECRET_ACCESS_KEY: "${{ secrets.INSTALLER_UPLOAD_SECRET }}" diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index aa24504b0..957b62e0d 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -5,6 +5,7 @@ on: branches: - main - dev + - nightly tags: - '**' pull_request: @@ -132,7 +133,7 @@ jobs: run: arch -arm64 twine upload --non-interactive --skip-existing --verbose 'target/wheels/*' - name: Publish Nightlies - if: steps.check_secrets.outputs.HAS_AWS_SECRET + if: steps.check_secrets.outputs.HAS_AWS_SECRET && github.ref == 'refs/heads/nightly' env: AWS_ACCESS_KEY_ID: "${{ secrets.INSTALLER_UPLOAD_KEY }}" AWS_SECRET_ACCESS_KEY: "${{ secrets.INSTALLER_UPLOAD_SECRET }}" diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index aeaf9c4e2..826796b17 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -6,6 +6,7 @@ on: branches: - base - dev + - nightly tags: - '**' pull_request: @@ -235,7 +236,7 @@ jobs: run: twine upload --non-interactive --skip-existing --verbose 'target/wheels/*' - name: Publish Nightlies - if: steps.check_secrets.outputs.HAS_AWS_SECRET + if: steps.check_secrets.outputs.HAS_AWS_SECRET && github.ref == 'refs/heads/nightly' shell: bash working-directory: ./target/wheels env: From 5f045de39be493d08147378ec4893244bd88ab84 Mon Sep 17 00:00:00 2001 From: Earle Lowe <30607889+emlowe@users.noreply.github.com> Date: Thu, 11 May 2023 16:06:59 -0700 Subject: [PATCH 07/75] Set macOS deployment target Make sure to set mac deployment target --- .github/workflows/build-test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 945f45b65..e5ced178b 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -47,6 +47,8 @@ jobs: - name: Build MacOs with maturin on Python ${{ matrix.python }} if: startsWith(matrix.os, 'macos') + env: + MACOSX_DEPLOYMENT_TARGET: '10.15' run: | python -m venv venv ln -s venv/bin/activate From 8e6b638c9d1f2c90b63ddb5d08140c47fee31cd9 Mon Sep 17 00:00:00 2001 From: Earle Lowe <30607889+emlowe@users.noreply.github.com> Date: Thu, 11 May 2023 16:25:06 -0700 Subject: [PATCH 08/75] Update build-test.yml --- .github/workflows/build-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index e5ced178b..570aec25f 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -48,7 +48,7 @@ jobs: - name: Build MacOs with maturin on Python ${{ matrix.python }} if: startsWith(matrix.os, 'macos') env: - MACOSX_DEPLOYMENT_TARGET: '10.15' + MACOSX_DEPLOYMENT_TARGET: '10.14' run: | python -m venv venv ln -s venv/bin/activate From 7e62cda1841db2a0ce23eeac48750f4774562a8f Mon Sep 17 00:00:00 2001 From: Adam Kelly <338792+aqk@users.noreply.github.com> Date: Mon, 22 May 2023 16:13:44 -0700 Subject: [PATCH 09/75] Change README to refer to nightly branch. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f6bd23e86..61862a6d4 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,13 @@ or via pip Note: `pip` installs a subset of the tools installed by `cargo`, including `brun`, `run`, `opc` and `opd`. -The most current version of the language is in the rollup branch: +The most current version of the language is in the nightly branch: - 20221005-rollup + [nightly](https://github.com/Chia-Network/clvm_tools_rs/tree/nightly) To install from a specific branch: - cargo install --no-default-features --git 'https://github.com/Chia-Network/clvm_tools_rs' --branch 20221005-rollup + cargo install --no-default-features --git 'https://github.com/Chia-Network/clvm_tools_rs' --branch nightly To install a git checkout into your current python environment (must be in some kind of venv or conda environment): From 76e01b62e51432f2f3f9bd92624ce285795c219a Mon Sep 17 00:00:00 2001 From: Adam Kelly <338792+aqk@users.noreply.github.com> Date: Tue, 23 May 2023 09:30:59 -0700 Subject: [PATCH 10/75] Add pip / PYPI install --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 61862a6d4..6a402d8aa 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,10 @@ To install a git checkout into your current python environment (must be in some git clone https://github.com/Chia-Network/clvm_tools_rs cd clvm_tools_rs maturin develop + +Install from PYPI: + + pip install -i https://pypi.chia.net/nightlies/ clvm_tools_rs Most people still compile chialisp via python. One way to set up compilation in that way is like this: From 37fde915d922423890d8e959b0810ccfbcd12983 Mon Sep 17 00:00:00 2001 From: Earle Lowe <30607889+emlowe@users.noreply.github.com> Date: Thu, 25 May 2023 15:44:30 -0700 Subject: [PATCH 11/75] Update version to 0.1.33 (#174) * Update version to 0.1.32 * 33 --------- Co-authored-by: William Blanke --- Cargo.lock | 2 +- Cargo.toml | 2 +- wasm/Cargo.lock | 4 ++-- wasm/Cargo.toml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e5b6585a..85970c9d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,7 +92,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clvm_tools_rs" -version = "0.1.31" +version = "0.1.33" dependencies = [ "binascii", "bls12_381", diff --git a/Cargo.toml b/Cargo.toml index 4619abb5e..aeee00ba4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clvm_tools_rs" -version = "0.1.31" +version = "0.1.33" edition = "2018" authors = ["Art Yerkes "] description = "tools for working with chialisp language; compiler, repl, python and wasm bindings" diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 9b479e1c1..93c408292 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -92,7 +92,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clvm_tools_rs" -version = "0.1.31" +version = "0.1.33" dependencies = [ "binascii", "bls12_381", @@ -124,7 +124,7 @@ dependencies = [ [[package]] name = "clvm_tools_wasm" -version = "0.1.31" +version = "0.1.33" dependencies = [ "clvm_tools_rs", "clvmr", diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index 4cf269c34..73c51f1ac 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clvm_tools_wasm" -version = "0.1.31" +version = "0.1.33" edition = "2018" authors = ["Art Yerkes "] description = "tools for working with chialisp language; compiler, repl, python and wasm bindings" From 3ad269adef5f38dfb41b2dc07fff19bdadd8548b Mon Sep 17 00:00:00 2001 From: Earle Lowe <30607889+emlowe@users.noreply.github.com> Date: Thu, 25 May 2023 16:28:36 -0700 Subject: [PATCH 12/75] Update CHANGELOG.md --- CHANGELOG.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 642f91426..f8518b8dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,17 @@ # clvm_tools_rs Changelog -## 0.0.31 Chia CLVM Tools Rust 2023-04-17 +## 0.1.33 +### Changed +- Set macOS deployment target to 10.14 +- Ensure we flush streams in case the runtime system doesn't get a chance +### Fixed +- Fix erroneous detection of recursion when two similar inline siblings + + +## 0.1.32 +Skipped + +## 0.1.31 Chia CLVM Tools Rust 2023-04-17 ### Added From b49d0a41d42026ddf2fa58b1f6420ad84a2532b6 Mon Sep 17 00:00:00 2001 From: arty Date: Fri, 2 Jun 2023 12:28:41 -0700 Subject: [PATCH 13/75] Modify our code so we try to overwrite the target file if the dates imply that compilation should take place but don't error if we couldn't overwrite when the target file already had the right date. Always overwrite (or error) otherwise. --- .github/workflows/build-test.yml | 6 + .../tests/test-clvm-recompile-behavior.py | 120 ++++++++++++++++++ src/classic/clvm_tools/clvmc.rs | 57 ++++++--- 3 files changed, 164 insertions(+), 19 deletions(-) create mode 100644 resources/tests/test-clvm-recompile-behavior.py diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 18c817645..07c50967f 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -176,6 +176,12 @@ jobs: python support/wheelname.py (cd resources/tests && python check-recompiles.py) + - name: Verify recompilation follows date and modification rules + if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.7') + run: | + python support/wheelname.py + python resources/tests/test-clvm-recompile-behavior.py + - name: Run tests from clvm run: | . ./activate diff --git a/resources/tests/test-clvm-recompile-behavior.py b/resources/tests/test-clvm-recompile-behavior.py new file mode 100644 index 000000000..d8ae516d1 --- /dev/null +++ b/resources/tests/test-clvm-recompile-behavior.py @@ -0,0 +1,120 @@ +import os +import sys +import shutil +import stat +import time +import hashlib +from clvm_tools_rs import compile_clvm + +TESTDIR = 'testdir' +COMPILED_HASH = '6956b7c3af37e220819dc6e4919e7a1058167192db8eec81714218c4c3d8286d' +SOURCE_FILE = './resources/tests/did_innerpuz.clsp' +TARGET_FILE = './testdir/did_innerpuz.clvm.hex' +SEARCH_PATHS = ['./resources/tests'] + +def hash_file(path): + hasher = hashlib.sha256() + hasher.update(open(path).read().encode('utf8')) + return hasher.hexdigest() + +def test_compile_clvm(source, output, paths, want_sha256): + compile_clvm(source, output, paths) + if want_sha256 is not None: + have_digest = hash_file(output) + assert want_sha256 == have_digest + +def update_file(fname): + source_content = open(fname).read() + time.sleep(5.0) + # Rewrite file. + with open(fname,'w') as f: + f.write(source_content) + +def try_delete_dir(path): + try: + os.chmod(path, stat.S_IREAD | stat.S_IWRITE | stat.S_IXUSR) + shutil.rmtree(path) + except: + pass + +def lock_file(testdir, path): + os.chmod(path, stat.S_IREAD) + os.chmod(testdir, stat.S_IREAD | stat.S_IXUSR) + +def unlock_file(testdir, path): + os.chmod(testdir, stat.S_IREAD | stat.S_IWRITE | stat.S_IXUSR) + os.chmod(path, stat.S_IREAD | stat.S_IWRITE) + +try_delete_dir(TESTDIR) +os.mkdir(TESTDIR) + +# Get baseline date +source_file_date = os.stat(SOURCE_FILE).st_mtime + +# Verify that we recompile when the target file isn't present. +test_compile_clvm(SOURCE_FILE, TARGET_FILE, SEARCH_PATHS, COMPILED_HASH) + +hex_mod_date = os.stat(TARGET_FILE).st_mtime +assert hex_mod_date > source_file_date + +# Update the source file. +update_file(SOURCE_FILE) +source_file_updated_date = os.stat(SOURCE_FILE).st_mtime +assert source_file_updated_date > hex_mod_date +assert source_file_updated_date > source_file_date + +# Ensure that we updated the date. +test_compile_clvm(SOURCE_FILE, TARGET_FILE, SEARCH_PATHS, COMPILED_HASH) + +updated_hex_mod_date = os.stat(TARGET_FILE).st_mtime +assert updated_hex_mod_date > hex_mod_date +assert updated_hex_mod_date > source_file_updated_date + +time.sleep(5.0) +# Mess with the target file, ensure it gets recompiled. +with open(TARGET_FILE,'a') as f: + f.write('0a0a0a0a0a') + +update_file(SOURCE_FILE) +test_compile_clvm(SOURCE_FILE, TARGET_FILE, SEARCH_PATHS, COMPILED_HASH) +# Coming out of here means the new hash matched. +second_updated_hex_mod_date = os.stat(TARGET_FILE).st_mtime + +# Update the hex file again and protect it. +update_file(TARGET_FILE) +lock_file(TESTDIR, TARGET_FILE) +hex_date_when_protected = os.stat(TARGET_FILE).st_mtime + +update_file(SOURCE_FILE) +test_compile_clvm(SOURCE_FILE, TARGET_FILE, SEARCH_PATHS, COMPILED_HASH) +third_updated_hex_mod_date = os.stat(TARGET_FILE).st_mtime +assert third_updated_hex_mod_date == hex_date_when_protected + +# Unprotect and modify. Compilation should throw because the content won't be +# what's expected. +unlock_file(TESTDIR, TARGET_FILE) +time.sleep(5.0) +# Mess with the target file, ensure it gets recompiled. +with open(TARGET_FILE,'a') as f: + f.write('0a0a0a0a0a') +lock_file(TESTDIR, TARGET_FILE) + +# Update the time on the source file so we'll try to recompile +update_file(SOURCE_FILE) + +# Check that we got the wrong hash because the file was modified. +try: + test_compile_clvm(SOURCE_FILE, TARGET_FILE, SEARCH_PATHS, None) + have_digest = hash_file(TARGET_FILE) + assert False +except: + # We threw because the file wasn't right but we couldn't overwrite it. + assert COMPILED_HASH != hash_file(TARGET_FILE) + +# Set it writable and recompile. +unlock_file(TESTDIR, TARGET_FILE) +test_compile_clvm(SOURCE_FILE, TARGET_FILE, SEARCH_PATHS, COMPILED_HASH) + +last_source_mtime = os.stat(SOURCE_FILE).st_mtime +last_hex_mtime = os.stat(TARGET_FILE).st_mtime +assert last_hex_mtime > last_source_mtime diff --git a/src/classic/clvm_tools/clvmc.rs b/src/classic/clvm_tools/clvmc.rs index b2ac08bab..448c8dacf 100644 --- a/src/classic/clvm_tools/clvmc.rs +++ b/src/classic/clvm_tools/clvmc.rs @@ -174,38 +174,57 @@ pub fn compile_clvm( false, )?; - let output_path_obj = Path::new(output_path); - let output_dir = output_path_obj - .parent() - .map(Ok) - .unwrap_or_else(|| Err("could not get parent of output path"))?; - let target_data = result_stream.get_value().hex(); + let write_file = |output_path: &str, target_data: &str| -> Result<(), String> { + let output_path_obj = Path::new(output_path); + let output_dir = output_path_obj + .parent() + .map(Ok) + .unwrap_or_else(|| Err("could not get parent of output path"))?; + + // Make the contents appear atomically so that other test processes + // won't mistake an empty file for intended output. + let mut temp_output_file = NamedTempFile::new_in(output_dir).map_err(|e| { + format!("error creating temporary compiler output for {input_path}: {e:?}") + })?; + + let err_text = format!("failed to write to {:?}", temp_output_file.path()); + let translate_err = |_| err_text.clone(); + + temp_output_file + .write_all(target_data.as_bytes()) + .map_err(translate_err)?; + + temp_output_file + .write_all(b"\n") + .map_err(translate_err)?; + + temp_output_file.persist(output_path).map_err(|e| { + format!("error persisting temporary compiler output {output_path}: {e:?}") + })?; + + Ok(()) + }; + // Try to detect whether we'd put the same output in the output file. // Don't proceed if true. if let Ok(prev_content) = fs::read_to_string(output_path) { let prev_trimmed = prev_content.trim(); let trimmed = target_data.trim(); if prev_trimmed == trimmed { + // We should try to overwrite here, but not fail if it doesn't + // work. This will accomodate both the read only scenario and + // the scenario where a target file is newer and people want the + // date to be updated. + write_file(output_path, &target_data).ok(); + // It's the same program, bail regardless. return Ok(output_path.to_string()); } } - // Make the contents appear atomically so that other test processes - // won't mistake an empty file for intended output. - let mut temp_output_file = NamedTempFile::new_in(output_dir).map_err(|e| { - format!("error creating temporary compiler output for {input_path}: {e:?}") - })?; - - temp_output_file - .write_all(target_data.as_bytes()) - .map_err(|_| format!("failed to write to {:?}", temp_output_file.path()))?; - - temp_output_file.persist(output_path).map_err(|e| { - format!("error persisting temporary compiler output {output_path}: {e:?}") - })?; + write_file(output_path, &target_data)?; } Ok(output_path.to_string()) From 63d432b4e5216cfc06b93f73672048ad191498be Mon Sep 17 00:00:00 2001 From: arty Date: Fri, 2 Jun 2023 12:30:13 -0700 Subject: [PATCH 14/75] fmt + clippy --- src/classic/clvm_tools/clvmc.rs | 4 +--- src/compiler/clvm.rs | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/classic/clvm_tools/clvmc.rs b/src/classic/clvm_tools/clvmc.rs index 448c8dacf..3e91ae099 100644 --- a/src/classic/clvm_tools/clvmc.rs +++ b/src/classic/clvm_tools/clvmc.rs @@ -196,9 +196,7 @@ pub fn compile_clvm( .write_all(target_data.as_bytes()) .map_err(translate_err)?; - temp_output_file - .write_all(b"\n") - .map_err(translate_err)?; + temp_output_file.write_all(b"\n").map_err(translate_err)?; temp_output_file.persist(output_path).map_err(|e| { format!("error persisting temporary compiler output {output_path}: {e:?}") diff --git a/src/compiler/clvm.rs b/src/compiler/clvm.rs index 5c2656c80..593cfddb6 100644 --- a/src/compiler/clvm.rs +++ b/src/compiler/clvm.rs @@ -188,7 +188,7 @@ fn eval_args( return Ok(RunStep::Op( head, context_, - sexp.clone(), + sexp, Some(eval_list), parent, )); From 022edeb84b75a4cf578d60a1a7370a0a748456fb Mon Sep 17 00:00:00 2001 From: arty Date: Fri, 2 Jun 2023 12:34:55 -0700 Subject: [PATCH 15/75] fmt --- src/compiler/clvm.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/compiler/clvm.rs b/src/compiler/clvm.rs index 593cfddb6..eaa6e9a4e 100644 --- a/src/compiler/clvm.rs +++ b/src/compiler/clvm.rs @@ -185,13 +185,7 @@ fn eval_args( loop { match sexp.borrow() { SExp::Nil(_l) => { - return Ok(RunStep::Op( - head, - context_, - sexp, - Some(eval_list), - parent, - )); + return Ok(RunStep::Op(head, context_, sexp, Some(eval_list), parent)); } SExp::Cons(_l, a, b) => { eval_list.push(a.clone()); From 5bd6ec029a28c53d633e3fdaff0728cfa9e4f97d Mon Sep 17 00:00:00 2001 From: arty Date: Fri, 2 Jun 2023 12:38:51 -0700 Subject: [PATCH 16/75] Add newline --- resources/tests/bridgeref/validation_taproot.clvm.hex.reference | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/tests/bridgeref/validation_taproot.clvm.hex.reference b/resources/tests/bridgeref/validation_taproot.clvm.hex.reference index 8bd449427..1335b0600 100644 --- a/resources/tests/bridgeref/validation_taproot.clvm.hex.reference +++ b/resources/tests/bridgeref/validation_taproot.clvm.hex.reference @@ -1 +1 @@ -ff02ffff01ff04ffff04ffff013effff04ffff0bffff05ffff06ff058080ffff02ffff03ffff09ff17ffff05ffff02ffff03ffff07ff8202ff80ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ffff04ffff01ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ff018080ff0180ffff04ffff0bffff0102ff09ff1380ffff04ffff02ff0effff04ff02ffff04ff15ffff04ff2bff8080808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff0effff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ffff04ffff0180ff01808080ffff04ff8202ffffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff2fffff01808080808080808080ffff01ff02ffff01ff02ffff03ffff09ff8205bfffff11ff8217bfff820bbf8080ffff01ff02ffff01ff02ffff03ffff09ff0bff820bbf80ffff01ff02ffff01ff02ffff03ffff20ffff15ff0bff8217bf8080ffff01ff02ffff01ff0bffff0102ffff05ffff06ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff0181e880ffff0bffff0102ff17ffff0bffff0102ffff0bffff0102ffff0bffff0102ffff0bffff0101ff8217bf80ffff0bffff0102ffff0bffff0101ff1780ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff02ff02ffff04ff02ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff04ff8202bfff80808080808080808080ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ffff04ffff01ff02ffff03ff5fffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ffff05ff5f8080ffff0bffff0102ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff02ff02ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ffff06ff5f80ff808080808080808080ff0180ffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013e80ffff0bffff0102ffff0bffff0101ff0580ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff014980ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ff1780ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ff018080ff0180ff018080ffff01ff02ffff01ff0880ffff04ffff0180ff01808080ffff04ff17ffff04ff2fffff04ff5fffff04ff8200bfffff04ff82017fffff04ffff04ffff05ffff02ffff03ffff07ff8202ff80ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ffff04ffff01ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ff018080ff0180ffff04ffff0bffff0102ff09ff1380ffff04ffff02ff0effff04ff02ffff04ff15ffff04ff2bff8080808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff0effff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ffff04ffff0180ff01808080ffff04ff8202ffffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff2fffff018080808080808080ffff04ffff05ffff06ffff02ffff03ffff07ff8202ff80ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ffff04ffff01ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ff018080ff0180ffff04ffff0bffff0102ff09ff1380ffff04ffff02ff0effff04ff02ffff04ff15ffff04ff2bff8080808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff0effff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ffff04ffff0180ff01808080ffff04ff8202ffffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff2fffff01808080808080808080ffff04ffff05ffff06ffff06ffff02ffff03ffff07ff8202ff80ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ffff04ffff01ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ff018080ff0180ffff04ffff0bffff0102ff09ff1380ffff04ffff02ff0effff04ff02ffff04ff15ffff04ff2bff8080808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff0effff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ffff04ffff0180ff01808080ffff04ff8202ffffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff2fffff0180808080808080808080ffff04ffff05ffff06ffff06ffff06ffff02ffff03ffff07ff8202ff80ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ffff04ffff01ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ff018080ff0180ffff04ffff0bffff0102ff09ff1380ffff04ffff02ff0effff04ff02ffff04ff15ffff04ff2bff8080808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff0effff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ffff04ffff0180ff01808080ffff04ff8202ffffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff2fffff018080808080808080808080ffff04ffff05ffff06ffff06ffff06ffff06ffff02ffff03ffff07ff8202ff80ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ffff04ffff01ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ff018080ff0180ffff04ffff0bffff0102ff09ff1380ffff04ffff02ff0effff04ff02ffff04ff15ffff04ff2bff8080808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff0effff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ffff04ffff0180ff01808080ffff04ff8202ffffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff2fffff01808080808080808080808080ffff01808080808080ffff01808080808080808080ffff01808080ffff04ffff04ffff013fffff04ffff0bffff0bffff01a102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffff05ff058080ffff0bffff0102ffff0bffff01a102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffff02ffff03ffff07ff0580ffff01ff02ffff01ff0bffff0102ffff02ff02ffff04ff02ffff04ffff05ff0580ff80808080ffff02ff02ffff04ff02ffff04ffff06ff0580ff8080808080ffff04ffff01ff02ffff03ffff07ff0580ffff01ff02ffff01ff0bffff0102ffff02ff02ffff04ff02ffff04ffff05ff0580ff80808080ffff02ff02ffff04ff02ffff04ffff06ff0580ff8080808080ff0180ffff01ff02ffff01ff0bffff0101ff0580ff018080ff0180ff018080ffff01ff02ffff01ff0bffff0101ff0580ffff04ffff0180ff01808080ffff04ff05ffff0180808080ffff0bffff0102ffff0bffff01a102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffff0bffff01a102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ff0b80ffff0bffff0102ffff0bffff01a102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffff0bffff0101ff0b8080ffff0bffff0102ffff0bffff01a102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffff0bffff0101ff2f8080ffff0bffff0102ffff0bffff01a102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffff0bffff0101ff5f8080ffff0bffff0102ffff0bffff01a102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ff8200bf80ffff01a0ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d468080ffff01a04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a808080ffff01a04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a808080ffff01a04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a808080ffff01a04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a80808080ffff01a0ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d468080ffff01a04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a808080ffff01a04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a808080ff2f80ffff01808080ffff01808080ffff04ffff01ffffff02ffff03ffff07ff0580ffff01ff02ffff01ff0bffff0102ffff02ff02ffff04ff02ffff04ffff05ff0580ff80808080ffff02ff02ffff04ff02ffff04ffff06ff0580ff8080808080ffff04ffff01ff02ffff03ffff07ff0580ffff01ff02ffff01ff0bffff0102ffff02ff02ffff04ff02ffff04ffff05ff0580ff80808080ffff02ff02ffff04ff02ffff04ffff06ff0580ff8080808080ff0180ffff01ff02ffff01ff0bffff0101ff0580ff018080ff0180ff018080ffff01ff02ffff01ff0bffff0101ff0580ffff04ffff0180ff01808080ffff04ff05ff808080ffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff02ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff02ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff010bffff04ffff0180ff01808080ffff04ff05ffff04ff0bff80808080ff04ffff0bffff0102ff09ff1380ffff04ffff02ffff03ff15ffff01ff02ffff01ff04ffff05ff0580ffff02ff02ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff02ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff010bffff04ffff0180ff01808080ffff04ff15ffff04ff2bff80808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ffff04ffff01ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ff018080ff0180ffff04ffff0bffff0102ff09ff1380ffff04ffff02ff0effff04ff02ffff04ff15ffff04ff2bff8080808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff0effff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ffff04ffff0180ff01808080ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff80808080808080ffff02ffff03ffff09ff05ff82013f80ffff01ff02ffff01ff02ffff03ffff09ff8205bfffff11ff8217bfff820bbf8080ffff01ff02ffff01ff02ffff03ffff09ff0bff820bbf80ffff01ff02ffff01ff02ffff03ffff20ffff15ff0bff8217bf8080ffff01ff02ffff01ff0bffff0102ffff05ffff06ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff0181e880ffff0bffff0102ff17ffff0bffff0102ffff0bffff0102ffff0bffff0102ffff0bffff0101ff8217bf80ffff0bffff0102ffff0bffff0101ff1780ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff02ff02ffff04ff02ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff04ff8202bfff80808080808080808080ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ffff04ffff01ff02ffff03ff5fffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ffff05ff5f8080ffff0bffff0102ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff02ff02ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ffff06ff5f80ff808080808080808080ff0180ffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013e80ffff0bffff0102ffff0bffff0101ff0580ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff014980ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ff1780ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ff018080ff0180ff018080ffff01ff02ffff01ff0880ffff04ffff0180ff01808080ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff04ffff04ff82013fffff04ff8202bfffff04ff8205bfffff04ff820bbfffff04ff8217bfff808080808080ff8080808080808080ff02ffff03ff5fffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ffff05ff5f8080ffff0bffff0102ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff02ff02ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ffff06ff5f80ff808080808080808080ffff04ffff01ff02ffff03ff5fffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ffff05ff5f8080ffff0bffff0102ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff02ff02ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ffff06ff5f80ff808080808080808080ff0180ffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013e80ffff0bffff0102ffff0bffff0101ff0580ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff014980ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ff1780ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ff018080ff0180ff018080ffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013e80ffff0bffff0102ffff0bffff0101ff0580ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff014980ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ff1780ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff04ffff0180ff01808080ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff80808080808080ff018080 \ No newline at end of file +ff02ffff01ff04ffff04ffff013effff04ffff0bffff05ffff06ff058080ffff02ffff03ffff09ff17ffff05ffff02ffff03ffff07ff8202ff80ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ffff04ffff01ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ff018080ff0180ffff04ffff0bffff0102ff09ff1380ffff04ffff02ff0effff04ff02ffff04ff15ffff04ff2bff8080808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff0effff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ffff04ffff0180ff01808080ffff04ff8202ffffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff2fffff01808080808080808080ffff01ff02ffff01ff02ffff03ffff09ff8205bfffff11ff8217bfff820bbf8080ffff01ff02ffff01ff02ffff03ffff09ff0bff820bbf80ffff01ff02ffff01ff02ffff03ffff20ffff15ff0bff8217bf8080ffff01ff02ffff01ff0bffff0102ffff05ffff06ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff0181e880ffff0bffff0102ff17ffff0bffff0102ffff0bffff0102ffff0bffff0102ffff0bffff0101ff8217bf80ffff0bffff0102ffff0bffff0101ff1780ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff02ff02ffff04ff02ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff04ff8202bfff80808080808080808080ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ffff04ffff01ff02ffff03ff5fffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ffff05ff5f8080ffff0bffff0102ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff02ff02ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ffff06ff5f80ff808080808080808080ff0180ffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013e80ffff0bffff0102ffff0bffff0101ff0580ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff014980ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ff1780ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ff018080ff0180ff018080ffff01ff02ffff01ff0880ffff04ffff0180ff01808080ffff04ff17ffff04ff2fffff04ff5fffff04ff8200bfffff04ff82017fffff04ffff04ffff05ffff02ffff03ffff07ff8202ff80ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ffff04ffff01ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ff018080ff0180ffff04ffff0bffff0102ff09ff1380ffff04ffff02ff0effff04ff02ffff04ff15ffff04ff2bff8080808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff0effff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ffff04ffff0180ff01808080ffff04ff8202ffffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff2fffff018080808080808080ffff04ffff05ffff06ffff02ffff03ffff07ff8202ff80ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ffff04ffff01ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ff018080ff0180ffff04ffff0bffff0102ff09ff1380ffff04ffff02ff0effff04ff02ffff04ff15ffff04ff2bff8080808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff0effff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ffff04ffff0180ff01808080ffff04ff8202ffffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff2fffff01808080808080808080ffff04ffff05ffff06ffff06ffff02ffff03ffff07ff8202ff80ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ffff04ffff01ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ff018080ff0180ffff04ffff0bffff0102ff09ff1380ffff04ffff02ff0effff04ff02ffff04ff15ffff04ff2bff8080808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff0effff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ffff04ffff0180ff01808080ffff04ff8202ffffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff2fffff0180808080808080808080ffff04ffff05ffff06ffff06ffff06ffff02ffff03ffff07ff8202ff80ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ffff04ffff01ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ff018080ff0180ffff04ffff0bffff0102ff09ff1380ffff04ffff02ff0effff04ff02ffff04ff15ffff04ff2bff8080808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff0effff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ffff04ffff0180ff01808080ffff04ff8202ffffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff2fffff018080808080808080808080ffff04ffff05ffff06ffff06ffff06ffff06ffff02ffff03ffff07ff8202ff80ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ffff04ffff01ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ff018080ff0180ffff04ffff0bffff0102ff09ff1380ffff04ffff02ff0effff04ff02ffff04ff15ffff04ff2bff8080808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff0effff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ffff04ffff0180ff01808080ffff04ff8202ffffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff2fffff01808080808080808080808080ffff01808080808080ffff01808080808080808080ffff01808080ffff04ffff04ffff013fffff04ffff0bffff0bffff01a102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffff05ff058080ffff0bffff0102ffff0bffff01a102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffff02ffff03ffff07ff0580ffff01ff02ffff01ff0bffff0102ffff02ff02ffff04ff02ffff04ffff05ff0580ff80808080ffff02ff02ffff04ff02ffff04ffff06ff0580ff8080808080ffff04ffff01ff02ffff03ffff07ff0580ffff01ff02ffff01ff0bffff0102ffff02ff02ffff04ff02ffff04ffff05ff0580ff80808080ffff02ff02ffff04ff02ffff04ffff06ff0580ff8080808080ff0180ffff01ff02ffff01ff0bffff0101ff0580ff018080ff0180ff018080ffff01ff02ffff01ff0bffff0101ff0580ffff04ffff0180ff01808080ffff04ff05ffff0180808080ffff0bffff0102ffff0bffff01a102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffff0bffff01a102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ff0b80ffff0bffff0102ffff0bffff01a102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffff0bffff0101ff0b8080ffff0bffff0102ffff0bffff01a102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffff0bffff0101ff2f8080ffff0bffff0102ffff0bffff01a102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffff0bffff0101ff5f8080ffff0bffff0102ffff0bffff01a102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5ffff0bffff0102ffff0bffff0102ffff01a09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ff8200bf80ffff01a0ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d468080ffff01a04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a808080ffff01a04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a808080ffff01a04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a808080ffff01a04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a80808080ffff01a0ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d468080ffff01a04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a808080ffff01a04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a808080ff2f80ffff01808080ffff01808080ffff04ffff01ffffff02ffff03ffff07ff0580ffff01ff02ffff01ff0bffff0102ffff02ff02ffff04ff02ffff04ffff05ff0580ff80808080ffff02ff02ffff04ff02ffff04ffff06ff0580ff8080808080ffff04ffff01ff02ffff03ffff07ff0580ffff01ff02ffff01ff0bffff0102ffff02ff02ffff04ff02ffff04ffff05ff0580ff80808080ffff02ff02ffff04ff02ffff04ffff06ff0580ff8080808080ff0180ffff01ff02ffff01ff0bffff0101ff0580ff018080ff0180ff018080ffff01ff02ffff01ff0bffff0101ff0580ffff04ffff0180ff01808080ffff04ff05ff808080ffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff02ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff02ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff010bffff04ffff0180ff01808080ffff04ff05ffff04ff0bff80808080ff04ffff0bffff0102ff09ff1380ffff04ffff02ffff03ff15ffff01ff02ffff01ff04ffff05ff0580ffff02ff02ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff02ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff010bffff04ffff0180ff01808080ffff04ff15ffff04ff2bff80808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ffff04ffff01ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff02ffff03ffff07ffff05ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff02ffff03ffff07ffff06ff058080ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff02ff04ffff04ff02ffff04ffff05ff0580ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fff8080808080808080ffff04ffff02ff04ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff8080808080ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff04ffff0bffff0101ffff05ff058080ffff04ffff0180ffff04ffff0180ffff04ff2fffff04ff5fffff01808080808080ffff04ffff04ffff0bffff0101ffff06ff058080ffff04ffff04ffff06ff0580ff0b80ffff04ffff10ff17ffff010180ffff04ffff05ff0580ffff04ffff05ff0580ffff01808080808080ff8080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ff018080ff0180ffff04ffff0bffff0102ff09ff1380ffff04ffff02ff0effff04ff02ffff04ff15ffff04ff2bff8080808080ffff04ffff10ff2dff5b80ffff04ffff03ffff15ff5dff8200bb80ff8200bbff5d80ffff04ffff03ffff15ff8200bdff82017b80ff8200bdff82017b80ff808080808080ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff0effff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080ffff01ff02ffff01ff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff01808080808080ffff04ffff0180ff01808080ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff80808080808080ffff02ffff03ffff09ff05ff82013f80ffff01ff02ffff01ff02ffff03ffff09ff8205bfffff11ff8217bfff820bbf8080ffff01ff02ffff01ff02ffff03ffff09ff0bff820bbf80ffff01ff02ffff01ff02ffff03ffff20ffff15ff0bff8217bf8080ffff01ff02ffff01ff0bffff0102ffff05ffff06ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff0181e880ffff0bffff0102ff17ffff0bffff0102ffff0bffff0102ffff0bffff0102ffff0bffff0101ff8217bf80ffff0bffff0102ffff0bffff0101ff1780ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff02ff02ffff04ff02ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff04ff8202bfff80808080808080808080ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ffff04ffff01ff02ffff03ff5fffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ffff05ff5f8080ffff0bffff0102ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff02ff02ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ffff06ff5f80ff808080808080808080ff0180ffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013e80ffff0bffff0102ffff0bffff0101ff0580ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff014980ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ff1780ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ff018080ff0180ff018080ffff01ff02ffff01ff0880ffff04ffff0180ff01808080ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff04ffff04ff82013fffff04ff8202bfffff04ff8205bfffff04ff820bbfffff04ff8217bfff808080808080ff8080808080808080ff02ffff03ff5fffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ffff05ff5f8080ffff0bffff0102ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff02ff02ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ffff06ff5f80ff808080808080808080ffff04ffff01ff02ffff03ff5fffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ffff05ff5f8080ffff0bffff0102ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff02ff02ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ffff06ff5f80ff808080808080808080ff0180ffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013e80ffff0bffff0102ffff0bffff0101ff0580ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff014980ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ff1780ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ff018080ff0180ff018080ffff01ff02ffff01ff0bffff0102ffff0bffff0102ffff0bffff0101ffff013e80ffff0bffff0102ffff0bffff0101ff0580ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff014980ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c580808080ffff0bffff0102ffff0bffff0102ffff0bffff0101ffff013380ffff0bffff0102ffff0bffff0101ff1780ffff0bffff0102ffff0bffff0101ff2f80ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff05ffff01ffa04bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459affa09dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222ffa102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c58080808080ffff04ffff0180ff01808080ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff80808080808080ff018080 From e115d99f68e8380c4687905a20843b75b854c555 Mon Sep 17 00:00:00 2001 From: arty Date: Fri, 2 Jun 2023 13:02:17 -0700 Subject: [PATCH 17/75] Add test file --- resources/tests/did_innerpuz.clsp | 135 ++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 resources/tests/did_innerpuz.clsp diff --git a/resources/tests/did_innerpuz.clsp b/resources/tests/did_innerpuz.clsp new file mode 100644 index 000000000..e65a98648 --- /dev/null +++ b/resources/tests/did_innerpuz.clsp @@ -0,0 +1,135 @@ +; The DID innerpuzzle is designed to sit inside the singleton layer and provide functionality related to being an identity. +; At the moment the two pieces of functionality are recovery and message creation. +; A DID's ID is it's Singleton ID +; Recovery is based around having a list of known other DIDs which can send messages approving you change the innerpuzzle of your DID singleton + +(mod + ( + INNER_PUZZLE ; Standard P2 inner puzzle, used to record the ownership of the DID. + RECOVERY_DID_LIST_HASH ; the list of DIDs that can send messages to you for recovery we store only the hash so that we don't have to reveal every time we make a message spend + NUM_VERIFICATIONS_REQUIRED ; how many of the above list are required for a recovery + SINGLETON_STRUCT ; my singleton_struct, formerly a Truth - ((SINGLETON_MOD_HASH, (LAUNCHER_ID, LAUNCHER_PUZZLE_HASH))) + METADATA ; Customized metadata, e.g KYC info + mode ; this indicates which spend mode we want. 0. Recovery mode 1. Run INNER_PUZZLE with p2_solution + my_amount_or_inner_solution ; In mode 0, we use this to recover our coin and assert it is our actual amount + ; In mode 1 this is the solution of the inner P2 puzzle, only required in the create message mode and transfer mode. + new_inner_puzhash ; In recovery mode, this will be the new wallet DID puzzle hash + parent_innerpuzhash_amounts_for_recovery_ids ; during a recovery we need extra information about our recovery list coins + pubkey ; this is the new pubkey used for a recovery + recovery_list_reveal ; this is the reveal of the stored list of DIDs approved for recovery + my_id ; my coin ID + ) + ;message is the new puzzle in the recovery and standard spend cases + + ;MOD_HASH, MY_PUBKEY, RECOVERY_DID_LIST_HASH are curried into the puzzle + ;EXAMPLE SOLUTION (0xcafef00d 0x12341234 0x923bf9a7856b19d335a65f12d68957d497e1f0c16c0e14baf6d120e60753a1ce 2 1 100 (q "source code") 0xdeadbeef 0xcafef00d ((0xdadadada 0xdad5dad5 200) () (0xfafafafa 0xfaf5faf5 200)) 0xfadeddab (0x22222222 0x33333333 0x44444444)) + + (include condition_codes.clvm) + (include curry-and-treehash.clinc) + + ; takes a lisp tree and returns the hash of it + (defun sha256tree1 (TREE) + (if (l TREE) + (sha256 2 (sha256tree1 (f TREE)) (sha256tree1 (r TREE))) + (sha256 1 TREE) + ) + ) + + ; recovery message module - gets values curried in to make the puzzle + (defun make_message_puzzle (recovering_coin newpuz pubkey) + (qq (q . (((unquote CREATE_COIN_ANNOUNCEMENT) (unquote recovering_coin)) ((unquote AGG_SIG_UNSAFE) (unquote pubkey) (unquote newpuz))))) + ) + + ; this function creates the assert announcement for each message coin approving a recovery + (defun-inline create_consume_message (coin_id my_id new_innerpuz pubkey) + (list ASSERT_COIN_ANNOUNCEMENT (sha256 (sha256 coin_id (sha256tree1 (make_message_puzzle my_id new_innerpuz pubkey))) my_id)) + ) + + ; this function calculates a coin ID given the inner puzzle and singleton information + (defun create_coin_ID_for_recovery (SINGLETON_STRUCT launcher_id parent innerpuzhash amount) + (sha256 parent (calculate_full_puzzle_hash (c (f SINGLETON_STRUCT) (c launcher_id (r (r SINGLETON_STRUCT)))) innerpuzhash) amount) + ) + + + ; return the full puzzlehash for a singleton with the innerpuzzle curried in + ; puzzle-hash-of-curried-function is imported from curry-and-treehash.clib + (defun-inline calculate_full_puzzle_hash (SINGLETON_STRUCT inner_puzzle_hash) + (puzzle-hash-of-curried-function (f SINGLETON_STRUCT) + inner_puzzle_hash + (sha256tree1 SINGLETON_STRUCT) + ) + ) + + ; this loops over our identities to check list, and checks if we have been given parent information for this identity + ; the reason for this is because we might only require 3/5 of the IDs give approval messages for a recovery + ; if we have the information for an identity then we create a consume message using that information + + (defun check_messages_from_identities (SINGLETON_STRUCT num_verifications_required identities my_id new_puz parent_innerpuzhash_amounts_for_recovery_ids pubkey num_verifications) + (if identities + (if (f parent_innerpuzhash_amounts_for_recovery_ids) + ; if we have parent information then we should create a consume coin condition + (c + (create_consume_message + ; create coin_id from DID + (create_coin_ID_for_recovery + SINGLETON_STRUCT + (f identities) + (f (f parent_innerpuzhash_amounts_for_recovery_ids)) + (f (r (f parent_innerpuzhash_amounts_for_recovery_ids))) + (f (r (r (f parent_innerpuzhash_amounts_for_recovery_ids))))) + my_id + new_puz + pubkey + ) + (check_messages_from_identities + SINGLETON_STRUCT + num_verifications_required + (r identities) + my_id + new_puz + (r parent_innerpuzhash_amounts_for_recovery_ids) + pubkey + (+ num_verifications 1) + ) + ) + ; if no parent information found for this identity, move on to next in list + (check_messages_from_identities + SINGLETON_STRUCT + (r identities) + my_id + new_puz + (r parent_innerpuzhash_amounts_for_recovery_ids) + pubkey + num_verifications + ) + ) + ;if we're out of identites to check for, check we have enough + (if (> num_verifications (- num_verifications_required 1)) + (list (list AGG_SIG_UNSAFE pubkey new_puz) ) + (x) + ) + ) + ) + + ;Spend modes: + ;0 = recovery + ;1 = run the INNER_PUZZLE + + ;MAIN + (if mode + ; mode 1 - run INNER_PUZZLE + (a INNER_PUZZLE my_amount_or_inner_solution) + + ; mode 0 - recovery + (if (all (= (sha256tree1 recovery_list_reveal) RECOVERY_DID_LIST_HASH) (> NUM_VERIFICATIONS_REQUIRED 0)) + (c (list ASSERT_MY_AMOUNT my_amount_or_inner_solution) + (c (list CREATE_COIN new_inner_puzhash my_amount_or_inner_solution (list new_inner_puzhash)) + (c (list ASSERT_MY_COIN_ID my_id) + (check_messages_from_identities SINGLETON_STRUCT NUM_VERIFICATIONS_REQUIRED recovery_list_reveal my_id new_inner_puzhash parent_innerpuzhash_amounts_for_recovery_ids pubkey 0) + ) + ) + ) + (x) + ) + ) +) From 93f6715d31a6f354dc5f64ce81f0ce7fce29dec2 Mon Sep 17 00:00:00 2001 From: wjblanke Date: Mon, 5 Jun 2023 17:09:46 -0700 Subject: [PATCH 18/75] Changed versiont to 0.1.34 (#179) * Changed versiont to 0.1.34 * Changed versiont to 0.1.34 --- CHANGELOG.md | 5 +++++ Cargo.lock | 2 +- Cargo.toml | 2 +- wasm/Cargo.lock | 4 ++-- wasm/Cargo.toml | 2 +- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8518b8dd..a2bbf5116 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # clvm_tools_rs Changelog +## 0.1.34 +### Fixed +- Fixed chialisp compilation issues + + ## 0.1.33 ### Changed - Set macOS deployment target to 10.14 diff --git a/Cargo.lock b/Cargo.lock index 85970c9d8..182446923 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,7 +92,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clvm_tools_rs" -version = "0.1.33" +version = "0.1.34" dependencies = [ "binascii", "bls12_381", diff --git a/Cargo.toml b/Cargo.toml index aeee00ba4..9aae5c82e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clvm_tools_rs" -version = "0.1.33" +version = "0.1.34" edition = "2018" authors = ["Art Yerkes "] description = "tools for working with chialisp language; compiler, repl, python and wasm bindings" diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 93c408292..9c0b27d34 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -92,7 +92,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clvm_tools_rs" -version = "0.1.33" +version = "0.1.34" dependencies = [ "binascii", "bls12_381", @@ -124,7 +124,7 @@ dependencies = [ [[package]] name = "clvm_tools_wasm" -version = "0.1.33" +version = "0.1.34" dependencies = [ "clvm_tools_rs", "clvmr", diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index 73c51f1ac..703831506 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clvm_tools_wasm" -version = "0.1.33" +version = "0.1.34" edition = "2018" authors = ["Art Yerkes "] description = "tools for working with chialisp language; compiler, repl, python and wasm bindings" From 94a9ed1f8f16b0d03aff8f6b5eecb7d91eff3de3 Mon Sep 17 00:00:00 2001 From: Chris Marslender Date: Wed, 14 Jun 2023 16:05:41 -0500 Subject: [PATCH 19/75] Swap to build w/ docker instead of podman --- .github/workflows/build-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 07c50967f..809d04813 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -59,8 +59,8 @@ jobs: - name: Build Linux in manylinux2010 with maturin on Python ${{ matrix.python }} if: startsWith(matrix.os, 'ubuntu') run: | - podman run --rm=true \ - -v ${{ github.workspace }}:/ws:rw --workdir=/ws \ + docker run --rm \ + -v ${{ github.workspace }}:/ws --workdir=/ws \ ghcr.io/chia-network/build-images/centos-pypa-rust-x86_64 \ bash -exc '\ yum -y install libc6 openssl-devel && \ @@ -181,7 +181,7 @@ jobs: run: | python support/wheelname.py python resources/tests/test-clvm-recompile-behavior.py - + - name: Run tests from clvm run: | . ./activate From 864c2ad8b3543ef68996a3a30431c315e1043bb9 Mon Sep 17 00:00:00 2001 From: arty Date: Sun, 18 Jun 2023 09:34:03 -0700 Subject: [PATCH 20/75] Specify the version of wasm-pack --- .github/workflows/npm-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index d8424af7c..395a02866 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -30,7 +30,7 @@ jobs: components: rustfmt, clippy - name: install wasm-pack - run: cargo install wasm-pack + run: cargo install --version 0.11.1 wasm-pack - name: wasm-pack build and pack run: wasm-pack build --release --target=nodejs wasm && wasm-pack pack wasm From 9cbf4f7c59c474d556373f2d6fcac54f2f9ac556 Mon Sep 17 00:00:00 2001 From: Patrick Maslana Date: Mon, 19 Jun 2023 12:34:44 -0700 Subject: [PATCH 21/75] Pull rust from source vice the rustup script --- .github/workflows/build-m1-wheel.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index 957b62e0d..191ae9911 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -33,8 +33,15 @@ jobs: - name: Set up rust run: | - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rust.sh - arch -arm64 sh rust.sh -y + curl https://static.rust-lang.org/rustup/dist/aarch64-unknown-linux-gnu/rustup-init.sha256 | awk '{print $1 " rustup-init"}' > checksum.txt + curl -O https://static.rust-lang.org/rustup/dist/aarch64-unknown-linux-gnu/rustup-init + cat checksum.txt + sha256sum -c checksum.txt + + - name: Install rust + run: | + ./rustup-init -y + rm rustup-init checksum.txt - name: Build m1 wheels run: | From 82c6984151f720d232476edc253b480f75909e15 Mon Sep 17 00:00:00 2001 From: Patrick Maslana Date: Wed, 21 Jun 2023 15:47:58 -0700 Subject: [PATCH 22/75] Change the sha256sum command over to shasum --- .github/workflows/build-m1-wheel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index 191ae9911..f9dc86923 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -36,7 +36,7 @@ jobs: curl https://static.rust-lang.org/rustup/dist/aarch64-unknown-linux-gnu/rustup-init.sha256 | awk '{print $1 " rustup-init"}' > checksum.txt curl -O https://static.rust-lang.org/rustup/dist/aarch64-unknown-linux-gnu/rustup-init cat checksum.txt - sha256sum -c checksum.txt + shasum -a 512 checksum.txt - name: Install rust run: | From 8dae48dd5c51925d5a45dde97eadffbfa1d37d41 Mon Sep 17 00:00:00 2001 From: Patrick Maslana Date: Thu, 22 Jun 2023 14:52:44 -0700 Subject: [PATCH 23/75] Add sudo to the run the rustup-init script --- .github/workflows/build-m1-wheel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index f9dc86923..acb0a06dd 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -40,7 +40,7 @@ jobs: - name: Install rust run: | - ./rustup-init -y + sudo ./rustup-init -y rm rustup-init checksum.txt - name: Build m1 wheels From e418db1b43f5dbbcef23c98c8d2fed2191a90068 Mon Sep 17 00:00:00 2001 From: Patrick Maslana Date: Thu, 22 Jun 2023 15:20:34 -0700 Subject: [PATCH 24/75] Fix error in the URL for curl'ing the checksum and rustup-init file --- .github/workflows/build-m1-wheel.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index acb0a06dd..f73644544 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -33,8 +33,8 @@ jobs: - name: Set up rust run: | - curl https://static.rust-lang.org/rustup/dist/aarch64-unknown-linux-gnu/rustup-init.sha256 | awk '{print $1 " rustup-init"}' > checksum.txt - curl -O https://static.rust-lang.org/rustup/dist/aarch64-unknown-linux-gnu/rustup-init + curl https://static.rust-lang.org/rustup/dist/aarch64-apple-darwin/rustup-init.sha256 | awk '{print $1 " rustup-init"}' > checksum.txt + curl -O https://static.rust-lang.org/rustup/dist/aarch64-apple-darwin/rustup-init cat checksum.txt shasum -a 512 checksum.txt From f9fa357ab79f1a24d279d46b6d68a9a15b213a97 Mon Sep 17 00:00:00 2001 From: Patrick Maslana Date: Mon, 26 Jun 2023 14:55:29 -0700 Subject: [PATCH 25/75] Fix the shasum command --- .github/workflows/build-m1-wheel.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index f73644544..392d9b9a0 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -33,10 +33,10 @@ jobs: - name: Set up rust run: | - curl https://static.rust-lang.org/rustup/dist/aarch64-apple-darwin/rustup-init.sha256 | awk '{print $1 " rustup-init"}' > checksum.txt + curl https://static.rust-lang.org/rustup/dist/aarch64-apple-darwin/rustup-init.sha256 | awk '{print $1 " *rustup-init"}' > checksum.txt curl -O https://static.rust-lang.org/rustup/dist/aarch64-apple-darwin/rustup-init cat checksum.txt - shasum -a 512 checksum.txt + shasum -a 256 checksum.txt - name: Install rust run: | From 5aae8e03e01d9b79741ee8e60bd156fb996a76a8 Mon Sep 17 00:00:00 2001 From: Patrick Maslana Date: Tue, 27 Jun 2023 09:24:24 -0700 Subject: [PATCH 26/75] Fix errors with the rustup install --- .github/workflows/build-m1-wheel.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index 392d9b9a0..2a0a1fc25 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -33,14 +33,15 @@ jobs: - name: Set up rust run: | - curl https://static.rust-lang.org/rustup/dist/aarch64-apple-darwin/rustup-init.sha256 | awk '{print $1 " *rustup-init"}' > checksum.txt + curl https://static.rust-lang.org/rustup/dist/aarch64-apple-darwin/rustup-init.sha256 | awk '{print $1 " * rustup-init"}' > checksum.txt curl -O https://static.rust-lang.org/rustup/dist/aarch64-apple-darwin/rustup-init cat checksum.txt shasum -a 256 checksum.txt - name: Install rust run: | - sudo ./rustup-init -y + chmod +x rustup-init + ./rustup-init rm rustup-init checksum.txt - name: Build m1 wheels From ed674fba2180dc053e26131da75b7299aaa9c5ad Mon Sep 17 00:00:00 2001 From: Patrick Maslana Date: Tue, 27 Jun 2023 09:38:22 -0700 Subject: [PATCH 27/75] Include the "-y" flag --- .github/workflows/build-m1-wheel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index 2a0a1fc25..599f65a94 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -41,7 +41,7 @@ jobs: - name: Install rust run: | chmod +x rustup-init - ./rustup-init + ./rustup-init -y rm rustup-init checksum.txt - name: Build m1 wheels From fad58437a032842292f624cb96986e608d00cb81 Mon Sep 17 00:00:00 2001 From: Patrick Maslana Date: Tue, 27 Jun 2023 13:53:28 -0700 Subject: [PATCH 28/75] Add an OR operator and exit if installed --- .github/workflows/build-m1-wheel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index 599f65a94..d2e700a4b 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -41,7 +41,7 @@ jobs: - name: Install rust run: | chmod +x rustup-init - ./rustup-init -y + ./rustup-init -y ./rustup-init.sh -y || (echo "Rust is already installed. Exiting..." && exit 2) rm rustup-init checksum.txt - name: Build m1 wheels From ecf72e02edf9b15aa6f28e6e4c5066095ae83845 Mon Sep 17 00:00:00 2001 From: Patrick Maslana Date: Tue, 27 Jun 2023 14:25:02 -0700 Subject: [PATCH 29/75] Remove extra command --- .github/workflows/build-m1-wheel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index d2e700a4b..5eb9ca121 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -41,7 +41,7 @@ jobs: - name: Install rust run: | chmod +x rustup-init - ./rustup-init -y ./rustup-init.sh -y || (echo "Rust is already installed. Exiting..." && exit 2) + ./rustup-init -y || (echo "Rust is already installed. Exiting..." && exit 2) rm rustup-init checksum.txt - name: Build m1 wheels From ffa5c4761f848cb2606a06219028b28be14d2c42 Mon Sep 17 00:00:00 2001 From: arty Date: Tue, 27 Jun 2023 15:35:15 -0700 Subject: [PATCH 30/75] The github workflow for running the clvm_tools tests wasn't working, so fix that --- .github/workflows/build-m1-wheel.yml | 5 ++--- .github/workflows/build-test.yml | 6 ++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index 957b62e0d..12a30cfb3 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -84,11 +84,10 @@ jobs: # arch -arm64 python -m py.test tests - name: Run tests from clvm_tools - continue-on-error: true run: | . ./venv/bin/activate - cd clvm_tools_rs - arch -arm64 cargo test + cd clvm_tools + arch -arm64 python -m py.test - name: Upload wheels uses: actions/upload-artifact@v3 diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 809d04813..f617ffd54 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -189,6 +189,12 @@ jobs: pip install pytest pytest-asyncio pytest tests + - name: Run tests from clvm_tools + run: | + . ./activate + cd clvm_tools + python -m py.test + - name: Run tests if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.7') run: cargo test --no-default-features From d87676d172288ae73d826a4b5468fb8ba0a23e9b Mon Sep 17 00:00:00 2001 From: arty Date: Tue, 27 Jun 2023 15:44:09 -0700 Subject: [PATCH 31/75] Install clvm_tools from its repo --- .github/workflows/build-test.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index f617ffd54..50f5abc1e 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -129,8 +129,10 @@ jobs: pip install clvm_rs echo "installing clvm_tools for clvm tests" - # clvm tools is required to run the tests is clvm - python -m pip install clvm_tools + + # Ensure clvm_tools is installed from its own repo. + arch -arm64 git clone https://github.com/Chia-Network/clvm_tools.git --branch=main --single-branch + arch -arm64 python -m pip install ./clvm_tools - name: Ensure clvm, clvm_rs, clvm_tools_rs are installed run: | From 5c9d74d5bf9228850fd3efbe3d132ff368717204 Mon Sep 17 00:00:00 2001 From: arty Date: Tue, 27 Jun 2023 15:48:58 -0700 Subject: [PATCH 32/75] Make installing pytest its own step --- .github/workflows/build-m1-wheel.yml | 5 +++++ .github/workflows/build-test.yml | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index 12a30cfb3..cb4e6d01a 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -76,6 +76,11 @@ jobs: arch -arm64 python -c 'import clvm_tools; print(clvm_tools.__file__)' arch -arm64 python -c 'import clvm_tools_rs; print(clvm_tools_rs.__file__)' + - name: Install pytest + run: | + . ./activate + pip install pytest pytest-asyncio + # Cost tests are currently failing. # - name: Run tests from clvm # run: | diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 50f5abc1e..2c56b39f0 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -184,11 +184,15 @@ jobs: python support/wheelname.py python resources/tests/test-clvm-recompile-behavior.py + - name: Install pytest + run: | + . ./activate + pip install pytest pytest-asyncio + - name: Run tests from clvm run: | . ./activate cd clvm - pip install pytest pytest-asyncio pytest tests - name: Run tests from clvm_tools From 2a75097f1d472ff34d6efc12e452da4c76d2679b Mon Sep 17 00:00:00 2001 From: arty Date: Tue, 27 Jun 2023 15:55:46 -0700 Subject: [PATCH 33/75] copy error --- .github/workflows/build-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 2c56b39f0..ef9a308fa 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -131,8 +131,8 @@ jobs: echo "installing clvm_tools for clvm tests" # Ensure clvm_tools is installed from its own repo. - arch -arm64 git clone https://github.com/Chia-Network/clvm_tools.git --branch=main --single-branch - arch -arm64 python -m pip install ./clvm_tools + git clone https://github.com/Chia-Network/clvm_tools.git --branch=main --single-branch + python -m pip install ./clvm_tools - name: Ensure clvm, clvm_rs, clvm_tools_rs are installed run: | From 1a1930f0f83039d7b015e042d407f7b409b87229 Mon Sep 17 00:00:00 2001 From: arty Date: Tue, 27 Jun 2023 16:01:51 -0700 Subject: [PATCH 34/75] run the less conservative way by relying on the venv to provide a 'pytest' command in the environment since that is working in the clvm case --- .github/workflows/build-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index ef9a308fa..61a9264fb 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -199,7 +199,7 @@ jobs: run: | . ./activate cd clvm_tools - python -m py.test + pytest tests - name: Run tests if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.7') From 7e21510e26d376bdd43dc4c3907905cddd2226c7 Mon Sep 17 00:00:00 2001 From: arty Date: Wed, 28 Jun 2023 05:51:34 -0700 Subject: [PATCH 35/75] Fix yaml indent in m1 build --- .github/workflows/build-m1-wheel.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index cb4e6d01a..e727b9f72 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -76,8 +76,8 @@ jobs: arch -arm64 python -c 'import clvm_tools; print(clvm_tools.__file__)' arch -arm64 python -c 'import clvm_tools_rs; print(clvm_tools_rs.__file__)' - - name: Install pytest - run: | + - name: Install pytest + run: | . ./activate pip install pytest pytest-asyncio From b87b2e32f9ff8d2f4b88f0a965f0f196c881aade Mon Sep 17 00:00:00 2001 From: arty Date: Wed, 28 Jun 2023 05:56:11 -0700 Subject: [PATCH 36/75] Correct venv path --- .github/workflows/build-m1-wheel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index e727b9f72..16533a6d7 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -78,7 +78,7 @@ jobs: - name: Install pytest run: | - . ./activate + . ./venv/bin/activate pip install pytest pytest-asyncio # Cost tests are currently failing. From ffcd6f0dd16881b57dcf08c659f1020930f1c1ba Mon Sep 17 00:00:00 2001 From: arty Date: Wed, 28 Jun 2023 06:00:09 -0700 Subject: [PATCH 37/75] Run the less conservative way --- .github/workflows/build-m1-wheel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index 16533a6d7..f0fc6bf57 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -92,7 +92,7 @@ jobs: run: | . ./venv/bin/activate cd clvm_tools - arch -arm64 python -m py.test + arch -arm64 pytest - name: Upload wheels uses: actions/upload-artifact@v3 From c7fc62e11657b0ef9fb15665b1d47ae8365d8edb Mon Sep 17 00:00:00 2001 From: Patrick Maslana Date: Wed, 28 Jun 2023 09:08:41 -0700 Subject: [PATCH 38/75] Add a "-c" for the shasum check --- .github/workflows/build-m1-wheel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index 5eb9ca121..dd9bc5521 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -36,7 +36,7 @@ jobs: curl https://static.rust-lang.org/rustup/dist/aarch64-apple-darwin/rustup-init.sha256 | awk '{print $1 " * rustup-init"}' > checksum.txt curl -O https://static.rust-lang.org/rustup/dist/aarch64-apple-darwin/rustup-init cat checksum.txt - shasum -a 256 checksum.txt + shasum -a 256 -c checksum.txt - name: Install rust run: | From e9cd39fb236717d3349b1bacbd525677c86baab7 Mon Sep 17 00:00:00 2001 From: Patrick Maslana Date: Wed, 28 Jun 2023 09:10:40 -0700 Subject: [PATCH 39/75] Remove additional whitespace --- .github/workflows/build-m1-wheel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index dd9bc5521..a6fb5ddb6 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -33,7 +33,7 @@ jobs: - name: Set up rust run: | - curl https://static.rust-lang.org/rustup/dist/aarch64-apple-darwin/rustup-init.sha256 | awk '{print $1 " * rustup-init"}' > checksum.txt + curl https://static.rust-lang.org/rustup/dist/aarch64-apple-darwin/rustup-init.sha256 | awk '{print $1 " *rustup-init"}' > checksum.txt curl -O https://static.rust-lang.org/rustup/dist/aarch64-apple-darwin/rustup-init cat checksum.txt shasum -a 256 -c checksum.txt From 9a258235e85ce1d0de0d1f4db46996d58bfce2ad Mon Sep 17 00:00:00 2001 From: Chris Marslender Date: Thu, 29 Jun 2023 15:06:36 -0500 Subject: [PATCH 40/75] Move nightly -> dev and use simple-dev for the url --- .github/workflows/build-arm64-wheels.yml | 7 +++---- .github/workflows/build-m1-wheel.yml | 7 +++---- .github/workflows/build-test.yml | 9 ++++----- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-arm64-wheels.yml b/.github/workflows/build-arm64-wheels.yml index 0da03a96b..6516c2073 100644 --- a/.github/workflows/build-arm64-wheels.yml +++ b/.github/workflows/build-arm64-wheels.yml @@ -5,7 +5,6 @@ on: branches: - main - dev - - nightly tags: - '**' pull_request: @@ -107,8 +106,8 @@ jobs: . ./activate twine upload --non-interactive --skip-existing --verbose 'target/wheels/*' - - name: Publish Nightlies - if: steps.check_secrets.outputs.HAS_AWS_SECRET && github.ref == 'refs/heads/nightly' + - name: Publish Dev + if: steps.check_secrets.outputs.HAS_AWS_SECRET && github.ref == 'refs/heads/dev' env: AWS_ACCESS_KEY_ID: "${{ secrets.INSTALLER_UPLOAD_KEY }}" AWS_SECRET_ACCESS_KEY: "${{ secrets.INSTALLER_UPLOAD_SECRET }}" @@ -117,5 +116,5 @@ jobs: FILES=$(find ${{ github.workspace }}/target/wheels -type f -name '*.whl') while IFS= read -r file; do filename=$(basename $file) - aws --no-progress s3 cp "$file" "s3://download.chia.net/nightlies/clvm-tools-rs/$filename" + aws --no-progress s3 cp "$file" "s3://download.chia.net/simple-dev/clvm-tools-rs/$filename" done <<< "$FILES" diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index ff76e0b10..622743ab4 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -5,7 +5,6 @@ on: branches: - main - dev - - nightly tags: - '**' pull_request: @@ -144,8 +143,8 @@ jobs: TWINE_PASSWORD: ${{ secrets.test_pypi_password }} run: arch -arm64 twine upload --non-interactive --skip-existing --verbose 'target/wheels/*' - - name: Publish Nightlies - if: steps.check_secrets.outputs.HAS_AWS_SECRET && github.ref == 'refs/heads/nightly' + - name: Publish Dev + if: steps.check_secrets.outputs.HAS_AWS_SECRET && github.ref == 'refs/heads/dev' env: AWS_ACCESS_KEY_ID: "${{ secrets.INSTALLER_UPLOAD_KEY }}" AWS_SECRET_ACCESS_KEY: "${{ secrets.INSTALLER_UPLOAD_SECRET }}" @@ -154,5 +153,5 @@ jobs: FILES=$(find ${{ github.workspace }}/target/wheels -type f -name '*.whl') while IFS= read -r file; do filename=$(basename $file) - aws --no-progress s3 cp "$file" "s3://download.chia.net/nightlies/clvm-tools-rs/$filename" + aws --no-progress s3 cp "$file" "s3://download.chia.net/simple-dev/clvm-tools-rs/$filename" done <<< "$FILES" diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 61a9264fb..98330573c 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -6,7 +6,6 @@ on: branches: - base - dev - - nightly tags: - '**' pull_request: @@ -188,7 +187,7 @@ jobs: run: | . ./activate pip install pytest pytest-asyncio - + - name: Run tests from clvm run: | . ./activate @@ -255,8 +254,8 @@ jobs: TWINE_PASSWORD: ${{ secrets.test_pypi_password }} run: twine upload --non-interactive --skip-existing --verbose 'target/wheels/*' - - name: Publish Nightlies - if: steps.check_secrets.outputs.HAS_AWS_SECRET && github.ref == 'refs/heads/nightly' + - name: Publish Dev + if: steps.check_secrets.outputs.HAS_AWS_SECRET && github.ref == 'refs/heads/dev' shell: bash working-directory: ./target/wheels env: @@ -267,7 +266,7 @@ jobs: FILES=$(find . -type f -name '*.whl') while IFS= read -r file; do filename=$(basename $file) - aws --no-progress s3 cp "$file" "s3://download.chia.net/nightlies/clvm-tools-rs/$filename" + aws --no-progress s3 cp "$file" "s3://download.chia.net/simple-dev/clvm-tools-rs/$filename" done <<< "$FILES" fmt: From b9f7630a69c6bf05fda641a312996bc723201a1a Mon Sep 17 00:00:00 2001 From: arty Date: Tue, 25 Jul 2023 08:34:48 -0700 Subject: [PATCH 41/75] Update recompile check for new tree layout in chia-blockchain --- support/recompile_check.py | 80 +++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/support/recompile_check.py b/support/recompile_check.py index 81c1244d3..6294106b4 100644 --- a/support/recompile_check.py +++ b/support/recompile_check.py @@ -1,24 +1,56 @@ import os +from pathlib import Path import subprocess import traceback +FULL_NODE='chia/full_node/puzzles' +CAT_WALLET='chia/wallet/cat_wallet/puzzles' +DID_WALLET='chia/wallet/did_wallet/puzzles' +NFT_WALLET='chia/wallet/nft_wallet/puzzles' +POOLS='chia/pools/puzzles' +CONSENSUS='chia/consensus/puzzles' +GENTEST='tests/generator/puzzles' + +def full_node(x): + return {'fname': x, 'dirname': FULL_NODE} + +def cat_wallet(x): + return {'fname': x, 'dirname': CAT_WALLET} + +def did_wallet(x): + return {'fname': x, 'dirname': DID_WALLET} + +def nft_wallet(x): + return {'fname': x, 'dirname': NFT_WALLET} + +def pools(x): + return {'fname': x, 'dirname': POOLS} + +def consensus(x): + return {'fname': x, 'dirname': CONSENSUS} + +def gentest(x): + return {'fname': x, 'dirname': GENTEST} + recompile_list = [ - 'block_program_zero.clsp', + full_node('block_program_zero.clsp'), + full_node('decompress_coin_spend_entry.clsp'), + full_node('decompress_coin_spend_entry_with_prefix.clsp'), + full_node('decompress_puzzle.clsp'), + cat_wallet('delegated_tail.clsp'), + cat_wallet('everything_with_signature.clsp'), + cat_wallet('genesis_by_coin_id.clsp'), + cat_wallet('genesis_by_puzzle_hash.clsp'), + did_wallet('did_innerpuz.clsp'), + nft_wallet('nft_metadata_updater_default.clsp'), + nft_wallet('nft_metadata_updater_updateable.clsp'), + nft_wallet('nft_ownership_layer.clsp'), + nft_wallet('nft_ownership_transfer_program_one_way_claim_with_royalties.clsp'), + nft_wallet('nft_state_layer.clsp'), + pools('pool_member_innerpuz.clsp'), + pools('pool_waitingroom_innerpuz.clsp'), + consensus('rom_bootstrap_generator.clsp'), 'calculate_synthetic_public_key.clsp', - 'chialisp_deserialisation.clsp', - 'decompress_coin_spend_entry.clsp', - 'decompress_coin_spend_entry_with_prefix.clsp', - 'decompress_puzzle.clsp', - 'delegated_tail.clsp', - 'did_innerpuz.clsp', - 'everything_with_signature.clsp', - 'genesis_by_coin_id.clsp', - 'genesis_by_puzzle_hash.clsp', - 'nft_metadata_updater_default.clsp', - 'nft_metadata_updater_updateable.clsp', - 'nft_ownership_layer.clsp', - 'nft_ownership_transfer_program_one_way_claim_with_royalties.clsp', - 'nft_state_layer.clsp', 'p2_conditions.clsp', 'p2_delegated_conditions.clsp', 'p2_delegated_puzzle.clsp', @@ -27,24 +59,28 @@ 'p2_puzzle_hash.clsp', 'p2_singleton.clsp', 'p2_singleton_or_delayed_puzhash.clsp', - 'pool_member_innerpuz.clsp', - 'pool_waitingroom_innerpuz.clsp', - 'rom_bootstrap_generator.clsp', 'settlement_payments.clsp', 'sha256tree_module.clsp', 'singleton_launcher.clsp', 'singleton_top_layer.clsp', 'singleton_top_layer_v1_1.clsp', - 'test_generator_deserialize.clsp', - 'test_multiple_generator_input_arguments.clsp' + gentest('test_generator_deserialize.clsp'), + gentest('test_multiple_generator_input_arguments.clsp') ] for fname in recompile_list: - hexfile = f'./chia/wallet/puzzles/{fname}.hex' + if 'dirname' in fname and 'fname' in fname: + dirname = fname['dirname'] + fname = fname['fname'] + else: + dirname = 'chia/wallet/puzzles' + + srcfile = str(Path(dirname) / Path(fname)) + hexfile = f'{str(srcfile)}.hex' hexdata = open(hexfile).read().strip() os.unlink(hexfile) try: - compiled = subprocess.check_output(['../target/release/run', '-i', 'chia/wallet/puzzles/', f'chia/wallet/puzzles/{fname}']).strip() + compiled = subprocess.check_output(['../target/release/run', '-i', dirname, '-i', 'chia/wallet/puzzles', srcfile]).strip() recompile = subprocess.check_output(['../target/release/opc', compiled]).decode('utf8').strip() except: print(f'compiling {fname}') From 7264b180fddf2c55c33249b8361e8ae49731f3c1 Mon Sep 17 00:00:00 2001 From: arty Date: Tue, 25 Jul 2023 08:42:07 -0700 Subject: [PATCH 42/75] New clippy edition issues --- src/classic/clvm_tools/stages/stage_2/optimize.rs | 5 ++--- src/compiler/codegen.rs | 2 +- src/compiler/compiler.rs | 4 ++-- src/compiler/frontend.rs | 2 +- src/compiler/sexp.rs | 4 ++-- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/classic/clvm_tools/stages/stage_2/optimize.rs b/src/classic/clvm_tools/stages/stage_2/optimize.rs index d723e279f..7fde38552 100644 --- a/src/classic/clvm_tools/stages/stage_2/optimize.rs +++ b/src/classic/clvm_tools/stages/stage_2/optimize.rs @@ -1,4 +1,3 @@ -use std::borrow::Borrow; use std::cell::{Ref, RefCell}; use std::collections::HashMap; use std::mem::swap; @@ -635,7 +634,7 @@ pub fn optimize_sexp_( // pass and need to cache the result. { let memo_ref: Ref> = memo.borrow(); - let memo: &HashMap = memo_ref.borrow(); + let memo: &HashMap = &memo_ref; if let Some(res) = memo.get(&AllocatorRefOrTreeHash::new_from_nodeptr(r_)) { return Ok(*res); } @@ -645,7 +644,7 @@ pub fn optimize_sexp_( let footprint = AllocatorRefOrTreeHash::new_from_sexp(allocator, r_); { let memo_ref: Ref> = memo.borrow(); - let memo: &HashMap = memo_ref.borrow(); + let memo: &HashMap = &memo_ref; if let Some(res) = memo.get(&footprint) { return Ok(*res); } diff --git a/src/compiler/codegen.rs b/src/compiler/codegen.rs index 20fff0062..48527f81f 100644 --- a/src/compiler/codegen.rs +++ b/src/compiler/codegen.rs @@ -91,7 +91,7 @@ fn helper_atom(h: &HelperForm) -> SExp { fn build_tree(l: Srcloc, s: usize, e: usize, helper_array: &[HelperForm]) -> SExp { if e - s == 1 { - helper_atom(helper_array[s].borrow()) + helper_atom(&helper_array[s]) } else { let mid = (e + s) / 2; let car = build_tree(l.clone(), s, mid, helper_array); diff --git a/src/compiler/compiler.rs b/src/compiler/compiler.rs index 7639f88b5..bab6a1020 100644 --- a/src/compiler/compiler.rs +++ b/src/compiler/compiler.rs @@ -472,7 +472,7 @@ pub fn extract_program_and_env(program: Rc) -> Option<(Rc, Rc) return None; } - match (is_apply(&lst[0]), lst[1].borrow(), lst[2].proper_list()) { + match (is_apply(&lst[0]), &lst[1], lst[2].proper_list()) { (true, real_program, Some(cexp)) => { if cexp.len() != 3 || !is_cons(&cexp[0]) || !is_whole_env(&cexp[2]) { None @@ -492,7 +492,7 @@ pub fn is_at_capture(head: Rc, rest: Rc) -> Option<(Vec, Rc { - let compiled_val: &CompileForm = v.borrow(); + let compiled_val: &CompileForm = &v; Ok(compiled_val.clone()) } }; diff --git a/src/compiler/sexp.rs b/src/compiler/sexp.rs index 599eea3fe..881694f82 100644 --- a/src/compiler/sexp.rs +++ b/src/compiler/sexp.rs @@ -143,7 +143,7 @@ impl Display for SExp { } else { let vlen = s.len() * 2; let mut outbuf = vec![0; vlen]; - bin2hex(s, &mut outbuf).map_err(|_e| std::fmt::Error::default())?; + bin2hex(s, &mut outbuf).map_err(|_e| std::fmt::Error)?; formatter.write_str("0x")?; formatter.write_str( std::str::from_utf8(&outbuf).expect("only hex digits expected"), @@ -781,7 +781,7 @@ where for this_char in s { let next_location = start.clone().advance(this_char); - match parse_sexp_step(start.clone(), parse_state.borrow(), this_char) { + match parse_sexp_step(start.clone(), &parse_state, this_char) { SExpParseResult::Error(l, e) => { return Err((l, e)); } From 960b9fb3c4804679afe8bf21de991da0f75c57bd Mon Sep 17 00:00:00 2001 From: arty Date: Tue, 25 Jul 2023 16:57:06 -0700 Subject: [PATCH 43/75] Use nicer names --- support/recompile_check.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/support/recompile_check.py b/support/recompile_check.py index 6294106b4..7b5f726ba 100644 --- a/support/recompile_check.py +++ b/support/recompile_check.py @@ -68,14 +68,15 @@ def gentest(x): gentest('test_multiple_generator_input_arguments.clsp') ] -for fname in recompile_list: - if 'dirname' in fname and 'fname' in fname: - dirname = fname['dirname'] - fname = fname['fname'] +for recompile_entry in recompile_list: + if 'dirname' in recompile_entry and 'fname' in recompile_entry: + dirname = recompile_entry['dirname'] + filename = recompile_entry['fname'] else: + filename = recompile_entry dirname = 'chia/wallet/puzzles' - srcfile = str(Path(dirname) / Path(fname)) + srcfile = str(Path(dirname) / Path(filename)) hexfile = f'{str(srcfile)}.hex' hexdata = open(hexfile).read().strip() os.unlink(hexfile) From 4c08b012db9c787ef730ae2a4a4d92a23719923a Mon Sep 17 00:00:00 2001 From: arty Date: Wed, 26 Jul 2023 04:24:20 -0700 Subject: [PATCH 44/75] Two removed modules upstream (calculate_synthetic_public_key.clsp and sha256tree_module.clsp) --- support/recompile_check.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/support/recompile_check.py b/support/recompile_check.py index 7b5f726ba..c991198e4 100644 --- a/support/recompile_check.py +++ b/support/recompile_check.py @@ -50,7 +50,6 @@ def gentest(x): pools('pool_member_innerpuz.clsp'), pools('pool_waitingroom_innerpuz.clsp'), consensus('rom_bootstrap_generator.clsp'), - 'calculate_synthetic_public_key.clsp', 'p2_conditions.clsp', 'p2_delegated_conditions.clsp', 'p2_delegated_puzzle.clsp', @@ -60,7 +59,6 @@ def gentest(x): 'p2_singleton.clsp', 'p2_singleton_or_delayed_puzhash.clsp', 'settlement_payments.clsp', - 'sha256tree_module.clsp', 'singleton_launcher.clsp', 'singleton_top_layer.clsp', 'singleton_top_layer_v1_1.clsp', From 8f1412fcb4ec62c01df5dbcdc215a3c138c1326e Mon Sep 17 00:00:00 2001 From: arty Date: Thu, 27 Jul 2023 15:17:02 -0700 Subject: [PATCH 45/75] Maturin now allows features= so we can remove extension-module from default features and mac no longer needs a special command line to build with cargo --- Cargo.toml | 10 +++- pyproject.toml | 1 + wasm/Cargo.lock | 154 +----------------------------------------------- 3 files changed, 10 insertions(+), 155 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9aae5c82e..1db6a50cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,11 @@ yaml-rust = "0.4" linked-hash-map = "0.5.6" serde = { version = "1.0", features = ["derive", "rc"] } +[dependencies.pyo3] +version = "0.14.2" +features = ["abi3-py37", "extension-module"] +optional = true + [dev-dependencies] rand = "0.8.5" rand_chacha = "0.3.1" @@ -47,8 +52,8 @@ name = "clvm_tools_rs" crate-type = ["cdylib", "rlib"] [features] -extension-module = ["pyo3"] -default = ["extension-module"] +extension-module = ["dep:pyo3"] +default = [] [target.'cfg(target_family="wasm")'.dependencies] wasm-bindgen = { version = "0.2.80", features = ["serde-serialize"] } @@ -57,7 +62,6 @@ js-sys = "0.3.58" getrandom = { version = "0.2", features = ["js"] } [target.'cfg(not(target_family="wasm"))'.dependencies] -pyo3 = { version = "0.14.2", features = ["abi3-py37", "extension-module"], optional = true } getrandom = { version = "0.2" } [build-dependencies] diff --git a/pyproject.toml b/pyproject.toml index e3d896403..bd9c56524 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,6 +4,7 @@ build-backend = "maturin" [tool.maturin] bindings = "pyo3" +features = ["extension-module"] [project] name = "clvm_tools_rs" diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 9c0b27d34..67f0de9bb 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -103,15 +103,14 @@ dependencies = [ "encoding8", "getrandom", "hex", - "indoc 1.0.7", + "indoc", "js-sys", "lazy_static", "linked-hash-map", "num", "num-bigint", "num-traits", - "pyo3", - "pyo3-build-config 0.15.2", + "pyo3-build-config", "serde", "serde_json", "sha2 0.9.9", @@ -285,35 +284,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "indoc" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8" -dependencies = [ - "indoc-impl", - "proc-macro-hack", -] - [[package]] name = "indoc" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adab1eaa3408fb7f0c777a73e7465fd5656136fc93b670eb6df3c88c2c1344e3" -[[package]] -name = "indoc-impl" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", - "unindent", -] - [[package]] name = "instant" version = "0.1.12" @@ -356,16 +332,6 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" -[[package]] -name = "lock_api" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "log" version = "0.4.17" @@ -473,56 +439,6 @@ dependencies = [ "group", ] -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", -] - -[[package]] -name = "paste" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" -dependencies = [ - "paste-impl", - "proc-macro-hack", -] - -[[package]] -name = "paste-impl" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" -dependencies = [ - "proc-macro-hack", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - [[package]] name = "proc-macro2" version = "1.0.47" @@ -532,31 +448,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "pyo3" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35100f9347670a566a67aa623369293703322bb9db77d99d7df7313b575ae0c8" -dependencies = [ - "cfg-if", - "indoc 0.3.6", - "libc", - "parking_lot", - "paste", - "pyo3-build-config 0.14.5", - "pyo3-macros", - "unindent", -] - -[[package]] -name = "pyo3-build-config" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d12961738cacbd7f91b7c43bc25cfeeaa2698ad07a04b3be0aa88b950865738f" -dependencies = [ - "once_cell", -] - [[package]] name = "pyo3-build-config" version = "0.15.2" @@ -566,29 +457,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "pyo3-macros" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0bc5215d704824dfddddc03f93cb572e1155c68b6761c37005e1c288808ea8" -dependencies = [ - "pyo3-macros-backend", - "quote", - "syn", -] - -[[package]] -name = "pyo3-macros-backend" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71623fc593224afaab918aa3afcaf86ed2f43d34f6afde7f3922608f253240df" -dependencies = [ - "proc-macro2", - "pyo3-build-config 0.14.5", - "quote", - "syn", -] - [[package]] name = "quote" version = "1.0.21" @@ -640,12 +508,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - [[package]] name = "serde" version = "1.0.147" @@ -701,12 +563,6 @@ dependencies = [ "digest 0.10.5", ] -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - [[package]] name = "subtle" version = "2.4.1" @@ -762,12 +618,6 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" -[[package]] -name = "unindent" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ee9362deb4a96cef4d437d1ad49cffc9b9e92d202b6995674e928ce684f112" - [[package]] name = "version_check" version = "0.9.4" From 74985b6226d1ce327d76c1e4948dfb5d91b2de1c Mon Sep 17 00:00:00 2001 From: arty Date: Thu, 27 Jul 2023 15:41:49 -0700 Subject: [PATCH 46/75] Update version of maturin --- .github/workflows/build-arm64-wheels.yml | 2 +- .github/workflows/build-m1-wheel.yml | 2 +- .github/workflows/build-test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-arm64-wheels.yml b/.github/workflows/build-arm64-wheels.yml index 6516c2073..1e907f77e 100644 --- a/.github/workflows/build-arm64-wheels.yml +++ b/.github/workflows/build-arm64-wheels.yml @@ -38,7 +38,7 @@ jobs: /opt/python/cp38-cp38/bin/python -m venv venv if [ ! -f "activate" ]; then ln -s venv/bin/activate; fi . ./activate - pip install maturin==0.12.20 + pip install maturin==1.1.0 CC=gcc maturin build --release --strip --manylinux 2014 --no-sdist --cargo-extra-args=--all-features - name: Upload artifacts uses: actions/upload-artifact@v3 diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index 622743ab4..b4ae3532c 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -48,7 +48,7 @@ jobs: arch -arm64 python3 -m venv venv . ./venv/bin/activate export PATH=~/.cargo/bin:$PATH - arch -arm64 pip install maturin==0.12.20 + arch -arm64 pip install maturin==1.1.0 arch -arm64 maturin build --no-sdist -i python --release --strip --cargo-extra-args="--all-features" arch -arm64 cargo test --no-default-features diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 98330573c..3167d606e 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -43,7 +43,7 @@ jobs: - name: Install dependencies run: | - python -m pip install maturin==0.12.20 + python -m pip install maturin==1.1.0 - name: Build MacOs with maturin on Python ${{ matrix.python }} if: startsWith(matrix.os, 'macos') From 0357301381006360e31bb817d47d36a129755ba7 Mon Sep 17 00:00:00 2001 From: arty Date: Thu, 27 Jul 2023 15:45:04 -0700 Subject: [PATCH 47/75] Update some command line arguments --- .github/workflows/build-arm64-wheels.yml | 2 +- .github/workflows/build-m1-wheel.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-arm64-wheels.yml b/.github/workflows/build-arm64-wheels.yml index 1e907f77e..ba40fe845 100644 --- a/.github/workflows/build-arm64-wheels.yml +++ b/.github/workflows/build-arm64-wheels.yml @@ -39,7 +39,7 @@ jobs: if [ ! -f "activate" ]; then ln -s venv/bin/activate; fi . ./activate pip install maturin==1.1.0 - CC=gcc maturin build --release --strip --manylinux 2014 --no-sdist --cargo-extra-args=--all-features + CC=gcc maturin build --release --strip --manylinux 2014 - name: Upload artifacts uses: actions/upload-artifact@v3 with: diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index b4ae3532c..917451d4f 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -49,8 +49,8 @@ jobs: . ./venv/bin/activate export PATH=~/.cargo/bin:$PATH arch -arm64 pip install maturin==1.1.0 - arch -arm64 maturin build --no-sdist -i python --release --strip --cargo-extra-args="--all-features" - arch -arm64 cargo test --no-default-features + arch -arm64 maturin build -i python --release --strip + arch -arm64 cargo test - name: Install clvm_tools_rs wheel run: | From 6ebf2b3fbfaf782a3ccd42904395e2c87dfefd1d Mon Sep 17 00:00:00 2001 From: arty Date: Thu, 27 Jul 2023 15:54:00 -0700 Subject: [PATCH 48/75] Update for windows --- .github/workflows/build-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 3167d606e..27a37f9ae 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -97,7 +97,7 @@ jobs: python -m venv venv echo ". .\venv\Scripts\Activate.ps1" > activate.ps1 . ./activate - maturin build --no-sdist -i python --release --strip + maturin build -i python --release --strip # Find and install the newly built wheel python support/wheelname.py From c3db5b7618fff285c8b80a9fd4ad753ea23da8a0 Mon Sep 17 00:00:00 2001 From: arty Date: Thu, 27 Jul 2023 19:03:14 -0700 Subject: [PATCH 49/75] Isolated change to upgrade clvmr --- .github/workflows/build-test.yml | 2 +- Cargo.lock | 267 +++++++++++++++--- Cargo.toml | 4 +- src/classic/clvm/serialize.rs | 8 +- src/classic/clvm/sexp.rs | 22 +- src/classic/clvm_tools/binutils.rs | 7 +- src/classic/clvm_tools/clvmc.rs | 11 +- src/classic/clvm_tools/debug.rs | 2 +- src/classic/clvm_tools/pattern_match.rs | 50 ++-- src/classic/clvm_tools/sha256tree.rs | 5 +- src/classic/clvm_tools/stages/stage_0.rs | 8 +- .../clvm_tools/stages/stage_2/compile.rs | 73 +++-- .../clvm_tools/stages/stage_2/inline.rs | 19 +- .../clvm_tools/stages/stage_2/module.rs | 23 +- .../clvm_tools/stages/stage_2/operators.rs | 66 +++-- .../clvm_tools/stages/stage_2/optimize.rs | 46 +-- .../clvm_tools/stages/stage_2/reader.rs | 10 +- src/compiler/clvm.rs | 6 +- src/tests/classic/smoke.rs | 61 +++- wasm/Cargo.lock | 106 +++---- wasm/Cargo.toml | 2 +- 21 files changed, 542 insertions(+), 256 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 98330573c..24a3522d6 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -79,7 +79,7 @@ jobs: . ./activate && \ pip install --upgrade pip ' - docker run --rm -v $(pwd):/io ghcr.io/pyo3/maturin:v0.13.1 build --release --strip --manylinux 2010 + docker run --rm -v $(pwd):/io ghcr.io/pyo3/maturin:v1.1.0 build --release --strip --manylinux 2014 # Refresh in case any ownerships changed. mv target target.docker && cp -r target.docker target # Ensure an empty .cargo-lock file exists. diff --git a/Cargo.lock b/Cargo.lock index 182446923..740e20834 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,18 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "binascii" version = "0.1.4" @@ -43,19 +55,20 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "bls12_381" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62250ece575fa9b22068b3a8d59586f01d426dd7785522efd97632959e71c986" +checksum = "d7bc6d6292be3a19e6379786dac800f551e5865a5bb51ebbe3064ab80433f403" dependencies = [ + "digest 0.9.0", "ff", "group", "pairing", @@ -116,7 +129,7 @@ dependencies = [ "rand_chacha", "serde", "serde_json", - "sha2 0.9.5", + "sha2 0.9.9", "tempfile", "unicode-segmentation", "wasm-bindgen", @@ -126,17 +139,21 @@ dependencies = [ [[package]] name = "clvmr" -version = "0.1.24" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5e907612d322d0d7def6b0ecb3ad681f6af2db106bcfabe4153746c60ef9e4" +checksum = "83afaa6d5081706f202d31ed08ddb2425c902ca968d9832429bcdf9474ca6c9f" dependencies = [ "bls12_381", + "getrandom", + "group", "hex", + "k256", "lazy_static", "num-bigint", "num-integer", "num-traits", - "sha2 0.10.2", + "p256", + "sha2 0.9.9", ] [[package]] @@ -150,13 +167,10 @@ dependencies = [ ] [[package]] -name = "cpufeatures" -version = "0.1.5" +name = "const-oid" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef" -dependencies = [ - "libc", -] +checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" [[package]] name = "cpufeatures" @@ -167,6 +181,18 @@ dependencies = [ "libc", ] +[[package]] +name = "crypto-bigint" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -177,6 +203,17 @@ dependencies = [ "typenum", ] +[[package]] +name = "der" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56acb310e15652100da43d130af8d97b509e95af61aab1c5a7939ef24337ee17" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "derivative" version = "2.2.0" @@ -199,12 +236,14 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.3", + "block-buffer 0.10.4", + "const-oid", "crypto-common", + "subtle", ] [[package]] @@ -213,6 +252,40 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e16a80c1dda2cf52fa07106427d3d798b6331dca8155fcb8c39f7fc78f6dd2" +[[package]] +name = "ecdsa" +version = "0.16.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pem-rfc7468", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "encoding8" version = "0.3.2" @@ -230,9 +303,9 @@ dependencies = [ [[package]] name = "ff" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ "bitvec", "rand_core", @@ -247,19 +320,20 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" dependencies = [ "cfg-if", "js-sys", @@ -270,9 +344,9 @@ dependencies = [ [[package]] name = "group" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "rand_core", @@ -285,6 +359,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "indoc" version = "0.3.6" @@ -338,6 +421,20 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "k256" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2 0.10.7", + "signature", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -346,9 +443,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "linked-hash-map" @@ -454,9 +551,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.12.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "opaque-debug" @@ -464,11 +561,23 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2 0.10.7", +] + [[package]] name = "pairing" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135590d8bdba2b31346f9cd1fb2a912329f5135e832a4f422942eb6ead8b6b3b" +checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" dependencies = [ "group", ] @@ -517,12 +626,40 @@ dependencies = [ "proc-macro-hack", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "ppv-lite86" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +[[package]] +name = "primeorder" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c2fcef82c0ec6eefcc179b978446c399b3cdf73c392c35604e399eee6df1ee3" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -633,9 +770,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] @@ -658,6 +795,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "ryu" version = "1.0.10" @@ -676,6 +823,20 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "sec1" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "serde" version = "1.0.137" @@ -709,26 +870,36 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.5" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362ae5752fd2137731f9fa25fd4d9058af34666ca1966fb969119cc35719f12" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", "cfg-if", - "cpufeatures 0.1.5", + "cpufeatures", "digest 0.9.0", "opaque-debug", ] [[package]] name = "sha2" -version = "0.10.2" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if", - "cpufeatures 0.2.5", - "digest 0.10.6", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +dependencies = [ + "digest 0.10.7", + "rand_core", ] [[package]] @@ -737,6 +908,16 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +[[package]] +name = "spki" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "subtle" version = "2.4.1" @@ -951,3 +1132,9 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" diff --git a/Cargo.toml b/Cargo.toml index 9aae5c82e..1c5a933aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ python-source = "python" [dependencies] hex = "0.4.3" num-bigint = { version = "0.4.0", features = ["serde"] } -bls12_381 = "0.7.0" +bls12_381 = { version = "=0.8.0", features = ["experimental"] } bytestream = "0.4.1" num-traits = "0.2.14" lazy_static = "1.4.0" @@ -32,7 +32,7 @@ do-notation = "0.1.3" serde_json = "1.0" sha2 = "0.9.5" tempfile = "3.3.0" -clvmr = "0.1.24" +clvmr = { version = "0.2.6", features = ["pre-eval"] } binascii = "0.1.4" yaml-rust = "0.4" linked-hash-map = "0.5.6" diff --git a/src/classic/clvm/serialize.rs b/src/classic/clvm/serialize.rs index 95ab47c63..05246789a 100644 --- a/src/classic/clvm/serialize.rs +++ b/src/classic/clvm/serialize.rs @@ -98,9 +98,11 @@ impl<'a> Iterator for SExpToBytesIterator<'a> { fn next(&mut self) -> Option { self.state.pop().and_then(|step| match step { SExpToByteOp::Object(x) => match self.allocator.sexp(x) { - SExp::Atom(b) => { - let buf = self.allocator.buf(&b).to_vec(); - let bytes = Bytes::new(Some(BytesFromType::Raw(buf.to_vec()))); + SExp::Atom() => { + // The only node we have in scope is x, so this atom + // capture is trivial. + let buf = self.allocator.atom(x).to_vec(); + let bytes = Bytes::new(Some(BytesFromType::Raw(buf.clone()))); match atom_size_blob(&bytes) { Ok((original, b)) => { if original { diff --git a/src/classic/clvm/sexp.rs b/src/classic/clvm/sexp.rs index 2cc433912..ef730eedd 100644 --- a/src/classic/clvm/sexp.rs +++ b/src/classic/clvm/sexp.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; use std::rc::Rc; use std::string::String; -use clvm_rs::allocator::{Allocator, AtomBuf, NodePtr, SExp}; +use clvm_rs::allocator::{Allocator, NodePtr, SExp}; use clvm_rs::reduction::EvalErr; use bls12_381::G1Affine; @@ -150,7 +150,7 @@ pub fn to_sexp_type(allocator: &mut Allocator, value: CastableType) -> Result { + SExp::Atom() => { return Err(EvalErr( *target_value, "attempt to set_pair in atom".to_string(), @@ -335,7 +335,8 @@ pub fn bool_sexp(allocator: &mut Allocator, b: bool) -> NodePtr { pub fn non_nil(allocator: &mut Allocator, sexp: NodePtr) -> bool { match allocator.sexp(sexp) { SExp::Pair(_, _) => true, - SExp::Atom(b) => !b.is_empty(), + // sexp is the only node in scope, was !is_empty + SExp::Atom() => allocator.atom_len(sexp) != 0, } } @@ -353,9 +354,9 @@ pub fn rest(allocator: &mut Allocator, sexp: NodePtr) -> Result Result { +pub fn atom(allocator: &mut Allocator, sexp: NodePtr) -> Result, EvalErr> { match allocator.sexp(sexp) { - SExp::Atom(abuf) => Ok(abuf), + SExp::Atom() => Ok(allocator.atom(sexp).to_vec()), // only sexp in scope _ => Err(EvalErr(sexp, "not an atom".to_string())), } } @@ -365,7 +366,7 @@ pub fn proper_list(allocator: &mut Allocator, sexp: NodePtr, store: bool) -> Opt let mut args_sexp = sexp; loop { match allocator.sexp(args_sexp) { - SExp::Atom(_) => { + SExp::Atom() => { if !non_nil(allocator, args_sexp) { return Some(args); } else { @@ -453,10 +454,9 @@ pub fn equal_to(allocator: &mut Allocator, first_: NodePtr, second_: NodePtr) -> return true; } match (allocator.sexp(first), allocator.sexp(second)) { - (SExp::Atom(fbuf), SExp::Atom(sbuf)) => { - let fvec = allocator.buf(&fbuf); - let svec = allocator.buf(&sbuf); - return fvec == svec; + (SExp::Atom(), SExp::Atom()) => { + // two atoms in scope, both are used + return allocator.atom(first) == allocator.atom(second); } (SExp::Pair(ff, fr), SExp::Pair(rf, rr)) => { if !equal_to(allocator, ff, rf) { @@ -477,7 +477,7 @@ pub fn flatten(allocator: &mut Allocator, tree_: NodePtr, res: &mut Vec loop { match allocator.sexp(tree) { - SExp::Atom(_) => { + SExp::Atom() => { if non_nil(allocator, tree) { res.push(tree); } diff --git a/src/classic/clvm_tools/binutils.rs b/src/classic/clvm_tools/binutils.rs index 9e5e160ff..deac313cc 100644 --- a/src/classic/clvm_tools/binutils.rs +++ b/src/classic/clvm_tools/binutils.rs @@ -127,8 +127,9 @@ pub fn disassemble_to_ir_with_kw( IRRepr::Cons(Rc::new(v0), Rc::new(v1)) } - SExp::Atom(a) => { - let bytes = Bytes::new(Some(BytesFromType::Raw(allocator.buf(&a).to_vec()))); + SExp::Atom() => { + // sexp is the only node in scope. + let bytes = Bytes::new(Some(BytesFromType::Raw(allocator.atom(sexp).to_vec()))); ir_for_atom(&bytes, allow_keyword, keyword_from_atom) } } @@ -139,7 +140,7 @@ pub fn disassemble_with_kw( sexp: NodePtr, keyword_from_atom: &Record, String>, ) -> String { - let with_keywords = !matches!(allocator.sexp(sexp), SExp::Atom(_)); + let with_keywords = !matches!(allocator.sexp(sexp), SExp::Atom()); let symbols = disassemble_to_ir_with_kw(allocator, sexp, keyword_from_atom, with_keywords); write_ir(Rc::new(symbols)) } diff --git a/src/classic/clvm_tools/clvmc.rs b/src/classic/clvm_tools/clvmc.rs index 3e91ae099..322791c64 100644 --- a/src/classic/clvm_tools/clvmc.rs +++ b/src/classic/clvm_tools/clvmc.rs @@ -33,9 +33,12 @@ fn include_dialect( dialects: &HashMap, i32>, e: &[NodePtr], ) -> Option { - if let (SExp::Atom(inc), SExp::Atom(name)) = (allocator.sexp(e[0]), allocator.sexp(e[1])) { - if allocator.buf(&inc) == "include".as_bytes().to_vec() { - if let Some(dialect) = dialects.get(allocator.buf(&name)) { + // Propogated names from let capture to labeled nodes. + let inc_node = e[0]; + let name_node = e[1]; + if let (SExp::Atom(), SExp::Atom()) = (allocator.sexp(inc_node), allocator.sexp(name_node)) { + if allocator.atom(inc_node) == "include".as_bytes().to_vec() { + if let Some(dialect) = dialects.get(allocator.atom(name_node)) { return Some(*dialect); } } @@ -137,7 +140,7 @@ pub fn compile_clvm_inner( ) -> Result<(), String> { let result = compile_clvm_text( allocator, - opts, + opts.clone(), symbol_table, text, filename, diff --git a/src/classic/clvm_tools/debug.rs b/src/classic/clvm_tools/debug.rs index 761a5640f..bbed5519b 100644 --- a/src/classic/clvm_tools/debug.rs +++ b/src/classic/clvm_tools/debug.rs @@ -180,7 +180,7 @@ fn table_trace( ) { let (sexp, args) = match allocator.sexp(form) { SExp::Pair(sexp, args) => (sexp, args), - SExp::Atom(_) => (form, allocator.null()), + SExp::Atom() => (form, allocator.null()), }; stdout.write_str(&format!("exp: {}\n", disassemble_f(allocator, sexp))); diff --git a/src/classic/clvm_tools/pattern_match.rs b/src/classic/clvm_tools/pattern_match.rs index df24d3c77..0df1345cd 100644 --- a/src/classic/clvm_tools/pattern_match.rs +++ b/src/classic/clvm_tools/pattern_match.rs @@ -51,40 +51,34 @@ pub fn match_sexp( */ match (allocator.sexp(pattern), allocator.sexp(sexp)) { - (SExp::Atom(pat_buf), SExp::Atom(sexp_buf)) => { - let sexp_bytes = allocator.buf(&sexp_buf).to_vec(); - if allocator.buf(&pat_buf).to_vec() == sexp_bytes { + (SExp::Atom(), SExp::Atom()) => { + // Two nodes in scope, both used. + if allocator.atom(pattern) == allocator.atom(sexp) { Some(known_bindings) } else { None } } (SExp::Pair(pleft, pright), _) => match (allocator.sexp(pleft), allocator.sexp(pright)) { - (SExp::Atom(pat_left), SExp::Atom(pat_right)) => { - let pat_right_bytes = allocator.buf(&pat_right).to_vec(); - let pat_left_bytes = allocator.buf(&pat_left).to_vec(); - + (SExp::Atom(), SExp::Atom()) => { + let pright_atom = allocator.atom(pright).to_vec(); match allocator.sexp(sexp) { - SExp::Atom(sexp_buf) => { - let sexp_bytes = allocator.buf(&sexp_buf).to_vec(); - if pat_left_bytes == ATOM_MATCH.to_vec() { - if pat_right_bytes == ATOM_MATCH.to_vec() { - if sexp_bytes == ATOM_MATCH.to_vec() { + SExp::Atom() => { + // Expression is ($ . $), sexp is '$', result: no capture. + // Avoid double borrow. + if allocator.atom(pleft) == ATOM_MATCH { + if allocator.atom(pright) == ATOM_MATCH { + if allocator.atom(sexp) == ATOM_MATCH { return Some(HashMap::new()); } return None; } - return unify_bindings( - allocator, - known_bindings, - &pat_right_bytes, - sexp, - ); + return unify_bindings(allocator, known_bindings, &pright_atom, sexp); } - if pat_left_bytes == SEXP_MATCH.to_vec() { - if pat_right_bytes == SEXP_MATCH.to_vec() - && sexp_bytes == SEXP_MATCH.to_vec() + if allocator.atom(pleft) == SEXP_MATCH { + if allocator.atom(pright) == SEXP_MATCH + && allocator.atom(sexp) == SEXP_MATCH { return Some(HashMap::new()); } @@ -92,7 +86,8 @@ pub fn match_sexp( return unify_bindings( allocator, known_bindings, - &pat_right_bytes, + // pat_right_bytes + &pright_atom, sexp, ); } @@ -100,13 +95,14 @@ pub fn match_sexp( None } SExp::Pair(sleft, sright) => { - if pat_left_bytes == SEXP_MATCH.to_vec() - && pat_right_bytes != SEXP_MATCH.to_vec() + if allocator.atom(pleft) == SEXP_MATCH + && allocator.atom(pright) != SEXP_MATCH { return unify_bindings( allocator, known_bindings, - &pat_right_bytes, + // pat_right_bytes + &pright_atom, sexp, ); } @@ -118,11 +114,11 @@ pub fn match_sexp( } } _ => match allocator.sexp(sexp) { - SExp::Atom(_) => None, + SExp::Atom() => None, SExp::Pair(sleft, sright) => match_sexp(allocator, pleft, sleft, known_bindings) .and_then(|new_bindings| match_sexp(allocator, pright, sright, new_bindings)), }, }, - (SExp::Atom(_), _) => None, + (SExp::Atom(), _) => None, } } diff --git a/src/classic/clvm_tools/sha256tree.rs b/src/classic/clvm_tools/sha256tree.rs index 3c9986cc3..0212d0c78 100644 --- a/src/classic/clvm_tools/sha256tree.rs +++ b/src/classic/clvm_tools/sha256tree.rs @@ -34,9 +34,10 @@ pub fn sha256tree(allocator: &mut Allocator, v: NodePtr) -> Bytes { .concat(&right), ) } - SExp::Atom(a) => sha256( + SExp::Atom() => sha256( Bytes::new(Some(BytesFromType::Raw(vec![1]))).concat(&Bytes::new(Some( - BytesFromType::Raw(allocator.buf(&a).to_vec()), + // only v in scope. + BytesFromType::Raw(allocator.atom(v).to_vec()), ))), ), } diff --git a/src/classic/clvm_tools/stages/stage_0.rs b/src/classic/clvm_tools/stages/stage_0.rs index a447b90bb..6292411b1 100644 --- a/src/classic/clvm_tools/stages/stage_0.rs +++ b/src/classic/clvm_tools/stages/stage_0.rs @@ -1,9 +1,9 @@ use clvm_rs::allocator::{Allocator, NodePtr}; -use clvm_rs::chia_dialect::{ChiaDialect, NO_NEG_DIV, NO_UNKNOWN_OPS}; +use clvm_rs::chia_dialect::{ChiaDialect, ENABLE_BLS_OPS, ENABLE_SECP_OPS, NO_UNKNOWN_OPS}; use clvm_rs::cost::Cost; use clvm_rs::reduction::Response; -use clvm_rs::run_program::{run_program, PreEval}; +use clvm_rs::run_program::{run_program_with_pre_eval, PreEval}; pub struct RunProgramOption { pub max_cost: Option, @@ -45,9 +45,9 @@ impl TRunProgram for DefaultProgramRunner { ) -> Response { let max_cost = option.as_ref().and_then(|o| o.max_cost).unwrap_or(0); - run_program( + run_program_with_pre_eval( allocator, - &ChiaDialect::new(NO_NEG_DIV | NO_UNKNOWN_OPS), + &ChiaDialect::new(NO_UNKNOWN_OPS | ENABLE_BLS_OPS | ENABLE_SECP_OPS), program, args, max_cost, diff --git a/src/classic/clvm_tools/stages/stage_2/compile.rs b/src/classic/clvm_tools/stages/stage_2/compile.rs index a1866bbda..bf433bdf1 100644 --- a/src/classic/clvm_tools/stages/stage_2/compile.rs +++ b/src/classic/clvm_tools/stages/stage_2/compile.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use std::rc::Rc; -use clvm_rs::allocator::{Allocator, AtomBuf, NodePtr, SExp}; +use clvm_rs::allocator::{Allocator, NodePtr, SExp}; use clvm_rs::reduction::{EvalErr, Reduction, Response}; use crate::classic::clvm::__type_compatibility__::{Bytes, BytesFromType}; @@ -121,13 +121,14 @@ pub fn compile_qq( }; match allocator.sexp(sexp) { - SExp::Atom(_) => { + SExp::Atom() => { // (qq ATOM) => (q . ATOM) quote(allocator, sexp) } SExp::Pair(op, sexp_rest) => { - if let SExp::Atom(opbuf) = allocator.sexp(op) { - if allocator.buf(&opbuf).to_vec() == qq_atom() { + if let SExp::Atom() = allocator.sexp(op) { + // opbuf => op + if allocator.atom(op).to_vec() == qq_atom() { return m! { cons_atom <- allocator.new_atom(&[4]); subexp <- @@ -137,7 +138,8 @@ pub fn compile_qq( run_list <- enlist(allocator, &[cons_atom, op, consed]); com_qq(allocator, "qq sexp pair".to_string(), macro_lookup, symbol_table, runner, run_list) }; - } else if allocator.buf(&opbuf).to_vec() == unquote_atom() { + } else if allocator.atom(op).to_vec() == unquote_atom() { + // opbuf if level == 1 { // (qq (unquote X)) => X return m! { @@ -206,8 +208,10 @@ fn lower_quote_(allocator: &mut Allocator, prog: NodePtr) -> Result { - if allocator.buf(¯o_name).to_vec() == *operator { + SExp::Atom() => { + // was macro_name, but it's singular and probably + // not useful to rename. + if allocator.atom(mp_list[0]) == operator { return Ok(Some(value)); } } @@ -356,10 +362,10 @@ fn get_macro_program( fn transform_program_atom( allocator: &mut Allocator, prog: NodePtr, - a: &AtomBuf, + a: &[u8], symbol_table: NodePtr, ) -> Response { - if allocator.buf(a).to_vec() == "@".as_bytes().to_vec() { + if a == b"@" { return allocator .new_atom(NodePath::new(None).as_path().data()) .map(|x| Reduction(1, x)); @@ -378,8 +384,10 @@ fn transform_program_atom( let value = if v.len() > 1 { v[1] } else { allocator.null() }; match allocator.sexp(v[0]) { - SExp::Atom(s) => { - if allocator.buf(&s).to_vec() == allocator.buf(a).to_vec() { + SExp::Atom() => { + // v[0] is close by, and probably not useful to + // rename here. + if allocator.atom(v[0]) == a { return Ok(Reduction(1, value)); } } @@ -453,7 +461,7 @@ fn find_symbol_match( } match allocator.sexp(symdef[0]) { - SExp::Atom(symptr) => { + SExp::Atom() => { let symbol = symdef[0]; let value = if symdef.len() == 1 { allocator.null() @@ -461,10 +469,10 @@ fn find_symbol_match( symdef[1] }; - let symbuf = allocator.buf(&symptr).to_vec(); - if vec![b'*'] == symbuf { + let symbuf = allocator.atom(symdef[0]); + if b"*" == symbuf { return Ok(Some(SymbolResult::Direct(r))); - } else if *opname == symbuf { + } else if opname == symbuf { return Ok(Some(SymbolResult::Matched(symbol, value))); } } @@ -629,18 +637,21 @@ fn do_com_prog_( // quote atoms match allocator.sexp(prog) { - SExp::Atom(a) => { + SExp::Atom() => { + // Note: can't co-borrow with allocator below. + let prog_bytes = allocator.atom(prog).to_vec(); transform_program_atom( allocator, prog, - &a, + &prog_bytes, symbol_table ) }, SExp::Pair(operator,prog_rest) => { match allocator.sexp(operator) { - SExp::Atom(a) => { - let opbuf = allocator.buf(&a).to_vec(); + SExp::Atom() => { + // Note: can't co-borrow with allocator below. + let opbuf = allocator.atom(operator).to_vec(); get_macro_program(allocator, &opbuf, macro_lookup). and_then(|x| match x { Some(value) => { @@ -764,14 +775,16 @@ pub fn get_compile_filename( ) -> Result, EvalErr> { let cvt_prog = assemble(allocator, "(_get_compile_filename)")?; - let cvt_prog_result = runner.run_program(allocator, cvt_prog, allocator.null(), None)?; + let Reduction(_, cvt_prog_result) = + runner.run_program(allocator, cvt_prog, allocator.null(), None)?; - if cvt_prog_result.1 == allocator.null() { + if cvt_prog_result == allocator.null() { return Ok(None); } - if let SExp::Atom(buf) = allocator.sexp(cvt_prog_result.1) { - let abuf = allocator.buf(&buf).to_vec(); + if let SExp::Atom() = allocator.sexp(cvt_prog_result) { + // only cvt_prog_result in scope. + let abuf = allocator.atom(cvt_prog_result).to_vec(); return Ok(Some(Bytes::new(Some(BytesFromType::Raw(abuf))).decode())); } @@ -791,10 +804,12 @@ pub fn get_search_paths( let mut res = Vec::new(); if let Some(l) = proper_list(allocator, search_path_result.1, true) { - for elt in l.iter() { - if let SExp::Atom(buf) = allocator.sexp(*elt) { - let abuf = allocator.buf(&buf).to_vec(); - res.push(Bytes::new(Some(BytesFromType::Raw(abuf))).decode()); + for elt in l.iter().copied() { + if let SExp::Atom() = allocator.sexp(elt) { + // Only elt in scope. + res.push( + Bytes::new(Some(BytesFromType::Raw(allocator.atom(elt).to_vec()))).decode(), + ); } } } diff --git a/src/classic/clvm_tools/stages/stage_2/inline.rs b/src/classic/clvm_tools/stages/stage_2/inline.rs index c989b6ad0..e47abbf73 100644 --- a/src/classic/clvm_tools/stages/stage_2/inline.rs +++ b/src/classic/clvm_tools/stages/stage_2/inline.rs @@ -15,11 +15,11 @@ pub fn is_at_capture( tree_first: NodePtr, tree_rest: NodePtr, ) -> Option<(NodePtr, NodePtr)> { - if let (SExp::Atom(a), Some(spec)) = ( + if let (SExp::Atom(), Some(spec)) = ( allocator.sexp(tree_first), proper_list(allocator, tree_rest, true), ) { - if allocator.buf(&a) == [b'@'] && spec.len() == 2 { + if allocator.atom(tree_first) == b"@" && spec.len() == 2 { return Some((spec[0], spec[1])); } } @@ -88,7 +88,7 @@ fn formulate_path_selections_for_destructuring_arg( SExp::Pair(a, b) => { let next_depth = arg_depth.clone() * 2_u32.to_bigint().unwrap(); if let Some((capture, substructure)) = is_at_capture(allocator, a, b) { - if let SExp::Atom(cbuf) = allocator.sexp(capture) { + if let SExp::Atom() = allocator.sexp(capture) { let (new_arg_path, new_arg_depth, tail) = if let Some(prev_ref) = referenced_from { (arg_path, arg_depth, prev_ref) @@ -99,7 +99,8 @@ fn formulate_path_selections_for_destructuring_arg( (bi_zero(), bi_one(), qtail) }; - selections.insert(allocator.buf(&cbuf).to_vec(), tail); + // Was cbuf from capture. + selections.insert(allocator.atom(capture).to_vec(), tail); return formulate_path_selections_for_destructuring_arg( allocator, @@ -146,8 +147,9 @@ fn formulate_path_selections_for_destructuring_arg( ) } } - SExp::Atom(b) => { - let buf = allocator.buf(&b).to_vec(); + SExp::Atom() => { + // Note: can't co-borrow with allocator below. + let buf = allocator.atom(arg_sexp).to_vec(); if !buf.is_empty() { if let Some(capture) = referenced_from { let tail = wrap_path_selection(allocator, arg_path + arg_depth, capture)?; @@ -223,10 +225,11 @@ pub fn formulate_path_selections_for_destructuring( ) -> Result { if let SExp::Pair(a, b) = allocator.sexp(args_sexp) { if let Some((capture, substructure)) = is_at_capture(allocator, a, b) { - if let SExp::Atom(cbuf) = allocator.sexp(capture) { + if let SExp::Atom() = allocator.sexp(capture) { let quoted_arg_list = wrap_in_unquote(allocator, capture)?; let tail = wrap_in_compile_time_list(allocator, quoted_arg_list)?; - let buf = allocator.buf(&cbuf); + // Was: cbuf from capture. + let buf = allocator.atom(capture); selections.insert(buf.to_vec(), tail); let newsub = formulate_path_selections_for_destructuring_arg( allocator, diff --git a/src/classic/clvm_tools/stages/stage_2/module.rs b/src/classic/clvm_tools/stages/stage_2/module.rs index cbf134365..de8023542 100644 --- a/src/classic/clvm_tools/stages/stage_2/module.rs +++ b/src/classic/clvm_tools/stages/stage_2/module.rs @@ -144,8 +144,9 @@ fn build_used_constants_names( .collect::>(); let matching_names = matching_names_1.iter().filter_map(|v| { - if let SExp::Atom(b) = allocator.sexp(*v) { - Some(allocator.buf(&b).to_vec()) + // Only v usefully in scope. + if let SExp::Atom() = allocator.sexp(*v) { + Some(allocator.atom(*v).to_vec()) } else { None } @@ -222,8 +223,9 @@ fn unquote_args( matches: &HashMap, NodePtr>, ) -> Result { match allocator.sexp(code) { - SExp::Atom(code_buf) => { - let code_atom = allocator.buf(&code_buf); + SExp::Atom() => { + // Only code in scope. + let code_atom = allocator.atom(code); let matching_args = args .iter() .filter(|arg| *arg == code_atom) @@ -283,8 +285,9 @@ fn defun_inline_to_macro( let arg_name_list = arg_atom_list .iter() .filter_map(|x| { - if let SExp::Atom(a) = allocator.sexp(*x) { - Some(allocator.buf(&a)) + if let SExp::Atom() = allocator.sexp(*x) { + // only x usefully in scope. + Some(allocator.atom(*x)) } else { None } @@ -321,11 +324,13 @@ fn parse_mod_sexp( .select_nodes(allocator, declaration_sexp)?; let op = match allocator.sexp(op_node) { - SExp::Atom(b) => allocator.buf(&b).to_vec(), + // op_node in use. + SExp::Atom() => allocator.atom(op_node).to_vec(), _ => Vec::new(), }; let name = match allocator.sexp(name_node) { - SExp::Atom(b) => allocator.buf(&b).to_vec(), + // name_node in use. + SExp::Atom() => allocator.atom(name_node).to_vec(), _ => Vec::new(), }; @@ -540,7 +545,7 @@ fn symbol_table_for_tree( } match allocator.sexp(tree) { - SExp::Atom(_) => Ok(vec![(tree, root_node.as_path().data().to_vec())]), + SExp::Atom() => Ok(vec![(tree, root_node.as_path().data().to_vec())]), SExp::Pair(_, _) => { let left_bytes = NodePath::new(None).first(); let right_bytes = NodePath::new(None).rest(); diff --git a/src/classic/clvm_tools/stages/stage_2/operators.rs b/src/classic/clvm_tools/stages/stage_2/operators.rs index ae202bf67..c13ef1ed6 100644 --- a/src/classic/clvm_tools/stages/stage_2/operators.rs +++ b/src/classic/clvm_tools/stages/stage_2/operators.rs @@ -5,11 +5,11 @@ use std::path::PathBuf; use std::rc::Rc; use clvm_rs::allocator::{Allocator, NodePtr, SExp}; -use clvm_rs::chia_dialect::{ChiaDialect, NO_NEG_DIV, NO_UNKNOWN_OPS}; +use clvm_rs::chia_dialect::{ChiaDialect, ENABLE_BLS_OPS, ENABLE_SECP_OPS, NO_UNKNOWN_OPS}; use clvm_rs::cost::Cost; -use clvm_rs::dialect::Dialect; +use clvm_rs::dialect::{Dialect, OperatorSet}; use clvm_rs::reduction::{EvalErr, Reduction, Response}; -use clvm_rs::run_program::run_program; +use clvm_rs::run_program::run_program_with_pre_eval; use crate::classic::clvm::__type_compatibility__::{Bytes, BytesFromType, Stream}; @@ -118,7 +118,9 @@ impl Drop for CompilerOperators { impl CompilerOperatorsInternal { pub fn new(source_file: &str, search_paths: Vec, symbols_extra_info: bool) -> Self { - let base_dialect = Rc::new(ChiaDialect::new(NO_NEG_DIV | NO_UNKNOWN_OPS)); + let base_dialect = Rc::new(ChiaDialect::new( + NO_UNKNOWN_OPS | ENABLE_BLS_OPS | ENABLE_SECP_OPS, + )); let base_runner = Rc::new(DefaultProgramRunner::new()); CompilerOperatorsInternal { base_dialect, @@ -176,9 +178,9 @@ impl CompilerOperatorsInternal { match allocator.sexp(sexp) { SExp::Pair(f, _) => match allocator.sexp(f) { - SExp::Atom(b) => { + SExp::Atom() => { let filename = - Bytes::new(Some(BytesFromType::Raw(allocator.buf(&b).to_vec()))).decode(); + Bytes::new(Some(BytesFromType::Raw(allocator.atom(f).to_vec()))).decode(); // Use the read interface in CompilerOpts if we have one. if let Some(opts) = self.get_compiler_opts() { if let Ok((_, content)) = @@ -209,8 +211,8 @@ impl CompilerOperatorsInternal { fn write(&self, allocator: &mut Allocator, sexp: NodePtr) -> Response { if let SExp::Pair(filename_sexp, r) = allocator.sexp(sexp) { if let SExp::Pair(data, _) = allocator.sexp(r) { - if let SExp::Atom(filename_buf) = allocator.sexp(filename_sexp) { - let filename_buf = allocator.buf(&filename_buf); + if let SExp::Atom() = allocator.sexp(filename_sexp) { + let filename_buf = allocator.atom(filename_sexp); let filename_bytes = Bytes::new(Some(BytesFromType::Raw(filename_buf.to_vec()))); let ir = disassemble_to_ir_with_kw(allocator, data, keyword_from_atom(), true); @@ -251,9 +253,10 @@ impl CompilerOperatorsInternal { }; if let SExp::Pair(l, _r) = allocator.sexp(sexp) { - if let SExp::Atom(b) = allocator.sexp(l) { + if let SExp::Atom() = allocator.sexp(l) { + // l most relevant in scope. let filename = - Bytes::new(Some(BytesFromType::Raw(allocator.buf(&b).to_vec()))).decode(); + Bytes::new(Some(BytesFromType::Raw(allocator.atom(l).to_vec()))).decode(); // If we have a compiler opts injected, let that handle reading // files. The name will bubble up to the _read function. if self.get_compiler_opts().is_some() { @@ -284,14 +287,15 @@ impl CompilerOperatorsInternal { { for kv in symtable.iter() { if let SExp::Pair(hash, name) = allocator.sexp(*kv) { - if let (SExp::Atom(hash), SExp::Atom(name)) = + if let (SExp::Atom(), SExp::Atom()) = (allocator.sexp(hash), allocator.sexp(name)) { + // hash and name in scope. let hash_text = - Bytes::new(Some(BytesFromType::Raw(allocator.buf(&hash).to_vec()))) + Bytes::new(Some(BytesFromType::Raw(allocator.atom(hash).to_vec()))) .decode(); let name_text = - Bytes::new(Some(BytesFromType::Raw(allocator.buf(&name).to_vec()))) + Bytes::new(Some(BytesFromType::Raw(allocator.atom(name).to_vec()))) .decode(); self.compile_outcomes.replace_with(|co| { @@ -309,26 +313,39 @@ impl CompilerOperatorsInternal { } impl Dialect for CompilerOperatorsInternal { - fn val_stack_limit(&self) -> usize { - 10000000 - } fn quote_kw(&self) -> &[u8] { &[1] } + fn apply_kw(&self) -> &[u8] { &[2] } + fn softfork_kw(&self) -> &[u8] { + &[36] + } + + // The softfork operator comes with an extension argument. + fn softfork_extension(&self, ext: u32) -> OperatorSet { + match ext { + 0 => OperatorSet::BLS, + // new extensions go here + _ => OperatorSet::Default, + } + } + fn op( &self, allocator: &mut Allocator, op: NodePtr, sexp: NodePtr, max_cost: Cost, + _extension: OperatorSet, ) -> Response { match allocator.sexp(op) { - SExp::Atom(opname) => { - let opbuf = allocator.buf(&opname); + SExp::Atom() => { + // use of op obvious. + let opbuf = allocator.atom(op); if opbuf == "_read".as_bytes() { self.read(allocator, sexp) } else if opbuf == "_write".as_bytes() { @@ -350,12 +367,19 @@ impl Dialect for CompilerOperatorsInternal { } else if opbuf == "_get_source_file".as_bytes() { self.get_source_file(allocator) } else { - self.base_dialect.op(allocator, op, sexp, max_cost) + self.base_dialect + .op(allocator, op, sexp, max_cost, OperatorSet::BLS) } } - _ => self.base_dialect.op(allocator, op, sexp, max_cost), + _ => self + .base_dialect + .op(allocator, op, sexp, max_cost, OperatorSet::BLS), } } + + fn allow_unknown_ops(&self) -> bool { + false + } } impl CompilerOperatorsInternal { @@ -383,7 +407,7 @@ impl TRunProgram for CompilerOperatorsInternal { option: Option, ) -> Response { let max_cost = option.as_ref().and_then(|o| o.max_cost).unwrap_or(0); - run_program( + run_program_with_pre_eval( allocator, self, program, diff --git a/src/classic/clvm_tools/stages/stage_2/optimize.rs b/src/classic/clvm_tools/stages/stage_2/optimize.rs index 7fde38552..5e1e2306d 100644 --- a/src/classic/clvm_tools/stages/stage_2/optimize.rs +++ b/src/classic/clvm_tools/stages/stage_2/optimize.rs @@ -41,7 +41,7 @@ pub fn seems_constant_tail(allocator: &mut Allocator, sexp_: NodePtr) -> bool { sexp = r; } - SExp::Atom(_) => { + SExp::Atom() => { return sexp == allocator.null(); } } @@ -50,13 +50,14 @@ pub fn seems_constant_tail(allocator: &mut Allocator, sexp_: NodePtr) -> bool { pub fn seems_constant(allocator: &mut Allocator, sexp: NodePtr) -> bool { match allocator.sexp(sexp) { - SExp::Atom(_b) => { + SExp::Atom() => { return sexp == allocator.null(); } SExp::Pair(operator, r) => { match allocator.sexp(operator) { - SExp::Atom(b) => { - let atom = allocator.buf(&b); + SExp::Atom() => { + // Was buf of operator. + let atom = allocator.atom(operator); if atom.len() == 1 && atom[0] == 1 { return true; } else if atom.len() == 1 && atom[0] == 8 { @@ -91,8 +92,9 @@ pub fn constant_optimizer( * return the quoted result. */ if let SExp::Pair(first, _) = allocator.sexp(r) { - if let SExp::Atom(b) = allocator.sexp(first) { - let buf = allocator.buf(&b); + // first relevant in scope. + if let SExp::Atom() = allocator.sexp(first) { + let buf = allocator.atom(first); if buf.len() == 1 && buf[0] == 1 { // Short circuit already quoted expression. return Ok(r); @@ -135,8 +137,9 @@ pub fn constant_optimizer( } pub fn is_args_call(allocator: &mut Allocator, r: NodePtr) -> bool { - if let SExp::Atom(b) = allocator.sexp(r) { - let buf = allocator.buf(&b); + if let SExp::Atom() = allocator.sexp(r) { + // Only r in scope. + let buf = allocator.atom(r); buf.len() == 1 && buf[0] == 1 } else { false @@ -217,8 +220,9 @@ fn path_from_args( new_args: NodePtr, ) -> Result { match allocator.sexp(sexp) { - SExp::Atom(v_buf) => { - let v = number_from_u8(allocator.buf(&v_buf)); + SExp::Atom() => { + // Only sexp in scope. + let v = number_from_u8(allocator.atom(sexp)); if v <= bi_one() { Ok(new_args) } else { @@ -242,7 +246,7 @@ pub fn sub_args( new_args: NodePtr, ) -> Result { match allocator.sexp(sexp) { - SExp::Atom(_) => path_from_args(allocator, sexp, new_args), + SExp::Atom() => path_from_args(allocator, sexp, new_args), SExp::Pair(first_pre, rest) => { let first; @@ -250,8 +254,9 @@ pub fn sub_args( SExp::Pair(_, _) => { first = sub_args(allocator, first_pre, new_args)?; } - SExp::Atom(b) => { - let atom = allocator.buf(&b); + SExp::Atom() => { + // Atom is a reflection of first_pre. + let atom = allocator.atom(first_pre); if atom.len() == 1 && atom[0] == 1 { return Ok(sexp); } else { @@ -369,8 +374,9 @@ pub fn var_change_optimizer_cons_eval( } let increment = match allocator.sexp(val) { SExp::Pair(val_first, _) => match allocator.sexp(val_first) { - SExp::Atom(b) => { - let vf_buf = allocator.buf(&b); + SExp::Atom() => { + // Atom reflects val_first. + let vf_buf = allocator.atom(val_first); (vf_buf.len() != 1 || vf_buf[0] != 1) as i32 } _ => 0, @@ -413,8 +419,8 @@ pub fn children_optimizer( if list.is_empty() { return Ok(r); } - if let SExp::Atom(op_buf) = allocator.sexp(list[0]) { - if allocator.buf(&op_buf).to_vec() == vec![1] { + if let SExp::Atom() = allocator.sexp(list[0]) { + if allocator.atom(list[0]).to_vec() == vec![1] { return Ok(r); } } @@ -518,7 +524,7 @@ fn path_optimizer( match first. get("atom"). and_then(|a| atom(allocator, *a).ok()). - map(|atom| number_from_u8(allocator.buf(&atom))) + map(|atom| number_from_u8(&atom)) { Some(atom) => { let node = @@ -533,7 +539,7 @@ fn path_optimizer( match rest. get("atom"). and_then(|a| atom(allocator, *a).ok()). - map(|atom| number_from_u8(allocator.buf(&atom))) + map(|atom| number_from_u8(&atom)) { Some(atom) => { let node = @@ -677,7 +683,7 @@ pub fn optimize_sexp_( let mut name = "".to_string(); match allocator.sexp(r) { - SExp::Atom(_) => { + SExp::Atom() => { return Ok(r); } SExp::Pair(_, _) => { diff --git a/src/classic/clvm_tools/stages/stage_2/reader.rs b/src/classic/clvm_tools/stages/stage_2/reader.rs index 0ff21e906..bc91c89b4 100644 --- a/src/classic/clvm_tools/stages/stage_2/reader.rs +++ b/src/classic/clvm_tools/stages/stage_2/reader.rs @@ -90,16 +90,16 @@ pub fn process_embed_file( )); } - if let (SExp::Atom(name), SExp::Atom(kind), SExp::Atom(filename)) = ( + if let (SExp::Atom(), SExp::Atom(), SExp::Atom()) = ( allocator.sexp(l[0]), allocator.sexp(l[1]), allocator.sexp(l[2]), ) { // Note: we don't want to keep borrowing here because we // need the mutable borrow below. - let name_buf = allocator.buf(&name).to_vec(); - let kind_buf = allocator.buf(&kind).to_vec(); - let filename_buf = allocator.buf(&filename).to_vec(); + let name_buf = allocator.atom(l[0]).to_vec(); + let kind_buf = allocator.atom(l[1]); + let filename_buf = allocator.atom(l[2]).to_vec(); let file_data = if kind_buf == b"bin" { let file = read_file( runner, @@ -128,7 +128,7 @@ pub fn process_embed_file( return Err(EvalErr(declaration_sexp, "no such embed kind".to_string())); }; - Ok((name_buf, quote(allocator, file_data)?)) + Ok((name_buf.to_vec(), quote(allocator, file_data)?)) } else { Err(EvalErr( declaration_sexp, diff --git a/src/compiler/clvm.rs b/src/compiler/clvm.rs index eaa6e9a4e..dd4ad017c 100644 --- a/src/compiler/clvm.rs +++ b/src/compiler/clvm.rs @@ -242,11 +242,11 @@ pub fn convert_from_clvm_rs( head: NodePtr, ) -> Result, RunFailure> { match allocator.sexp(head) { - allocator::SExp::Atom(h) => { - if h.is_empty() { + allocator::SExp::Atom() => { + let atom_data = allocator.atom(head); + if atom_data.is_empty() { Ok(Rc::new(SExp::Nil(loc))) } else { - let atom_data = allocator.buf(&h); let integer = number_from_u8(atom_data); // Ensure that atom values that don't evaluate equal to integers // are represented faithfully as atoms. diff --git a/src/tests/classic/smoke.rs b/src/tests/classic/smoke.rs index e7a7d6639..bb4b2e680 100644 --- a/src/tests/classic/smoke.rs +++ b/src/tests/classic/smoke.rs @@ -1,5 +1,6 @@ use num_bigint::ToBigInt; +use std::collections::HashMap; use std::fs; use std::io; use std::path::PathBuf; @@ -20,9 +21,11 @@ use crate::classic::clvm_tools::binutils::{assemble, assemble_from_ir, disassemb use crate::classic::clvm_tools::ir::r#type::IRRepr; use crate::classic::clvm_tools::ir::reader::read_ir; use crate::classic::clvm_tools::node_path::NodePath; +use crate::classic::clvm_tools::pattern_match::match_sexp; use crate::classic::clvm_tools::stages; use crate::classic::clvm_tools::stages::stage_0::{DefaultProgramRunner, TRunProgram}; use crate::classic::clvm_tools::stages::stage_2::operators::run_program_for_search_paths; +use crate::classic::clvm_tools::stages::stage_2::optimize::sub_args; use crate::classic::platform::argparse::{ Argument, ArgumentParser, NArgsSpec, TArgumentParserProps, }; @@ -139,8 +142,8 @@ fn mid_negative_value_bin() { Box::new(SimpleCreateCLVMObject {}), ) .expect("should be able to make nodeptr"); - if let SExp::Atom(abuf) = allocator.sexp(atom.1) { - let res_bytes = allocator.buf(&abuf); + if let SExp::Atom() = allocator.sexp(atom.1) { + let res_bytes = allocator.atom(atom.1); assert_eq!(res_bytes, &[0xff, 0xff]); } else { assert!(false); @@ -267,8 +270,8 @@ fn can_run_from_source_nil() { let mut allocator = Allocator::new(); let res = run_from_source(&mut allocator, "()".to_string()); match allocator.sexp(res) { - SExp::Atom(b) => { - let res_bytes = allocator.buf(&b).to_vec(); + SExp::Atom() => { + let res_bytes = allocator.atom(res); assert_eq!(res_bytes.len(), 0); } _ => { @@ -282,8 +285,8 @@ fn can_echo_quoted_nil() { let mut allocator = Allocator::new(); let res = run_from_source(&mut allocator, "(1)".to_string()); match allocator.sexp(res) { - SExp::Atom(b) => { - let res_bytes = allocator.buf(&b).to_vec(); + SExp::Atom() => { + let res_bytes = allocator.atom(res); assert_eq!(res_bytes.len(), 0); } _ => { @@ -313,8 +316,8 @@ fn can_echo_quoted_atom() { let mut allocator = Allocator::new(); let res = run_from_source(&mut allocator, "(1 . 3)".to_string()); match allocator.sexp(res) { - SExp::Atom(b) => { - let res_bytes = allocator.buf(&b).to_vec(); + SExp::Atom() => { + let res_bytes = allocator.atom(res); assert_eq!(res_bytes.len(), 1); assert_eq!(res_bytes[0], 3); } @@ -329,8 +332,8 @@ fn can_do_operations() { let mut allocator = Allocator::new(); let res = run_from_source(&mut allocator, "(16 (1 . 3) (1 . 5))".to_string()); match allocator.sexp(res) { - SExp::Atom(b) => { - let res_bytes = allocator.buf(&b).to_vec(); + SExp::Atom() => { + let res_bytes = allocator.atom(res); assert_eq!(res_bytes.len(), 1); assert_eq!(res_bytes[0], 8); } @@ -345,8 +348,8 @@ fn can_do_operations_kw() { let mut allocator = Allocator::new(); let res = run_from_source(&mut allocator, "(+ (q . 3) (q . 5))".to_string()); match allocator.sexp(res) { - SExp::Atom(b) => { - let res_bytes = allocator.buf(&b).to_vec(); + SExp::Atom() => { + let res_bytes = allocator.atom(res); assert_eq!(res_bytes.len(), 1); assert_eq!(res_bytes[0], 8); } @@ -770,3 +773,37 @@ fn test_bytes_to_pybytes_repr_0() { "b'\\x11\\x01abc\\r\\ntest\\ttest\\r\\n'" ); } + +#[test] +fn test_pattern_match_dollar_for_dollar() { + let mut allocator = Allocator::new(); + let pattern = assemble(&mut allocator, "($ . $)").expect("should assemble"); + let target_expr = assemble(&mut allocator, "$").expect("should assemble"); + let empty_map = HashMap::new(); + let matched = match_sexp(&mut allocator, pattern, target_expr, empty_map.clone()); + // Returns empty map. + assert_eq!(Some(empty_map), matched); +} + +#[test] +fn test_pattern_match_colon_for_colon() { + let mut allocator = Allocator::new(); + let pattern = assemble(&mut allocator, "(: . :)").expect("should assemble"); + let target_expr = assemble(&mut allocator, ":").expect("should assemble"); + let empty_map = HashMap::new(); + let matched = match_sexp(&mut allocator, pattern, target_expr, empty_map.clone()); + // Returns empty map. + assert_eq!(Some(empty_map), matched); +} + +#[test] +fn test_sub_args() { + let mut allocator = Allocator::new(); + let expr_sexp = assemble(&mut allocator, "(body 2 5)").expect("should assemble"); + let new_args = assemble(&mut allocator, "(test1 test2)").expect("should assemble"); + let result = sub_args(&mut allocator, expr_sexp, new_args).expect("should run"); + assert_eq!( + disassemble(&mut allocator, result), + "(\"body\" (f (\"test1\" \"test2\")) (f (r (\"test1\" \"test2\"))))" + ); +} diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 9c0b27d34..1b4343cb0 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -42,23 +42,28 @@ dependencies = [ ] [[package]] -name = "block-buffer" -version = "0.10.3" +name = "bls12_381" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +checksum = "62250ece575fa9b22068b3a8d59586f01d426dd7785522efd97632959e71c986" dependencies = [ - "generic-array", + "ff 0.12.1", + "group 0.12.1", + "pairing 0.22.0", + "rand_core", + "subtle", ] [[package]] name = "bls12_381" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62250ece575fa9b22068b3a8d59586f01d426dd7785522efd97632959e71c986" +checksum = "d7bc6d6292be3a19e6379786dac800f551e5865a5bb51ebbe3064ab80433f403" dependencies = [ - "ff", - "group", - "pairing", + "digest", + "ff 0.13.0", + "group 0.13.0", + "pairing 0.23.0", "rand_core", "subtle", ] @@ -95,7 +100,7 @@ name = "clvm_tools_rs" version = "0.1.34" dependencies = [ "binascii", - "bls12_381", + "bls12_381 0.7.0", "bytestream", "clvmr", "derivative", @@ -114,7 +119,7 @@ dependencies = [ "pyo3-build-config 0.15.2", "serde", "serde_json", - "sha2 0.9.9", + "sha2", "tempfile", "unicode-segmentation", "wasm-bindgen", @@ -135,17 +140,18 @@ dependencies = [ [[package]] name = "clvmr" -version = "0.1.24" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5e907612d322d0d7def6b0ecb3ad681f6af2db106bcfabe4153746c60ef9e4" +checksum = "d234802ce73011e01f7019ef5701df1f9bffad9326d7d0a6dbca8d4b7591f083" dependencies = [ - "bls12_381", + "bls12_381 0.8.0", + "group 0.13.0", "hex", "lazy_static", "num-bigint", "num-integer", "num-traits", - "sha2 0.10.2", + "sha2", ] [[package]] @@ -167,16 +173,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - [[package]] name = "derivative" version = "2.2.0" @@ -197,16 +193,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "digest" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" -dependencies = [ - "block-buffer 0.10.3", - "crypto-common", -] - [[package]] name = "do-notation" version = "0.1.3" @@ -239,6 +225,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "bitvec", + "rand_core", + "subtle", +] + [[package]] name = "funty" version = "2.0.0" @@ -274,7 +271,18 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ - "ff", + "ff 0.12.1", + "rand_core", + "subtle", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff 0.13.0", "rand_core", "subtle", ] @@ -470,7 +478,16 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "135590d8bdba2b31346f9cd1fb2a912329f5135e832a4f422942eb6ead8b6b3b" dependencies = [ - "group", + "group 0.12.1", +] + +[[package]] +name = "pairing" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" +dependencies = [ + "group 0.13.0", ] [[package]] @@ -683,24 +700,13 @@ version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ - "block-buffer 0.9.0", + "block-buffer", "cfg-if", "cpufeatures", - "digest 0.9.0", + "digest", "opaque-debug", ] -[[package]] -name = "sha2" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.5", -] - [[package]] name = "smallvec" version = "1.10.0" diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index 703831506..4388b2dc0 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -18,7 +18,7 @@ path = "src/mod.rs" [dependencies] clvm_tools_rs = { path= "..", features = [] } -clvmr = "0.1.24" +clvmr = { version = "0.2.5", features = ["pre-eval"] } wasm-bindgen = "=0.2.83" wasm-bindgen-test = "=0.3.25" js-sys = "0.3.60" From 2d3a899a670cab2c7ce058a6839c1e6da7d0b13d Mon Sep 17 00:00:00 2001 From: arty Date: Fri, 28 Jul 2023 13:36:39 -0700 Subject: [PATCH 50/75] Pass through op extension --- src/classic/clvm_tools/stages/stage_2/operators.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/classic/clvm_tools/stages/stage_2/operators.rs b/src/classic/clvm_tools/stages/stage_2/operators.rs index c13ef1ed6..2d281c20a 100644 --- a/src/classic/clvm_tools/stages/stage_2/operators.rs +++ b/src/classic/clvm_tools/stages/stage_2/operators.rs @@ -340,7 +340,7 @@ impl Dialect for CompilerOperatorsInternal { op: NodePtr, sexp: NodePtr, max_cost: Cost, - _extension: OperatorSet, + extension: OperatorSet, ) -> Response { match allocator.sexp(op) { SExp::Atom() => { @@ -368,12 +368,12 @@ impl Dialect for CompilerOperatorsInternal { self.get_source_file(allocator) } else { self.base_dialect - .op(allocator, op, sexp, max_cost, OperatorSet::BLS) + .op(allocator, op, sexp, max_cost, extension) } } _ => self .base_dialect - .op(allocator, op, sexp, max_cost, OperatorSet::BLS), + .op(allocator, op, sexp, max_cost, extension), } } From 9283c63b30ff77254e20cd68481ba7105de5d606 Mon Sep 17 00:00:00 2001 From: arty Date: Fri, 28 Jul 2023 14:05:53 -0700 Subject: [PATCH 51/75] Merge, update interface --- src/classic/clvm_tools/stages/stage_2/operators.rs | 3 ++- src/tests/classic/stage_2.rs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/classic/clvm_tools/stages/stage_2/operators.rs b/src/classic/clvm_tools/stages/stage_2/operators.rs index c13ef1ed6..95406eae9 100644 --- a/src/classic/clvm_tools/stages/stage_2/operators.rs +++ b/src/classic/clvm_tools/stages/stage_2/operators.rs @@ -27,6 +27,7 @@ use crate::classic::clvm_tools::stages::stage_2::compile::do_com_prog_for_dialec use crate::classic::clvm_tools::stages::stage_2::optimize::do_optimize; use crate::compiler::comptypes::CompilerOpts; +use crate::compiler::sexp::decode_string; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum AllocatorRefOrTreeHash { @@ -186,7 +187,7 @@ impl CompilerOperatorsInternal { if let Ok((_, content)) = opts.read_new_file(self.source_file.clone(), filename.clone()) { - return parse_file_content(allocator, &content); + return parse_file_content(allocator, &decode_string(&content)); } } diff --git a/src/tests/classic/stage_2.rs b/src/tests/classic/stage_2.rs index 0d80b005a..78a019cd6 100644 --- a/src/tests/classic/stage_2.rs +++ b/src/tests/classic/stage_2.rs @@ -371,9 +371,9 @@ impl CompilerOpts for TestCompilerOptsPresentsOwnFiles { &self, inc_from: String, filename: String, - ) -> Result<(String, String), CompileErr> { + ) -> Result<(String, Vec), CompileErr> { if let Some(content) = self.files.get(&filename) { - return Ok((filename.clone(), content.clone())); + return Ok((filename.clone(), content.bytes().collect())); } Err(CompileErr( From f92cf5506fe9260a2487147c232729315ecca88a Mon Sep 17 00:00:00 2001 From: arty Date: Fri, 28 Jul 2023 14:24:44 -0700 Subject: [PATCH 52/75] Add more comments --- src/compiler/comptypes.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/compiler/comptypes.rs b/src/compiler/comptypes.rs index 799ac4318..3fb715514 100644 --- a/src/compiler/comptypes.rs +++ b/src/compiler/comptypes.rs @@ -231,8 +231,11 @@ pub enum HelperForm { /// To what purpose is the file included. #[derive(Clone, Debug, PartialEq, Eq, Serialize)] pub enum IncludeProcessType { + /// Include the bytes on disk as an atom. Bin, + /// Parse the hex on disk and present it as a clvm value. Hex, + /// Read clvm in s-expression form as a clvm value. SExpression, } From b113c8c003c0ee71710cd4a139a6b6a17574c137 Mon Sep 17 00:00:00 2001 From: arty Date: Fri, 28 Jul 2023 14:26:01 -0700 Subject: [PATCH 53/75] Fix error string --- src/compiler/preprocessor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/preprocessor.rs b/src/compiler/preprocessor.rs index ed3ae4209..3f760a87d 100644 --- a/src/compiler/preprocessor.rs +++ b/src/compiler/preprocessor.rs @@ -100,7 +100,7 @@ fn process_embed( let parsed = parse_sexp(Srcloc::start(&full_name), content.iter().copied()) .map_err(|e| CompileErr(e.0, e.1))?; if parsed.len() != 1 { - return Err(CompileErr(loc, format!("More than one form in {fname}"))); + return Err(CompileErr(loc, format!("More than one form (or empty data) in {fname}"))); } parsed[0].clone() From b27d63fc3441a2dc86853d675ed9f1871469273a Mon Sep 17 00:00:00 2001 From: arty Date: Fri, 28 Jul 2023 14:28:44 -0700 Subject: [PATCH 54/75] Add comment --- src/compiler/preprocessor.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/compiler/preprocessor.rs b/src/compiler/preprocessor.rs index 3f760a87d..8470bb63e 100644 --- a/src/compiler/preprocessor.rs +++ b/src/compiler/preprocessor.rs @@ -164,6 +164,10 @@ fn process_pp_form( } } + // Accepted forms: + // (embed-file varname bin file.dat) + // (embed-file varname sexp file.clvm) + // (embed-file varname hex file.hex) [SExp::Atom(kl, embed_file), SExp::Atom(_, name), SExp::Atom(_, kind), SExp::Atom(nl, fname)] => { if embed_file == b"embed-file" { if kind == b"hex" { From 57adf26366f335cca9f1cacb722e8ea2927322ba Mon Sep 17 00:00:00 2001 From: arty Date: Fri, 28 Jul 2023 14:30:07 -0700 Subject: [PATCH 55/75] use brun -n --- src/tests/classic/run.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/classic/run.rs b/src/tests/classic/run.rs index ba86e53ce..011306c3f 100644 --- a/src/tests/classic/run.rs +++ b/src/tests/classic/run.rs @@ -577,10 +577,10 @@ fn test_embed_file_5() { ]) .trim() .to_string(); - let run_result = do_basic_brun(&vec!["brun".to_string(), program, "()".to_string()]) + let run_result = do_basic_brun(&vec!["brun".to_string(), "-n".to_string(), program, "()".to_string()]) .trim() .to_string(); - assert_eq!(run_result, "(lsh 24 25)"); + assert_eq!(run_result, "(23 24 25)"); } #[test] From 7ae094c031545d56fd9f73536609dcad154c22d4 Mon Sep 17 00:00:00 2001 From: arty Date: Fri, 28 Jul 2023 14:31:31 -0700 Subject: [PATCH 56/75] fmt + clippy --- src/compiler/preprocessor.rs | 5 ++++- src/tests/classic/run.rs | 11 ++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/compiler/preprocessor.rs b/src/compiler/preprocessor.rs index 8470bb63e..640f90b4b 100644 --- a/src/compiler/preprocessor.rs +++ b/src/compiler/preprocessor.rs @@ -100,7 +100,10 @@ fn process_embed( let parsed = parse_sexp(Srcloc::start(&full_name), content.iter().copied()) .map_err(|e| CompileErr(e.0, e.1))?; if parsed.len() != 1 { - return Err(CompileErr(loc, format!("More than one form (or empty data) in {fname}"))); + return Err(CompileErr( + loc, + format!("More than one form (or empty data) in {fname}"), + )); } parsed[0].clone() diff --git a/src/tests/classic/run.rs b/src/tests/classic/run.rs index 011306c3f..93e096f80 100644 --- a/src/tests/classic/run.rs +++ b/src/tests/classic/run.rs @@ -577,9 +577,14 @@ fn test_embed_file_5() { ]) .trim() .to_string(); - let run_result = do_basic_brun(&vec!["brun".to_string(), "-n".to_string(), program, "()".to_string()]) - .trim() - .to_string(); + let run_result = do_basic_brun(&vec![ + "brun".to_string(), + "-n".to_string(), + program, + "()".to_string(), + ]) + .trim() + .to_string(); assert_eq!(run_result, "(23 24 25)"); } From 9974849cfb0de46356d998f09fd3c2d3ffa5a245 Mon Sep 17 00:00:00 2001 From: arty Date: Mon, 31 Jul 2023 00:47:30 -0700 Subject: [PATCH 57/75] Add test matrix --- src/tests/classic/embed.rs | 81 ++++++++++++++++++++++++++++++++++++++ src/tests/classic/mod.rs | 1 + src/tests/classic/run.rs | 4 +- 3 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 src/tests/classic/embed.rs diff --git a/src/tests/classic/embed.rs b/src/tests/classic/embed.rs new file mode 100644 index 000000000..11fc126e6 --- /dev/null +++ b/src/tests/classic/embed.rs @@ -0,0 +1,81 @@ +use crate::tests::classic::run::{do_basic_brun, do_basic_run}; + +const EMBED_BIN_FILE: &str = "hello.bin"; +const EMBED_HEX_FILE: &str = "hex-embed-01.hex"; +const EMBED_SEXP_FILE: &str = "embed.sexp"; +const EMBED_NOT_EXIST: &str = "not-exist.txt"; + +const BIN_HASH: &str = "0xcceeb7a985ecc3dabcb4c8f666cd637f16f008e3c963db6aa6f83a7b288c54ef"; // sha256(b'\x01hello') +const HEX_HASH: &str = "0xd59489bcba845c9a04cde90e94ae0cb1efaa81befcd3a9b6603a5fa6f8327bef"; // (mod () (include sha256tree.clib) (sha256tree (q 65 66 67))) +const SEXP_HASH: &str = "0x392f4227bfc31a238b4738b0b0c7f10afb1a55c674286bc99cf89b4b22610aba"; // '(mod () (include sha256tree.clib) (sha256tree (q 23 24 25)))' + +const BIN_TYPE: &str = "bin"; +const HEX_TYPE: &str = "hex"; +const SEXP_TYPE: &str = "sexp"; + +// Embed test matrix (suggested) +// Exists, NotExists vs Bin, Hex, Sexp vs Modern, Classic +// - Exists +// - Bin Modern +// - Bin Classic +// - Hex Modern +// - Hex Classic +// - Sexp Modern +// - Sexp Classic +// - NotExists +// - Bin Modern +// - Bin Classic +// - Hex Modern +// - Hex Classic +// - Sexp Modern +// - Sexp Classic +#[test] +fn test_embed_exhaustive() { + let include_list = &[ + (BIN_TYPE, EMBED_BIN_FILE, BIN_HASH), + (HEX_TYPE, EMBED_HEX_FILE, HEX_HASH), + (SEXP_TYPE, EMBED_SEXP_FILE, SEXP_HASH), + ]; + + for exists in 0..=1 { + for (include_kind, include_file, want_hash) in include_list.iter() { + for modern in 0..=1 { + let modern_sigil = + if modern > 0 { + "(include *standard-cl-21*)" + } else { + "" + }; + let filename = + if exists > 0 { + include_file + } else { + EMBED_NOT_EXIST + }; + + let program = format!("(mod () {modern_sigil} (include sha256tree.clib) (embed-file embedded-data {include_kind} {filename}) (sha256tree embedded-data))"); + let compiled = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + program, + ]); + + if exists > 0 { + let output = do_basic_brun(&vec![ + "brun".to_string(), + compiled, + "()".to_string() + ]).trim().to_string(); + assert_eq!(want_hash, &output); + } else { + if modern > 0 { + assert!(compiled.contains("could not find not-exist.txt")); + } else { + assert!(compiled.starts_with("FAIL:")); + } + } + } + } + } +} diff --git a/src/tests/classic/mod.rs b/src/tests/classic/mod.rs index 7b505ccf2..1a83a2eda 100644 --- a/src/tests/classic/mod.rs +++ b/src/tests/classic/mod.rs @@ -1,4 +1,5 @@ mod clvmc; +mod embed; mod optimize; pub mod run; mod smoke; diff --git a/src/tests/classic/run.rs b/src/tests/classic/run.rs index 93e096f80..ad858ffe7 100644 --- a/src/tests/classic/run.rs +++ b/src/tests/classic/run.rs @@ -29,13 +29,13 @@ use crate::util::{number_from_u8, Number}; const NUM_GEN_ATOMS: usize = 16; -fn do_basic_brun(args: &Vec) -> String { +pub fn do_basic_brun(args: &Vec) -> String { let mut s = Stream::new(None); launch_tool(&mut s, args, &"run".to_string(), 0); return s.get_value().decode(); } -fn do_basic_run(args: &Vec) -> String { +pub fn do_basic_run(args: &Vec) -> String { let mut s = Stream::new(None); launch_tool(&mut s, args, &"run".to_string(), 2); return s.get_value().decode(); From 0f8b56d9f652ff07895781ca454520d1a2babbe9 Mon Sep 17 00:00:00 2001 From: arty Date: Mon, 31 Jul 2023 00:48:06 -0700 Subject: [PATCH 58/75] fmt + clippy --- src/tests/classic/embed.rs | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/tests/classic/embed.rs b/src/tests/classic/embed.rs index 11fc126e6..5267594b5 100644 --- a/src/tests/classic/embed.rs +++ b/src/tests/classic/embed.rs @@ -40,18 +40,16 @@ fn test_embed_exhaustive() { for exists in 0..=1 { for (include_kind, include_file, want_hash) in include_list.iter() { for modern in 0..=1 { - let modern_sigil = - if modern > 0 { - "(include *standard-cl-21*)" - } else { - "" - }; - let filename = - if exists > 0 { - include_file - } else { - EMBED_NOT_EXIST - }; + let modern_sigil = if modern > 0 { + "(include *standard-cl-21*)" + } else { + "" + }; + let filename = if exists > 0 { + include_file + } else { + EMBED_NOT_EXIST + }; let program = format!("(mod () {modern_sigil} (include sha256tree.clib) (embed-file embedded-data {include_kind} {filename}) (sha256tree embedded-data))"); let compiled = do_basic_run(&vec![ @@ -62,11 +60,10 @@ fn test_embed_exhaustive() { ]); if exists > 0 { - let output = do_basic_brun(&vec![ - "brun".to_string(), - compiled, - "()".to_string() - ]).trim().to_string(); + let output = + do_basic_brun(&vec!["brun".to_string(), compiled, "()".to_string()]) + .trim() + .to_string(); assert_eq!(want_hash, &output); } else { if modern > 0 { From 5c2cd8a78e04cda8bf655cc80d5aa7e4ce1b57fa Mon Sep 17 00:00:00 2001 From: Earle Lowe <30607889+emlowe@users.noreply.github.com> Date: Mon, 31 Jul 2023 08:03:30 -0700 Subject: [PATCH 59/75] Change macOS target to macOS 11 Update MACOSX_DEPLOYMENT_TARGET to 11 --- .github/workflows/build-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 24a3522d6..bec2dfb87 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -48,7 +48,7 @@ jobs: - name: Build MacOs with maturin on Python ${{ matrix.python }} if: startsWith(matrix.os, 'macos') env: - MACOSX_DEPLOYMENT_TARGET: '10.14' + MACOSX_DEPLOYMENT_TARGET: '11' run: | python -m venv venv ln -s venv/bin/activate From e1bd823108a43d618c1f37ad6463af9c14688223 Mon Sep 17 00:00:00 2001 From: Earle Lowe <30607889+emlowe@users.noreply.github.com> Date: Mon, 31 Jul 2023 08:33:28 -0700 Subject: [PATCH 60/75] Remove python 3.7 ; add 3.11 --- .github/workflows/build-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index bec2dfb87..08cdaa45d 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -20,7 +20,7 @@ jobs: fail-fast: false matrix: os: [macos-latest, ubuntu-latest, windows-latest] - python: [3.7, 3.8, 3.9, '3.10'] + python: [3.8, 3.9, 3.10, 3.11] steps: - uses: actions/checkout@v3 From eb5b4999951d675695ec98e4a0980012685cc43c Mon Sep 17 00:00:00 2001 From: Earle Lowe <30607889+emlowe@users.noreply.github.com> Date: Mon, 31 Jul 2023 08:48:14 -0700 Subject: [PATCH 61/75] Update build-test.yml --- .github/workflows/build-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 08cdaa45d..3764d4626 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -48,7 +48,7 @@ jobs: - name: Build MacOs with maturin on Python ${{ matrix.python }} if: startsWith(matrix.os, 'macos') env: - MACOSX_DEPLOYMENT_TARGET: '11' + MACOSX_DEPLOYMENT_TARGET: 11 run: | python -m venv venv ln -s venv/bin/activate From b98a8181d09b98f10aa6aed060d9365181d8738c Mon Sep 17 00:00:00 2001 From: Earle Lowe <30607889+emlowe@users.noreply.github.com> Date: Mon, 31 Jul 2023 08:51:19 -0700 Subject: [PATCH 62/75] Update build-test.yml --- .github/workflows/build-test.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 3764d4626..51977f934 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -86,7 +86,7 @@ jobs: touch target/release/.cargo-lock - name: Build alpine wheel via docker - if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.7') + if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.8') run: | cd resources/alpine && docker build -t clvm-tools-rs-alpine . docker run -v ${GITHUB_WORKSPACE}:/root/clvm_tools_rs -t clvm-tools-rs-alpine sh /root/build-alpine.sh @@ -142,7 +142,7 @@ jobs: python -c 'import clvm_tools_rs; print(clvm_tools_rs.__file__)' - name: Verify recompilation of old sources match - if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.7') + if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.8') run: | . ./activate # Build cmd line tools @@ -157,7 +157,7 @@ jobs: (cd chia-blockchain && python recompile_check.py) - name: Test Classic command line tools with pytest - if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.7') + if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.8') run: | python -m pip install pytest # This script installs the wheel built during this workflow. @@ -166,7 +166,7 @@ jobs: (cd resources/tests/cmdline/tests && py.test cmds_test.py ) - name: Verify recompilation of cl21 sources - if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.7') + if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.8') run: | . ./activate # We need chia-rs for the following. @@ -178,7 +178,7 @@ jobs: (cd resources/tests && python check-recompiles.py) - name: Verify recompilation follows date and modification rules - if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.7') + if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.8') run: | python support/wheelname.py python resources/tests/test-clvm-recompile-behavior.py @@ -201,11 +201,11 @@ jobs: pytest tests - name: Run tests - if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.7') + if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.8') run: cargo test --no-default-features - name: Check coverage - if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.7') + if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.8') run: | cargo install grcov rustup component add llvm-tools-preview From 5c12d602cc81d6c53152e3e17b194ee03e4d8214 Mon Sep 17 00:00:00 2001 From: Earle Lowe <30607889+emlowe@users.noreply.github.com> Date: Mon, 31 Jul 2023 09:02:04 -0700 Subject: [PATCH 63/75] Change to 11.0 from just 11 --- .github/workflows/build-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 51977f934..76a80339f 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -48,7 +48,7 @@ jobs: - name: Build MacOs with maturin on Python ${{ matrix.python }} if: startsWith(matrix.os, 'macos') env: - MACOSX_DEPLOYMENT_TARGET: 11 + MACOSX_DEPLOYMENT_TARGET: '11.0' run: | python -m venv venv ln -s venv/bin/activate From 394e7cb8d3c4a6b8ca87a392d38fcdd5cabdd069 Mon Sep 17 00:00:00 2001 From: Earle Lowe <30607889+emlowe@users.noreply.github.com> Date: Mon, 31 Jul 2023 09:15:46 -0700 Subject: [PATCH 64/75] Update build-test.yml --- .github/workflows/build-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 76a80339f..f064ea238 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -20,7 +20,7 @@ jobs: fail-fast: false matrix: os: [macos-latest, ubuntu-latest, windows-latest] - python: [3.8, 3.9, 3.10, 3.11] + python: [3.8, 3.9, '3.10', 3.11] steps: - uses: actions/checkout@v3 From 887d136d9749c43c0fdaa9e239f49519ddaf08bc Mon Sep 17 00:00:00 2001 From: Earle Lowe <30607889+emlowe@users.noreply.github.com> Date: Mon, 31 Jul 2023 10:48:29 -0700 Subject: [PATCH 65/75] Set minimum python version to 3.8 Change abi3-py37 to abi3-py38 to set minimum python version to 3.8 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 1c5a933aa..f11892ec9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,7 @@ js-sys = "0.3.58" getrandom = { version = "0.2", features = ["js"] } [target.'cfg(not(target_family="wasm"))'.dependencies] -pyo3 = { version = "0.14.2", features = ["abi3-py37", "extension-module"], optional = true } +pyo3 = { version = "0.14.2", features = ["abi3-py38", "extension-module"], optional = true } getrandom = { version = "0.2" } [build-dependencies] From f3cb2a36d1e0e2c89d6042dd45143dc55599c2df Mon Sep 17 00:00:00 2001 From: arty Date: Mon, 31 Jul 2023 13:20:31 -0700 Subject: [PATCH 66/75] WIP Compiling, not perfect --- src/compiler/codegen.rs | 57 ++- src/compiler/comptypes.rs | 29 +- src/compiler/evaluate.rs | 154 +++--- src/compiler/frontend.rs | 65 ++- src/compiler/inline.rs | 283 ++++++++--- src/compiler/optimize.rs | 6 +- src/compiler/rename.rs | 14 +- src/tests/compiler/compiler.rs | 44 +- src/tests/compiler/mod.rs | 1 + src/tests/compiler/repl.rs | 2 +- src/tests/compiler/restargs.rs | 903 +++++++++++++++++++++++++++++++++ 11 files changed, 1377 insertions(+), 181 deletions(-) create mode 100644 src/tests/compiler/restargs.rs diff --git a/src/compiler/codegen.rs b/src/compiler/codegen.rs index 48527f81f..86a4597c9 100644 --- a/src/compiler/codegen.rs +++ b/src/compiler/codegen.rs @@ -64,6 +64,7 @@ fn cons_bodyform(loc: Srcloc, left: Rc, right: Rc) -> BodyFo left, right, ], + None, ) } @@ -329,7 +330,7 @@ fn process_defun_call( let env = primcons( l.clone(), Rc::new(SExp::Integer(l.clone(), 2_u32.to_bigint().unwrap())), - cons_up(args), + args, ); Ok(CompiledCode( l.clone(), @@ -360,7 +361,8 @@ fn compile_call( l: Srcloc, opts: Rc, compiler: &PrimaryCodegen, - list: Vec>, + list: &[Rc], + tail: Option>, ) -> Result { let arg_string_list: Vec> = list .iter() @@ -403,6 +405,7 @@ fn compile_call( &inline, l, &tl, + tail.clone() ), Callable::CallDefun(l, lookup) => { @@ -559,14 +562,14 @@ pub fn generate_expr_code( )), } } - BodyForm::Call(l, list) => { + BodyForm::Call(l, list, tail) => { if list.is_empty() { Err(CompileErr( l.clone(), "created a call with no forms".to_string(), )) } else { - compile_call(allocator, runner, l.clone(), opts, compiler, list.to_vec()) + compile_call(allocator, runner, l.clone(), opts, compiler, &list, tail.clone()) } } BodyForm::Mod(_, program) => { @@ -857,6 +860,7 @@ pub fn hoist_body_let_binding( "@".as_bytes().to_vec(), ))), ], + None, ) }); @@ -866,19 +870,28 @@ pub fn hoist_body_let_binding( ]; call_args.append(&mut let_args); - let final_call = BodyForm::Call(letdata.loc.clone(), call_args); + // Calling desugared let so we decide what the tail looks like. + let final_call = BodyForm::Call(letdata.loc.clone(), call_args, None); (out_defuns, Rc::new(final_call)) } - BodyForm::Call(l, list) => { + BodyForm::Call(l, list, tail) => { let mut vres = Vec::new(); let mut new_call_list = vec![list[0].clone()]; for i in list.iter().skip(1) { - let (new_helper, new_arg) = + let (mut new_helpers, new_arg) = hoist_body_let_binding(outer_context.clone(), args.clone(), i.clone()); new_call_list.push(new_arg); - vres.append(&mut new_helper.clone()); + vres.append(&mut new_helpers); } - (vres, Rc::new(BodyForm::Call(l.clone(), new_call_list))) + + let new_tail = tail.as_ref().map(|t| { + let (mut new_tail_helpers, new_tail) = + hoist_body_let_binding(outer_context.clone(), args.clone(), t.clone()); + vres.append(&mut new_tail_helpers); + new_tail + }); + + (vres, Rc::new(BodyForm::Call(l.clone(), new_call_list, new_tail))) } _ => (Vec::new(), body.clone()), } @@ -1119,17 +1132,21 @@ fn finalize_env_( Some(res) => Ok(res.code.clone()), None => { match c.inlines.get(v) { - Some(res) => replace_in_inline( - allocator, - runner.clone(), - opts.clone(), - c, - l.clone(), - res, - res.args.loc(), - &synthesize_args(res.args.clone()), - ) - .map(|x| x.1), + Some(res) => { + let (arg_list, arg_tail) = synthesize_args(res.args.clone()); + return replace_in_inline( + allocator, + runner.clone(), + opts.clone(), + c, + l.clone(), + res, + res.args.loc(), + &arg_list, + arg_tail, + ) + .map(|x| x.1); + } None => { /* Parentfns are functions in progress in the parent */ if c.parentfns.get(v).is_some() { diff --git a/src/compiler/comptypes.rs b/src/compiler/comptypes.rs index 0b7b89e1a..e173ea0f4 100644 --- a/src/compiler/comptypes.rs +++ b/src/compiler/comptypes.rs @@ -142,7 +142,7 @@ pub enum BodyForm { /// /// So tail improper calls aren't allowed. In real lisp, (apply ...) can /// generate them if needed. - Call(Srcloc, Vec>), + Call(Srcloc, Vec>, Option>), /// (mod ...) can be used in chialisp as an expression, in which it returns /// the compiled code. Here, it contains a CompileForm, which represents /// the full significant input of a program (yielded by frontend()). @@ -379,6 +379,23 @@ pub struct ModAccum { pub exp_form: Option, } +/// A specification of a function call including elements useful for evaluation. +#[derive(Debug, Clone)] +pub struct CallSpec<'a> { + pub loc: Srcloc, + pub name: &'a [u8], + pub args: &'a [Rc], + pub tail: Option>, + pub original: Rc, +} + +/// A pair of arguments and an optional tail for function calls. +#[derive(Debug, Default, Clone)] +pub struct ArgsAndTail { + pub args: Vec>, + pub tail: Option>, +} + impl ModAccum { pub fn set_final(&self, c: &CompileForm) -> Self { ModAccum { @@ -568,7 +585,7 @@ impl BodyForm { match self { BodyForm::Let(_, letdata) => letdata.loc.clone(), BodyForm::Quoted(a) => a.loc(), - BodyForm::Call(loc, _) => loc.clone(), + BodyForm::Call(loc, _, _) => loc.clone(), BodyForm::Value(a) => a.loc(), BodyForm::Mod(kl, program) => kl.ext(&program.loc), } @@ -609,8 +626,12 @@ impl BodyForm { Rc::new(body.clone()), )), BodyForm::Value(body) => Rc::new(body.clone()), - BodyForm::Call(loc, exprs) => { - let converted: Vec> = exprs.iter().map(|x| x.to_sexp()).collect(); + BodyForm::Call(loc, exprs, tail) => { + let mut converted: Vec> = exprs.iter().map(|x| x.to_sexp()).collect(); + if let Some(t) = tail.as_ref() { + converted.push(Rc::new(SExp::Atom(t.loc(), "&rest".as_bytes().to_vec()))); + converted.push(t.to_sexp()); + } Rc::new(list_to_cons(loc.clone(), &converted)) } BodyForm::Mod(loc, program) => Rc::new(SExp::Cons( diff --git a/src/compiler/evaluate.rs b/src/compiler/evaluate.rs index 485a1dd84..097473dea 100644 --- a/src/compiler/evaluate.rs +++ b/src/compiler/evaluate.rs @@ -13,7 +13,7 @@ use crate::compiler::clvm::run; use crate::compiler::codegen::codegen; use crate::compiler::compiler::is_at_capture; use crate::compiler::comptypes::{ - Binding, BodyForm, CompileErr, CompileForm, CompilerOpts, HelperForm, LetData, LetFormKind, + ArgsAndTail, Binding, BodyForm, CallSpec, CompileErr, CompileForm, CompilerOpts, HelperForm, LetData, LetFormKind, }; use crate::compiler::frontend::frontend; use crate::compiler::runtypes::RunFailure; @@ -134,6 +134,7 @@ fn make_operator1(l: &Srcloc, op: String, arg: Rc) -> BodyForm { Rc::new(BodyForm::Value(SExp::atom_from_string(l.clone(), &op))), arg, ], + None, ) } @@ -145,6 +146,7 @@ fn make_operator2(l: &Srcloc, op: String, arg1: Rc, arg2: Rc arg1, arg2, ], + None, ) } @@ -267,9 +269,11 @@ fn arg_inputs_primitive(arginputs: Rc) -> bool { fn build_argument_captures( l: &Srcloc, arguments_to_convert: &[Rc], + tail: Option>, args: Rc, ) -> Result, Rc>, CompileErr> { - let mut formed_arguments = ArgInputs::Whole(Rc::new(BodyForm::Quoted(SExp::Nil(l.clone())))); + let formed_tail = tail.unwrap_or_else(|| Rc::new(BodyForm::Quoted(SExp::Nil(l.clone())))); + let mut formed_arguments = ArgInputs::Whole(formed_tail); for i_reverse in 0..arguments_to_convert.len() { let i = arguments_to_convert.len() - i_reverse - 1; @@ -375,6 +379,7 @@ fn synthesize_args( synthesize_args(f.clone(), env)?, synthesize_args(r.clone(), env)?, ], + None, ))) } } @@ -418,7 +423,8 @@ fn is_cons_atom(h: Rc) -> bool { } fn match_cons(args: Rc) -> Option<(Rc, Rc)> { - if let BodyForm::Call(_, v) = args.borrow() { + // Since this matches a primitve, there's no alternative for a tail. + if let BodyForm::Call(_, v, None) = args.borrow() { if v.len() < 3 { return None; } @@ -487,6 +493,7 @@ fn choose_from_env_by_path(path_: Number, args_program: Rc) -> Rc { // A program that is an atom refers to a position @@ -531,7 +538,8 @@ fn promote_program_to_bodyform( } fn match_i_op(candidate: Rc) -> Option<(Rc, Rc, Rc)> { - if let BodyForm::Call(_, cvec) = candidate.borrow() { + // Matches a primitve, no possibility of a tail item. + if let BodyForm::Call(_, cvec, None) = candidate.borrow() { if cvec.len() != 4 { return None; } @@ -574,7 +582,7 @@ fn flatten_expression_to_names(expr: Rc) -> Rc { 0, Rc::new(BodyForm::Value(SExp::Atom(expr.loc(), vec![b'+']))), ); - Rc::new(BodyForm::Call(expr.loc(), call_vec)) + Rc::new(BodyForm::Call(expr.loc(), call_vec, None)) } impl<'info> Evaluator { @@ -664,40 +672,37 @@ impl<'info> Evaluator { &self, allocator: &mut Allocator, visited: &mut VisitedMarker<'info, VisitedInfo>, - l: Srcloc, - call_name: &[u8], - parts: &[Rc], - body: Rc, + call: &CallSpec, prog_args: Rc, arguments_to_convert: &[Rc], env: &HashMap, Rc>, only_inline: bool, ) -> Result, CompileErr> { let mut all_primitive = true; - let mut target_vec: Vec> = parts.to_owned(); + let mut target_vec: Vec> = call.args.to_owned(); - if call_name == "@".as_bytes() { + if call.name == "@".as_bytes() { // Synthesize the environment for this function Ok(Rc::new(BodyForm::Quoted(SExp::Cons( - l.clone(), - Rc::new(SExp::Nil(l)), + call.loc.clone(), + Rc::new(SExp::Nil(call.loc.clone())), prog_args, )))) - } else if call_name == "com".as_bytes() { + } else if call.name == "com".as_bytes() { let mut end_of_list = Rc::new(SExp::Cons( - l.clone(), + call.loc.clone(), arguments_to_convert[0].to_sexp(), - Rc::new(SExp::Nil(l.clone())), + Rc::new(SExp::Nil(call.loc.clone())), )); for h in self.helpers.iter() { - end_of_list = Rc::new(SExp::Cons(l.clone(), h.to_sexp(), end_of_list)) + end_of_list = Rc::new(SExp::Cons(call.loc.clone(), h.to_sexp(), end_of_list)) } let use_body = SExp::Cons( - l.clone(), - Rc::new(SExp::Atom(l.clone(), "mod".as_bytes().to_vec())), - Rc::new(SExp::Cons(l, prog_args, end_of_list)), + call.loc.clone(), + Rc::new(SExp::Atom(call.loc.clone(), "mod".as_bytes().to_vec())), + Rc::new(SExp::Cons(call.loc.clone(), prog_args, end_of_list)), ); let compiled = self.compile_code(allocator, false, Rc::new(use_body))?; @@ -705,10 +710,10 @@ impl<'info> Evaluator { Ok(Rc::new(BodyForm::Quoted(compiled_borrowed.clone()))) } else { let pres = self - .lookup_prim(l.clone(), call_name) + .lookup_prim(call.loc.clone(), &call.name) .map(|prim| { // Reduce all arguments. - let mut converted_args = SExp::Nil(l.clone()); + let mut converted_args = SExp::Nil(call.loc.clone()); for i_reverse in 0..arguments_to_convert.len() { let i = arguments_to_convert.len() - i_reverse - 1; @@ -728,27 +733,28 @@ impl<'info> Evaluator { } converted_args = - SExp::Cons(l.clone(), shrunk.to_sexp(), Rc::new(converted_args)); + SExp::Cons(call.loc.clone(), shrunk.to_sexp(), Rc::new(converted_args)); } if all_primitive { match self.run_prim( allocator, - l.clone(), - make_prim_call(l.clone(), prim, Rc::new(converted_args)), - Rc::new(SExp::Nil(l.clone())), + call.loc.clone(), + make_prim_call(call.loc.clone(), prim, Rc::new(converted_args)), + Rc::new(SExp::Nil(call.loc.clone())), ) { Ok(res) => Ok(res), Err(e) => { if only_inline || self.ignore_exn { - Ok(Rc::new(BodyForm::Call(l.clone(), target_vec.clone()))) + Ok(Rc::new(BodyForm::Call(call.loc.clone(), target_vec.clone(), None))) } else { Err(e) } } } } else { - let reformed = BodyForm::Call(l.clone(), target_vec.clone()); + // Since this is a primitive, there's no tail transform. + let reformed = BodyForm::Call(call.loc.clone(), target_vec.clone(), call.tail.clone()); self.chase_apply(allocator, visited, Rc::new(reformed)) } }) @@ -757,11 +763,11 @@ impl<'info> Evaluator { // return the unevaluated chunk with minimized // arguments. Err(CompileErr( - l.clone(), + call.loc.clone(), format!( "Don't yet support this call type {} {:?}", - body.to_sexp(), - body + call.original.to_sexp(), + call.original ), )) })?; @@ -814,6 +820,7 @@ impl<'info> Evaluator { Rc::new(BodyForm::Call( maybe_condition.loc(), vec![x_head.clone(), cond.clone()], + None, )), ); @@ -823,6 +830,7 @@ impl<'info> Evaluator { Rc::new(BodyForm::Call( iftrue.loc(), vec![apply_head.clone(), iftrue.clone(), env.clone()], + None, )), ); @@ -832,6 +840,7 @@ impl<'info> Evaluator { Rc::new(BodyForm::Call( iffalse.loc(), vec![apply_head, iffalse.clone(), env], + None, )), ); @@ -847,6 +856,7 @@ impl<'info> Evaluator { flatten_expression_to_names(surrogate_apply_true?.to_sexp()), flatten_expression_to_names(surrogate_apply_false?.to_sexp()), ], + None, )); return Ok(res); @@ -861,7 +871,7 @@ impl<'info> Evaluator { visited: &'_ mut VisitedMarker<'info, VisitedInfo>, body: Rc, ) -> Result, CompileErr> { - if let BodyForm::Call(l, vec) = body.borrow() { + if let BodyForm::Call(l, vec, None) = body.borrow() { if is_apply_atom(vec[0].to_sexp()) { if let Ok(run_program) = dequote(l.clone(), vec[1].clone()) { return self.continue_apply(allocator, visited, vec[2].clone(), run_program); @@ -885,36 +895,39 @@ impl<'info> Evaluator { &self, allocator: &mut Allocator, visited: &'_ mut VisitedMarker<'info, VisitedInfo>, - l: Srcloc, - call_loc: Srcloc, - call_name: &[u8], - _head_expr: Rc, - parts: &[Rc], - body: Rc, + call: &CallSpec, prog_args: Rc, arguments_to_convert: &[Rc], env: &HashMap, Rc>, only_inline: bool, ) -> Result, CompileErr> { - let helper = select_helper(&self.helpers, call_name); + let helper = select_helper(&self.helpers, &call.name); match helper { - Some(HelperForm::Defmacro(mac)) => self.invoke_macro_expansion( - allocator, - visited, - mac.loc.clone(), - call_loc, - mac.program, - prog_args, - arguments_to_convert, - env, - ), + Some(HelperForm::Defmacro(mac)) => { + if call.tail.is_some() { + return Err(CompileErr( + call.loc.clone(), + "Macros cannot use runtime rest arguments".to_string(), + )); + } + self.invoke_macro_expansion( + allocator, + visited, + mac.loc.clone(), + call.loc.clone(), + mac.program, + prog_args, + arguments_to_convert, + env, + ) + } Some(HelperForm::Defun(inline, defun)) => { if !inline && only_inline { - return Ok(body); + return Ok(call.original.clone()); } let argument_captures_untranslated = - build_argument_captures(&call_loc, arguments_to_convert, defun.args.clone())?; + build_argument_captures(&call.loc.clone(), arguments_to_convert, call.tail.clone(), defun.args.clone())?; let mut argument_captures = HashMap::new(); // Do this to protect against misalignment @@ -945,10 +958,7 @@ impl<'info> Evaluator { .invoke_primitive( allocator, visited, - l, - call_name, - parts, - body, + call, prog_args, arguments_to_convert, env, @@ -1066,7 +1076,7 @@ impl<'info> Evaluator { } } BodyForm::Value(v) => Ok(Rc::new(BodyForm::Quoted(v.clone()))), - BodyForm::Call(l, parts) => { + BodyForm::Call(l, parts, tail) => { if parts.is_empty() { return Err(CompileErr( l.clone(), @@ -1079,29 +1089,31 @@ impl<'info> Evaluator { parts.iter().skip(1).cloned().collect(); match head_expr.borrow() { - BodyForm::Value(SExp::Atom(call_loc, call_name)) => self.handle_invoke( + BodyForm::Value(SExp::Atom(_call_loc, call_name)) => self.handle_invoke( allocator, &mut visited, - l.clone(), - call_loc.clone(), - call_name, - head_expr.clone(), - parts, - body.clone(), + &CallSpec { + loc: l.clone(), + name: call_name, + args: parts, + original: body.clone(), + tail: tail.clone(), + }, prog_args, &arguments_to_convert, env, only_inline, ), - BodyForm::Value(SExp::Integer(call_loc, call_int)) => self.handle_invoke( + BodyForm::Value(SExp::Integer(_call_loc, call_int)) => self.handle_invoke( allocator, &mut visited, - l.clone(), - call_loc.clone(), - &u8_from_number(call_int.clone()), - head_expr.clone(), - parts, - body.clone(), + &CallSpec { + loc: l.clone(), + name: &u8_from_number(call_int.clone()), + args: parts, + original: body.clone(), + tail: None, + }, prog_args, &arguments_to_convert, env, diff --git a/src/compiler/frontend.rs b/src/compiler/frontend.rs index e93b87c3c..989f8a0c7 100644 --- a/src/compiler/frontend.rs +++ b/src/compiler/frontend.rs @@ -5,7 +5,7 @@ use std::rc::Rc; use crate::classic::clvm::__type_compatibility__::bi_one; use crate::compiler::comptypes::{ - list_to_cons, Binding, BodyForm, CompileErr, CompileForm, CompilerOpts, ConstantKind, + list_to_cons, ArgsAndTail, Binding, BodyForm, CallSpec, CompileErr, CompileForm, CompilerOpts, ConstantKind, DefconstData, DefmacData, DefunData, HelperForm, IncludeDesc, LetData, LetFormKind, ModAccum, }; use crate::compiler::preprocessor::preprocess; @@ -55,12 +55,16 @@ fn collect_used_names_bodyform(body: &BodyForm) -> Vec> { } _ => Vec::new(), }, - BodyForm::Call(_l, vs) => { + BodyForm::Call(_l, vs, tail) => { let mut result = Vec::new(); for a in vs { let mut argnames = collect_used_names_bodyform(a); result.append(&mut argnames); } + if let Some(t) = tail { + let mut tail_names = collect_used_names_bodyform(t); + result.append(&mut tail_names); + } result } BodyForm::Mod(_, _) => vec![], @@ -173,7 +177,7 @@ fn qq_to_expression_list( )), Rc::new(f_qq), Rc::new(r_qq) - ))) + ), None)) } } SExp::Nil(l) => Ok(BodyForm::Quoted(SExp::Nil(l.clone()))), @@ -187,23 +191,50 @@ fn qq_to_expression_list( fn args_to_expression_list( opts: Rc, body: Rc, -) -> Result>, CompileErr> { +) -> Result { if body.nilp() { - Ok(vec![]) + Ok(Default::default()) } else { match body.borrow() { SExp::Cons(_l, first, rest) => { + if let SExp::Atom(_fl, fname) = first.borrow() { + if fname == b"&rest" { + // Rest is a list containing one item that becomes the + // tail. + let args_no_tail = args_to_expression_list(opts, rest.clone())?; + + if args_no_tail.tail.is_some() { + return Err(CompileErr( + rest.loc(), + "only one use of &rest is allowed".to_string(), + )); + } + + if args_no_tail.args.len() != 1 { + return Err(CompileErr( + body.loc(), + "&rest specified with bad tail".to_string(), + )); + } + + // Return a tail. + return Ok(ArgsAndTail { + args: vec![], + tail: Some(args_no_tail.args[0].clone()), + }); + } + } let mut result_list = Vec::new(); let f_compiled = compile_bodyform(opts.clone(), first.clone())?; result_list.push(Rc::new(f_compiled)); - let mut args = args_to_expression_list(opts, rest.clone())?; - result_list.append(&mut args); - Ok(result_list) + let mut args_and_tail = args_to_expression_list(opts, rest.clone())?; + result_list.append(&mut args_and_tail.args); + Ok(ArgsAndTail { + args: result_list, + tail: args_and_tail.tail, + }) } - _ => Err(CompileErr( - body.loc(), - "Bad arg list tail ".to_string() + &body.to_string(), - )), + _ => Err(CompileErr(body.loc(), format!("Bad arg list tail {body}"))), } } } @@ -248,17 +279,17 @@ pub fn compile_bodyform( match body.borrow() { SExp::Cons(l, op, tail) => { let application = || { - args_to_expression_list(opts.clone(), tail.clone()).and_then(|args| { + args_to_expression_list(opts.clone(), tail.clone()).and_then(|atail| { compile_bodyform(opts.clone(), op.clone()).map(|func| { let mut result_call = vec![Rc::new(func)]; - let mut args_clone = args.to_vec(); - let ending = if args.is_empty() { + let mut args_clone = atail.args.to_vec(); + let ending = if atail.args.is_empty() { l.ending() } else { - args[args.len() - 1].loc().ending() + atail.args[atail.args.len() - 1].loc().ending() }; result_call.append(&mut args_clone); - BodyForm::Call(l.ext(&ending), result_call) + BodyForm::Call(l.ext(&ending), result_call, atail.tail) }) }) }; diff --git a/src/compiler/inline.rs b/src/compiler/inline.rs index dfb27f848..4a04417cd 100644 --- a/src/compiler/inline.rs +++ b/src/compiler/inline.rs @@ -11,7 +11,7 @@ use crate::classic::clvm_tools::stages::stage_0::TRunProgram; use crate::compiler::codegen::{generate_expr_code, get_call_name, get_callable}; use crate::compiler::compiler::is_at_capture; use crate::compiler::comptypes::{ - BodyForm, Callable, CompileErr, CompiledCode, CompilerOpts, InlineFunction, PrimaryCodegen, + ArgsAndTail, BodyForm, Callable, CallSpec, CompileErr, CompiledCode, CompilerOpts, InlineFunction, PrimaryCodegen, }; use crate::compiler::sexp::{decode_string, SExp}; use crate::compiler::srcloc::Srcloc; @@ -25,6 +25,8 @@ fn apply_fn(loc: Srcloc, name: String, expr: Rc) -> Rc { Rc::new(BodyForm::Value(SExp::atom_from_string(loc, &name))), expr, ], + // Ok: applying a primitive or builtin requires no tail. + None, )) } @@ -36,40 +38,57 @@ fn at_form(loc: Srcloc, path: Number) -> Rc { ) } -pub fn synthesize_args(arg_: Rc) -> Vec> { +/// Generates a list of paths that correspond to the toplevel positions in arg_ +/// and if given, the improper tail. +pub fn synthesize_args(arg_: Rc) -> (Vec>, Option>) { + let two = 2_i32.to_bigint().unwrap(); let mut start = 5_i32.to_bigint().unwrap(); + let mut tail = bi_one(); let mut result = Vec::new(); let mut arg = arg_; loop { match arg.borrow() { SExp::Cons(l, _, b) => { result.push(at_form(l.clone(), start.clone())); - start = bi_one() + start.clone() * 2_i32.to_bigint().unwrap(); + tail = bi_one() | (two.clone() * tail); + start = bi_one() + start.clone() * two.clone(); arg = b.clone(); } + SExp::Atom(l, _) => { + return (result, Some(at_form(l.clone(), tail))); + } _ => { - return result; + return (result, None); } } } } -fn enlist_remaining_args(loc: Srcloc, arg_choice: usize, args: &[Rc]) -> Rc { - let mut result_body = BodyForm::Value(SExp::Nil(loc.clone())); +fn enlist_remaining_args( + loc: Srcloc, + arg_choice: usize, + args: &[Rc], + tail: Option>, +) -> Rc { + let mut result_body = tail.unwrap_or_else(|| Rc::new(BodyForm::Value(SExp::Nil(loc.clone())))); - for i_reverse in arg_choice..args.len() { - let i = args.len() - i_reverse - 1; - result_body = BodyForm::Call( + for arg in args.iter().skip(arg_choice).rev() { + result_body = Rc::new(BodyForm::Call( loc.clone(), vec![ - Rc::new(BodyForm::Value(SExp::atom_from_string(loc.clone(), "c"))), - args[i].clone(), - Rc::new(result_body), + Rc::new(BodyForm::Value(SExp::Integer( + loc.clone(), + 4_u32.to_bigint().unwrap(), + ))), + arg.clone(), + result_body, ], - ); + // Ok: applying cons. + None, + )); } - Rc::new(result_body) + result_body } fn pick_value_from_arg_element( @@ -117,38 +136,95 @@ fn pick_value_from_arg_element( } } +fn choose_arg_from_list_or_tail( + callsite: &Srcloc, + args: &[Rc], + tail: Option>, + index: usize, +) -> Result, CompileErr> { + let two = 2_i32.to_bigint().unwrap(); + + if index >= args.len() { + if let Some(t) = tail { + let target_shift = index - args.len(); + let target_path = + (two.clone() << target_shift) | (((two << target_shift) - bi_one()) >> 2); + return Ok(Rc::new(BodyForm::Call( + callsite.clone(), + vec![ + Rc::new(BodyForm::Value(SExp::Integer( + t.loc(), + 2_u32.to_bigint().unwrap(), + ))), + Rc::new(BodyForm::Value(SExp::Integer(t.loc(), target_path))), + t.clone(), + ], + // Applying a primitive. + None, + ))); + } + + return Err(CompileErr( + callsite.clone(), + format!("Lookup for argument {} that wasn't passed", index + 1), + )); + } + + Ok(args[index].clone()) +} + fn arg_lookup( callsite: Srcloc, - match_args: Rc, - arg_choice: usize, + mut match_args: Rc, args: &[Rc], + mut tail: Option>, name: Vec, ) -> Result>, CompileErr> { - match match_args.borrow() { - SExp::Cons(_l, f, r) => { - if arg_choice >= args.len() { - return Err(CompileErr( - callsite, - format!("Lookup for argument {} that wasn't passed", arg_choice + 1), - )); + let two = 2_i32.to_bigint().unwrap(); + let mut arg_choice = 0; + + loop { + match match_args.borrow() { + SExp::Cons(_l, f, r) => { + if let Some(x) = pick_value_from_arg_element( + f.clone(), + choose_arg_from_list_or_tail(&callsite, args, tail.clone(), arg_choice)?, + &|x| x, + name.clone(), + ) { + return Ok(Some(x)); + } else { + arg_choice += 1; + match_args = r.clone(); + continue; + } } + _ => { + if arg_choice > args.len() { + let underflow = arg_choice - args.len(); + let tail_path = (two.clone() << underflow) - bi_one(); + tail = tail.map(|t| { + Rc::new(BodyForm::Call( + t.loc(), + vec![ + Rc::new(BodyForm::Value(SExp::Integer(t.loc(), two.clone()))), + Rc::new(BodyForm::Value(SExp::Integer(t.loc(), tail_path))), + t.clone(), + ], + None, + )) + }); + } - match pick_value_from_arg_element( - f.clone(), - args[arg_choice].clone(), - &|x| x, - name.clone(), - ) { - Some(x) => Ok(Some(x)), - None => arg_lookup(callsite, r.clone(), arg_choice + 1, args, name), + let tail_list = enlist_remaining_args(match_args.loc(), arg_choice, args, tail); + return Ok(pick_value_from_arg_element( + match_args.clone(), + tail_list, + &|x: Rc| x, + name, + )); } } - _ => Ok(pick_value_from_arg_element( - match_args.clone(), - enlist_remaining_args(match_args.loc(), arg_choice, args), - &|x: Rc| x, - name, - )), } } @@ -163,6 +239,71 @@ fn get_inline_callable( get_callable(opts, compiler, loc, name) } +fn make_args_for_call_from_inline( + visited_inlines: &mut HashSet>, + runner: Rc, + opts: Rc, + compiler: &PrimaryCodegen, + inline: &InlineFunction, + incoming_spec: &CallSpec, + call_spec: &CallSpec, +) -> Result { + if call_spec.args.is_empty() { + // This is a nil. + return Ok(ArgsAndTail { + args: vec![], + tail: call_spec.tail.clone(), + }); + } + + let mut new_args = Vec::new(); + + for (i, arg) in call_spec.args.iter().enumerate() { + if i == 0 { + new_args.push(arg.clone()); + continue; + } + + let mut new_visited = visited_inlines.clone(); + let replaced = replace_inline_body( + &mut new_visited, + runner.clone(), + opts.clone(), + compiler, + arg.loc(), + inline, + incoming_spec.args, + incoming_spec.tail.clone(), + call_spec.loc.clone(), + arg.clone(), + )?; + new_args.push(replaced); + } + + let mut new_visited = visited_inlines.clone(); + let replaced_tail = if let Some(t) = call_spec.tail.as_ref() { + Some(replace_inline_body( + &mut new_visited, + runner, + opts, + compiler, + t.loc(), + inline, + incoming_spec.args, + incoming_spec.tail.clone(), + call_spec.loc.clone(), + t.clone(), + )?) + } else { + None + }; + + Ok(ArgsAndTail { + args: new_args, + tail: replaced_tail, + }) +} + #[allow(clippy::too_many_arguments)] fn replace_inline_body( visited_inlines: &mut HashSet>, @@ -172,6 +313,7 @@ fn replace_inline_body( loc: Srcloc, inline: &InlineFunction, args: &[Rc], + tail: Option>, callsite: Srcloc, expr: Rc, ) -> Result, CompileErr> { @@ -180,8 +322,7 @@ fn replace_inline_body( loc, "let binding should have been hoisted before optimization".to_string(), )), - BodyForm::Call(l, call_args) => { - let mut new_args = Vec::new(); + BodyForm::Call(l, call_args, call_tail) => { // Ensure that we don't count branched invocations when checking // each call downstream of the main expr is recursive. // @@ -204,25 +345,29 @@ fn replace_inline_body( // We ensure here that each argument has a separate visited stack. // Recursion only happens when the same stack encounters an inline // twice. - for (i, arg) in call_args.iter().enumerate() { - if i == 0 { - new_args.push(arg.clone()); - } else { - let mut new_visited = visited_inlines.clone(); - let replaced = replace_inline_body( - &mut new_visited, - runner.clone(), - opts.clone(), - compiler, - arg.loc(), - inline, - args, - callsite.clone(), - arg.clone(), - )?; - new_args.push(replaced); - } - } + // + let args_and_tail = make_args_for_call_from_inline( + visited_inlines, + runner.clone(), + opts.clone(), + compiler, + inline, + &CallSpec { + loc: callsite.clone(), + name: &inline.name, + args, + tail, + original: expr.clone(), + }, + &CallSpec { + loc: callsite.clone(), + name: &inline.name, + args: call_args, + tail: call_tail.clone(), + original: expr.clone(), + }, + )?; + // If the called function is an inline, we'll expand it here. // This is so we can preserve the context of argument expressions // so no new mapping is needed. This solves a number of problems @@ -230,6 +375,8 @@ fn replace_inline_body( // // If it's a macro we'll expand it here so we can recurse and // determine whether an inline is the next level. + // + // It's an inline, so we need to fulfill its arguments. match get_inline_callable(opts.clone(), compiler, l.clone(), call_args[0].clone())? { Callable::CallInline(l, new_inline) => { if visited_inlines.contains(&new_inline.name) { @@ -245,7 +392,7 @@ fn replace_inline_body( visited_inlines.insert(new_inline.name.clone()); let pass_on_args: Vec> = - new_args.iter().skip(1).cloned().collect(); + args_and_tail.args.iter().skip(1).cloned().collect(); replace_inline_body( visited_inlines, runner, @@ -254,18 +401,20 @@ fn replace_inline_body( l, // clippy update since 1.59 &new_inline, &pass_on_args, + args_and_tail.tail, callsite, new_inline.body.clone(), ) } _ => { - let call = BodyForm::Call(l.clone(), new_args); + // Tail passes through to a normal call form. + let call = BodyForm::Call(l.clone(), args_and_tail.args, args_and_tail.tail); Ok(Rc::new(call)) } } } BodyForm::Value(SExp::Atom(_, a)) => { - let alookup = arg_lookup(callsite, inline.args.clone(), 0, args, a.clone())? + let alookup = arg_lookup(callsite, inline.args.clone(), args, tail.clone(), a.clone())? .unwrap_or_else(|| expr.clone()); Ok(alookup) } @@ -279,6 +428,16 @@ fn replace_inline_body( /// /// This will probably be changed at some point to return Rc so it /// can be treated as a desugaring step that's subject to frontend optimization. +/// +/// There are two cases when we have rest arguments: +/// +/// 1) Too few arguments are provided along with a rest argument. +/// In this case, we can't tell what's been provided for the variable arguments +/// so we synthesize paths into the rest argument and hope for the best. +/// +/// 2) Too many arguments are provided (optionally with a rest argument). +/// In this case, we collect the following arguments and pass them to a +/// tail argument if one exists. If not, then they're discarded. #[allow(clippy::too_many_arguments)] pub fn replace_in_inline( allocator: &mut Allocator, @@ -289,6 +448,7 @@ pub fn replace_in_inline( inline: &InlineFunction, callsite: Srcloc, args: &[Rc], + tail: Option>, ) -> Result { let mut visited = HashSet::new(); visited.insert(inline.name.clone()); @@ -300,6 +460,7 @@ pub fn replace_in_inline( loc, inline, args, + tail, callsite, inline.body.clone(), ) diff --git a/src/compiler/optimize.rs b/src/compiler/optimize.rs index 03dda32e9..6bb13abb8 100644 --- a/src/compiler/optimize.rs +++ b/src/compiler/optimize.rs @@ -31,7 +31,7 @@ pub fn optimize_expr( ) -> Option<(bool, Rc)> { match body.borrow() { BodyForm::Quoted(_) => Some((true, body)), - BodyForm::Call(l, forms) => { + BodyForm::Call(l, forms, None) => { // () evaluates to () if forms.is_empty() { return Some((true, body)); @@ -80,7 +80,8 @@ pub fn optimize_expr( let mut replaced_args = optimized_args.iter().map(|x| x.1.clone()).collect(); result_list.append(&mut replaced_args); - let code = BodyForm::Call(l.clone(), result_list); + // Calling a primitive. + let code = BodyForm::Call(l.clone(), result_list, None); if constant { run( @@ -114,6 +115,7 @@ pub fn optimize_expr( _ => None, } } + BodyForm::Call(l, forms, Some(_)) => None, BodyForm::Value(SExp::Integer(l, i)) => Some(( true, Rc::new(BodyForm::Quoted(SExp::Integer(l.clone(), i.clone()))), diff --git a/src/compiler/rename.rs b/src/compiler/rename.rs index 9b2e42ed5..b549a0b16 100644 --- a/src/compiler/rename.rs +++ b/src/compiler/rename.rs @@ -161,12 +161,15 @@ fn rename_in_bodyform(namemap: &HashMap, Vec>, b: Rc) -> B _ => BodyForm::Value(atom.clone()), }, - BodyForm::Call(l, vs) => { + BodyForm::Call(l, vs, tail) => { let new_vs = vs .iter() .map(|x| Rc::new(rename_in_bodyform(namemap, x.clone()))) .collect(); - BodyForm::Call(l.clone(), new_vs) + let new_tail = tail + .as_ref() + .map(|t| Rc::new(rename_in_bodyform(namemap, t.clone()))); + BodyForm::Call(l.clone(), new_vs, new_tail) } BodyForm::Mod(l, prog) => BodyForm::Mod(l.clone(), prog.clone()), @@ -249,12 +252,15 @@ fn rename_args_bodyform(b: &BodyForm) -> BodyForm { BodyForm::Quoted(e) => BodyForm::Quoted(e.clone()), BodyForm::Value(v) => BodyForm::Value(v.clone()), - BodyForm::Call(l, vs) => { + BodyForm::Call(l, vs, tail) => { let new_vs = vs .iter() .map(|a| Rc::new(rename_args_bodyform(a))) .collect(); - BodyForm::Call(l.clone(), new_vs) + let new_tail = tail + .as_ref() + .map(|t| Rc::new(rename_args_bodyform(t.borrow()))); + BodyForm::Call(l.clone(), new_vs, new_tail) } BodyForm::Mod(l, program) => BodyForm::Mod(l.clone(), program.clone()), } diff --git a/src/tests/compiler/compiler.rs b/src/tests/compiler/compiler.rs index e72b37c59..c3447f9ab 100644 --- a/src/tests/compiler/compiler.rs +++ b/src/tests/compiler/compiler.rs @@ -58,7 +58,7 @@ fn run_string_maybe_opt( }) } -fn run_string(content: &String, args: &String) -> Result, CompileErr> { +pub fn run_string(content: &String, args: &String) -> Result, CompileErr> { run_string_maybe_opt(content, args, false) } @@ -1205,3 +1205,45 @@ fn test_inline_in_assign_not_actually_recursive() { let res = run_string(&prog, &"()".to_string()).expect("should compile and run"); assert_eq!(res.to_string(), "9999"); } + +#[test] +fn test_simple_rest_call_0() { + let prog = indoc! {" +(mod X + (include *standard-cl-23*) + + (defun F Xs + (if Xs + (+ (f Xs) (F &rest (r Xs))) + () + ) + ) + + (F &rest X) + )"} + .to_string(); + let res = run_string(&prog, &"(13 99 144)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "256"); +} + +#[test] +fn test_simple_rest_call_inline() { + let prog = indoc! {" +(mod X + (include *standard-cl-23*) + + (defun sum (Xs) + (if Xs + (+ (f Xs) (sum (r Xs))) + () + ) + ) + + (defun-inline F (A1 . A2) (* A1 (sum A2))) + + (F 3 &rest X) + )"} + .to_string(); + let res = run_string(&prog, &"(13 99 144)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "768"); +} diff --git a/src/tests/compiler/mod.rs b/src/tests/compiler/mod.rs index 4bc5e40f8..b0ea66ffb 100644 --- a/src/tests/compiler/mod.rs +++ b/src/tests/compiler/mod.rs @@ -9,6 +9,7 @@ mod clvm; mod compiler; mod evaluate; mod repl; +mod restargs; mod runtypes; mod srcloc; mod usecheck; diff --git a/src/tests/compiler/repl.rs b/src/tests/compiler/repl.rs index d614bef78..d0fd84e9f 100644 --- a/src/tests/compiler/repl.rs +++ b/src/tests/compiler/repl.rs @@ -31,7 +31,7 @@ where res.map(|r| r.map(|r| r.to_sexp().to_string())) } -fn test_repl_outcome(inputs: Vec) -> Result, CompileErr> +pub fn test_repl_outcome(inputs: Vec) -> Result, CompileErr> where S: ToString, { diff --git a/src/tests/compiler/restargs.rs b/src/tests/compiler/restargs.rs new file mode 100644 index 000000000..22ae04a23 --- /dev/null +++ b/src/tests/compiler/restargs.rs @@ -0,0 +1,903 @@ +use crate::tests::compiler::compiler::run_string; +use crate::tests::compiler::repl::test_repl_outcome; + +// All tests needed for rest calls: +// +// Call from non-inline to inline +// 01 - Too many arguments, no tail position argument to absorb. +// 02 - Too many arguments, tail position argument to absorb, &rest. +// 03 - Too many arguments, tail position argument to absorb, no &rest. +// 04 - Exact number of arguments, no tail position argument. +// 05 - Exact number of arguments, tail position argument, &rest. +// 06 - Exact number of arguments, tail position argument, no &rest. +// 07 - Too few arguments, &rest, tail. +// 08 - Too few arguments, &rest, no tail. +// 09 - Too few arguments, no &rest, tail. (error) +// 10 - Too few arguments, &rest, no tail. +// Call from inline to inline +// 11 - Too many arguments, no tail position argument to absorb. +// 12 - Too many arguments, tail position argument to absorb, &rest. +// 13 - Too many arguments, tail position argument to absorb, no &rest. +// 14 - Exact number of arguments, no tail position argument. +// 15 - Exact number of arguments, tail position argument, &rest. +// 16 - Exact number of arguments, tail position argument, no &rest. +// 17 - Too few arguments, &rest, tail. +// 18 - Too few arguments, &rest, no tail. +// 19 - Too few arguments, no &rest, tail. (error) +// 20 - Too few arguments, &rest, no tail. +// Call from non-inline to non-inline +// 21 - Too many arguments, no tail position argument to absorb. +// 22 - Too many arguments, tail position argument to absorb, &rest. +// 23 - Too many arguments, tail position argument to absorb, no &rest. +// 24 - Exact number of arguments, no tail position argument. +// 25 - Exact number of arguments, tail position argument, &rest. +// 26 - Exact number of arguments, tail position argument, no &rest. +// 27 - Too few arguments, &rest, tail. +// 28 - Too few arguments, &rest, no tail. +// 29 - Too few arguments, no &rest, tail. (not error) +// 30 - Too few arguments, &rest, no tail. +// Call from inline to non-inline +// 31 - Too many arguments, no tail position argument to absorb. +// 32 - Too many arguments, tail position argument to absorb, &rest. +// 33 - Too many arguments, tail position argument to absorb, no &rest. +// 34 - Exact number of arguments, no tail position argument. +// 35 - Exact number of arguments, tail position argument, &rest. +// 36 - Exact number of arguments, tail position argument, no &rest. +// 37 - Too few arguments, &rest, tail. +// 38 - Too few arguments, &rest, no tail. +// 39 - Too few arguments, no &rest, tail. (not error) +// 40 - Too few arguments, &rest, no tail. +// +#[test] +fn test_simple_inline_toomany_args_01() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun-inline F (A B) (+ A B)) + + (F X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 9)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "12"); +} + +#[test] +fn test_simple_inline_toomany_args_improper_tail_02() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun sum (Xs) + (if Xs + (+ (f Xs) (sum (r Xs))) + () + ) + ) + + (defun-inline F (A B . C) (* A B (sum C))) + + (F X Y 99 101 &rest Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (301 313))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "28490"); +} + +#[test] +fn test_simple_inline_toomany_args_improper_no_tail_03() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun sum (Xs) + (if Xs + (+ (f Xs) (sum (r Xs))) + () + ) + ) + + (defun-inline F (A B . C) (* A B (sum C))) + + (F X Y 99 101) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "7000"); +} + +#[test] +fn test_simple_inline_exact_no_tails_04() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun-inline F (A B) (* A B)) + + (F X Y) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "35"); +} + +#[test] +fn test_simple_inline_exact_improper_tail_05() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun-inline F (A B . C) (* A B C)) + + (F X Y &rest Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 9)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "315"); +} + +#[test] +fn test_simple_inline_exact_improper_no_tail_06() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun-inline F (A B . C) (+ A B C)) + + (F X Y) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "12"); +} + +#[test] +fn test_simple_inline_exact_toofew_improper_tail_07() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun-inline F (A B C . D) (list A B C (f D))) + + (F X Y &rest Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (101 103))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 101 103)"); +} + +#[test] +fn test_simple_inline_exact_toofew_tail_08() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun-inline F (A B C) (list A B C)) + + (F X Y &rest Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (101 103))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 101)"); +} + +#[test] +fn test_simple_inline_exact_toofew_improper_no_tail_09() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun-inline F (A B C . D) (list A B C (f D))) + + (F X Y) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()); + if let Err(e) = res { + assert!(e.1.contains("Lookup for argument 3")); + } else { + assert!(false); + } +} + +#[test] +fn test_simple_inline_exact_toofew_tail_10() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun-inline F (A B C) (list A B C)) + + (F X Y &rest Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (101 103))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 101)"); +} + +#[test] +fn test_inline_inline_toomany_args_11() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun-inline F (A B) (+ A B)) + + (defun-inline G (X Y Z) (F X Y Z)) + + (G X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 9)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "12"); +} + +#[test] +fn test_inline_inline_toomany_args_improper_tail_12() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun-inline return-list (Xs) Xs) + + (defun-inline F (A B . C) (list A B (return-list C))) + + (F X Y 99 101 &rest Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (301 313))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 (c e 301 313))"); +} + +#[test] +fn test_simple_inline_toomany_args_improper_no_tail_13() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun-inline return-list (Xs) Xs) + + (defun-inline F (A B . C) (list A B (return-list C))) + + (F X Y 99 101) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 (c e))"); +} + +#[test] +fn test_inline_inline_exact_no_tails_14() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun-inline F (A B) (* A B)) + + (defun-inline G (A B) (F A B)) + + (G X Y) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "35"); +} + +#[test] +fn test_inline_inline_exact_improper_tail_15() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun-inline F (A B . C) (* A B C)) + + (defun-inline G (X Y Z) (F X Y &rest Z)) + + (G X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 9)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "315"); +} + +#[test] +fn test_inline_inline_exact_improper_no_tail_16() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun-inline F (A B . C) (+ A B C)) + + (defun-inline G (X Y) (F X Y)) + + (G X Y) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "12"); +} + +#[test] +fn test_simple_inline_exact_toofew_improper_tail_17() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun-inline F (A B C . D) (list A B C (f D))) + + (defun-inline G (X Y Z) (F X Y &rest Z)) + + (G X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (101 103))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 101 103)"); +} + +#[test] +fn test_inline_inline_exact_toofew_tail_18() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun-inline F (A B C) (list A B C)) + + (defun-inline G (X Y Z) (F X Y &rest Z)) + + (G X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (101 103))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 101)"); +} + +#[test] +fn test_inline_inline_exact_toofew_improper_no_tail_19() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun-inline F (A B C . D) (list A B C (f D))) + + (defun-inline G (X Y) (F X Y)) + + (G X Y) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()); + if let Err(e) = res { + assert!(e.1.contains("Lookup for argument 3")); + } else { + assert!(false); + } +} + +#[test] +fn test_simple_inline_exact_toofew_tail_20() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun-inline F (A B C) (list A B C)) + + (defun-inline G (X Y Z) (F X Y &rest Z)) + + (G X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (101 103))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 101)"); +} + +#[test] +fn test_ni_ni_toomany_args_21() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun F (A B) (+ A B)) + + (defun G (X Y Z) (F X Y Z)) + + (G X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 9)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "12"); +} + +#[test] +fn test_ni_ni_toomany_args_improper_tail_22() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun return-list (Xs) Xs) + + (defun F (A B . C) (list A B (return-list C))) + + (F X Y 99 101 &rest Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (301 313))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 (c e 301 313))"); +} + +#[test] +fn test_simple_inline_toomany_args_improper_no_tail_23() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun return-list (Xs) Xs) + + (defun F (A B . C) (list A B (return-list C))) + + (F X Y 99 101) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 (c e))"); +} + +#[test] +fn test_ni_ni_exact_no_tails_24() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun F (A B) (* A B)) + + (defun G (A B) (F A B)) + + (G X Y) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "35"); +} + +#[test] +fn test_ni_ni_exact_improper_tail_25() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun F (A B . C) (* A B C)) + + (defun G (X Y Z) (F X Y &rest Z)) + + (G X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 9)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "315"); +} + +#[test] +fn test_ni_ni_rest_call_25() { + let prog = indoc! {" +(mod X + (include *standard-cl-23*) + + (defun F Xs + (if Xs + (+ (f Xs) (F &rest (r Xs))) + () + ) + ) + + (F &rest X) + )"} + .to_string(); + let res = run_string(&prog, &"(13 99 144)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "256"); +} + +#[test] +fn test_ni_ni_exact_improper_no_tail_26() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun F (A B . C) (+ A B C)) + + (defun G (X Y) (F X Y)) + + (G X Y) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "12"); +} + +#[test] +fn test_simple_inline_exact_toofew_improper_tail_27() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun F (A B C . D) (list A B C (f D))) + + (defun G (X Y Z) (F X Y &rest Z)) + + (G X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (101 103))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 101 103)"); +} + +#[test] +fn test_ni_ni_exact_toofew_tail_28() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun F (A B C) (list A B C)) + + (defun G (X Y Z) (F X Y &rest Z)) + + (G X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (101 103))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 101)"); +} + +#[test] +fn test_ni_ni_exact_toofew_improper_no_tail_29() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun F (A B C . D) (list A B C (f D))) + + (defun G (X Y) (F X Y)) + + (G X Y) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()); + if let Err(e) = res { + assert!(e.1.contains("bad path")); + } else { + assert!(false); + } +} + +#[test] +fn test_ni_ni_exact_toofew_tail_30() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun F (A B C) (list A B C)) + + (defun G (X Y Z) (F X Y &rest Z)) + + (G X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (101 103))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 101)"); +} + +#[test] +fn test_inline_ni_toomany_args_31() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun F (A B) (+ A B)) + + (defun-inline G (X Y Z) (F X Y Z)) + + (G X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 9)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "12"); +} + +#[test] +fn test_inline_ni_toomany_args_improper_tail_32() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun return-list (Xs) Xs) + + (defun F (A B . C) (list A B (return-list C))) + + (F X Y 99 101 &rest Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (301 313))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 (c e 301 313))"); +} + +#[test] +fn test_simple_inline_toomany_args_improper_no_tail_33() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun return-list (Xs) Xs) + + (defun F (A B . C) (list A B (return-list C))) + + (F X Y 99 101) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 (c e))"); +} + +#[test] +fn test_inline_ni_exact_no_tails_34() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun F (A B) (* A B)) + + (defun-inline G (A B) (F A B)) + + (G X Y) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "35"); +} + +#[test] +fn test_inline_ni_exact_improper_tail_35() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun F (A B . C) (* A B C)) + + (defun-inline G (X Y Z) (F X Y &rest Z)) + + (G X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 9)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "315"); +} + +#[test] +fn test_simple_rest_call_inline_35() { + let prog = indoc! {" +(mod X + (include *standard-cl-23*) + + (defun sum (Xs) + (if Xs + (+ (f Xs) (sum (r Xs))) + () + ) + ) + + (defun-inline F (A1 . A2) (* A1 (sum A2))) + + (F 3 &rest X) + )"} + .to_string(); + let res = run_string(&prog, &"(13 99 144)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "768"); +} + +#[test] +fn test_inline_ni_exact_improper_no_tail_36() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun F (A B . C) (+ A B C)) + + (defun-inline G (X Y) (F X Y)) + + (G X Y) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "12"); +} + +#[test] +fn test_simple_inline_exact_toofew_improper_tail_37() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun F (A B C . D) (list A B C (f D))) + + (defun-inline G (X Y Z) (F X Y &rest Z)) + + (G X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (101 103))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 101 103)"); +} + +#[test] +fn test_inline_ni_exact_toofew_tail_38() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun F (A B C) (list A B C)) + + (defun-inline G (X Y Z) (F X Y &rest Z)) + + (G X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (101 103))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 101)"); +} + +#[test] +fn test_inline_ni_exact_toofew_improper_no_tail_39() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-23*) + + (defun F (A B C . D) (list A B C (f D))) + + (defun-inline G (X Y) (F X Y)) + + (G X Y) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()); + if let Err(e) = res { + assert!(e.1.contains("bad path")); + } else { + assert!(false); + } +} + +#[test] +fn test_inline_ni_exact_toofew_tail_40() { + let prog = indoc! {" +(mod (X Y Z) + (include *standard-cl-23*) + + (defun F (A B C) (list A B C)) + + (defun-inline G (X Y Z) (F X Y &rest Z)) + + (G X Y Z) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7 (101 103))".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 101)"); +} + +#[test] +fn test_repl_01() { + assert_eq!( + test_repl_outcome(vec!["(defun-inline F (A B) (+ A B))", "(F 5 7 9)"]) + .unwrap() + .unwrap(), + "(q . 12)" + ); +} + +const REPL_TEST_SUM: &'static str = indoc! {" +(defun sum (Xs) + (if Xs + (+ (f Xs) (sum (r Xs))) + () + ) + )"}; + +#[test] +fn test_repl_02() { + assert_eq!( + test_repl_outcome(vec![ + REPL_TEST_SUM, + "(defun-inline F (A B . C) (* A B (sum C)))", + "(F 5 7 99 101 &rest (list 301 313))" + ]) + .unwrap() + .unwrap(), + "(q . 28490)" + ); +} + +#[test] +fn test_repl_03() { + assert_eq!( + test_repl_outcome(vec![ + REPL_TEST_SUM, + "(defun-inline F (A B . C) (* A B (sum C)))", + "(F 5 7 99 101)" + ]) + .unwrap() + .unwrap(), + "(q . 7000)" + ); +} + +#[test] +fn test_repl_04() { + assert_eq!( + test_repl_outcome(vec!["(defun F (A B) (* A B))", "(F 5 7)"]) + .unwrap() + .unwrap(), + "(q . 35)" + ); +} + +#[test] +fn test_repl_05() { + assert_eq!( + test_repl_outcome(vec!["(defun F (A B . C) (* A B C))", "(F 5 7 &rest 9)"]) + .unwrap() + .unwrap(), + "(q . 315)" + ); +} + +#[test] +fn test_repl_06() { + assert_eq!( + test_repl_outcome(vec!["(defun F (A B . C) (+ A B C))", "(F 5 7)"]) + .unwrap() + .unwrap(), + "(q . 12)" + ); +} + +#[test] +fn test_repl_07() { + assert_eq!( + test_repl_outcome(vec![ + "(defun F (A B C . D) (list A B C (f D)))", + "(F 5 7 &rest (list 101 103))" + ]) + .unwrap() + .unwrap(), + "(q 5 7 101 103)" + ); +} + +#[test] +fn test_repl_08() { + assert_eq!( + test_repl_outcome(vec![ + "(defun F (A B C) (list A B C))", + "(F 5 7 &rest (list 101 103))" + ]) + .unwrap() + .unwrap(), + "(q 5 7 101)" + ); +} + +#[test] +fn test_repl_09() { + assert!( + test_repl_outcome(vec!["(defun F (A B C . D) (list A B C (f D)))", "(F 5 7)"]).is_err() + ); +} + +#[test] +fn test_repl_10() { + assert_eq!( + test_repl_outcome(vec![ + "(defun F (A B C) (list A B C))", + "(F 5 7 &rest (list 101 103))" + ]) + .unwrap() + .unwrap(), + "(q 5 7 101)" + ); +} From 701420849a405d0a2cbc14969b73840280cc18c0 Mon Sep 17 00:00:00 2001 From: arty Date: Mon, 31 Jul 2023 13:47:00 -0700 Subject: [PATCH 67/75] Improve --- src/tests/compiler/restargs.rs | 84 +++++++++++++++++----------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/src/tests/compiler/restargs.rs b/src/tests/compiler/restargs.rs index 22ae04a23..360457674 100644 --- a/src/tests/compiler/restargs.rs +++ b/src/tests/compiler/restargs.rs @@ -52,7 +52,7 @@ use crate::tests::compiler::repl::test_repl_outcome; fn test_simple_inline_toomany_args_01() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B) (+ A B)) @@ -67,7 +67,7 @@ fn test_simple_inline_toomany_args_01() { fn test_simple_inline_toomany_args_improper_tail_02() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun sum (Xs) (if Xs @@ -89,7 +89,7 @@ fn test_simple_inline_toomany_args_improper_tail_02() { fn test_simple_inline_toomany_args_improper_no_tail_03() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun sum (Xs) (if Xs @@ -111,7 +111,7 @@ fn test_simple_inline_toomany_args_improper_no_tail_03() { fn test_simple_inline_exact_no_tails_04() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B) (* A B)) @@ -126,7 +126,7 @@ fn test_simple_inline_exact_no_tails_04() { fn test_simple_inline_exact_improper_tail_05() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B . C) (* A B C)) @@ -141,7 +141,7 @@ fn test_simple_inline_exact_improper_tail_05() { fn test_simple_inline_exact_improper_no_tail_06() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B . C) (+ A B C)) @@ -156,7 +156,7 @@ fn test_simple_inline_exact_improper_no_tail_06() { fn test_simple_inline_exact_toofew_improper_tail_07() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B C . D) (list A B C (f D))) @@ -171,7 +171,7 @@ fn test_simple_inline_exact_toofew_improper_tail_07() { fn test_simple_inline_exact_toofew_tail_08() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B C) (list A B C)) @@ -186,7 +186,7 @@ fn test_simple_inline_exact_toofew_tail_08() { fn test_simple_inline_exact_toofew_improper_no_tail_09() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B C . D) (list A B C (f D))) @@ -205,7 +205,7 @@ fn test_simple_inline_exact_toofew_improper_no_tail_09() { fn test_simple_inline_exact_toofew_tail_10() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B C) (list A B C)) @@ -220,7 +220,7 @@ fn test_simple_inline_exact_toofew_tail_10() { fn test_inline_inline_toomany_args_11() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B) (+ A B)) @@ -237,7 +237,7 @@ fn test_inline_inline_toomany_args_11() { fn test_inline_inline_toomany_args_improper_tail_12() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline return-list (Xs) Xs) @@ -254,7 +254,7 @@ fn test_inline_inline_toomany_args_improper_tail_12() { fn test_simple_inline_toomany_args_improper_no_tail_13() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline return-list (Xs) Xs) @@ -271,7 +271,7 @@ fn test_simple_inline_toomany_args_improper_no_tail_13() { fn test_inline_inline_exact_no_tails_14() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B) (* A B)) @@ -288,7 +288,7 @@ fn test_inline_inline_exact_no_tails_14() { fn test_inline_inline_exact_improper_tail_15() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B . C) (* A B C)) @@ -305,7 +305,7 @@ fn test_inline_inline_exact_improper_tail_15() { fn test_inline_inline_exact_improper_no_tail_16() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B . C) (+ A B C)) @@ -322,7 +322,7 @@ fn test_inline_inline_exact_improper_no_tail_16() { fn test_simple_inline_exact_toofew_improper_tail_17() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B C . D) (list A B C (f D))) @@ -339,7 +339,7 @@ fn test_simple_inline_exact_toofew_improper_tail_17() { fn test_inline_inline_exact_toofew_tail_18() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B C) (list A B C)) @@ -356,7 +356,7 @@ fn test_inline_inline_exact_toofew_tail_18() { fn test_inline_inline_exact_toofew_improper_no_tail_19() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B C . D) (list A B C (f D))) @@ -377,7 +377,7 @@ fn test_inline_inline_exact_toofew_improper_no_tail_19() { fn test_simple_inline_exact_toofew_tail_20() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun-inline F (A B C) (list A B C)) @@ -394,7 +394,7 @@ fn test_simple_inline_exact_toofew_tail_20() { fn test_ni_ni_toomany_args_21() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B) (+ A B)) @@ -411,7 +411,7 @@ fn test_ni_ni_toomany_args_21() { fn test_ni_ni_toomany_args_improper_tail_22() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun return-list (Xs) Xs) @@ -428,7 +428,7 @@ fn test_ni_ni_toomany_args_improper_tail_22() { fn test_simple_inline_toomany_args_improper_no_tail_23() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun return-list (Xs) Xs) @@ -445,7 +445,7 @@ fn test_simple_inline_toomany_args_improper_no_tail_23() { fn test_ni_ni_exact_no_tails_24() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B) (* A B)) @@ -462,7 +462,7 @@ fn test_ni_ni_exact_no_tails_24() { fn test_ni_ni_exact_improper_tail_25() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B . C) (* A B C)) @@ -479,7 +479,7 @@ fn test_ni_ni_exact_improper_tail_25() { fn test_ni_ni_rest_call_25() { let prog = indoc! {" (mod X - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F Xs (if Xs @@ -499,7 +499,7 @@ fn test_ni_ni_rest_call_25() { fn test_ni_ni_exact_improper_no_tail_26() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B . C) (+ A B C)) @@ -516,7 +516,7 @@ fn test_ni_ni_exact_improper_no_tail_26() { fn test_simple_inline_exact_toofew_improper_tail_27() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B C . D) (list A B C (f D))) @@ -533,7 +533,7 @@ fn test_simple_inline_exact_toofew_improper_tail_27() { fn test_ni_ni_exact_toofew_tail_28() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B C) (list A B C)) @@ -550,7 +550,7 @@ fn test_ni_ni_exact_toofew_tail_28() { fn test_ni_ni_exact_toofew_improper_no_tail_29() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B C . D) (list A B C (f D))) @@ -571,7 +571,7 @@ fn test_ni_ni_exact_toofew_improper_no_tail_29() { fn test_ni_ni_exact_toofew_tail_30() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B C) (list A B C)) @@ -588,7 +588,7 @@ fn test_ni_ni_exact_toofew_tail_30() { fn test_inline_ni_toomany_args_31() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B) (+ A B)) @@ -605,7 +605,7 @@ fn test_inline_ni_toomany_args_31() { fn test_inline_ni_toomany_args_improper_tail_32() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun return-list (Xs) Xs) @@ -622,7 +622,7 @@ fn test_inline_ni_toomany_args_improper_tail_32() { fn test_simple_inline_toomany_args_improper_no_tail_33() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun return-list (Xs) Xs) @@ -639,7 +639,7 @@ fn test_simple_inline_toomany_args_improper_no_tail_33() { fn test_inline_ni_exact_no_tails_34() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B) (* A B)) @@ -656,7 +656,7 @@ fn test_inline_ni_exact_no_tails_34() { fn test_inline_ni_exact_improper_tail_35() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B . C) (* A B C)) @@ -673,7 +673,7 @@ fn test_inline_ni_exact_improper_tail_35() { fn test_simple_rest_call_inline_35() { let prog = indoc! {" (mod X - (include *standard-cl-23*) + (include *standard-cl-21*) (defun sum (Xs) (if Xs @@ -695,7 +695,7 @@ fn test_simple_rest_call_inline_35() { fn test_inline_ni_exact_improper_no_tail_36() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B . C) (+ A B C)) @@ -712,7 +712,7 @@ fn test_inline_ni_exact_improper_no_tail_36() { fn test_simple_inline_exact_toofew_improper_tail_37() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B C . D) (list A B C (f D))) @@ -729,7 +729,7 @@ fn test_simple_inline_exact_toofew_improper_tail_37() { fn test_inline_ni_exact_toofew_tail_38() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B C) (list A B C)) @@ -746,7 +746,7 @@ fn test_inline_ni_exact_toofew_tail_38() { fn test_inline_ni_exact_toofew_improper_no_tail_39() { let prog = indoc! {" (mod (X Y) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B C . D) (list A B C (f D))) @@ -767,7 +767,7 @@ fn test_inline_ni_exact_toofew_improper_no_tail_39() { fn test_inline_ni_exact_toofew_tail_40() { let prog = indoc! {" (mod (X Y Z) - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F (A B C) (list A B C)) From 9698dbbcabbf2bf22260e606f1ddf8d432b32ddb Mon Sep 17 00:00:00 2001 From: arty Date: Mon, 31 Jul 2023 19:09:11 -0700 Subject: [PATCH 68/75] Backported tail arguments --- src/compiler/cldb.rs | 1 + src/compiler/codegen.rs | 115 +++++++++++++++++++++------------ src/compiler/evaluate.rs | 24 +++++-- src/compiler/frontend.rs | 5 +- src/compiler/inline.rs | 5 +- src/compiler/optimize.rs | 2 +- src/tests/compiler/compiler.rs | 4 +- 7 files changed, 101 insertions(+), 55 deletions(-) diff --git a/src/compiler/cldb.rs b/src/compiler/cldb.rs index 95df3dcd2..b9cba0b15 100644 --- a/src/compiler/cldb.rs +++ b/src/compiler/cldb.rs @@ -157,6 +157,7 @@ impl CldbRun { match &new_step { Ok(RunStep::OpResult(l, x, _p)) => { + eprintln!("OpResult {x}"); if self.in_expr { self.to_print .insert("Result-Location".to_string(), l.to_string()); diff --git a/src/compiler/codegen.rs b/src/compiler/codegen.rs index 86a4597c9..ccee21e13 100644 --- a/src/compiler/codegen.rs +++ b/src/compiler/codegen.rs @@ -13,7 +13,7 @@ use crate::classic::clvm::__type_compatibility__::bi_one; use crate::compiler::clvm::run; use crate::compiler::compiler::{is_at_capture, run_optimizer}; use crate::compiler::comptypes::{ - fold_m, join_vecs_to_string, list_to_cons, Binding, BodyForm, Callable, CompileErr, + fold_m, join_vecs_to_string, list_to_cons, Binding, BodyForm, CallSpec, Callable, CompileErr, CompileForm, CompiledCode, CompilerOpts, ConstantKind, DefunCall, DefunData, HelperForm, InlineFunction, LetData, LetFormKind, PrimaryCodegen, }; @@ -291,32 +291,39 @@ fn generate_args_code( runner: Rc, opts: Rc, compiler: &PrimaryCodegen, - l: Srcloc, - list: &[Rc], -) -> Result { - if list.is_empty() { - Ok(SExp::Nil(l)) + call: &CallSpec, + with_primcons: bool, +) -> Result, CompileErr> { + if call.args.is_empty() && call.tail.is_none() { + Ok(Rc::new(SExp::Nil(call.loc.clone()))) } else { - let mut compiled_args: Vec> = Vec::new(); - for hd in list.iter() { + let mut compiled_args: Rc = if let Some(t) = call.tail.as_ref() { + generate_expr_code(allocator, runner.clone(), opts.clone(), compiler, t.clone())?.1 + } else { + Rc::new(SExp::Nil(call.loc.clone())) + }; + + for hd in call.args.iter().rev() { let generated = generate_expr_code( allocator, runner.clone(), opts.clone(), compiler, hd.clone(), - ) - .map(|x| x.1)?; - compiled_args.push(generated); + )? + .1; + if with_primcons { + compiled_args = + Rc::new(primcons(generated.loc(), generated.clone(), compiled_args)); + } else { + compiled_args = Rc::new(SExp::Cons( + generated.loc(), + generated.clone(), + compiled_args, + )); + } } - Ok(list_to_cons(l, &compiled_args)) - } -} - -fn cons_up(at: Rc) -> Rc { - match at.borrow() { - SExp::Cons(l, h, r) => Rc::new(primcons(l.clone(), h.clone(), cons_up(r.clone()))), - _ => at, + Ok(compiled_args) } } @@ -405,27 +412,42 @@ fn compile_call( &inline, l, &tl, - tail.clone() + tail, ), - Callable::CallDefun(l, lookup) => { - generate_args_code(allocator, runner, opts.clone(), compiler, l.clone(), &tl) - .and_then(|args| { - process_defun_call( - opts.clone(), - compiler, - l.clone(), - Rc::new(args), - Rc::new(lookup), - ) - }) - } + Callable::CallDefun(l, lookup) => generate_args_code( + allocator, + runner, + opts.clone(), + compiler, + &CallSpec { + loc: l.clone(), + name: an, + args: &tl, + tail, + original: Rc::new(BodyForm::Value(SExp::Nil(l.clone()))), + }, + true, + ) + .and_then(|args| { + process_defun_call(opts.clone(), compiler, l.clone(), args, Rc::new(lookup)) + }), - Callable::CallPrim(l, p) => { - generate_args_code(allocator, runner, opts, compiler, l.clone(), &tl).map(|args| { - CompiledCode(l.clone(), Rc::new(SExp::Cons(l, Rc::new(p), Rc::new(args)))) - }) - } + Callable::CallPrim(l, p) => generate_args_code( + allocator, + runner.clone(), + opts, + compiler, + &CallSpec { + loc: l.clone(), + name: an, + args: &tl, + tail: None, + original: Rc::new(BodyForm::Value(SExp::Nil(l.clone()))), + }, + false, + ) + .map(|args| CompiledCode(l.clone(), Rc::new(SExp::Cons(l, Rc::new(p), args)))), Callable::EnvPath => { if tl.len() == 1 { @@ -569,7 +591,15 @@ pub fn generate_expr_code( "created a call with no forms".to_string(), )) } else { - compile_call(allocator, runner, l.clone(), opts, compiler, &list, tail.clone()) + compile_call( + allocator, + runner, + l.clone(), + opts, + compiler, + list, + tail.clone(), + ) } } BodyForm::Mod(_, program) => { @@ -891,7 +921,10 @@ pub fn hoist_body_let_binding( new_tail }); - (vres, Rc::new(BodyForm::Call(l.clone(), new_call_list, new_tail))) + ( + vres, + Rc::new(BodyForm::Call(l.clone(), new_call_list, new_tail)), + ) } _ => (Vec::new(), body.clone()), } @@ -1134,7 +1167,7 @@ fn finalize_env_( match c.inlines.get(v) { Some(res) => { let (arg_list, arg_tail) = synthesize_args(res.args.clone()); - return replace_in_inline( + replace_in_inline( allocator, runner.clone(), opts.clone(), @@ -1145,7 +1178,7 @@ fn finalize_env_( &arg_list, arg_tail, ) - .map(|x| x.1); + .map(|x| x.1) } None => { /* Parentfns are functions in progress in the parent */ diff --git a/src/compiler/evaluate.rs b/src/compiler/evaluate.rs index 097473dea..2eec38783 100644 --- a/src/compiler/evaluate.rs +++ b/src/compiler/evaluate.rs @@ -13,7 +13,8 @@ use crate::compiler::clvm::run; use crate::compiler::codegen::codegen; use crate::compiler::compiler::is_at_capture; use crate::compiler::comptypes::{ - ArgsAndTail, Binding, BodyForm, CallSpec, CompileErr, CompileForm, CompilerOpts, HelperForm, LetData, LetFormKind, + Binding, BodyForm, CallSpec, CompileErr, CompileForm, CompilerOpts, HelperForm, LetData, + LetFormKind, }; use crate::compiler::frontend::frontend; use crate::compiler::runtypes::RunFailure; @@ -710,7 +711,7 @@ impl<'info> Evaluator { Ok(Rc::new(BodyForm::Quoted(compiled_borrowed.clone()))) } else { let pres = self - .lookup_prim(call.loc.clone(), &call.name) + .lookup_prim(call.loc.clone(), call.name) .map(|prim| { // Reduce all arguments. let mut converted_args = SExp::Nil(call.loc.clone()); @@ -746,7 +747,11 @@ impl<'info> Evaluator { Ok(res) => Ok(res), Err(e) => { if only_inline || self.ignore_exn { - Ok(Rc::new(BodyForm::Call(call.loc.clone(), target_vec.clone(), None))) + Ok(Rc::new(BodyForm::Call( + call.loc.clone(), + target_vec.clone(), + None, + ))) } else { Err(e) } @@ -754,7 +759,8 @@ impl<'info> Evaluator { } } else { // Since this is a primitive, there's no tail transform. - let reformed = BodyForm::Call(call.loc.clone(), target_vec.clone(), call.tail.clone()); + let reformed = + BodyForm::Call(call.loc.clone(), target_vec.clone(), call.tail.clone()); self.chase_apply(allocator, visited, Rc::new(reformed)) } }) @@ -901,7 +907,7 @@ impl<'info> Evaluator { env: &HashMap, Rc>, only_inline: bool, ) -> Result, CompileErr> { - let helper = select_helper(&self.helpers, &call.name); + let helper = select_helper(&self.helpers, call.name); match helper { Some(HelperForm::Defmacro(mac)) => { if call.tail.is_some() { @@ -926,8 +932,12 @@ impl<'info> Evaluator { return Ok(call.original.clone()); } - let argument_captures_untranslated = - build_argument_captures(&call.loc.clone(), arguments_to_convert, call.tail.clone(), defun.args.clone())?; + let argument_captures_untranslated = build_argument_captures( + &call.loc.clone(), + arguments_to_convert, + call.tail.clone(), + defun.args.clone(), + )?; let mut argument_captures = HashMap::new(); // Do this to protect against misalignment diff --git a/src/compiler/frontend.rs b/src/compiler/frontend.rs index 989f8a0c7..74ee466aa 100644 --- a/src/compiler/frontend.rs +++ b/src/compiler/frontend.rs @@ -5,8 +5,9 @@ use std::rc::Rc; use crate::classic::clvm::__type_compatibility__::bi_one; use crate::compiler::comptypes::{ - list_to_cons, ArgsAndTail, Binding, BodyForm, CallSpec, CompileErr, CompileForm, CompilerOpts, ConstantKind, - DefconstData, DefmacData, DefunData, HelperForm, IncludeDesc, LetData, LetFormKind, ModAccum, + list_to_cons, ArgsAndTail, Binding, BodyForm, CompileErr, CompileForm, CompilerOpts, + ConstantKind, DefconstData, DefmacData, DefunData, HelperForm, IncludeDesc, LetData, + LetFormKind, ModAccum, }; use crate::compiler::preprocessor::preprocess; use crate::compiler::rename::rename_children_compileform; diff --git a/src/compiler/inline.rs b/src/compiler/inline.rs index 4a04417cd..59f7ec2c8 100644 --- a/src/compiler/inline.rs +++ b/src/compiler/inline.rs @@ -11,7 +11,8 @@ use crate::classic::clvm_tools::stages::stage_0::TRunProgram; use crate::compiler::codegen::{generate_expr_code, get_call_name, get_callable}; use crate::compiler::compiler::is_at_capture; use crate::compiler::comptypes::{ - ArgsAndTail, BodyForm, Callable, CallSpec, CompileErr, CompiledCode, CompilerOpts, InlineFunction, PrimaryCodegen, + ArgsAndTail, BodyForm, CallSpec, Callable, CompileErr, CompiledCode, CompilerOpts, + InlineFunction, PrimaryCodegen, }; use crate::compiler::sexp::{decode_string, SExp}; use crate::compiler::srcloc::Srcloc; @@ -414,7 +415,7 @@ fn replace_inline_body( } } BodyForm::Value(SExp::Atom(_, a)) => { - let alookup = arg_lookup(callsite, inline.args.clone(), args, tail.clone(), a.clone())? + let alookup = arg_lookup(callsite, inline.args.clone(), args, tail, a.clone())? .unwrap_or_else(|| expr.clone()); Ok(alookup) } diff --git a/src/compiler/optimize.rs b/src/compiler/optimize.rs index 6bb13abb8..84a262042 100644 --- a/src/compiler/optimize.rs +++ b/src/compiler/optimize.rs @@ -115,7 +115,7 @@ pub fn optimize_expr( _ => None, } } - BodyForm::Call(l, forms, Some(_)) => None, + BodyForm::Call(_l, _forms, Some(_)) => None, BodyForm::Value(SExp::Integer(l, i)) => Some(( true, Rc::new(BodyForm::Quoted(SExp::Integer(l.clone(), i.clone()))), diff --git a/src/tests/compiler/compiler.rs b/src/tests/compiler/compiler.rs index c3447f9ab..25a41784c 100644 --- a/src/tests/compiler/compiler.rs +++ b/src/tests/compiler/compiler.rs @@ -1210,7 +1210,7 @@ fn test_inline_in_assign_not_actually_recursive() { fn test_simple_rest_call_0() { let prog = indoc! {" (mod X - (include *standard-cl-23*) + (include *standard-cl-21*) (defun F Xs (if Xs @@ -1230,7 +1230,7 @@ fn test_simple_rest_call_0() { fn test_simple_rest_call_inline() { let prog = indoc! {" (mod X - (include *standard-cl-23*) + (include *standard-cl-21*) (defun sum (Xs) (if Xs From 087f39e3ac4186aa8188908827d6fe087f153750 Mon Sep 17 00:00:00 2001 From: arty Date: Mon, 31 Jul 2023 19:14:06 -0700 Subject: [PATCH 69/75] Add tail let test cases to nail them down --- src/tests/compiler/restargs.rs | 51 ++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/src/tests/compiler/restargs.rs b/src/tests/compiler/restargs.rs index 360457674..7e427b34b 100644 --- a/src/tests/compiler/restargs.rs +++ b/src/tests/compiler/restargs.rs @@ -896,8 +896,55 @@ fn test_repl_10() { "(defun F (A B C) (list A B C))", "(F 5 7 &rest (list 101 103))" ]) - .unwrap() - .unwrap(), + .unwrap() + .unwrap(), "(q 5 7 101)" ); } + +#[test] +fn test_compiler_tail_let_inline() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-21*) + + (defun F (A B C) (list A B C)) + + (defun-inline G (X Y) (F X &rest (let ((Q (+ Y 1))) (list Y Q)))) + + (G X Y) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 8)"); +} + +#[test] +fn test_compiler_tail_let_ni() { + let prog = indoc! {" +(mod (X Y) + (include *standard-cl-21*) + + (defun F (A B C) (list A B C)) + + (defun G (X Y) (F X &rest (let ((Q (+ Y 1))) (list Y Q)))) + + (G X Y) + )"} + .to_string(); + let res = run_string(&prog, &"(5 7)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "(5 7 8)"); +} + +#[test] +fn test_repl_tail_let() { + assert_eq!( + test_repl_outcome(vec![ + "(defun F (A B C D) (list A B C D))", + "(F 5 7 &rest (let ((Q (list 101 103))) (c 99 Q)))" + ]) + .unwrap() + .unwrap(), + "(q 5 7 99 101)" + ); +} From 1c080346ecaccbccc74400ea28d41cee323bb837 Mon Sep 17 00:00:00 2001 From: arty Date: Mon, 31 Jul 2023 19:16:44 -0700 Subject: [PATCH 70/75] Silence --- src/compiler/cldb.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/compiler/cldb.rs b/src/compiler/cldb.rs index b9cba0b15..95df3dcd2 100644 --- a/src/compiler/cldb.rs +++ b/src/compiler/cldb.rs @@ -157,7 +157,6 @@ impl CldbRun { match &new_step { Ok(RunStep::OpResult(l, x, _p)) => { - eprintln!("OpResult {x}"); if self.in_expr { self.to_print .insert("Result-Location".to_string(), l.to_string()); From 20541919e9044d431bb12949392e6c2863faae9c Mon Sep 17 00:00:00 2001 From: arty Date: Mon, 31 Jul 2023 19:18:11 -0700 Subject: [PATCH 71/75] Add --- src/tests/compiler/restargs.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tests/compiler/restargs.rs b/src/tests/compiler/restargs.rs index 7e427b34b..0bd66c842 100644 --- a/src/tests/compiler/restargs.rs +++ b/src/tests/compiler/restargs.rs @@ -896,8 +896,8 @@ fn test_repl_10() { "(defun F (A B C) (list A B C))", "(F 5 7 &rest (list 101 103))" ]) - .unwrap() - .unwrap(), + .unwrap() + .unwrap(), "(q 5 7 101)" ); } @@ -943,8 +943,8 @@ fn test_repl_tail_let() { "(defun F (A B C D) (list A B C D))", "(F 5 7 &rest (let ((Q (list 101 103))) (c 99 Q)))" ]) - .unwrap() - .unwrap(), + .unwrap() + .unwrap(), "(q 5 7 99 101)" ); } From 1c75dec6ee9155186d48f1a51df4550bf2242905 Mon Sep 17 00:00:00 2001 From: arty Date: Tue, 1 Aug 2023 23:10:27 -0700 Subject: [PATCH 72/75] Add a RawCallSpec, many comments --- src/compiler/codegen.rs | 116 ++++++++++++++++++++++---------------- src/compiler/comptypes.rs | 12 +++- src/compiler/frontend.rs | 8 +++ src/compiler/inline.rs | 27 +++++++++ 4 files changed, 112 insertions(+), 51 deletions(-) diff --git a/src/compiler/codegen.rs b/src/compiler/codegen.rs index ccee21e13..60df525d4 100644 --- a/src/compiler/codegen.rs +++ b/src/compiler/codegen.rs @@ -15,7 +15,7 @@ use crate::compiler::compiler::{is_at_capture, run_optimizer}; use crate::compiler::comptypes::{ fold_m, join_vecs_to_string, list_to_cons, Binding, BodyForm, CallSpec, Callable, CompileErr, CompileForm, CompiledCode, CompilerOpts, ConstantKind, DefunCall, DefunData, HelperForm, - InlineFunction, LetData, LetFormKind, PrimaryCodegen, + InlineFunction, LetData, LetFormKind, PrimaryCodegen, RawCallSpec, }; use crate::compiler::debug::{build_swap_table_mut, relabel}; use crate::compiler::evaluate::{Evaluator, EVAL_STACK_LIMIT}; @@ -294,37 +294,44 @@ fn generate_args_code( call: &CallSpec, with_primcons: bool, ) -> Result, CompileErr> { + // Early return for the case where there are no provided arguments and no tail. if call.args.is_empty() && call.tail.is_none() { - Ok(Rc::new(SExp::Nil(call.loc.clone()))) + return Ok(Rc::new(SExp::Nil(call.loc.clone()))); + } + + // Ensure we start with either the specified tail or nil. + let mut compiled_args: Rc = if let Some(t) = call.tail.as_ref() { + generate_expr_code(allocator, runner.clone(), opts.clone(), compiler, t.clone())?.1 } else { - let mut compiled_args: Rc = if let Some(t) = call.tail.as_ref() { - generate_expr_code(allocator, runner.clone(), opts.clone(), compiler, t.clone())?.1 - } else { - Rc::new(SExp::Nil(call.loc.clone())) - }; + Rc::new(SExp::Nil(call.loc.clone())) + }; - for hd in call.args.iter().rev() { - let generated = generate_expr_code( - allocator, - runner.clone(), - opts.clone(), - compiler, - hd.clone(), - )? - .1; - if with_primcons { - compiled_args = - Rc::new(primcons(generated.loc(), generated.clone(), compiled_args)); - } else { - compiled_args = Rc::new(SExp::Cons( - generated.loc(), - generated.clone(), - compiled_args, - )); - } + // Now that we have the tail, generate the code for each argument in reverse + // order to cons on. + for hd in call.args.iter().rev() { + let generated = generate_expr_code( + allocator, + runner.clone(), + opts.clone(), + compiler, + hd.clone(), + )? + .1; + + // This function is now reused for purposes that make a simple list of the + // converted arguments, or generate valid code with primitive conses. + if with_primcons { + compiled_args = Rc::new(primcons(generated.loc(), generated.clone(), compiled_args)); + } else { + compiled_args = Rc::new(SExp::Cons( + generated.loc(), + generated.clone(), + compiled_args, + )); } - Ok(compiled_args) } + + Ok(compiled_args) } fn process_defun_call( @@ -365,19 +372,18 @@ pub fn get_call_name(l: Srcloc, body: BodyForm) -> Result, CompileErr> fn compile_call( allocator: &mut Allocator, runner: Rc, - l: Srcloc, opts: Rc, compiler: &PrimaryCodegen, - list: &[Rc], - tail: Option>, + call: &RawCallSpec, ) -> Result { - let arg_string_list: Vec> = list + let arg_string_list: Vec> = call + .args .iter() .map(|v| v.to_sexp().to_string().as_bytes().to_vec()) .collect(); let error = Err(CompileErr( - l.clone(), + call.loc.clone(), format!( "wierdly formed compile request: {}", join_vecs_to_string(";".as_bytes().to_vec(), &arg_string_list) @@ -385,11 +391,11 @@ fn compile_call( )); let compile_atom_head = |al: Srcloc, an: &Vec| { - let tl = list.iter().skip(1).cloned().collect(); + let tl = call.args.iter().skip(1).cloned().collect(); get_callable( opts.clone(), compiler, - l.clone(), + call.loc.clone(), Rc::new(SExp::Atom(al.clone(), an.to_vec())), ) .and_then(|calltype| match calltype { @@ -412,7 +418,7 @@ fn compile_call( &inline, l, &tl, - tail, + call.tail.clone(), ), Callable::CallDefun(l, lookup) => generate_args_code( @@ -420,12 +426,14 @@ fn compile_call( runner, opts.clone(), compiler, + // A callspec is a way to collect some info about a call, mainly + // to reduce the number of arguments to pass through. &CallSpec { loc: l.clone(), name: an, args: &tl, - tail, - original: Rc::new(BodyForm::Value(SExp::Nil(l.clone()))), + tail: call.tail.clone(), + original: call.original.clone(), }, true, ) @@ -470,7 +478,7 @@ fn compile_call( } Callable::RunCompiler => { - if list.len() >= 2 { + if call.args.len() >= 2 { let updated_opts = opts .set_stdenv(false) .set_in_defun(true) @@ -478,15 +486,15 @@ fn compile_call( .set_code_generator(compiler.clone()); let use_body = SExp::Cons( - l.clone(), - Rc::new(SExp::Atom(l.clone(), "mod".as_bytes().to_vec())), + call.loc.clone(), + Rc::new(SExp::Atom(call.loc.clone(), "mod".as_bytes().to_vec())), Rc::new(SExp::Cons( - l.clone(), - Rc::new(SExp::Nil(l.clone())), + call.loc.clone(), + Rc::new(SExp::Nil(call.loc.clone())), Rc::new(SExp::Cons( - list[1].loc(), - list[1].to_sexp(), - Rc::new(SExp::Nil(l.clone())), + call.args[1].loc(), + call.args[1].to_sexp(), + Rc::new(SExp::Nil(call.loc.clone())), )), )), ); @@ -500,7 +508,10 @@ fn compile_call( &mut unused_symbol_table, ) .map(|code| { - CompiledCode(l.clone(), Rc::new(primquote(l.clone(), Rc::new(code)))) + CompiledCode( + call.loc.clone(), + Rc::new(primquote(call.loc.clone(), Rc::new(code))), + ) }) } else { error.clone() @@ -509,7 +520,7 @@ fn compile_call( }) }; - match list[0].borrow() { + match call.args[0].borrow() { BodyForm::Value(SExp::Integer(al, an)) => { compile_atom_head(al.clone(), &u8_from_number(an.clone())) } @@ -594,11 +605,15 @@ pub fn generate_expr_code( compile_call( allocator, runner, - l.clone(), opts, compiler, - list, - tail.clone(), + // This is a partial callspec. + &RawCallSpec { + loc: l.clone(), + args: list, + tail: tail.clone(), + original: expr.clone(), + }, ) } } @@ -914,6 +929,7 @@ pub fn hoist_body_let_binding( vres.append(&mut new_helpers); } + // Ensure that we hoist a let occupying the &rest tail. let new_tail = tail.as_ref().map(|t| { let (mut new_tail_helpers, new_tail) = hoist_body_let_binding(outer_context.clone(), args.clone(), t.clone()); diff --git a/src/compiler/comptypes.rs b/src/compiler/comptypes.rs index e173ea0f4..081120105 100644 --- a/src/compiler/comptypes.rs +++ b/src/compiler/comptypes.rs @@ -389,7 +389,17 @@ pub struct CallSpec<'a> { pub original: Rc, } -/// A pair of arguments and an optional tail for function calls. +/// Raw callspec for use in codegen. +#[derive(Debug, Clone)] +pub struct RawCallSpec<'a> { + pub loc: Srcloc, + pub args: &'a [Rc], + pub tail: Option>, + pub original: Rc, +} + +/// A pair of arguments and an optional tail for function calls. The tail is +/// a function tail given by a final &rest argument. #[derive(Debug, Default, Clone)] pub struct ArgsAndTail { pub args: Vec>, diff --git a/src/compiler/frontend.rs b/src/compiler/frontend.rs index 74ee466aa..9340d5977 100644 --- a/src/compiler/frontend.rs +++ b/src/compiler/frontend.rs @@ -202,6 +202,11 @@ fn args_to_expression_list( if fname == b"&rest" { // Rest is a list containing one item that becomes the // tail. + // + // Downstream, we'll use the tail instead of a nil as the + // final element of a call form. In the inline case, this + // means that argument references will be generated into + // the runtime tail expression when appropriate. let args_no_tail = args_to_expression_list(opts, rest.clone())?; if args_no_tail.tail.is_some() { @@ -284,6 +289,9 @@ pub fn compile_bodyform( compile_bodyform(opts.clone(), op.clone()).map(|func| { let mut result_call = vec![Rc::new(func)]; let mut args_clone = atail.args.to_vec(); + // Ensure that the full extent of the call expression + // in the source file becomes the Srcloc given to the + // call itself. let ending = if atail.args.is_empty() { l.ending() } else { diff --git a/src/compiler/inline.rs b/src/compiler/inline.rs index 59f7ec2c8..0d27e8875 100644 --- a/src/compiler/inline.rs +++ b/src/compiler/inline.rs @@ -65,6 +65,17 @@ pub fn synthesize_args(arg_: Rc) -> (Vec>, Option], @@ -240,6 +256,11 @@ fn get_inline_callable( get_callable(opts, compiler, loc, name) } +/// Given a call to an inline function in incoming_spec from an inline function, +/// generate a list of expressions and optional tail expression that convert the +/// given argument expressions into their reified forms that inline the +/// expressions given in the ultimate original call. This allows inline functions +/// to seem to call each other as long as there's no cycle. fn make_args_for_call_from_inline( visited_inlines: &mut HashSet>, runner: Rc, @@ -265,6 +286,8 @@ fn make_args_for_call_from_inline( continue; } + // Since we're going into an argument, pass on a new copy of the visited + // set. let mut new_visited = visited_inlines.clone(); let replaced = replace_inline_body( &mut new_visited, @@ -281,6 +304,7 @@ fn make_args_for_call_from_inline( new_args.push(replaced); } + // Now that there are tail arguments, the tail gets a new visited set as well. let mut new_visited = visited_inlines.clone(); let replaced_tail = if let Some(t) = call_spec.tail.as_ref() { Some(replace_inline_body( @@ -305,6 +329,9 @@ fn make_args_for_call_from_inline( }) } +// The main workhorse of inlining, given a bodyform and the elements specifying +// how the inline function was called, generate an expansion of the expression +// that relies on the incoming argument expressions. #[allow(clippy::too_many_arguments)] fn replace_inline_body( visited_inlines: &mut HashSet>, From ad2c55c521909e34ffe15b172751a26544b6d311 Mon Sep 17 00:00:00 2001 From: arty Date: Tue, 1 Aug 2023 23:24:05 -0700 Subject: [PATCH 73/75] Rename hello.bin to a more obviously different name --- .../tests/{hello.bin => a-binary-file-called-hello.dat} | 0 src/tests/classic/embed.rs | 2 +- src/tests/classic/run.rs | 6 +++--- 3 files changed, 4 insertions(+), 4 deletions(-) rename resources/tests/{hello.bin => a-binary-file-called-hello.dat} (100%) diff --git a/resources/tests/hello.bin b/resources/tests/a-binary-file-called-hello.dat similarity index 100% rename from resources/tests/hello.bin rename to resources/tests/a-binary-file-called-hello.dat diff --git a/src/tests/classic/embed.rs b/src/tests/classic/embed.rs index 5267594b5..c451a885f 100644 --- a/src/tests/classic/embed.rs +++ b/src/tests/classic/embed.rs @@ -1,6 +1,6 @@ use crate::tests::classic::run::{do_basic_brun, do_basic_run}; -const EMBED_BIN_FILE: &str = "hello.bin"; +const EMBED_BIN_FILE: &str = "a-binary-file-called-hello.dat"; const EMBED_HEX_FILE: &str = "hex-embed-01.hex"; const EMBED_SEXP_FILE: &str = "embed.sexp"; const EMBED_NOT_EXIST: &str = "not-exist.txt"; diff --git a/src/tests/classic/run.rs b/src/tests/classic/run.rs index ad858ffe7..a926cec2e 100644 --- a/src/tests/classic/run.rs +++ b/src/tests/classic/run.rs @@ -611,7 +611,7 @@ fn test_embed_file_7() { "run".to_string(), "-i".to_string(), "resources/tests".to_string(), - "(mod () (embed-file hello bin hello.bin) hello)".to_string(), + "(mod () (embed-file hello bin a-binary-file-called-hello.dat) hello)".to_string(), ]) .trim() .to_string(); @@ -627,7 +627,7 @@ fn test_embed_file_8() { "run".to_string(), "-i".to_string(), "resources/tests".to_string(), - "(mod () (include *standard-cl-21*) (embed-file hello bin hello.bin) hello)".to_string(), + "(mod () (include *standard-cl-21*) (embed-file hello bin a-binary-file-called-hello.dat) hello)".to_string(), ]) .trim() .to_string(); @@ -643,7 +643,7 @@ fn test_embed_file_9() { "run".to_string(), "-i".to_string(), "resources/tests".to_string(), - "(mod () (include *standard-cl-21*) (embed-file hello bin hello.bin) (sha256 (sha256 hello)))".to_string(), + "(mod () (include *standard-cl-21*) (embed-file hello bin a-binary-file-called-hello.dat) (sha256 (sha256 hello)))".to_string(), ]) .trim() .to_string(); From 889374aba4268b20fc31ce0bdfbd68dcd2c7b557 Mon Sep 17 00:00:00 2001 From: arty Date: Wed, 2 Aug 2023 07:48:28 -0700 Subject: [PATCH 74/75] Change to ArgsAndTail::default() from feedback --- src/compiler/frontend.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/frontend.rs b/src/compiler/frontend.rs index 9340d5977..e4d66d510 100644 --- a/src/compiler/frontend.rs +++ b/src/compiler/frontend.rs @@ -194,7 +194,7 @@ fn args_to_expression_list( body: Rc, ) -> Result { if body.nilp() { - Ok(Default::default()) + Ok(ArgsAndTail::default()) } else { match body.borrow() { SExp::Cons(_l, first, rest) => { From d45e5f3219972984311ef5d44102dbb520f8d6a9 Mon Sep 17 00:00:00 2001 From: arty Date: Wed, 2 Aug 2023 13:43:11 -0700 Subject: [PATCH 75/75] more tests --- src/tests/classic/embed.rs | 94 ++++++++++++++++++++++++++------------ 1 file changed, 64 insertions(+), 30 deletions(-) diff --git a/src/tests/classic/embed.rs b/src/tests/classic/embed.rs index c451a885f..45691e57d 100644 --- a/src/tests/classic/embed.rs +++ b/src/tests/classic/embed.rs @@ -13,6 +13,26 @@ const BIN_TYPE: &str = "bin"; const HEX_TYPE: &str = "hex"; const SEXP_TYPE: &str = "sexp"; +#[test] +fn test_embed_file_as_variable_name() { + let program = indoc! {" +(mod (X) (defun embed-file (embed-file) (+ 1 embed-file)) (embed-file X)) + "} + .to_string(); + let compiled = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + program, + ]); + + let result = do_basic_brun(&vec!["brun".to_string(), compiled, "(103)".to_string()]) + .trim() + .to_string(); + + assert_eq!(result, "104"); +} + // Embed test matrix (suggested) // Exists, NotExists vs Bin, Hex, Sexp vs Modern, Classic // - Exists @@ -37,39 +57,53 @@ fn test_embed_exhaustive() { (SEXP_TYPE, EMBED_SEXP_FILE, SEXP_HASH), ]; - for exists in 0..=1 { - for (include_kind, include_file, want_hash) in include_list.iter() { - for modern in 0..=1 { - let modern_sigil = if modern > 0 { - "(include *standard-cl-21*)" - } else { - "" - }; - let filename = if exists > 0 { - include_file - } else { - EMBED_NOT_EXIST - }; + for order in 0..=1 { + for exists in 0..=1 { + for (include_kind, include_file, want_hash) in include_list.iter() { + for modern in 0..=1 { + let modern_sigil = if modern > 0 { + "(include *standard-cl-21*)" + } else { + "" + }; + let filename = if exists > 0 { + include_file + } else { + EMBED_NOT_EXIST + }; + + let embed_pt: Vec = (0..=1) + .map(|i| { + if i == order { + format!("(embed-file embedded-data {include_kind} {filename})") + } else { + "".to_string() + } + }) + .collect(); + + let program = format!("(mod () {modern_sigil} {} (include sha256tree.clib) {} (sha256tree embedded-data))", embed_pt[0], embed_pt[1]); + eprintln!("program {program}"); - let program = format!("(mod () {modern_sigil} (include sha256tree.clib) (embed-file embedded-data {include_kind} {filename}) (sha256tree embedded-data))"); - let compiled = do_basic_run(&vec![ - "run".to_string(), - "-i".to_string(), - "resources/tests".to_string(), - program, - ]); + let compiled = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + program, + ]); - if exists > 0 { - let output = - do_basic_brun(&vec!["brun".to_string(), compiled, "()".to_string()]) - .trim() - .to_string(); - assert_eq!(want_hash, &output); - } else { - if modern > 0 { - assert!(compiled.contains("could not find not-exist.txt")); + if exists > 0 { + let output = + do_basic_brun(&vec!["brun".to_string(), compiled, "()".to_string()]) + .trim() + .to_string(); + assert_eq!(want_hash, &output); } else { - assert!(compiled.starts_with("FAIL:")); + if modern > 0 { + assert!(compiled.contains("could not find not-exist.txt")); + } else { + assert!(compiled.starts_with("FAIL:")); + } } } }