use std::collections::HashMap;
use clvmr::allocator::{Allocator, NodePtr, SExp};
use crate::classic::clvm::sexp::proper_list;
use crate::compiler::sexp::decode_string;
pub const OPT_STRATEGY_BASE_STEPPING: i32 = 23;
pub const MAX_STEPPING: i32 = 24;
#[derive(Clone, Debug, Default)]
pub struct AcceptedDialect {
pub stepping: Option<i32>,
pub strict: bool,
pub int_fix: bool,
}
#[derive(Clone, Debug)]
pub struct DialectDescription {
pub accepted: AcceptedDialect,
pub content: String,
}
lazy_static! {
pub static ref KNOWN_DIALECTS: HashMap<String, DialectDescription> = {
let mut dialects: HashMap<String, DialectDescription> = HashMap::new();
let dialect_list = [
(
"*standard-cl-21*",
DialectDescription {
accepted: AcceptedDialect {
stepping: Some(21),
..AcceptedDialect::default()
},
content: indoc! {"(
(defconstant *chialisp-version* 21)
)"}
.to_string(),
},
),
(
"*strict-cl-21*",
DialectDescription {
accepted: AcceptedDialect {
stepping: Some(21),
strict: true,
int_fix: false,
},
content: indoc! {"(
(defconstant *chialisp-version* 22)
)"}
.to_string(),
},
),
(
"*standard-cl-22*",
DialectDescription {
accepted: AcceptedDialect {
stepping: Some(22),
strict: false,
int_fix: false,
},
content: indoc! {"(
(defconstant *chialisp-version* 22)
)"}
.to_string(),
},
),
(
"*standard-cl-23*",
DialectDescription {
accepted: AcceptedDialect {
stepping: Some(23),
strict: true,
int_fix: false,
},
content: indoc! {"(
(defconstant *chialisp-version* 23)
)"}
.to_string(),
},
),
(
"*standard-cl-23.1*",
DialectDescription {
accepted: AcceptedDialect {
stepping: Some(23),
strict: true,
int_fix: true,
},
content: indoc! {"(
(defconstant *chialisp-version* 23)
)"}
.to_string(),
},
),
(
"*standard-cl-24*",
DialectDescription {
accepted: AcceptedDialect {
stepping: Some(24),
strict: true,
int_fix: true,
},
content: indoc! {"(
(defconstant *chialisp-version* 24)
)"}
.to_string(),
},
),
];
for (n, v) in dialect_list.iter() {
dialects.insert(n.to_string(), v.clone());
}
dialects
};
}
fn include_dialect(allocator: &Allocator, e: &[NodePtr]) -> Option<AcceptedDialect> {
let include_keyword_sexp = e[0];
let name_sexp = e[1];
if let (SExp::Atom, SExp::Atom) = (
allocator.sexp(include_keyword_sexp),
allocator.sexp(name_sexp),
) {
let include_keyword_atom = allocator.atom(include_keyword_sexp);
let name_atom = allocator.atom(name_sexp);
if include_keyword_atom.as_ref() == b"include" {
if let Some(dialect) = KNOWN_DIALECTS.get(&decode_string(name_atom.as_ref())) {
return Some(dialect.accepted.clone());
}
}
}
None
}
pub fn detect_modern(allocator: &mut Allocator, sexp: NodePtr) -> AcceptedDialect {
let mut result = AcceptedDialect::default();
if let Some(l) = proper_list(allocator, sexp, true) {
for elt in l.iter() {
let detect_modern_result = detect_modern(allocator, *elt);
if detect_modern_result.stepping.is_some() {
result = detect_modern_result;
break;
}
match proper_list(allocator, *elt, true) {
None => {
continue;
}
Some(e) => {
if e.len() != 2 {
continue;
}
if let Some(dialect) = include_dialect(allocator, &e) {
result = dialect;
break;
}
}
}
}
}
result
}