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_lt);
|
||||||
lenv_add_builtin(env, ">=", builtin_comp_ge);
|
lenv_add_builtin(env, ">=", builtin_comp_ge);
|
||||||
lenv_add_builtin(env, "<=", builtin_comp_le);
|
lenv_add_builtin(env, "<=", builtin_comp_le);
|
||||||
|
lenv_add_builtin(env, "==", builtin_comp_eq);
|
||||||
|
lenv_add_builtin(env, "!=", builtin_comp_neq);
|
||||||
|
|
||||||
//List/Util functions
|
//List/Util functions
|
||||||
lenv_add_builtin(env, "list", builtin_list);
|
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_LT: return "<";
|
||||||
case BUILTIN_COMP_GE: return ">=";
|
case BUILTIN_COMP_GE: return ">=";
|
||||||
case BUILTIN_COMP_LE: return "<=";
|
case BUILTIN_COMP_LE: return "<=";
|
||||||
|
case BUILTIN_COMP_EQ: return "==";
|
||||||
|
case BUILTIN_COMP_NEQ: return "!=";
|
||||||
default: return "UNKNOWN";
|
default: return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,7 +132,7 @@ lval* builtin_pow(lenv* env, lval* val){
|
|||||||
//End Math Functions
|
//End Math Functions
|
||||||
|
|
||||||
//Start Comparison 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);
|
char* opName = builtin_op_strname(op);
|
||||||
LASSERT_ARG_COUNT(opName, val, val, 2);
|
LASSERT_ARG_COUNT(opName, val, val, 2);
|
||||||
LASSERT_TYPE(opName, val, val->cell_list[0], LVAL_NUM);
|
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);
|
return lval_num(r);
|
||||||
}
|
}
|
||||||
lval* builtin_comp_gt(lenv* env, lval* val) {
|
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) {
|
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) {
|
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) {
|
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
|
//End Comparison Functions
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ extern "C" {
|
|||||||
|
|
||||||
enum BUILTIN_OP_TYPE {
|
enum BUILTIN_OP_TYPE {
|
||||||
BUILTIN_OP_ADD, BUILTIN_OP_SUB, BUILTIN_OP_DIV, BUILTIN_OP_MUL, BUILTIN_OP_POW,
|
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);
|
char* builtin_op_strname(BUILTIN_OP_TYPE op);
|
||||||
@@ -36,11 +37,14 @@ extern "C" {
|
|||||||
lval* builtin_pow(lenv* env, lval* val);
|
lval* builtin_pow(lenv* env, lval* val);
|
||||||
|
|
||||||
//Comparison Functions
|
//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_gt(lenv* env, lval* val);
|
||||||
lval* builtin_comp_lt(lenv* env, lval* val);
|
lval* builtin_comp_lt(lenv* env, lval* val);
|
||||||
lval* builtin_comp_ge(lenv* env, lval* val);
|
lval* builtin_comp_ge(lenv* env, lval* val);
|
||||||
lval* builtin_comp_le(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
|
//List/Util functions
|
||||||
lval* builtin_list(lenv* env, lval* val);
|
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, \
|
LASSERT(val, subject->cell_count >= expectedNum, \
|
||||||
LERR_SYNTAX, "%s Expected %ld or more arguments got %ld", name, expectedNum, subject->cell_count )
|
LERR_SYNTAX, "%s Expected %ld or more arguments got %ld", name, expectedNum, subject->cell_count )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mpc_ast_t* tokenize(char *input);
|
mpc_ast_t* tokenize(char *input);
|
||||||
lval* parse(mpc_ast_t *t);
|
lval* parse(mpc_ast_t *t);
|
||||||
lval* eval_builtin_op(lval* val, char* op);
|
lval* eval_builtin_op(lval* val, char* op);
|
||||||
|
|||||||
1
lenv.c
1
lenv.c
@@ -1,5 +1,4 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <bits/stdlib-bsearch.h>
|
|
||||||
|
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|||||||
40
lval.c
40
lval.c
@@ -1,4 +1,5 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
#include "util.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)));
|
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) {
|
void lval_delete(lval* val) {
|
||||||
switch(val->type) {
|
switch(val->type) {
|
||||||
case LVAL_NUM: break;
|
case LVAL_NUM: break;
|
||||||
|
|||||||
3
lval.h
3
lval.h
@@ -19,6 +19,7 @@ typedef struct lval lval;
|
|||||||
struct lval_func;
|
struct lval_func;
|
||||||
typedef struct lval_func lval_func;
|
typedef struct lval_func lval_func;
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
#include "lenv.h"
|
#include "lenv.h"
|
||||||
|
|
||||||
enum VAL_TYPE { LVAL_ERR, LVAL_NUM, LVAL_SYM, LVAL_FUNC, LVAL_S_EXPR, LVAL_Q_EXPR, LVAL_EXIT };
|
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_pop(lval* val, int i);
|
||||||
lval* lval_take(lval* val, int i);
|
lval* lval_take(lval* val, int i);
|
||||||
lval* lval_join(lval* a, lval* b);
|
lval* lval_join(lval* a, lval* b);
|
||||||
|
|
||||||
lval* lval_call(lenv* env, lval* function, lval* args);
|
lval* lval_call(lenv* env, lval* function, lval* args);
|
||||||
|
BOOL lval_equal(lval* a, lval* b);
|
||||||
|
|
||||||
void lval_delete(lval* val);
|
void lval_delete(lval* val);
|
||||||
lval* lval_copy(lval* current);
|
lval* lval_copy(lval* current);
|
||||||
|
|||||||
5
main.h
5
main.h
@@ -14,6 +14,11 @@ extern "C" {
|
|||||||
|
|
||||||
#define VERSION "0.1"
|
#define VERSION "0.1"
|
||||||
|
|
||||||
|
typedef unsigned char BOOL;
|
||||||
|
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
|
||||||
int main(int argc, char** argv);
|
int main(int argc, char** argv);
|
||||||
|
|
||||||
void lval_expr_print(lval* val, char* open, char* close);
|
void lval_expr_print(lval* val, char* open, char* close);
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ FFLAGS=
|
|||||||
ASFLAGS=
|
ASFLAGS=
|
||||||
|
|
||||||
# Link Libraries and Options
|
# Link Libraries and Options
|
||||||
LDLIBSOPTIONS=
|
LDLIBSOPTIONS=-lm `pkg-config --libs libedit`
|
||||||
|
|
||||||
# Build Targets
|
# Build Targets
|
||||||
.build-conf: ${BUILD_SUBPROJECTS}
|
.build-conf: ${BUILD_SUBPROJECTS}
|
||||||
@@ -71,37 +71,37 @@ ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/klisp: ${OBJECTFILES}
|
|||||||
${OBJECTDIR}/functions.o: functions.c
|
${OBJECTDIR}/functions.o: functions.c
|
||||||
${MKDIR} -p ${OBJECTDIR}
|
${MKDIR} -p ${OBJECTDIR}
|
||||||
${RM} "$@.d"
|
${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
|
${OBJECTDIR}/lang.o: lang.c
|
||||||
${MKDIR} -p ${OBJECTDIR}
|
${MKDIR} -p ${OBJECTDIR}
|
||||||
${RM} "$@.d"
|
${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
|
${OBJECTDIR}/lenv.o: lenv.c
|
||||||
${MKDIR} -p ${OBJECTDIR}
|
${MKDIR} -p ${OBJECTDIR}
|
||||||
${RM} "$@.d"
|
${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
|
${OBJECTDIR}/lib/mpc/mpc.o: lib/mpc/mpc.c
|
||||||
${MKDIR} -p ${OBJECTDIR}/lib/mpc
|
${MKDIR} -p ${OBJECTDIR}/lib/mpc
|
||||||
${RM} "$@.d"
|
${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
|
${OBJECTDIR}/lval.o: lval.c
|
||||||
${MKDIR} -p ${OBJECTDIR}
|
${MKDIR} -p ${OBJECTDIR}
|
||||||
${RM} "$@.d"
|
${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
|
${OBJECTDIR}/main.o: main.c
|
||||||
${MKDIR} -p ${OBJECTDIR}
|
${MKDIR} -p ${OBJECTDIR}
|
||||||
${RM} "$@.d"
|
${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
|
${OBJECTDIR}/util.o: util.c
|
||||||
${MKDIR} -p ${OBJECTDIR}
|
${MKDIR} -p ${OBJECTDIR}
|
||||||
${RM} "$@.d"
|
${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
|
# Subprojects
|
||||||
.build-subprojects:
|
.build-subprojects:
|
||||||
|
|||||||
@@ -104,7 +104,12 @@
|
|||||||
</toolsSet>
|
</toolsSet>
|
||||||
<compileType>
|
<compileType>
|
||||||
<cTool>
|
<cTool>
|
||||||
<developmentMode>5</developmentMode>
|
<developmentMode>6</developmentMode>
|
||||||
|
<standard>3</standard>
|
||||||
|
<incDir>
|
||||||
|
<pElem>lib/mpc</pElem>
|
||||||
|
</incDir>
|
||||||
|
<warningLevel>0</warningLevel>
|
||||||
</cTool>
|
</cTool>
|
||||||
<ccTool>
|
<ccTool>
|
||||||
<developmentMode>5</developmentMode>
|
<developmentMode>5</developmentMode>
|
||||||
@@ -115,6 +120,12 @@
|
|||||||
<asmTool>
|
<asmTool>
|
||||||
<developmentMode>5</developmentMode>
|
<developmentMode>5</developmentMode>
|
||||||
</asmTool>
|
</asmTool>
|
||||||
|
<linkerTool>
|
||||||
|
<linkerLibItems>
|
||||||
|
<linkerLibStdlibItem>Mathematics</linkerLibStdlibItem>
|
||||||
|
<linkerOptionItem>`pkg-config --libs libedit`</linkerOptionItem>
|
||||||
|
</linkerLibItems>
|
||||||
|
</linkerTool>
|
||||||
</compileType>
|
</compileType>
|
||||||
<item path="functions.c" ex="false" tool="0" flavor2="0">
|
<item path="functions.c" ex="false" tool="0" flavor2="0">
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
Reference in New Issue
Block a user