commit 46bbd5288532255e64ba0c5b5a4a7a1f912ebd34 Author: Sam Stevens Date: Tue May 20 15:32:21 2014 +0100 Initial Commit diff --git a/.dep.inc b/.dep.inc new file mode 100644 index 0000000..4560e55 --- /dev/null +++ b/.dep.inc @@ -0,0 +1,5 @@ +# This code depends on make tool being used +DEPFILES=$(wildcard $(addsuffix .d, ${OBJECTFILES})) +ifneq (${DEPFILES},) +include ${DEPFILES} +endif diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..74812ef --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Libraries +*.lib +*.a + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +#Other +/dist +/build diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..2a157f3 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/mpc"] + path = lib/mpc + url = https://github.com/orangeduck/mpc.git diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..05de621 --- /dev/null +++ b/Makefile @@ -0,0 +1,128 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help mesage +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_PLATFORM_${CONF} platform name (current configuration) +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# build tests +build-tests: .build-tests-post + +.build-tests-pre: +# Add your pre 'build-tests' code here... + +.build-tests-post: .build-tests-impl +# Add your post 'build-tests' code here... + + +# run tests +test: .test-post + +.test-pre: build-tests +# Add your pre 'test' code here... + +.test-post: .test-impl +# Add your post 'test' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/core b/core new file mode 100644 index 0000000..31ff299 Binary files /dev/null and b/core differ diff --git a/functions.c b/functions.c new file mode 100644 index 0000000..ba8b0c5 --- /dev/null +++ b/functions.c @@ -0,0 +1,184 @@ +#include +#include + +#include "lang.h" +#include "main.h" + +void lenv_add_builtin(lenv* env, char* sym, lbuiltin func) { + lval* symval = lval_sym(sym); + lval* funcval = lval_func(func, sym); + + lenv_put(env, symval, funcval); + + lval_delete(symval); + lval_delete(funcval); +} + +void lenv_add_builtin_funcs(lenv* env) { + //Math functions + lenv_add_builtin(env, "+", builtin_add); + lenv_add_builtin(env, "-", builtin_sub); + lenv_add_builtin(env, "/", builtin_div); + lenv_add_builtin(env, "*", builtin_mul); + lenv_add_builtin(env, "^", builtin_pow); + + //List/Util functions + lenv_add_builtin(env, "list", builtin_list); + lenv_add_builtin(env, "eval", builtin_eval); + lenv_add_builtin(env, "join", builtin_join); + lenv_add_builtin(env, "head", builtin_head); + lenv_add_builtin(env, "tail", builtin_tail); + + //ENV Functions + lenv_add_builtin(env, "def", builtin_def); + lenv_add_builtin(env, "listenv", builtin_listenv); + lenv_add_builtin(env, "exit", builtin_exit); +} + +lval* builtin_add(lenv* env, lval* val) { + return builtin_op(env, val, "+"); +} +lval* builtin_sub(lenv* env, lval* val) { + return builtin_op(env, val, "-"); +} +lval* builtin_div(lenv* env, lval* val) { + return builtin_op(env, val, "+"); +} +lval* builtin_mul(lenv* env, lval* val) { + return builtin_op(env, val, "*"); +} +lval* builtin_pow(lenv* env, lval* val){ + return builtin_op(env, val, "^"); +} +lval* builtin_op(lenv* env, lval* val, char* op) { + //Ensure numbers only + for(int i = 0; i < val->cell_count; i++) { + if (val->cell_list[i]->type != LVAL_NUM) { + lval_delete(val); + return lval_err(LERR_BAD_NUM); + } + } + + //Get the first element + lval* x = lval_pop(val, 0); + + if (strcmp(op, "-") == 0 && val->cell_count == 0) { + x->data.num = -x->data.num; + } + + while(val->cell_count > 0) { + //Get next to process + lval* y = lval_pop(val, 0); + + if (strcmp(op, "+") == 0) { x->data.num += y->data.num; } + if (strcmp(op, "-") == 0) { x->data.num -= y->data.num; } + if (strcmp(op, "*") == 0) { x->data.num *= y->data.num; } + if (strcmp(op, "^") == 0) { x->data.num = pow(x->data.num,y->data.num); } + if (strcmp(op, "/") == 0) { + int zero = 0; + if (y->type == LVAL_NUM && fabs(y->data.num) <= DBL_EPSILON) {zero = 1;} + + if (zero) { + lval_delete(x); + lval_delete(y); + x = lval_err(LERR_DIV_ZERO); + break; + } + x->data.num /= y->data.num; + } + + lval_delete(y); + } + + lval_delete(val); + return x; +} + +lval* builtin_list(lenv* env, lval* val){ + val->type = LVAL_Q_EXPR; + return val; +} +lval* builtin_eval(lenv* env, lval* val){ + LASSERT_ARG_COUNT("eval", val, val, 1); + LASSERT_TYPE("eval", val, val->cell_list[0], LVAL_Q_EXPR); + + lval* x = lval_take(val, 0); + x->type = LVAL_S_EXPR; + return eval(env, x); +} +lval* builtin_join(lenv* env, lval* val){ + LASSERT_MIN_ARG_COUNT("join", val, val, 1); + for(int i = 0; i < val->cell_count; i++) { + LASSERT_TYPE("join", val, val->cell_list[i], LVAL_Q_EXPR); + } + + lval* x = lval_pop(val,0); + + while(val->cell_count > 0) { + x = lval_join(x, lval_pop(val, 0)); + } + + return x; +} +lval* builtin_head(lenv* env, lval* val){ + LASSERT_ARG_COUNT("head",val , val, 1); + LASSERT_TYPE("head",val , val->cell_list[0], LVAL_Q_EXPR); + LASSERT_MIN_ARG_COUNT("head", val, val->cell_list[0], 1); + + lval* x = lval_take(val, 0); + while(x->cell_count > 1) { lval_delete(lval_pop(x, 1)); } + return x; +} +lval* builtin_tail(lenv* env, lval* val){ + LASSERT_ARG_COUNT("tail",val , val, 1); + LASSERT_TYPE("tail", val, val->cell_list[0], LVAL_Q_EXPR); + LASSERT_MIN_ARG_COUNT("tail", val, val->cell_list[0], 1); + + lval* x = lval_take(val, 0); + lval_delete(lval_pop(x, 0)); + return x; +} + +lval* builtin_def(lenv* env, lval* val) { + LASSERT_MIN_ARG_COUNT("def", val, val, 1); + LASSERT_TYPE("def", val, val->cell_list[0], LVAL_Q_EXPR); + + lval* symbols = val->cell_list[0]; + + for(int i = 0; i < symbols->cell_count; i++) { + LASSERT_TYPE("def", val, symbols->cell_list[i], LVAL_SYM); + } + + LASSERT(val, symbols->cell_count == val->cell_count -1, + LERR_OTHER, "def: incorrect number of definitions for symbols"); + + for(int i = 0; i < symbols->cell_count; i++) { + lenv_put(env, symbols->cell_list[i], val->cell_list[i+1]); + } + + lval_delete(val); + return lval_s_expr(); +} + +lval* builtin_listenv(lenv* env, lval* val) { + for(int i=0; i< env->count; i++) { + printf("%s: ", env->syms[i]->sym); + lval_println(env->syms[i]->lval); + } + lval_delete(val); + return lval_s_expr(); +} + +lval* builtin_exit(lenv* env, lval* val) { + lval* args = lval_q_expr(); + for(int i=0; icell_count; i++) { + lval_add(args, lval_copy(val->cell_list[i])); + } + lval* sym = lval_sym("exitcode"); + lenv_put(env, sym, args); + lval_delete(args); + lval_delete(sym); + + lval_delete(val); + return lval_exit(); +} \ No newline at end of file diff --git a/functions.h b/functions.h new file mode 100644 index 0000000..fab3d91 --- /dev/null +++ b/functions.h @@ -0,0 +1,46 @@ +/* + * File: functions.h + * Author: sam + * + * Created on 18 May 2014, 22:41 + */ + +#ifndef FUNCTIONS_H +#define FUNCTIONS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lang.h" + + void lenv_add_builtin(lenv* env, char* sym, lbuiltin func); + + void lenv_add_builtin_funcs(lenv* env); + + //Math functions + lval* builtin_add(lenv* env, lval* val); + lval* builtin_sub(lenv* env, lval* val); + lval* builtin_div(lenv* env, lval* val); + lval* builtin_mul(lenv* env, lval* val); + lval* builtin_pow(lenv* env, lval* val); + lval* builtin_op(lenv* env, lval* val, char* op); + + //List/Util functions + lval* builtin_list(lenv* env, lval* val); + lval* builtin_eval(lenv* env, lval* val); + lval* builtin_join(lenv* env, lval* val); + lval* builtin_head(lenv* env, lval* val); + lval* builtin_tail(lenv* env, lval* val); + + //ENV Functions + lval* builtin_def(lenv* env, lval* val); + lval* builtin_listenv(lenv* env, lval* val); + lval* builtin_exit(lenv* env, lval* val); + +#ifdef __cplusplus +} +#endif + +#endif /* FUNCTIONS_H */ + diff --git a/lang.c b/lang.c new file mode 100644 index 0000000..b321928 --- /dev/null +++ b/lang.c @@ -0,0 +1,121 @@ +#include +#include + +#include "mpc.h" +#include "lang.h" + +mpc_ast_t* tokenize(char *input) { + + mpc_parser_t* Number = mpc_new("number"); + mpc_parser_t* Symbol = mpc_new("symbol"); + mpc_parser_t* S_Expr = mpc_new("s_expr"); + mpc_parser_t* Q_Expr = mpc_new("q_expr"); + mpc_parser_t* Expr = mpc_new("expr"); + mpc_parser_t* Lispy = mpc_new("lispy"); + + mpca_lang(MPCA_LANG_DEFAULT, + " \ + number : /-?[0-9]+(\\.[0-9]+)?/ ; \ + symbol : /[a-zA-Z0-9_+\\-*\\/\\\\=<>!&]+/ ; \ + s_expr : '(' * ')' ; \ + q_expr : '{' * '}' ; \ + expr : | | | ; \ + lispy : /^/ + /$/ ; \ + ", + Number, Symbol, Expr, S_Expr, Q_Expr, Lispy); + + mpc_result_t result; + int success = 1; + + if (!mpc_parse("", input,Lispy, &result)) { + success = 0; + mpc_err_print(result.error); + mpc_err_delete(result.error); + } + + mpc_cleanup(6, Number, Symbol, S_Expr, Expr, Lispy, Q_Expr); + + return success ? (mpc_ast_t*)result.output : NULL; +} + +lval* parse(mpc_ast_t *t) { + if (strstr(t->tag, "number")) { + errno = 0; + double_t d = strtod(t->contents, NULL); + return errno != 0 ? lval_err_detail(LERR_BAD_NUM, strerror(errno)) : lval_num(d); + } + if (strstr(t->tag, "symbol")) { + return lval_sym(t->contents); + } + + lval* result = NULL; + if (strcmp(t->tag, ">") == 0) { result = lval_s_expr(); } + if (result == NULL && strstr(t->tag, "s_expr")) { result = lval_s_expr(); } + if (result == NULL && strstr(t->tag, "q_expr")) { result = lval_q_expr(); } + + for (int i = 0; i < t->children_num; i++) { + if (strcmp(t->children[i]->contents, "(") == 0) { continue; } + if (strcmp(t->children[i]->contents, ")") == 0) { continue; } + if (strcmp(t->children[i]->contents, "}") == 0) { continue; } + if (strcmp(t->children[i]->contents, "{") == 0) { continue; } + if (strcmp(t->children[i]->tag, "regex") == 0) { continue; } + result = lval_add(result, parse(t->children[i])); + } + return result; +} + +lval* eval_s_expr(lenv* env, lval* val) { + + //Eval children + for(int i = 0; i < val->cell_count; i++) { + val->cell_list[i] = eval(env, val->cell_list[i]); + } + + //Check for errors or exit + for(int i = 0; i < val->cell_count; i++) { + if (val->cell_list[i]->type == LVAL_ERR) { + return lval_take(val, i); + } + if (val->cell_list[i]->type == LVAL_EXIT) { + lval* exit = lval_copy(val->cell_list[i]); + lval_delete(val); + return exit; + } + } + + //empty + if (val->cell_count == 0) { + return val; + } + + //single + if (val->cell_count == 1) { + return lval_take(val, 0); + } + + //Ensure first is symbol + lval* func = lval_pop(val, 0); + if (func->type != LVAL_FUNC) { + VAL_TYPE type = func->type; + lval_delete(func); + lval_delete(val); + return lval_err_detail(LERR_BAD_OP, "First element is not %s got %s", lval_str_name(LVAL_FUNC), lval_str_name(type)); + } + + //Call builtin + lval* result = func->data.func.call(env, val); + lval_delete(func); + return result; + +} +lval* eval(lenv* env, lval* val) { + if (val->type == LVAL_SYM) { + lval* x = lenv_get(env, val); + lval_delete(val); + return x; + } + if (val->type == LVAL_S_EXPR) { + return eval_s_expr(env, val); + } + return val; +} \ No newline at end of file diff --git a/lang.h b/lang.h new file mode 100644 index 0000000..4939aa0 --- /dev/null +++ b/lang.h @@ -0,0 +1,49 @@ +/* + * File: lang.h + * Author: sam + * + * Created on 18 May 2014, 21:19 + */ + +#ifndef LANG_H +#define LANG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mpc.h" +#include "lval.h" +#include "lenv.h" +#include "functions.h" + +#define LASSERT(val, cond, errnum, errdetail, ...) \ + if (!(cond)) { \ + lval * err = lval_err_detail(errnum, errdetail, ##__VA_ARGS__); \ + lval_delete(val); \ + return err; \ + } + +#define LASSERT_TYPE(name, val, subject, expectedType) \ + LASSERT(val, subject->type == expectedType, \ + LERR_SYNTAX, "%s Expected type %s got %s", name, lval_str_name(expectedType), lval_str_name(subject->type)) +#define LASSERT_ARG_COUNT(name, val, subject, expectedNum) \ + LASSERT(val, subject->cell_count == expectedNum, \ + LERR_SYNTAX, "%s Expected %ld arguments got %ld", name, expectedNum, subject->cell_count ) +#define LASSERT_MIN_ARG_COUNT(name, val, subject, expectedNum) \ + 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); + lval* eval_s_expr(lenv* env, lval* val); + lval* eval(lenv* env, lval* val); + + +#ifdef __cplusplus +} +#endif + +#endif /* LANG_H */ + diff --git a/lenv.c b/lenv.c new file mode 100644 index 0000000..c1140b1 --- /dev/null +++ b/lenv.c @@ -0,0 +1,92 @@ +#include +#include + +#include "lang.h" +#include "util.h" + +lenv* lenv_new() { + lenv* env = calloc(1, sizeof(lenv)); + env->count = 0; + env->syms = NULL; + return env; +} +void lenv_delete(lenv* env) { + for(int i = 0; i < env->count; i++) { + lval_delete(env->syms[i]->lval); + free(env->syms[i]->sym); + free(env->syms[i]); + } + free(env->syms); + free(env); +} + +int lenv_compare_symtabs(const void *lhs, const void *rhs) { + const struct symtab* l = *(const struct symtab**)lhs; + const struct symtab* r = *(const struct symtab**)rhs; + + return strcmp(l->sym, r->sym); +} + +void lenv_sort(lenv* env) { + qsort(env->syms, env->count, sizeof(symtab*), lenv_compare_symtabs); +} + +symtab* lenv_search(lenv* env, char* sym) { + if (env->count == 0) { + return NULL; + } + symtab* searchElem = symtab_new(sym, NULL); + + symtab** searchComp = calloc(1, sizeof(symtab*)); + searchComp[0] = searchElem; + + symtab** result = bsearch(searchComp, env->syms, env->count, sizeof(symtab*), lenv_compare_symtabs); + + free(searchComp); + symtab_delete(searchElem); + + if (result == NULL) { + return NULL; + } + return *result; +} + +lval* lenv_get(lenv* env, lval* sym) { + LASSERT(sym, sym->type == LVAL_SYM, LERR_BAD_OP, "Expected symbol"); + + symtab* result = lenv_search(env, sym->data.sym); + return result != NULL ? lval_copy(result->lval) : lval_err(LERR_BAD_SYM); +} + +void lenv_put(lenv* env, lval* key, lval* val) { + symtab* result = lenv_search(env, key->data.sym); + if (result != NULL) { + lval_delete(result->lval); + result->lval = lval_copy(val); + + lenv_sort(env); + return; + } + + env->count ++; + + env->syms = realloc(env->syms, sizeof(symtab*) * env->count); + + env->syms[env->count-1] = symtab_new(key->data.sym, val); + + lenv_sort(env); +} + +symtab* symtab_new(char* sym, lval* lval) { + symtab* new = calloc(1, sizeof(symtab)); + new->lval = lval == NULL ? NULL : lval_copy(lval); + new->sym = strdup(sym); + return new; +} +void symtab_delete(symtab* symtab) { + if (symtab->lval != NULL) { + lval_delete(symtab->lval); + } + free(symtab->sym); + free(symtab); +} \ No newline at end of file diff --git a/lenv.h b/lenv.h new file mode 100644 index 0000000..3b1eb53 --- /dev/null +++ b/lenv.h @@ -0,0 +1,49 @@ +/* + * File: lenv.h + * Author: sam + * + * Created on 18 May 2014, 21:36 + */ + +#ifndef LENV_H +#define LENV_H + +#ifdef __cplusplus +extern "C" { +#endif + + struct lenv; + typedef struct lenv lenv; + + struct symtab; + typedef struct symtab symtab; + + struct symtab { + char* sym; + lval* lval; + }; + + struct lenv { + size_t count; + struct symtab** syms; + }; + + lenv* lenv_new(); + void lenv_delete(lenv* env); + + int lenv_compare_symtabs(const void *a, const void *b); + void lenv_sort(lenv* env); + symtab* lenv_search(lenv* env, char* sym); + + lval* lenv_get(lenv* env, lval* sym); + void lenv_put(lenv* env, lval* key, lval* val); + + symtab* symtab_new(char* sym, lval* lval); + void symtab_delete(symtab* symtab); + +#ifdef __cplusplus +} +#endif + +#endif /* LENV_H */ + diff --git a/lib/mpc b/lib/mpc new file mode 160000 index 0000000..6af8360 --- /dev/null +++ b/lib/mpc @@ -0,0 +1 @@ +Subproject commit 6af8360517a4d6091fe1580914be72f4d01c82c3 diff --git a/lval.c b/lval.c new file mode 100644 index 0000000..a800e6b --- /dev/null +++ b/lval.c @@ -0,0 +1,190 @@ +#include + +#include "lang.h" +#include "util.h" + +lval* lval_new(int type) { + lval* val = calloc(1,sizeof(lval)); + val->type = type; + return val; +} + +lval* lval_num(double_t x) { + lval* val = lval_new(LVAL_NUM); + val->data.num = x; + return val; +} + +lval* lval_sym(char* x) { + lval* val = lval_new(LVAL_SYM); + val->data.sym = strdup(x); + return val; +} + +lval* lval_s_expr() { + lval* val = lval_new(LVAL_S_EXPR); + val->cell_count = 0; + val->cell_list = NULL; + return val; +} + +lval* lval_q_expr() { + lval* val = lval_new(LVAL_Q_EXPR); + val->cell_count = 0; + val->cell_list = NULL; + return val; +} + +lval* lval_func(lbuiltin func, char* name) { + lval* val = lval_new(LVAL_FUNC); + val->data.func.call = func; + val->data.func.name = strdup(name); + return val; +} +lval* lval_exit() { + lval* val = lval_new(LVAL_EXIT); + return val; +} + +lval* lval_add(lval* val, lval* x) { + val->cell_count++; + val->cell_list = realloc(val->cell_list, sizeof(lval*)*val->cell_count); + val->cell_list[val->cell_count-1] = x; + return val; +} + +lval* lval_pop(lval* val, int index) { + //Get the item + lval* x = val->cell_list[index]; + + //Re-create the list ignoring the index we are extracting + lval** newList = NULL; + if (val->cell_count-1 > 0) { + newList = calloc(val->cell_count-1, sizeof(lval*)); + int k = 0; + for(int i=0; i < val->cell_count; i++) { + if (i == index) { + continue; + } + newList[k++] = val->cell_list[i]; + } + } + + val->cell_count--; + free(val->cell_list); + val->cell_list = newList; + + return x; +} + +lval* lval_take(lval* val, int i) { + lval* x = lval_pop(val, i); + lval_delete(val); + return x; +} + +lval* lval_join(lval* a, lval* b) { + while(b->cell_count > 0) { + lval_add(a, lval_pop(b,0)); + } + lval_delete(b); + return a; +} + +void lval_delete(lval* val) { + switch(val->type) { + case LVAL_NUM: break; + case LVAL_EXIT: break; + case LVAL_FUNC: free(val->data.func.name); break; + + case LVAL_SYM: free(val->data.sym); break; + case LVAL_ERR: + if (val->data.err.detail != NULL) { + free(val->data.err.detail); + } + break; + case LVAL_Q_EXPR: + case LVAL_S_EXPR: + for (int i = 0; i < val->cell_count; i++) { + lval_delete(val->cell_list[i]); + } + if (val->cell_count > 0) { + free(val->cell_list); + } + break; + } + free(val); +} + +lval* lval_copy(lval* current) { + lval* new = lval_new(current->type); + + switch(current->type) { + case LVAL_FUNC: + new->data.func.call = current->data.func.call; + new->data.func.name = strdup(current->data.func.name); + break; + case LVAL_NUM: new->data.num = current->data.num; break; + case LVAL_EXIT: break; + + case LVAL_SYM: new->data.sym = strdup(current->data.sym); break; + case LVAL_ERR: + new->data.err.num = current->data.err.num; + new->data.err.detail = current->data.err.detail == NULL ? NULL : strdup(current->data.err.detail); + break; + + case LVAL_Q_EXPR: + case LVAL_S_EXPR: + new->cell_count = current->cell_count; + if (new->cell_count == 0) { + new->cell_list = NULL; + } else { + new->cell_list = calloc(new->cell_count, sizeof(lval*)); + for(int i=0; i < new->cell_count; i++) { + new->cell_list[i] = lval_copy(current->cell_list[i]); + } + } + break; + } + + return new; +} + +lval* lval_err(VAL_ERROR err){ + return lval_err_detail(err, NULL); +} + +lval* lval_err_detail(VAL_ERROR err, char* format, ...){ + lval* val = lval_new(LVAL_ERR); + val->data.err.num = err; + + va_list va; + va_start(va, format); + + val->data.err.detail = calloc(512, sizeof(char)); + + vsnprintf(val->data.err.detail, 511, format, va); + + if (strlen(val->data.err.detail) == 0) { + free(val->data.err.detail); + val->data.err.detail = NULL; + } else { + val->data.err.detail = realloc(val->data.err.detail, strlen(val->data.err.detail)+1); + } + + va_end(va); + + return val; +} + +char* lval_str_name(VAL_TYPE type) { + switch(type) { + case LVAL_ERR: return "Error"; + case LVAL_FUNC: return "Function"; + case LVAL_NUM: return "Numeric"; + case LVAL_Q_EXPR: return "Q-Expression"; + case LVAL_SYM: return "Symbol"; + case LVAL_S_EXPR: return "S-Expression"; + default: return "UNKNOWN"; + } +} \ No newline at end of file diff --git a/lval.h b/lval.h new file mode 100644 index 0000000..61442c4 --- /dev/null +++ b/lval.h @@ -0,0 +1,72 @@ +/* + * File: lval.h + * Author: sam + * + * Created on 18 May 2014, 21:22 + */ + +#ifndef LVAL_H +#define LVAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct lval; +typedef struct lval lval; + +#include "lenv.h" + +enum VAL_TYPE { LVAL_ERR, LVAL_NUM, LVAL_SYM, LVAL_FUNC, LVAL_S_EXPR, LVAL_Q_EXPR, LVAL_EXIT }; +enum VAL_ERROR { LERR_DIV_ZERO, LERR_BAD_OP, LERR_BAD_NUM, LERR_BAD_SYM, LERR_OTHER, LERR_SYNTAX }; +typedef enum VAL_TYPE VAL_TYPE; +typedef enum VAL_ERROR VAL_ERROR; + +typedef lval*(*lbuiltin)(lenv*, lval*); + +typedef struct lval { + enum VAL_TYPE type; + union { + double_t num; + char* sym; + struct { + enum VAL_ERROR num; + char* detail; + } err; + struct { + char* name; + lbuiltin call; + } func; + } data; + + int cell_count; + struct lval** cell_list; + +} lval; + +lval* lval_new(int type); +lval* lval_num(double_t x); +lval* lval_sym(char* x); +lval* lval_s_expr(); +lval* lval_q_expr(); +lval* lval_func(lbuiltin func, char* name); +lval* lval_exit(); + +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); + +void lval_delete(lval* val); +lval* lval_copy(lval* current); + +lval* lval_err(VAL_ERROR x); +lval* lval_err_detail(VAL_ERROR x, char* format, ...); +char* lval_str_name(VAL_TYPE type); + +#ifdef __cplusplus +} +#endif + +#endif /* LVAL_H */ + diff --git a/main.c b/main.c new file mode 100644 index 0000000..ad2a20a --- /dev/null +++ b/main.c @@ -0,0 +1,124 @@ +/* + * File: main.c + * Author: sam + * + * Created on 17 May 2014, 11:49 + */ + +#include +#include + +#include +#include + +#include "mpc.h" +#include "lang.h" +#include "main.h" + +/* + * + */ +int main(int argc, char** argv) { + + printf("KLisp Version %s\n", VERSION); + + //Init environment + lenv* env = lenv_new(); + lenv_add_builtin_funcs(env); + + while(1) { + char *input = readline("> "); + if (NULL == input) { + break; + } + add_history(input); + + mpc_ast_t* ast_result = tokenize(input); + + free(input); + + if (ast_result != NULL) { + + //Parse the ast + lval* result = parse(ast_result); + if (result == NULL) { + result = lval_err(LERR_OTHER); + } + + //Evaluate + result = eval(env, result); + + int exit = 0; + if (result != NULL && result->type == LVAL_EXIT) { + exit = 1; + } else { + //print the result + lval_println(result); + } + + //Cleanup + lval_delete(result); + mpc_ast_delete(ast_result); + + if (exit == 1) { + printf("Program Terminated: "); + + lval* sym = lval_sym("exitcode"); + lval* exitcode = lenv_get(env, sym); + lval_println(exitcode); + lval_delete(exitcode); + lval_delete(sym); + break; + } + } + + } + + lenv_delete(env); + + return (EXIT_SUCCESS); +} + +void lval_expr_print(lval* val, char* open, char* close) { + printf("%s", open); + + for(int i = 0; i < val->cell_count ; i++) { + lval_print(val->cell_list[i]); + + if (i != val->cell_count-1) { + putchar(' '); + } + } + + printf("%s", close); +} + +void lval_print(lval* val) { + switch(val->type) { + case LVAL_NUM: printf("%g", val->data.num); break; + case LVAL_SYM: printf("%s", val->data.sym); break; + case LVAL_S_EXPR: lval_expr_print(val, "(", ")"); break; + case LVAL_Q_EXPR: lval_expr_print(val, "{", "}"); break; + case LVAL_FUNC: printf("<%s>", val->data.func.name); break; + case LVAL_EXIT: printf("exit"); break; + case LVAL_ERR: + printf("Error: "); + switch(val->data.err.num) { + case LERR_DIV_ZERO: printf("Divide By Zero"); break; + case LERR_BAD_NUM: printf("Bad Number"); break; + case LERR_BAD_OP: printf("Invalid Operator"); break; + case LERR_BAD_SYM: printf("Unknown/Invalid Symbol"); break; + case LERR_OTHER: printf("Unknown Error"); break; + case LERR_SYNTAX: printf("Syntax Error"); break; + default: printf("Unknown Error"); break; + } + if (val->data.err.detail != NULL) { + printf(", %s", val->data.err.detail); + } + break; + } +} +void lval_println(lval* val) { + lval_print(val); + putchar('\n'); +} \ No newline at end of file diff --git a/main.h b/main.h new file mode 100644 index 0000000..c9494d5 --- /dev/null +++ b/main.h @@ -0,0 +1,28 @@ +/* + * File: main.h + * Author: sam + * + * Created on 17 May 2014, 16:15 + */ + +#ifndef MAIN_H +#define MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define VERSION "0.1" + +int main(int argc, char** argv); + +void lval_expr_print(lval* val, char* open, char* close); +void lval_print(lval* val); +void lval_println(lval* val); + +#ifdef __cplusplus +} +#endif + +#endif /* MAIN_H */ + diff --git a/nbproject/Makefile-Debug.mk b/nbproject/Makefile-Debug.mk new file mode 100644 index 0000000..391f7de --- /dev/null +++ b/nbproject/Makefile-Debug.mk @@ -0,0 +1,120 @@ +# +# Generated Makefile - do not edit! +# +# Edit the Makefile in the project folder instead (../Makefile). Each target +# has a -pre and a -post target defined where you can add customized code. +# +# This makefile implements configuration specific macros and targets. + + +# Environment +MKDIR=mkdir +CP=cp +GREP=grep +NM=nm +CCADMIN=CCadmin +RANLIB=ranlib +CC=gcc +CCC=g++ +CXX=g++ +FC=gfortran +AS=as + +# Macros +CND_PLATFORM=GNU-Linux-x86 +CND_DLIB_EXT=so +CND_CONF=Debug +CND_DISTDIR=dist +CND_BUILDDIR=build + +# Include project Makefile +include Makefile + +# Object Directory +OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM} + +# Object Files +OBJECTFILES= \ + ${OBJECTDIR}/_ext/1360931409/mpc.o \ + ${OBJECTDIR}/functions.o \ + ${OBJECTDIR}/lang.o \ + ${OBJECTDIR}/lenv.o \ + ${OBJECTDIR}/lval.o \ + ${OBJECTDIR}/main.o \ + ${OBJECTDIR}/util.o + + +# C Compiler Flags +CFLAGS=-O0 + +# CC Compiler Flags +CCFLAGS= +CXXFLAGS= + +# Fortran Compiler Flags +FFLAGS= + +# Assembler Flags +ASFLAGS= + +# Link Libraries and Options +LDLIBSOPTIONS=`pkg-config --libs libedit` -lm + +# Build Targets +.build-conf: ${BUILD_SUBPROJECTS} + "${MAKE}" -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/klisp + +${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/klisp: ${OBJECTFILES} + ${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM} + ${LINK.c} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/klisp ${OBJECTFILES} ${LDLIBSOPTIONS} + +${OBJECTDIR}/_ext/1360931409/mpc.o: ../mpc/mpc.c + ${MKDIR} -p ${OBJECTDIR}/_ext/1360931409 + ${RM} "$@.d" + $(COMPILE.c) -g -Wall -Ilib/mpc `pkg-config --cflags libedit` -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/_ext/1360931409/mpc.o ../mpc/mpc.c + +${OBJECTDIR}/functions.o: functions.c + ${MKDIR} -p ${OBJECTDIR} + ${RM} "$@.d" + $(COMPILE.c) -g -Wall -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) -g -Wall -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) -g -Wall -Ilib/mpc `pkg-config --cflags libedit` -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/lenv.o lenv.c + +${OBJECTDIR}/lval.o: lval.c + ${MKDIR} -p ${OBJECTDIR} + ${RM} "$@.d" + $(COMPILE.c) -g -Wall -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) -g -Wall -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) -g -Wall -Ilib/mpc `pkg-config --cflags libedit` -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/util.o util.c + +# Subprojects +.build-subprojects: + +# Clean Targets +.clean-conf: ${CLEAN_SUBPROJECTS} + ${RM} -r ${CND_BUILDDIR}/${CND_CONF} + ${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/klisp + +# Subprojects +.clean-subprojects: + +# Enable dependency checking +.dep.inc: .depcheck-impl + +include .dep.inc diff --git a/nbproject/Makefile-Release.mk b/nbproject/Makefile-Release.mk new file mode 100644 index 0000000..4eab6d2 --- /dev/null +++ b/nbproject/Makefile-Release.mk @@ -0,0 +1,120 @@ +# +# Generated Makefile - do not edit! +# +# Edit the Makefile in the project folder instead (../Makefile). Each target +# has a -pre and a -post target defined where you can add customized code. +# +# This makefile implements configuration specific macros and targets. + + +# Environment +MKDIR=mkdir +CP=cp +GREP=grep +NM=nm +CCADMIN=CCadmin +RANLIB=ranlib +CC=gcc +CCC=g++ +CXX=g++ +FC=gfortran +AS=as + +# Macros +CND_PLATFORM=GNU-Linux-x86 +CND_DLIB_EXT=so +CND_CONF=Release +CND_DISTDIR=dist +CND_BUILDDIR=build + +# Include project Makefile +include Makefile + +# Object Directory +OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM} + +# Object Files +OBJECTFILES= \ + ${OBJECTDIR}/_ext/1360931409/mpc.o \ + ${OBJECTDIR}/functions.o \ + ${OBJECTDIR}/lang.o \ + ${OBJECTDIR}/lenv.o \ + ${OBJECTDIR}/lval.o \ + ${OBJECTDIR}/main.o \ + ${OBJECTDIR}/util.o + + +# C Compiler Flags +CFLAGS= + +# CC Compiler Flags +CCFLAGS= +CXXFLAGS= + +# Fortran Compiler Flags +FFLAGS= + +# Assembler Flags +ASFLAGS= + +# Link Libraries and Options +LDLIBSOPTIONS= + +# Build Targets +.build-conf: ${BUILD_SUBPROJECTS} + "${MAKE}" -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/klisp + +${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/klisp: ${OBJECTFILES} + ${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM} + ${LINK.c} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/klisp ${OBJECTFILES} ${LDLIBSOPTIONS} + +${OBJECTDIR}/_ext/1360931409/mpc.o: ../mpc/mpc.c + ${MKDIR} -p ${OBJECTDIR}/_ext/1360931409 + ${RM} "$@.d" + $(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/_ext/1360931409/mpc.o ../mpc/mpc.c + +${OBJECTDIR}/functions.o: functions.c + ${MKDIR} -p ${OBJECTDIR} + ${RM} "$@.d" + $(COMPILE.c) -O2 -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 + +${OBJECTDIR}/lenv.o: lenv.c + ${MKDIR} -p ${OBJECTDIR} + ${RM} "$@.d" + $(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/lenv.o lenv.c + +${OBJECTDIR}/lval.o: lval.c + ${MKDIR} -p ${OBJECTDIR} + ${RM} "$@.d" + $(COMPILE.c) -O2 -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 + +${OBJECTDIR}/util.o: util.c + ${MKDIR} -p ${OBJECTDIR} + ${RM} "$@.d" + $(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/util.o util.c + +# Subprojects +.build-subprojects: + +# Clean Targets +.clean-conf: ${CLEAN_SUBPROJECTS} + ${RM} -r ${CND_BUILDDIR}/${CND_CONF} + ${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/klisp + +# Subprojects +.clean-subprojects: + +# Enable dependency checking +.dep.inc: .depcheck-impl + +include .dep.inc diff --git a/nbproject/Makefile-impl.mk b/nbproject/Makefile-impl.mk new file mode 100644 index 0000000..5b25bd3 --- /dev/null +++ b/nbproject/Makefile-impl.mk @@ -0,0 +1,133 @@ +# +# Generated Makefile - do not edit! +# +# Edit the Makefile in the project folder instead (../Makefile). Each target +# has a pre- and a post- target defined where you can add customization code. +# +# This makefile implements macros and targets common to all configurations. +# +# NOCDDL + + +# Building and Cleaning subprojects are done by default, but can be controlled with the SUB +# macro. If SUB=no, subprojects will not be built or cleaned. The following macro +# statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf +# and .clean-reqprojects-conf unless SUB has the value 'no' +SUB_no=NO +SUBPROJECTS=${SUB_${SUB}} +BUILD_SUBPROJECTS_=.build-subprojects +BUILD_SUBPROJECTS_NO= +BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}} +CLEAN_SUBPROJECTS_=.clean-subprojects +CLEAN_SUBPROJECTS_NO= +CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}} + + +# Project Name +PROJECTNAME=KLisp + +# Active Configuration +DEFAULTCONF=Debug +CONF=${DEFAULTCONF} + +# All Configurations +ALLCONFS=Debug Release + + +# build +.build-impl: .build-pre .validate-impl .depcheck-impl + @#echo "=> Running $@... Configuration=$(CONF)" + "${MAKE}" -f nbproject/Makefile-${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .build-conf + + +# clean +.clean-impl: .clean-pre .validate-impl .depcheck-impl + @#echo "=> Running $@... Configuration=$(CONF)" + "${MAKE}" -f nbproject/Makefile-${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .clean-conf + + +# clobber +.clobber-impl: .clobber-pre .depcheck-impl + @#echo "=> Running $@..." + for CONF in ${ALLCONFS}; \ + do \ + "${MAKE}" -f nbproject/Makefile-$${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .clean-conf; \ + done + +# all +.all-impl: .all-pre .depcheck-impl + @#echo "=> Running $@..." + for CONF in ${ALLCONFS}; \ + do \ + "${MAKE}" -f nbproject/Makefile-$${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .build-conf; \ + done + +# build tests +.build-tests-impl: .build-impl .build-tests-pre + @#echo "=> Running $@... Configuration=$(CONF)" + "${MAKE}" -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-tests-conf + +# run tests +.test-impl: .build-tests-impl .test-pre + @#echo "=> Running $@... Configuration=$(CONF)" + "${MAKE}" -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .test-conf + +# dependency checking support +.depcheck-impl: + @echo "# This code depends on make tool being used" >.dep.inc + @if [ -n "${MAKE_VERSION}" ]; then \ + echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \ + echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \ + echo "include \$${DEPFILES}" >>.dep.inc; \ + echo "endif" >>.dep.inc; \ + else \ + echo ".KEEP_STATE:" >>.dep.inc; \ + echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \ + fi + +# configuration validation +.validate-impl: + @if [ ! -f nbproject/Makefile-${CONF}.mk ]; \ + then \ + echo ""; \ + echo "Error: can not find the makefile for configuration '${CONF}' in project ${PROJECTNAME}"; \ + echo "See 'make help' for details."; \ + echo "Current directory: " `pwd`; \ + echo ""; \ + fi + @if [ ! -f nbproject/Makefile-${CONF}.mk ]; \ + then \ + exit 1; \ + fi + + +# help +.help-impl: .help-pre + @echo "This makefile supports the following configurations:" + @echo " ${ALLCONFS}" + @echo "" + @echo "and the following targets:" + @echo " build (default target)" + @echo " clean" + @echo " clobber" + @echo " all" + @echo " help" + @echo "" + @echo "Makefile Usage:" + @echo " make [CONF=] [SUB=no] build" + @echo " make [CONF=] [SUB=no] clean" + @echo " make [SUB=no] clobber" + @echo " make [SUB=no] all" + @echo " make help" + @echo "" + @echo "Target 'build' will build a specific configuration and, unless 'SUB=no'," + @echo " also build subprojects." + @echo "Target 'clean' will clean a specific configuration and, unless 'SUB=no'," + @echo " also clean subprojects." + @echo "Target 'clobber' will remove all built files from all configurations and," + @echo " unless 'SUB=no', also from subprojects." + @echo "Target 'all' will will build all configurations and, unless 'SUB=no'," + @echo " also build subprojects." + @echo "Target 'help' prints this message." + @echo "" + diff --git a/nbproject/Makefile-variables.mk b/nbproject/Makefile-variables.mk new file mode 100644 index 0000000..f8ab32e --- /dev/null +++ b/nbproject/Makefile-variables.mk @@ -0,0 +1,35 @@ +# +# Generated - do not edit! +# +# NOCDDL +# +CND_BASEDIR=`pwd` +CND_BUILDDIR=build +CND_DISTDIR=dist +# Debug configuration +CND_PLATFORM_Debug=GNU-Linux-x86 +CND_ARTIFACT_DIR_Debug=dist/Debug/GNU-Linux-x86 +CND_ARTIFACT_NAME_Debug=klisp +CND_ARTIFACT_PATH_Debug=dist/Debug/GNU-Linux-x86/klisp +CND_PACKAGE_DIR_Debug=dist/Debug/GNU-Linux-x86/package +CND_PACKAGE_NAME_Debug=klisp.tar +CND_PACKAGE_PATH_Debug=dist/Debug/GNU-Linux-x86/package/klisp.tar +# Release configuration +CND_PLATFORM_Release=GNU-Linux-x86 +CND_ARTIFACT_DIR_Release=dist/Release/GNU-Linux-x86 +CND_ARTIFACT_NAME_Release=klisp +CND_ARTIFACT_PATH_Release=dist/Release/GNU-Linux-x86/klisp +CND_PACKAGE_DIR_Release=dist/Release/GNU-Linux-x86/package +CND_PACKAGE_NAME_Release=klisp.tar +CND_PACKAGE_PATH_Release=dist/Release/GNU-Linux-x86/package/klisp.tar +# +# include compiler specific variables +# +# dmake command +ROOT:sh = test -f nbproject/private/Makefile-variables.mk || \ + (mkdir -p nbproject/private && touch nbproject/private/Makefile-variables.mk) +# +# gmake command +.PHONY: $(shell test -f nbproject/private/Makefile-variables.mk || (mkdir -p nbproject/private && touch nbproject/private/Makefile-variables.mk)) +# +include nbproject/private/Makefile-variables.mk diff --git a/nbproject/Package-Debug.bash b/nbproject/Package-Debug.bash new file mode 100644 index 0000000..ea4be55 --- /dev/null +++ b/nbproject/Package-Debug.bash @@ -0,0 +1,76 @@ +#!/bin/bash -x + +# +# Generated - do not edit! +# + +# Macros +TOP=`pwd` +CND_PLATFORM=GNU-Linux-x86 +CND_CONF=Debug +CND_DISTDIR=dist +CND_BUILDDIR=build +CND_DLIB_EXT=so +NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging +TMPDIRNAME=tmp-packaging +OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/klisp +OUTPUT_BASENAME=klisp +PACKAGE_TOP_DIR=klisp/ + +# Functions +function checkReturnCode +{ + rc=$? + if [ $rc != 0 ] + then + exit $rc + fi +} +function makeDirectory +# $1 directory path +# $2 permission (optional) +{ + mkdir -p "$1" + checkReturnCode + if [ "$2" != "" ] + then + chmod $2 "$1" + checkReturnCode + fi +} +function copyFileToTmpDir +# $1 from-file path +# $2 to-file path +# $3 permission +{ + cp "$1" "$2" + checkReturnCode + if [ "$3" != "" ] + then + chmod $3 "$2" + checkReturnCode + fi +} + +# Setup +cd "${TOP}" +mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package +rm -rf ${NBTMPDIR} +mkdir -p ${NBTMPDIR} + +# Copy files and create directories and links +cd "${TOP}" +makeDirectory "${NBTMPDIR}/klisp/bin" +copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755 + + +# Generate tar file +cd "${TOP}" +rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/klisp.tar +cd ${NBTMPDIR} +tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/klisp.tar * +checkReturnCode + +# Cleanup +cd "${TOP}" +rm -rf ${NBTMPDIR} diff --git a/nbproject/Package-Release.bash b/nbproject/Package-Release.bash new file mode 100644 index 0000000..3cc7765 --- /dev/null +++ b/nbproject/Package-Release.bash @@ -0,0 +1,76 @@ +#!/bin/bash -x + +# +# Generated - do not edit! +# + +# Macros +TOP=`pwd` +CND_PLATFORM=GNU-Linux-x86 +CND_CONF=Release +CND_DISTDIR=dist +CND_BUILDDIR=build +CND_DLIB_EXT=so +NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging +TMPDIRNAME=tmp-packaging +OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/klisp +OUTPUT_BASENAME=klisp +PACKAGE_TOP_DIR=klisp/ + +# Functions +function checkReturnCode +{ + rc=$? + if [ $rc != 0 ] + then + exit $rc + fi +} +function makeDirectory +# $1 directory path +# $2 permission (optional) +{ + mkdir -p "$1" + checkReturnCode + if [ "$2" != "" ] + then + chmod $2 "$1" + checkReturnCode + fi +} +function copyFileToTmpDir +# $1 from-file path +# $2 to-file path +# $3 permission +{ + cp "$1" "$2" + checkReturnCode + if [ "$3" != "" ] + then + chmod $3 "$2" + checkReturnCode + fi +} + +# Setup +cd "${TOP}" +mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package +rm -rf ${NBTMPDIR} +mkdir -p ${NBTMPDIR} + +# Copy files and create directories and links +cd "${TOP}" +makeDirectory "${NBTMPDIR}/klisp/bin" +copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755 + + +# Generate tar file +cd "${TOP}" +rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/klisp.tar +cd ${NBTMPDIR} +tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/klisp.tar * +checkReturnCode + +# Cleanup +cd "${TOP}" +rm -rf ${NBTMPDIR} diff --git a/nbproject/configurations.xml b/nbproject/configurations.xml new file mode 100644 index 0000000..20f2378 --- /dev/null +++ b/nbproject/configurations.xml @@ -0,0 +1,149 @@ + + + + + functions.h + lang.h + lenv.h + lval.h + main.h + ../mpc/mpc.h + util.h + + + + + functions.c + lang.c + lenv.c + lval.c + main.c + ../mpc/mpc.c + util.c + + + + + Makefile + + + Makefile + + + + default + true + false + + + + 3 + gcc + + lib/mpc + + -O0 + 2 + + + 2 + + + + `pkg-config --libs libedit` + Mathematics + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + default + true + false + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nbproject/private/Makefile-variables.mk b/nbproject/private/Makefile-variables.mk new file mode 100644 index 0000000..a64183e --- /dev/null +++ b/nbproject/private/Makefile-variables.mk @@ -0,0 +1,7 @@ +# +# Generated - do not edit! +# +# NOCDDL +# +# Debug configuration +# Release configuration diff --git a/nbproject/private/configurations.xml b/nbproject/private/configurations.xml new file mode 100644 index 0000000..a0dea49 --- /dev/null +++ b/nbproject/private/configurations.xml @@ -0,0 +1,72 @@ + + + Makefile + + + + localhost + 2 + + + + + + + + + + + + + + + gdb + + + + "${OUTPUT_PATH}" + + "${OUTPUT_PATH}" + + true + 0 + 0 + + + + + + + localhost + 2 + + + + + + + + + + + + + + + gdb + + + + "${OUTPUT_PATH}" + + "${OUTPUT_PATH}" + + true + 0 + 0 + + + + + + diff --git a/nbproject/private/launcher.properties b/nbproject/private/launcher.properties new file mode 100644 index 0000000..6cc2127 --- /dev/null +++ b/nbproject/private/launcher.properties @@ -0,0 +1,40 @@ +# Launchers File syntax: +# +# [Must-have property line] +# launcher1.runCommand= +# [Optional extra properties] +# launcher1.displayName= +# launcher1.buildCommand= +# launcher1.runDir= +# launcher1.symbolFiles= +# launcher1.env.= +# (If this value is quoted with ` it is handled as a native command which execution result will become the value) +# [Common launcher properties] +# common.runDir= +# (This value is overwritten by a launcher specific runDir value if the latter exists) +# common.env.= +# (Environment variables from common launcher are merged with launcher specific variables) +# common.symbolFiles= +# (This value is overwritten by a launcher specific symbolFiles value if the latter exists) +# +# In runDir, symbolFiles and env fields you can use these macroses: +# ${PROJECT_DIR} - project directory absolute path +# ${OUTPUT_PATH} - linker output path (relative to project directory path) +# ${OUTPUT_BASENAME}- linker output filename +# ${TESTDIR} - test files directory (relative to project directory path) +# ${OBJECTDIR} - object files directory (relative to project directory path) +# ${CND_DISTDIR} - distribution directory (relative to project directory path) +# ${CND_BUILDDIR} - build directory (relative to project directory path) +# ${CND_PLATFORM} - platform name +# ${CND_CONF} - configuration name +# ${CND_DLIB_EXT} - dynamic library extension +# +# All the project launchers must be listed in the file! +# +# launcher1.runCommand=... +# launcher2.runCommand=... +# ... +# common.runDir=... +# common.env.KEY=VALUE + +# launcher1.runCommand= \ No newline at end of file diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml new file mode 100644 index 0000000..8b040a7 --- /dev/null +++ b/nbproject/private/private.xml @@ -0,0 +1,21 @@ + + + + 1 + 0 + + + + + file:/home/sam/NetBeansProjects/CppApplication_1/lval.c + file:/home/sam/NetBeansProjects/CppApplication_1/main.c + file:/home/sam/NetBeansProjects/CppApplication_1/lval.h + file:/home/sam/NetBeansProjects/CppApplication_1/lang.c + file:/home/sam/NetBeansProjects/CppApplication_1/functions.c + file:/home/sam/NetBeansProjects/CppApplication_1/main.h + file:/home/sam/NetBeansProjects/CppApplication_1/functions.h + file:/home/sam/NetBeansProjects/CppApplication_1/lang.h + file:/home/sam/NetBeansProjects/CppApplication_1/lenv.c + + + diff --git a/nbproject/project.xml b/nbproject/project.xml new file mode 100644 index 0000000..e37d6dd --- /dev/null +++ b/nbproject/project.xml @@ -0,0 +1,28 @@ + + + org.netbeans.modules.cnd.makeproject + + + KLisp + c + + h + UTF-8 + + + + + Debug + 1 + + + Release + 1 + + + + false + + + + diff --git a/util.c b/util.c new file mode 100644 index 0000000..4fa9c44 --- /dev/null +++ b/util.c @@ -0,0 +1,11 @@ +#include +#include + +#include "util.h" + +char * strdup(char* s) { + char *d = calloc(1, strlen (s) + 1); + if (d == NULL) return NULL; + strcpy (d,s); + return d; +} diff --git a/util.h b/util.h new file mode 100644 index 0000000..0874f2d --- /dev/null +++ b/util.h @@ -0,0 +1,22 @@ +/* + * File: util.h + * Author: sam + * + * Created on 18 May 2014, 21:29 + */ + +#ifndef UTIL_H +#define UTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +char * strdup(char* s); + +#ifdef __cplusplus +} +#endif + +#endif /* UTIL_H */ +