Added equality comparisons == and !=
This commit is contained in:
30
functions.c
30
functions.c
@@ -27,6 +27,8 @@ void lenv_add_builtin_funcs(lenv* env) {
|
||||
lenv_add_builtin(env, "<", builtin_comp_lt);
|
||||
lenv_add_builtin(env, ">=", builtin_comp_ge);
|
||||
lenv_add_builtin(env, "<=", builtin_comp_le);
|
||||
lenv_add_builtin(env, "==", builtin_comp_eq);
|
||||
lenv_add_builtin(env, "!=", builtin_comp_neq);
|
||||
|
||||
//List/Util functions
|
||||
lenv_add_builtin(env, "list", builtin_list);
|
||||
@@ -57,6 +59,8 @@ char* builtin_op_strname(BUILTIN_OP_TYPE op) {
|
||||
case BUILTIN_COMP_LT: return "<";
|
||||
case BUILTIN_COMP_GE: return ">=";
|
||||
case BUILTIN_COMP_LE: return "<=";
|
||||
case BUILTIN_COMP_EQ: return "==";
|
||||
case BUILTIN_COMP_NEQ: return "!=";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
@@ -128,7 +132,7 @@ lval* builtin_pow(lenv* env, lval* val){
|
||||
//End Math Functions
|
||||
|
||||
//Start Comparison Functions
|
||||
lval* builtin_comp(lenv* env, lval* val, BUILTIN_OP_TYPE op) {
|
||||
lval* builtin_comp_num(lenv* env, lval* val, BUILTIN_OP_TYPE op) {
|
||||
char* opName = builtin_op_strname(op);
|
||||
LASSERT_ARG_COUNT(opName, val, val, 2);
|
||||
LASSERT_TYPE(opName, val, val->cell_list[0], LVAL_NUM);
|
||||
@@ -149,16 +153,32 @@ lval* builtin_comp(lenv* env, lval* val, BUILTIN_OP_TYPE op) {
|
||||
return lval_num(r);
|
||||
}
|
||||
lval* builtin_comp_gt(lenv* env, lval* val) {
|
||||
return builtin_comp(env, val, BUILTIN_COMP_GT);
|
||||
return builtin_comp_num(env, val, BUILTIN_COMP_GT);
|
||||
}
|
||||
lval* builtin_comp_lt(lenv* env, lval* val) {
|
||||
return builtin_comp(env, val, BUILTIN_COMP_LT);
|
||||
return builtin_comp_num(env, val, BUILTIN_COMP_LT);
|
||||
}
|
||||
lval* builtin_comp_ge(lenv* env, lval* val) {
|
||||
return builtin_comp(env, val, BUILTIN_COMP_GE);
|
||||
return builtin_comp_num(env, val, BUILTIN_COMP_GE);
|
||||
}
|
||||
lval* builtin_comp_le(lenv* env, lval* val) {
|
||||
return builtin_comp(env, val, BUILTIN_COMP_LE);
|
||||
return builtin_comp_num(env, val, BUILTIN_COMP_LE);
|
||||
}
|
||||
|
||||
lval* builtin_comp_value(lenv* env, lval* val, BUILTIN_OP_TYPE op) {
|
||||
LASSERT_ARG_COUNT(builtin_op_strname(op), val, val, 2);
|
||||
BOOL result = FALSE;
|
||||
result = lval_equal(val->cell_list[0], val->cell_list[1]);
|
||||
if (op == BUILTIN_COMP_NEQ) {
|
||||
result = !result;
|
||||
}
|
||||
return lval_num((int)result);
|
||||
}
|
||||
lval* builtin_comp_eq(lenv* env, lval* val) {
|
||||
return builtin_comp_value(env, val, BUILTIN_COMP_EQ);
|
||||
}
|
||||
lval* builtin_comp_neq(lenv* env, lval* val) {
|
||||
return builtin_comp_value(env, val, BUILTIN_COMP_NEQ);
|
||||
}
|
||||
//End Comparison Functions
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ extern "C" {
|
||||
|
||||
enum BUILTIN_OP_TYPE {
|
||||
BUILTIN_OP_ADD, BUILTIN_OP_SUB, BUILTIN_OP_DIV, BUILTIN_OP_MUL, BUILTIN_OP_POW,
|
||||
BUILTIN_COMP_GT, BUILTIN_COMP_LT, BUILTIN_COMP_GE, BUILTIN_COMP_LE
|
||||
BUILTIN_COMP_GT, BUILTIN_COMP_LT, BUILTIN_COMP_GE, BUILTIN_COMP_LE,
|
||||
BUILTIN_COMP_EQ, BUILTIN_COMP_NEQ
|
||||
};
|
||||
|
||||
char* builtin_op_strname(BUILTIN_OP_TYPE op);
|
||||
@@ -36,11 +37,14 @@ extern "C" {
|
||||
lval* builtin_pow(lenv* env, lval* val);
|
||||
|
||||
//Comparison Functions
|
||||
lval* builtin_comp(lenv* env, lval* val, BUILTIN_OP_TYPE op);
|
||||
lval* builtin_comp_num(lenv* env, lval* val, BUILTIN_OP_TYPE op);
|
||||
lval* builtin_comp_gt(lenv* env, lval* val);
|
||||
lval* builtin_comp_lt(lenv* env, lval* val);
|
||||
lval* builtin_comp_ge(lenv* env, lval* val);
|
||||
lval* builtin_comp_le(lenv* env, lval* val);
|
||||
lval* builtin_comp_value(lenv* env, lval* val, BUILTIN_OP_TYPE op);
|
||||
lval* builtin_comp_eq(lenv* env, lval* val);
|
||||
lval* builtin_comp_neq(lenv* env, lval* val);
|
||||
|
||||
//List/Util functions
|
||||
lval* builtin_list(lenv* env, lval* val);
|
||||
|
||||
2
lang.h
2
lang.h
@@ -34,6 +34,8 @@ extern "C" {
|
||||
LASSERT(val, subject->cell_count >= expectedNum, \
|
||||
LERR_SYNTAX, "%s Expected %ld or more arguments got %ld", name, expectedNum, subject->cell_count )
|
||||
|
||||
|
||||
|
||||
mpc_ast_t* tokenize(char *input);
|
||||
lval* parse(mpc_ast_t *t);
|
||||
lval* eval_builtin_op(lval* val, char* op);
|
||||
|
||||
1
lenv.c
1
lenv.c
@@ -1,5 +1,4 @@
|
||||
#include <stdlib.h>
|
||||
#include <bits/stdlib-bsearch.h>
|
||||
|
||||
#include "lang.h"
|
||||
#include "util.h"
|
||||
|
||||
40
lval.c
40
lval.c
@@ -1,4 +1,5 @@
|
||||
#include <stdlib.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "lang.h"
|
||||
#include "util.h"
|
||||
@@ -135,6 +136,45 @@ lval* lval_call(lenv* env, lval* function, lval* args) {
|
||||
return eval(func->env, lval_add(lval_s_expr(), lval_copy(func->body)));
|
||||
}
|
||||
|
||||
BOOL lval_equal(lval* a, lval* b) {
|
||||
if (a->type != b->type) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch(a->type) {
|
||||
case LVAL_ERR: return a->data.err.num == b->data.err.num;
|
||||
case LVAL_EXIT: return TRUE;
|
||||
case LVAL_NUM: return fabs(a->data.num - b->data.num) <= DBL_EPSILON;
|
||||
case LVAL_SYM: return strcmp(a->data.sym, b->data.sym) == 0;
|
||||
case LVAL_FUNC:
|
||||
if (a->data.func->builtin != NULL) {
|
||||
if (b->data.func->builtin != NULL) {
|
||||
return a->data.func->builtin == a->data.func->builtin;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
if (b->data.func->builtin == NULL) {
|
||||
return FALSE;
|
||||
} else {
|
||||
return lval_equal(b->data.func->formals, b->data.func->formals)
|
||||
&& lval_equal(b->data.func->body, b->data.func->body);
|
||||
}
|
||||
}
|
||||
case LVAL_Q_EXPR:
|
||||
case LVAL_S_EXPR:
|
||||
if (a->cell_count != b->cell_count) { return 0; }
|
||||
for (int i = 0; i < a->cell_count; i++) {
|
||||
if (!lval_equal(a->cell_list[i], b->cell_list[i])) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
default: return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void lval_delete(lval* val) {
|
||||
switch(val->type) {
|
||||
case LVAL_NUM: break;
|
||||
|
||||
3
lval.h
3
lval.h
@@ -19,6 +19,7 @@ typedef struct lval lval;
|
||||
struct lval_func;
|
||||
typedef struct lval_func lval_func;
|
||||
|
||||
#include "main.h"
|
||||
#include "lenv.h"
|
||||
|
||||
enum VAL_TYPE { LVAL_ERR, LVAL_NUM, LVAL_SYM, LVAL_FUNC, LVAL_S_EXPR, LVAL_Q_EXPR, LVAL_EXIT };
|
||||
@@ -67,7 +68,9 @@ lval* lval_add(lval* val, lval* x);
|
||||
lval* lval_pop(lval* val, int i);
|
||||
lval* lval_take(lval* val, int i);
|
||||
lval* lval_join(lval* a, lval* b);
|
||||
|
||||
lval* lval_call(lenv* env, lval* function, lval* args);
|
||||
BOOL lval_equal(lval* a, lval* b);
|
||||
|
||||
void lval_delete(lval* val);
|
||||
lval* lval_copy(lval* current);
|
||||
|
||||
5
main.h
5
main.h
@@ -14,6 +14,11 @@ extern "C" {
|
||||
|
||||
#define VERSION "0.1"
|
||||
|
||||
typedef unsigned char BOOL;
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
int main(int argc, char** argv);
|
||||
|
||||
void lval_expr_print(lval* val, char* open, char* close);
|
||||
|
||||
@@ -58,7 +58,7 @@ FFLAGS=
|
||||
ASFLAGS=
|
||||
|
||||
# Link Libraries and Options
|
||||
LDLIBSOPTIONS=
|
||||
LDLIBSOPTIONS=-lm `pkg-config --libs libedit`
|
||||
|
||||
# Build Targets
|
||||
.build-conf: ${BUILD_SUBPROJECTS}
|
||||
@@ -71,37 +71,37 @@ ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/klisp: ${OBJECTFILES}
|
||||
${OBJECTDIR}/functions.o: functions.c
|
||||
${MKDIR} -p ${OBJECTDIR}
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/functions.o functions.c
|
||||
$(COMPILE.c) -O3 -w -Ilib/mpc `pkg-config --cflags libedit` -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/functions.o functions.c
|
||||
|
||||
${OBJECTDIR}/lang.o: lang.c
|
||||
${MKDIR} -p ${OBJECTDIR}
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/lang.o lang.c
|
||||
$(COMPILE.c) -O3 -w -Ilib/mpc `pkg-config --cflags libedit` -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/lang.o lang.c
|
||||
|
||||
${OBJECTDIR}/lenv.o: lenv.c
|
||||
${MKDIR} -p ${OBJECTDIR}
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/lenv.o lenv.c
|
||||
$(COMPILE.c) -O3 -w -Ilib/mpc `pkg-config --cflags libedit` -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/lenv.o lenv.c
|
||||
|
||||
${OBJECTDIR}/lib/mpc/mpc.o: lib/mpc/mpc.c
|
||||
${MKDIR} -p ${OBJECTDIR}/lib/mpc
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/lib/mpc/mpc.o lib/mpc/mpc.c
|
||||
$(COMPILE.c) -O3 -w -Ilib/mpc `pkg-config --cflags libedit` -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/lib/mpc/mpc.o lib/mpc/mpc.c
|
||||
|
||||
${OBJECTDIR}/lval.o: lval.c
|
||||
${MKDIR} -p ${OBJECTDIR}
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/lval.o lval.c
|
||||
$(COMPILE.c) -O3 -w -Ilib/mpc `pkg-config --cflags libedit` -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/lval.o lval.c
|
||||
|
||||
${OBJECTDIR}/main.o: main.c
|
||||
${MKDIR} -p ${OBJECTDIR}
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/main.o main.c
|
||||
$(COMPILE.c) -O3 -w -Ilib/mpc `pkg-config --cflags libedit` -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/main.o main.c
|
||||
|
||||
${OBJECTDIR}/util.o: util.c
|
||||
${MKDIR} -p ${OBJECTDIR}
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/util.o util.c
|
||||
$(COMPILE.c) -O3 -w -Ilib/mpc `pkg-config --cflags libedit` -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/util.o util.c
|
||||
|
||||
# Subprojects
|
||||
.build-subprojects:
|
||||
|
||||
@@ -104,7 +104,12 @@
|
||||
</toolsSet>
|
||||
<compileType>
|
||||
<cTool>
|
||||
<developmentMode>5</developmentMode>
|
||||
<developmentMode>6</developmentMode>
|
||||
<standard>3</standard>
|
||||
<incDir>
|
||||
<pElem>lib/mpc</pElem>
|
||||
</incDir>
|
||||
<warningLevel>0</warningLevel>
|
||||
</cTool>
|
||||
<ccTool>
|
||||
<developmentMode>5</developmentMode>
|
||||
@@ -115,6 +120,12 @@
|
||||
<asmTool>
|
||||
<developmentMode>5</developmentMode>
|
||||
</asmTool>
|
||||
<linkerTool>
|
||||
<linkerLibItems>
|
||||
<linkerLibStdlibItem>Mathematics</linkerLibStdlibItem>
|
||||
<linkerOptionItem>`pkg-config --libs libedit`</linkerOptionItem>
|
||||
</linkerLibItems>
|
||||
</linkerTool>
|
||||
</compileType>
|
||||
<item path="functions.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
|
||||
Reference in New Issue
Block a user