// ---------------------------------------------------------------------------
// - Switch.cpp -
// - afnix engine - builtin selector function implementation -
// ---------------------------------------------------------------------------
// - This program is free software; you can redistribute it and/or modify -
// - it provided that this copyright notice is kept intact. -
// - -
// - This program is distributed in the hope that it will be useful, but -
// - without any warranty; without even the implied warranty of -
// - merchantability or fitness for a particular purpose. In no event shall -
// - the copyright holder be liable for any direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software. -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2007 amaury darsch -
// ---------------------------------------------------------------------------
#include "Cons.hpp"
#include "Builtin.hpp"
#include "Lexical.hpp"
#include "Boolean.hpp"
#include "Exception.hpp"
namespace afnix {
// this procedure check if an object is a lexical and if yes, check if it
// is the else lexical
static inline bool check_else (Object* object) {
Lexical* lex = dynamic_cast <Lexical*> (object);
if (lex == nilp) return false;
if (lex->tostring () == "else") return true;
return false;
}
// evaluate a switch statement
Object* builtin_switch (Runnable* robj, Nameset* nset, Cons* args) {
// trivial check first
if ((args == nilp) || (args->length () != 2)) {
throw Exception ("argument-error",
"missing or too many arguments with switch");
}
// extract selector and protect it
Object* car = args->getcar ();
Object* sel = (car == nilp) ? nilp : car->eval (robj, nset);
Object::iref (sel);
// extract body
Object* obj = args->getcadr ();
Cons* body = dynamic_cast <Cons*> (obj);
if (body == nilp) {
Object::dref (sel);
throw Exception ("type-error", "illegal object as switch body",
Object::repr (obj));
}
// perform the selection
while (body != nilp) {
// get a selection form
Object* elem = body->getcar ();
Cons* sobj = dynamic_cast <Cons*> (elem);
if (sobj == nilp) {
Object::dref (sel);
throw Exception ("type-error", "illegal object as switch selector",
Object::repr (elem));
}
// extract the condition form
Object* cond = sobj->getcar ();
// check for else as a lexical
if (check_else (cond) == true) {
Object* form = sobj->getcadr ();
Object* result = (form == nilp) ? nilp : form->eval (robj,nset);
Object::dref (sel);
return result;
}
// check for equality between the selector and the condition
Object* data = (cond == nilp) ? nilp : cond->eval (robj,nset);
Object::iref (data);
Object* bobj = sel->oper (Object::EQL, data);
Boolean* bval = dynamic_cast <Boolean*> (bobj);
bool bloc = (bval == nilp) ? false : bval->toboolean ();
Object::cref (bval);
if (bloc == true) {
Object* form = sobj->getcadr ();
Object* result = (form == nilp) ? nilp : form->eval (robj,nset);
Object::dref (sel);
Object::dref (data);
return result;
}
// no match - try next form
Object::dref (data);
body = body->getcdr ();
}
Object::dref (sel);
return nilp;
}
}
syntax highlighted by Code2HTML, v. 0.9.1