Interpretação
Arquivo: evaluator/evaluation.rs
use gc::Gc; use crate::maj_list; use crate::core::{ Maj, MajState }; use crate::axioms::predicates::{ maj_eq, maj_nilp, maj_symbolp, maj_errorp, maj_literalp, maj_numberp, maj_charp, maj_streamp, maj_stringp, maj_macrop }; use crate::axioms::primitives::{ maj_car, maj_cdr, maj_err, maj_length }; use crate::axioms::utils::{ STACK_RED_ZONE, STACK_PER_RECURSION }; use super::maj_apply;
1. TODO Interpretação genérica
- Um erro deverá suspender a interpretação imediatamente, sendo levado ao top-level da interpretação sem que mais ações sejam feitas;
- Um objeto auto-interpretável deverá ser interpretado para si mesmo;
- Um literal deve ser interpretado para si mesmo;
- Uma variável deve ser consultada no contexto atual;
- Uma expressão quotada deve retornar seu conteúdo;
- Uma expressão quasiquotada deverá realizar substituições apropriadamente e retornar seu valor apropriado;
- Uma definição deverá alterar o contexto global;
- Uma condição deverá ter seu predicado interpretado, e então realizar branching para a situação adequada;
- Uma clausura deverá ser transformada em um literal apropriado, condizente com clausuras;
- Uma forma do deverá ter cada um de seus elementos interpretados, e será retornado o valor de interpretação do último;
- and
- or
- Uma aplicação consistirá em delegar a aplicação do primeiro elemento aos argumentos informados. Antes desse passo de despacho, cada um dos elementos (incluindo o primeiro) deverá ser interpretado recursivamente;
- Caso nenhuma das situações se encaixe, então constitui-se um erro de interpretação de uma forma desconhecida.
pub fn maj_eval(mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj>) -> Gc<Maj> { // use crate::maj_format; // println!("EVAL: {}", maj_format(&state, expr.clone())); /* Errors */ if maj_errorp(expr.clone()).to_bool() { expr } /* Special forms */ // self-evaluating forms: // Literals, numbers, characters, streams else if maj_is_selfeval(expr.clone()) { expr } // variables else if maj_symbolp(expr.clone()).to_bool() { state.lookup(env, expr) } // quote else if maj_quotep(expr.clone()).to_bool() { maj_handle_quote(expr) } // quasiquote else if maj_quasiquotep(expr.clone()).to_bool() { maj_handle_quasiquote(&mut state, expr, env) } // macros else if maj_macp(expr.clone()).to_bool() { maj_handle_mac(expr, env) } // definitions else if maj_defp(&mut state, expr.clone()).to_bool() { maj_handle_definition(&mut state, expr, env) } // redefinitions else if maj_setp(&mut state, expr.clone()).to_bool() { maj_handle_redefinition(&mut state, expr, env) } // redefinitions for a cons cell else if maj_set_car_p(&mut state, expr.clone()).to_bool() { maj_handle_redefine_car(&mut state, expr, env) } else if maj_set_cdr_p(&mut state, expr.clone()).to_bool() { maj_handle_redefine_cdr(&mut state, expr, env) } // conditionals else if maj_ifp(&mut state, expr.clone()).to_bool() { maj_handle_if(&mut state, expr, env) } // closures else if maj_fnp(expr.clone()).to_bool() { maj_handle_fn(expr, env) } // do else if maj_dop(&mut state, expr.clone()).to_bool() { maj_handle_do(&mut state, expr, env) } // and else if maj_andp(&mut state, expr.clone()).to_bool() { maj_handle_and(&mut state, expr, env) } // or else if maj_orp(&mut state, expr.clone()).to_bool() { maj_handle_or(&mut state, expr, env) } // apply else if maj_applyp(expr.clone()).to_bool() { maj_handle_apply(&mut state, expr, env) } // while else if maj_whilep(&mut state, expr.clone()).to_bool() { maj_handle_while(&mut state, expr, env) } // letrec else if maj_letrecp(&mut state, expr.clone()).to_bool() { maj_handle_letrec(&mut state, expr, env) } // unwind-protect else if maj_unwind_protect_p(&mut state, expr.clone()).to_bool() { maj_handle_unwind_protect(&mut state, expr, env) } // application else { let fun = maj_eval(&mut state, maj_car(expr.clone()), env.clone()); if maj_errorp(fun.clone()).to_bool() { return fun; } let args = if maj_macrop(fun.clone()).to_bool() { maj_cdr(expr) } else { maj_evlist(&mut state, maj_cdr(expr), env.clone()) }; if maj_errorp(args.clone()).to_bool() { return args; } stacker::maybe_grow( STACK_RED_ZONE, STACK_PER_RECURSION, || maj_apply(&mut state, fun, args, env)) } }
2. TODO Interpretação iterativa de listas
fn maj_evlist(mut state: &mut MajState, list: Gc<Maj>, env: Gc<Maj>) -> Gc<Maj> { let mut elts = Vec::new(); let mut itr = list.clone(); // Evaluate member by member while !maj_nilp(itr.clone()).to_bool() { let elt = maj_car(itr.clone()); let elt = maj_eval(&mut state, elt, env.clone()); if maj_errorp(elt.clone()).to_bool() { return elt; } elts.push(elt); itr = maj_cdr(itr); } elts.reverse(); // Generate list of evaluated members backwards let mut new_list = Maj::nil(); for elt in elts.iter() { new_list = Maj::cons(elt.clone(), new_list.clone()); } new_list }
3. TODO Formas especiais
3.1. Expressão quotada
fn maj_handle_quote(expr: Gc<Maj>) -> Gc<Maj> { let length = maj_length(expr.clone()) .to_integer().unwrap(); if length != 2 { return maj_err( Maj::string("Invalid syntax: {}"), maj_list!(expr)); } maj_car(maj_cdr(expr)) }
3.2. Expressão quasiquotada
fn maj_handle_quasiquote(mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj>) -> Gc<Maj> { let length = maj_length(expr.clone()) .to_integer().unwrap(); if length != 2 { return maj_err( Maj::string("Invalid syntax: {}"), maj_list!(expr)); } maj_do_quasiquote(&mut state, maj_car(maj_cdr(expr)), env) }
fn maj_do_quasiquote( mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj> ) -> Gc<Maj> { use crate::axioms::predicates::maj_atomp; use crate::axioms::primitives::maj_append; if maj_atomp(expr.clone()).to_bool() { return expr; } let car = maj_car(expr.clone()); let cdr = maj_cdr(expr.clone()); let cadr = maj_car(cdr.clone()); if maj_unquotep(expr.clone()).to_bool() || maj_unquote_splice_p(expr.clone()).to_bool() { maj_eval(&mut state, cadr.clone(), env.clone()) } else { let should_append = maj_unquote_splice_p( car.clone() ).to_bool(); let car_qquote = maj_do_quasiquote( &mut state, car.clone(), env.clone()); if maj_errorp(car_qquote.clone()).to_bool() { return car_qquote; } let rest = maj_do_quasiquote( &mut state, cdr.clone(), env.clone()); if maj_errorp(rest.clone()).to_bool() { return rest; } if should_append { maj_append(maj_list!(car_qquote, rest)) } else { Maj::cons(car_qquote, rest) } } }
3.3. Definição (def
)
fn maj_handle_definition( mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj> ) -> Gc<Maj> { let length = maj_length(expr.clone()) .to_integer().unwrap(); if length != 3 { return maj_err( Maj::string("Invalid syntax: {}"), maj_list!(expr)); } let sym = maj_car(maj_cdr(expr.clone())); let val = maj_car(maj_cdr(maj_cdr(expr))); // Evaluate associated value before binding let val = maj_eval(&mut state, val, env); if maj_errorp(val.clone()).to_bool() { return val; } if maj_symbolp(sym.clone()).to_bool() { // Try finding thing on environment. // An error means it does not exist let element = state.assoc(Maj::nil(), sym.clone()); if !maj_errorp(element.clone()).to_bool() { // If exists, attribute destructively let new_entry = Maj::cons(sym.clone(), val); unsafe { let raw_element = Gc::into_raw(element.clone()); std::ptr::copy_nonoverlapping( Gc::into_raw(new_entry.clone()), raw_element as *mut Maj, 1); } sym } else { // Else, push new element to state state.push(sym, val) } } else { maj_err( Maj::string("{} is not a symbol"), maj_list!(sym)) } }
3.4. Redefinição (set
)
fn maj_handle_redefinition( mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj> ) -> Gc<Maj> { let length = maj_length(expr.clone()) .to_integer().unwrap(); if length != 3 { return maj_err( Maj::string("Invalid syntax: {}"), maj_list!(expr)); } let sym = maj_car(maj_cdr(expr.clone())); let val = maj_car(maj_cdr(maj_cdr(expr))); // Evaluate associated value before binding let val = maj_eval(&mut state, val, env.clone()); if maj_errorp(val.clone()).to_bool() { return val; } if maj_symbolp(sym.clone()).to_bool() { // Try finding thing on both environments. let element = state.assoc(env, sym.clone()); if maj_errorp(element.clone()).to_bool() { element } else { // When found, replace binding cons let new_binding = Maj::cons(sym.clone(), val); unsafe { let rawelement = Gc::into_raw(element.clone()); std::ptr::copy_nonoverlapping( Gc::into_raw(new_binding.clone()), rawelement as *mut Maj, 1); } sym } } else { maj_err( Maj::string("{} is not a symbol"), maj_list!(sym)) } }
3.5. Redefinições para células cons (set-car
e set-cdr
)
fn maj_handle_redefine_cxr_helper( mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj> ) -> Result<(Gc<Maj>, Gc<Maj>), Gc<Maj>> { use crate::axioms::predicates::maj_consp; let length = maj_length(expr.clone()) .to_integer().unwrap(); if length != 3 { return Err(maj_err( Maj::string("Invalid syntax: {}"), maj_list!(expr))); } let value = maj_car(maj_cdr(maj_cdr(expr.clone()))); let pair = maj_car(maj_cdr(expr)); let value = maj_eval(&mut state, value, env.clone()); if maj_errorp(value.clone()).to_bool() { return Err(value); } let pair = maj_eval(&mut state, pair, env.clone()); if maj_errorp(pair.clone()).to_bool() { return Err(pair); } else if !maj_consp(pair.clone()).to_bool() { return Err(maj_err( Maj::string("{} is not a cons cell"), maj_list!(pair))); } Ok((pair, value)) }
fn maj_handle_redefine_car( mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj> ) -> Gc<Maj> { match maj_handle_redefine_cxr_helper(&mut state, expr, env) { Ok((pair, value)) => { let new_pair = Maj::cons(value, maj_cdr(pair.clone())); unsafe { let rawpair = Gc::into_raw(pair.clone()); std::ptr::copy_nonoverlapping( Gc::into_raw(new_pair.clone()), rawpair as *mut Maj, 1); } pair }, Err(error) => error, } }
fn maj_handle_redefine_cdr( mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj> ) -> Gc<Maj> { match maj_handle_redefine_cxr_helper(&mut state, expr, env) { Ok((pair, value)) => { let new_pair = Maj::cons(maj_car(pair.clone()), value); unsafe { let rawpair = Gc::into_raw(pair.clone()); std::ptr::copy_nonoverlapping( Gc::into_raw(new_pair.clone()), rawpair as *mut Maj, 1); } pair }, Err(error) => error, } }
3.6. Condicional (if
)
fn maj_handle_if(mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj>) -> Gc<Maj> { let length = maj_length(expr.clone()) .to_integer().unwrap(); if length != 4 { return maj_err( Maj::string("Invalid syntax: {}"), maj_list!(expr)); } let pred = maj_car(maj_cdr(expr.clone())); let conseq = maj_car(maj_cdr(maj_cdr(expr.clone()))); let altern = maj_car(maj_cdr(maj_cdr(maj_cdr(expr)))); let pred_result = maj_eval(&mut state, pred, env.clone()); if maj_errorp(pred_result.clone()).to_bool() { pred_result } else { maj_eval(&mut state, if maj_nilp(pred_result).to_bool() { altern } else { conseq }, env) } }
3.7. Forma fn
fn maj_handle_fn(expr: Gc<Maj>, env: Gc<Maj>) -> Gc<Maj> { let length = maj_length(expr.clone()) .to_integer().unwrap(); if length < 3 { return maj_err( Maj::string("Invalid syntax: {}"), maj_list!(expr)); } // (fn lambda-list . body) let lambda_list = maj_car(maj_cdr(expr.clone())); let body = maj_cdr(maj_cdr(expr)); if maj_errorp(lambda_list.clone()).to_bool() { lambda_list } else if maj_errorp(body.clone()).to_bool() { body } else { // (lit closure <env> <lambda-list> ((<body>))) maj_list!(Maj::lit(), Maj::closure(), env, lambda_list, body) } }
3.8. Forma mac
fn maj_handle_mac(expr: Gc<Maj>, env: Gc<Maj>) -> Gc<Maj> { let length = maj_length(expr.clone()) .to_integer().unwrap(); if length < 3 { return maj_err( Maj::string("Invalid syntax: {}"), maj_list!(expr)); } // (mac lambda-list . body) let lambda_list = maj_car(maj_cdr(expr.clone())); let body = maj_cdr(maj_cdr(expr)); // (lit macro (lit closure <env> lambda-list (body))) maj_list!(Maj::lit(), Maj::macro_sym(), maj_list!( Maj::lit(), Maj::closure(), env, lambda_list, body)) }
3.9. Forma do
fn maj_handle_do(mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj>) -> Gc<Maj> { let mut itr = maj_cdr(expr.clone()); let mut result = Maj::nil(); while !maj_nilp(itr.clone()).to_bool() { let expr = maj_car(itr.clone()); result = maj_eval(&mut state, expr, env.clone()); if maj_errorp(result.clone()).to_bool() { return result; } itr = maj_cdr(itr.clone()); } result }
3.10. Forma apply
fn maj_handle_apply(mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj>) -> Gc<Maj> { let length = maj_length(expr.clone()) .to_integer().unwrap(); if length != 3 { return maj_err( Maj::string("Invalid syntax: {}"), maj_list!(expr)); } // (apply fun args) -> (eval (cons fun args)) let func = maj_car(maj_cdr(expr.clone())); let args = maj_car(maj_cdr(maj_cdr(expr))); let func = maj_eval(&mut state, func, env.clone()); let args = maj_eval(&mut state, args, env.clone()); if maj_errorp(func.clone()).to_bool() { func } else if maj_macrop(func.clone()).to_bool() || maj_macp(func.clone()).to_bool() { maj_err( Maj::string("Macros cannot be applied"), Maj::nil()) } else if maj_errorp(args.clone()).to_bool() { args } else { maj_eval(&mut state, Maj::cons(func, args), env) } }
3.11. Forma letrec
fn maj_handle_letrec( mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj> ) -> Gc<Maj> { use crate::axioms::predicates::maj_consp; let length = maj_length(expr.clone()) .to_integer().unwrap(); if length < 3 { return maj_err( Maj::string("Invalid syntax: {}"), maj_list!(expr)); } // (letrec bindings . body) let bindings = maj_car(maj_cdr(expr.clone())); let body = maj_cdr(maj_cdr(expr.clone())); // Implicit `do` let body = Maj::cons(Maj::do_sym(), body); let mut fnnames = vec![]; let mut fns = vec![]; let mut iter = bindings.clone(); while !maj_nilp(iter.clone()).to_bool() { // (sym lambda-list . body) let clause = maj_car(iter.clone()); if !maj_consp(clause.clone()).to_bool() { return maj_err(Maj::string( "Syntax error on letrec: {} is not a proper clause"), maj_list!(clause)); } let sym = maj_car(clause.clone()); if !maj_symbolp(sym.clone()).to_bool() { return maj_err(Maj::string( "Syntax error on letrec: {} is not a valid function name"), maj_list!(sym)); } let function = Maj::cons( Maj::fn_sym(), maj_cdr(clause)); fnnames.push(sym); fns.push(function); iter = maj_cdr(iter); } let mut closures = vec![]; // iterate over fns, interpreting, putting results in closures for function in fns.iter() { let closure = maj_eval( &mut state, function.clone(), env.clone()); if maj_errorp(closure.clone()).to_bool() { return closure; } closures.push(closure); } // iterate over fnnames and closures, creating an env. use crate::core::environment::maj_env_push; let mut new_env = Maj::nil(); for i in 0..closures.len() { new_env = maj_env_push(new_env, fnnames[i].clone(), closures[i].clone()); } // append new_env to env. use crate::core::environment::maj_env_union; new_env = maj_env_union(new_env, env.clone()); // for each closure, inject this new environment for closure in closures.iter() { // (lit closure <env> <ll> . <body>) let clorest = maj_cdr(maj_cdr(closure.clone())); let clobody = maj_cdr(clorest.clone()); // modify car of clobody unsafe { let rawclorest = Gc::into_raw(clorest.clone()); let newcons = Maj::cons(new_env.clone(), clobody); std::ptr::copy_nonoverlapping( Gc::into_raw(newcons.clone()), rawclorest as *mut Maj, 1); } } maj_eval(&mut state, body, new_env) }
3.12. Forma while
fn maj_handle_while( mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj> ) -> Gc<Maj> { // (while pred . body) let length = maj_length(expr.clone()) .to_integer().unwrap(); if length < 2 { return maj_err( Maj::string("Invalid syntax: {}"), maj_list!(expr)); } let pred = maj_car(maj_cdr(expr.clone())); let body = maj_cdr(maj_cdr(expr)); let body = Maj::cons(Maj::do_sym(), body); let mut body_result = Maj::nil(); loop { let pred_result = maj_eval(&mut state, pred.clone(), env.clone()); if maj_errorp(pred_result.clone()).to_bool() { return pred_result; } if !pred_result.to_bool() { break; } body_result = maj_eval(&mut state, body.clone(), env.clone()); if maj_errorp(body_result.clone()).to_bool() { return body_result; } } body_result }
3.13. Forma unwind-protect
fn maj_handle_unwind_protect( mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj> ) -> Gc<Maj> { // (unwind-protect expr cleanup) let length = maj_length(expr.clone()) .to_integer().unwrap(); if length != 3 { return maj_err( Maj::string("Invalid syntax: {}"), maj_list!(expr)); } let exp = maj_car(maj_cdr(expr.clone())); let cleanup = maj_car(maj_cdr(maj_cdr(expr))); let result = maj_eval(&mut state, exp, env.clone()); let _ = maj_eval(&mut state, cleanup, env); result }
3.14. Formas lógicas
3.14.1. and
fn maj_handle_and(mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj>) -> Gc<Maj> { let forms = maj_cdr(expr); let mut iter = forms; let mut result = Maj::t(); while !maj_nilp(iter.clone()).to_bool() { let form = maj_car(iter.clone()); result = maj_eval(&mut state, form, env.clone()); if maj_nilp(result.clone()).to_bool() { return Maj::nil(); } iter = maj_cdr(iter.clone()); } result }
3.14.2. or
fn maj_handle_or(mut state: &mut MajState, expr: Gc<Maj>, env: Gc<Maj>) -> Gc<Maj> { let forms = maj_cdr(expr); let mut iter = forms; let mut result = Maj::nil(); while !maj_nilp(iter.clone()).to_bool() { let form = maj_car(iter.clone()); result = maj_eval(&mut state, form, env.clone()); if !maj_nilp(result.clone()).to_bool() { return result; } iter = maj_cdr(iter.clone()); } result }
4. Predicados auxiliares
fn maj_is_selfeval(x: Gc<Maj>) -> bool { maj_literalp(x.clone()).to_bool() || maj_nilp(x.clone()).to_bool() || maj_eq(x.clone(), Maj::t()).to_bool() || maj_eq(x.clone(), Maj::ampersand()).to_bool() || maj_eq(x.clone(), Maj::apply()).to_bool() || maj_numberp(x.clone()).to_bool() || maj_charp(x.clone()).to_bool() || maj_streamp(x.clone()).to_bool() || maj_stringp(x.clone()).to_bool() }
pub fn maj_quotep(x: Gc<Maj>) -> Gc<Maj> { maj_eq(maj_car(x), Maj::quote()) }
pub fn maj_quasiquotep(x: Gc<Maj>) -> Gc<Maj> { maj_eq(maj_car(x), Maj::quasiquote()) }
pub fn maj_unquotep(x: Gc<Maj>) -> Gc<Maj> { maj_eq(maj_car(x), Maj::unquote()) }
pub fn maj_unquote_splice_p(x: Gc<Maj>) -> Gc<Maj> { maj_eq(maj_car(x), Maj::unquote_splice()) }
fn maj_defp(mut state: &mut MajState, x: Gc<Maj>) -> Gc<Maj> { let car = maj_car(x); maj_eq(car, Maj::symbol(&mut state, "def")) }
fn maj_setp(mut state: &mut MajState, x: Gc<Maj>) -> Gc<Maj> { let car = maj_car(x); maj_eq(car, Maj::symbol(&mut state, "set")) }
fn maj_set_car_p(mut state: &mut MajState, x: Gc<Maj>) -> Gc<Maj> { let car = maj_car(x); maj_eq(car, Maj::symbol(&mut state, "set-car")) }
fn maj_set_cdr_p(mut state: &mut MajState, x: Gc<Maj>) -> Gc<Maj> { let car = maj_car(x); maj_eq(car, Maj::symbol(&mut state, "set-cdr")) }
fn maj_dop(mut state: &mut MajState, x: Gc<Maj>) -> Gc<Maj> { let car = maj_car(x); maj_eq(car, Maj::symbol(&mut state, "do")) }
fn maj_andp(mut state: &mut MajState, x: Gc<Maj>) -> Gc<Maj> { let car = maj_car(x); maj_eq(car, Maj::symbol(&mut state, "and")) }
fn maj_orp(mut state: &mut MajState, x: Gc<Maj>) -> Gc<Maj> { let car = maj_car(x); maj_eq(car, Maj::symbol(&mut state, "or")) }
fn maj_ifp(mut state: &mut MajState, x: Gc<Maj>) -> Gc<Maj> { let car = maj_car(x); maj_eq(car, Maj::symbol(&mut state, "if")) }
#[inline] fn maj_fnp(x: Gc<Maj>) -> Gc<Maj> { maj_eq(maj_car(x), Maj::fn_sym()) }
#[inline] fn maj_applyp(x: Gc<Maj>) -> Gc<Maj> { maj_eq(maj_car(x), Maj::apply()) }
fn maj_whilep(mut state: &mut MajState, x: Gc<Maj>) -> Gc<Maj> { let car = maj_car(x); maj_eq(car, Maj::symbol(&mut state, "while")) }
#[inline] fn maj_macp(x: Gc<Maj>) -> Gc<Maj> { maj_eq(maj_car(x), Maj::mac()) }
#[inline] fn maj_letrecp(mut state: &mut MajState, x: Gc<Maj>) -> Gc<Maj> { let car = maj_car(x); maj_eq(car, Maj::symbol(&mut state, "letrec")) }
#[inline] fn maj_unwind_protect_p(mut state: &mut MajState, x: Gc<Maj>) -> Gc<Maj> { let car = maj_car(x); maj_eq(car, Maj::symbol(&mut state, "unwind-protect")) }