UP | HOME

Predicados

Table of Contents

Arquivo: axioms/predicates.rs.

use gc::Gc;
use crate::maj_list;
use crate::core::Maj;
use crate::core::MajState;
use super::primitives::{
    maj_car,
    maj_cdr,
    maj_err
};

1. symbolp: Teste de símbolo

pub fn maj_symbolp(x: Gc<Maj>) -> Gc<Maj> {
    if let Maj::Sym(_) = *x {
        return Maj::t();
    }
    Maj::nil()
}

2. eq: Teste de identidade simbólica

pub fn maj_eq(x: Gc<Maj>, y: Gc<Maj>) -> Gc<Maj> {
    if let Maj::Sym(idx) = *x {
        if let Maj::Sym(idy) = *y {
            if idx == idy {
                return Maj::t();
            }
        }
    }
    Maj::nil()
}

3. nilp: Teste de nulidade

pub fn maj_nilp(x: Gc<Maj>) -> Gc<Maj> {
    maj_eq(x, Maj::nil())
}

4. consp: Teste de célula cons

pub fn maj_consp(x: Gc<Maj>) -> Gc<Maj> {
    if let Maj::Cons { car: _, cdr: _ } = *x {
        return Maj::t();
    }
    Maj::nil()
}

5. atomp: Teste de atomicidade

pub fn maj_atomp(x: Gc<Maj>) -> Gc<Maj> {
    if let Maj::Cons { car: _, cdr: _ } = *x {
        return Maj::nil()
    }
    Maj::t()
}

6. charp: Teste de caractere

pub fn maj_charp(x: Gc<Maj>) -> Gc<Maj> {
    if let Maj::Char(_) = *x {
        return Maj::t();
    }
    Maj::nil()
}

7. char=: Comparação de caracteres

pub fn maj_char_equals(x: Gc<Maj>, y: Gc<Maj>) -> Gc<Maj> {
    if let Maj::Char(xc) = *x.clone() {
        if let Maj::Char(yc) = *y.clone() {
            if xc == yc {
                Maj::t()
            } else {
                Maj::nil()
            }
        } else {
            maj_err(Maj::string("{} is not a character"),
                    maj_list!(y))
        }
    } else {
        maj_err(Maj::string("{} is not a character"),
                maj_list!(x))
    }
}

8. streamp: Teste de stream

pub fn maj_streamp(x: Gc<Maj>) -> Gc<Maj> {
    if let Maj::Stream(_) = *x {
        return Maj::t();
    }
    Maj::nil()
}

9. numberp: Teste de número

pub fn maj_numberp(x: Gc<Maj>) -> Gc<Maj> {
    if let Maj::Number(_) = &*x {
        return Maj::t();
    }
    Maj::nil()
}

9.1. integerp: Teste de número inteiro

pub fn maj_integerp(x: Gc<Maj>) -> Gc<Maj> {
    use crate::core::types::MajNumber;
    if let Maj::Number(num) = &*x {
        if let MajNumber::Integer(_) = num {
            return Maj::t();
        }
    }
    Maj::nil()
}

9.2. floatp: Teste de ponto flutuante

pub fn maj_floatp(x: Gc<Maj>) -> Gc<Maj> {
    use crate::core::types::MajNumber;
    if let Maj::Number(num) = &*x {
        if let MajNumber::Float(_) = num {
            return Maj::t();
        }
    }
    Maj::nil()
}

9.3. fractionp: Teste de fração

pub fn maj_fractionp(x: Gc<Maj>) -> Gc<Maj> {
    use crate::core::types::MajNumber;
    if let Maj::Number(num) = &*x {
        if let MajNumber::Fraction(_, _) = num {
            return Maj::t();
        }
    }
    Maj::nil()
}

9.4. complexp: Teste de número complexo

pub fn maj_complexp(x: Gc<Maj>) -> Gc<Maj> {
    use crate::core::types::MajNumber;
    if let Maj::Number(num) = &*x {
        if let MajNumber::Complex {
            real: _,
            imag: _
        } = num {
            return Maj::t();
        }
    }
    Maj::nil()
}

10. vectorp: Teste de vetor

