qse/qse/lib/scm/eval.c

210 lines
4.1 KiB
C

/*
* $Id$
*
Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE.
QSE is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
QSE 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. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
*/
#include "scm.h"
static int eval_entity (qse_scm_t* scm);
#if 0
static int save (qse_scm_t* scm, qse_scm_ent_t* )
{
}
static int leave (qse_scm_t* scm)
{
}
#endif
int qse_scm_dolambda (qse_scm_t* scm)
{
qse_scm_ent_t* obj;
obj = qse_scm_makeclosent (scm, scm->e.cod, scm->e.env);
if (obj == QSE_NULL) return -1;
scm->e.out = obj;
return 0;
}
int qse_scm_doquote (qse_scm_t* scm)
{
/* For the expression (quote 10),
* scm.e.cod is (10).
* PAIR_CAR(scm.e.cod) is 10
*/
scm->e.out = PAIR_CAR(scm->e.cod);
return 0;
}
static int define_finish (qse_scm_t* scm)
{
// qse_scm_ent_t* var = scm->e.cod;
//set var in the environemtn....
//leave (scm);
return 0;
}
int qse_scm_dodefine (qse_scm_t* scm)
{
qse_scm_ent_t* car, * cdr;
car = PAIR_CAR(scm->e.cod);
cdr = PAIR_CDR(scm->e.cod);
/* TODO: support function defintion - (define (f x y) (+ x y) (* x y))
-> support it by converting it to lambda expression
-> (define f (lambda (x y) (+ x y) (* x y))
*/
if (IS_SMALLINT(scm,cdr) || TYPE(cdr) != QSE_SCM_ENT_PAIR)
{
/* (define x . 10) */
/* TODO: change error code ... */
qse_scm_seterror (scm, QSE_SCM_EARGBAD, QSE_NULL, QSE_NULL);
return -1;
}
if (!IS_NIL(scm,PAIR_CDR(cdr)))
{
/* (define x 10 . 20)
* (define x 10 20) */
qse_scm_seterror (scm, QSE_SCM_EARGMANY, QSE_NULL, QSE_NULL);
return -1;
}
if (IS_SMALLINT(scm,car) || TYPE(car) != QSE_SCM_ENT_SYM)
{
/* check if the variable is a symbol
* (define 20 10)
*/
qse_scm_seterror (scm, QSE_SCM_EVARBAD, QSE_NULL, QSE_NULL);
return -1;
}
// save car...
// let it jump to EVAL and come back to DEFINE_FINISH...
scm->e.cod = PAIR_CAR(cdr);
scm->e.op = eval_entity;
return 0;
}
int qse_scm_dobegin (qse_scm_t* scm)
{
/*
(begin
(print "hello")
(print "world")
)
*/
qse_scm_ent_t* car, * cdr;
if (IS_SMALLINT(scm, scm->e.cod) || TYPE(scm->e.cod) != QSE_SCM_ENT_PAIR)
{
/* (begin (+ x y) . 30) */
qse_scm_seterror (scm, QSE_SCM_EARGBAD, QSE_NULL, QSE_NULL);
return -1;
}
car = PAIR_CAR(scm->e.cod);
cdr = PAIR_CDR(scm->e.cod);
if (!IS_NIL(scm,cdr))
{
//save (BEGIN... cdr);
}
scm->e.cod = car;
scm->e.op = eval_entity;
return 0;
}
int qse_scm_doif (qse_scm_t* scm)
{
return 0;
}
static int eval_entity (qse_scm_t* scm)
{
if (IS_SMALLINT(scm,scm->e.cod))
{
}
else if (TYPE(scm->e.cod) == QSE_SCM_ENT_PAIR)
{
qse_scm_ent_t* car, * cdr;
/* the first item in the list */
car = PAIR_CAR(scm->e.cod);
if (SYNT(car))
{
/* the first item in the list is a syntax symbol */
cdr = PAIR_CDR(scm->e.cod);
if (IS_SMALLINT(scm,cdr) || TYPE(cdr) != QSE_SCM_ENT_PAIR)
{
/* check if the cdr part ends the list with a dot
* as in (quote . 10) */
qse_scm_seterror (scm, QSE_SCM_EARGBAD, 0, 0);
return -1;
}
/* go on to the syntax function */
scm->e.cod = cdr;
scm->e.op = SYNT_UPTR(car);
}
else
{
/*
push E1_ARG.... NIL, PAIR_CDR(code)
scm->e.cod = car;
goback to eval...
*/
}
}
else if (TYPE(scm->e.cod) == QSE_SCM_ENT_SYM)
{
/* resolve the symbol from the environment */
}
else
{
}
return 0;
}
qse_scm_ent_t* qse_scm_eval (qse_scm_t* scm, qse_scm_ent_t* obj)
{
scm->e.dmp = scm->nil;
scm->e.env = scm->gloenv;
scm->e.cod = obj;
scm->e.in = obj;
scm->e.out = scm->nil;
scm->e.op = eval_entity;
do
{
if (scm->e.op (scm) <= -1) return QSE_NULL;
break;
}
while (scm->e.op);
return scm->e.out;
}