pub fn maj_vectorp(x: Gc<Maj>) -> Gc<Maj> {
    if let Maj::Vector(_) = &*x {
        Maj::t()
    } else {
        Maj::nil()
    }
}

11. id: Teste de identidade

pub fn maj_id(x: Gc<Maj>, y: Gc<Maj>) -> Gc<Maj> {
    match *x {
        Maj::Sym(_) => {
            if let Maj::Sym(_) = *y {
                return maj_eq(x, y);
            }
        },
        Maj::Char(chrx) => {
            if let Maj::Char(chry) = *y {
                if chrx == chry {
                    return Maj::t();
                }
            }
        },
        _ => {
            let x_ptr = Gc::into_raw(x);
            let y_ptr = Gc::into_raw(y);
            if x_ptr == y_ptr {
                return Maj::t();
            }
        }
    }
    Maj::nil()
}

12. proper-list-p: Teste de lista adequada

Uma lista adequada é qualquer lista que termina com um símbolo nil apropriado. Então, por exemplo, (1 2 3) é uma lista adequada, mas (1 2 3 . 4) não é. Isto fica evidente quando comparamos a impressão de ambas as respectivas listas com notação de pontos:

  • (1 . (2 . (3 . nil)))
  • (1 . (2 . (3 . 4)))

Uma lista vazia (ou seja, o próprio símbolo nil) também é considerada uma lista adequada.

pub fn maj_proper_list_p(x: Gc<Maj>) -> Gc<Maj> {
    let is_cons = maj_consp(x.clone()).to_bool();
    let is_nil  = maj_nilp(x.clone()).to_bool();

    if !is_cons && !is_nil {
        return Maj::nil();
    }

    let mut itr = x.clone();
    while !maj_nilp(itr.clone()).to_bool()  {
        if let Maj::Cons { car: _, cdr } = &*itr.clone() {
            itr = cdr.clone();
        } else {
            return Maj::nil();
        }
    }
    Maj::t()
}

13. stringp: Teste de String

Uma string é um vetor de caracteres. Portanto, qualquer vetor que tenha char como seu tipo será uma string.

pub fn maj_stringp(x: Gc<Maj>) -> Gc<Maj> {
    use crate::core::types::MajVector;
    if let Maj::Vector(v) = &*x {
        if let MajVector::Char(_) = &v {
            return Maj::t();
        }
    }
    Maj::nil()
}

14. literalp: Teste de literal

Um literal é toda lista adequada que seja iniciada com o símbolo lit. Para tanto, basta que utilizemos car, das funções primitivas, para identificar tal símbolo, dado que a lista fornecida seja adequada.

pub fn maj_literalp(x: Gc<Maj>) -> Gc<Maj> {
    if maj_proper_list_p(x.clone()).to_bool() &&
        maj_eq(maj_car(x.clone()), Maj::lit()).to_bool() {
            return Maj::t();
        }
    Maj::nil()
}

15. primitivep: Teste de primitivas

Uma primitiva não possui representação realmente. Todavia, utilizamos literais para representá-la no sistema; essas literais servirão para invocarmos tais primitivas, como se fossem clausuras, onde forem necessárias.

A representação literal de uma primitiva tem, como segundo elemento, o símbolo prim.

pub fn maj_primitivep(x: Gc<Maj>) -> Gc<Maj> {
    if maj_literalp(x.clone()).to_bool() {
        let sym = maj_car(maj_cdr(x));
        if maj_eq(sym, Maj::prim()).to_bool() {
            return Maj::t();
        }
    }
    Maj::nil()
}

16. closurep: Teste de clausura

Uma clausura é definida como uma literal, tal que seu segundo elemento seja exatamente o símbolo closure. Podemos utilizar car e cdr para realizar essa comparação.

pub fn maj_closurep(x: Gc<Maj>) -> Gc<Maj> {
    if maj_literalp(x.clone()).to_bool() {
        let sym = maj_car(maj_cdr(x));
        if maj_eq(sym, Maj::closure()).to_bool() {
            return Maj::t();
        }
    }
    Maj::nil()
}

17. functionp: Teste de função

Uma função é um termo genérico que designa uma clausura ou uma primitiva. Sendo assim, qualquer desses dois será uma função.

pub fn maj_functionp(x: Gc<Maj>) -> Gc<Maj> {
    if maj_primitivep(x.clone()).to_bool()
        || maj_closurep(x).to_bool()
    {
        return Maj::t();
    }
    Maj::nil()
}

18. macrop: Teste de macro

Um macro também é definido como um literal, tal que seu segundo elemento seja exatamente o símbolo macro, e seu terceiro elemento seja uma clausura.

pub fn maj_macrop(x: Gc<Maj>) -> Gc<Maj> {
    if maj_literalp(x.clone()).to_bool() {
        let sym = maj_car(maj_cdr(x));
        if maj_eq(sym, Maj::macro_sym()).to_bool() {
            return Maj::t();
        }
    }
    Maj::nil()
}

19. errorp: Teste de erro

Pela mesma lógica de closurep e primitivep, erros também são literais, onde o segundo elemento precisa ser o símbolo error. Demais elementos serão a string de formato, e então demais objetos que ajudem a compor esse formato.

pub fn maj_errorp(x: Gc<Maj>) -> Gc<Maj> {
    if maj_proper_list_p(x.clone()).to_bool() {
        let sym = maj_car(maj_cdr(x));
        if maj_eq(sym, Maj::error()).to_bool() {
            return Maj::t();
        }
    }
    Maj::nil()
}

20. zerop: Teste de nulidade numérica

(v. comparação numérica)

pub fn maj_zerop(
    mut state: &mut MajState,
    env: Gc<Maj>,
    x: Gc<Maj>
) -> Gc<Maj> {
    use crate::axioms::primitives::maj_arithm_eq;
    maj_arithm_eq(&mut state, env,
                  Maj::integer(0), x, Maj::nil())
}

21. Registro em contexto global

De volta a axioms/predicates.rs

pub fn maj_gen_predicates(state: &mut MajState) {
    use crate::axioms::{ MajPrimFn, MajPrimArgs };
    use crate::maj_destructure_args;

    let predicates: Vec<(&str, MajPrimArgs, MajPrimFn)> = vec![
        ("symbolp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_symbolp(first)
        }),
        ("eq", MajPrimArgs::Required(2), |_, args, _| {
            maj_destructure_args!(args, first, rest, second);
            maj_eq(first, second)
        }),
        ("nilp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_nilp(first)
        }),
        ("consp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_consp(first)
        }),
        ("atomp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_atomp(first)
        }),
        ("charp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_charp(first)
        }),
        ("char=", MajPrimArgs::Required(2), |_, args, _| {
            maj_destructure_args!(args, first, rest, second);
            maj_char_equals(first, second)
        }),
        ("streamp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_streamp(first)
        }),
        ("numberp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_numberp(first)
        }),
        ("integerp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_integerp(first)
        }),
        ("floatp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_floatp(first)
        }),
        ("fractionp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_fractionp(first)
        }),
        ("complexp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_complexp(first)
        }),
        ("vectorp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_vectorp(first)
        }),
        ("id", MajPrimArgs::Required(2), |_, args, _| {
            maj_destructure_args!(args, first, rest, second);
            maj_id(first, second)
        }),
        ("proper-list-p", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_proper_list_p(first)
        }),
        ("stringp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_stringp(first)
        }),
        ("literalp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_literalp(first)
        }),
        ("primitivep", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_primitivep(first)
        }),
        ("closurep", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_closurep(first)
        }),
        ("functionp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_functionp(first)
        }),
        ("macrop", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_macrop(first)
        }),
        ("errorp", MajPrimArgs::Required(1), |_, args, _| {
            maj_destructure_args!(args, first);
            maj_errorp(first)
        }),
        ("zerop", MajPrimArgs::Required(1),
         |mut state, args, env| {
             maj_destructure_args!(args, first);
             maj_zerop(&mut state, env, first)
         }),
    ];

    for predicate in predicates.iter() {
        let (name, arity, f) = predicate;
        state.register_primitive(name, *arity, *f);
    }
}

Author: Lucas S. Vieira

Created: 2022-10-24 seg 00:27

Validate