diff --git a/.gitignore b/.gitignore
index 461a8c9..78ed071 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,9 @@
# Project exclude paths
/cmake-build-debug/
.idea
-/.idea/*
\ No newline at end of file
+/.idea/*
+cmake_install.cmake
+CMakeCache.txt
+Connery
+Makefile
+/CMakeFiles/
\ No newline at end of file
diff --git a/.run/Connery [test.connery].run.xml b/.run/Connery [test.connery].run.xml
new file mode 100644
index 0000000..9004d32
--- /dev/null
+++ b/.run/Connery [test.connery].run.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/Connery.run.xml b/.run/Connery.run.xml
new file mode 100644
index 0000000..a093685
--- /dev/null
+++ b/.run/Connery.run.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/local.run.run.xml b/.run/local.run.run.xml
new file mode 100644
index 0000000..d9e6478
--- /dev/null
+++ b/.run/local.run.run.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Buildfile b/Buildfile
new file mode 100644
index 0000000..02ff9ab
--- /dev/null
+++ b/Buildfile
@@ -0,0 +1,29 @@
+local.install:
+ sudo apt-get -y install build-essential
+ sudo apt-get -y install cmake
+ sudo apt-get -y install libcurl4-openssl-dev
+ sudo apt-get -y install libedit-dev
+
+local.build:
+ cmake src/.
+ make Connery
+
+local.clean:
+ make clean || true
+ rm cmake_install.cmake || true
+ rm CMakeCache.txt || true
+ rm -r CMakeFiles || true
+ rm -r stdlib || true
+ rm Makefile || true
+
+local.run:
+ ./Connery || cmake src/. && make Connery && ./Connery || sudo apt-get -y install build-essential; sudo apt-get -y install cmake; sudo apt-get -y install libcurl4-openssl-dev; sudo apt-get -y install libedit-dev; cmake src/. && make Connery && ./Connery || echo "There is nothing like a challenge to bring out the best in man."
+
+docker.build:
+ docker build --tag connerylang .
+
+docker.clean:
+ docker rmi connerylang --force
+
+docker.run:
+ docker run -it connerylang || docker build --tag connerylang . && docker run -it connerylang
\ No newline at end of file
diff --git a/install.sh b/install.sh
new file mode 100755
index 0000000..bb4fa3b
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+connery_install_path=$(eval echo ~$user);
+export CONNERY_INSTALL_PATH=$connery_install_path;
+export CONNERY_PATH=$connery_install_path"/Connery"
+
+pushd ./
+
+cd "$CONNERY_INSTALL_PATH" || exit &&
+git clone --single-branch --branch feature/traceback_system https://github.com/willcipriano/Connery.git
+
+
+cd "$CONNERY_PATH" || exit &&
+make -f Buildfile local.install ; make -f Buildfile local.build
+
+rm Buildfile || true ;
+rm CMakeCache.txt || true ;
+rm -rf CMakeFiles || true ;
+rm cmake_install.cmake || true ;
+rm Dockerfile || true ;
+rm -rf Makefile || true ;
+rm -rf src || true ;
+
+export PATH=$PATH:$CONNERY_PATH
+
+
+
+
+
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dea220b..77fffbf 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -5,7 +5,7 @@ set(CMAKE_C_STANDARD 99)
set(CURL_LIBRARY "-lcurl")
find_package(CURL REQUIRED)
-add_executable(Connery main.c mpc.c util.c util.h hashtable.c hashtable.h cval.h cval.c)
+add_executable(Connery main.c mpc.c util.c util.h hashtable.c hashtable.h cval.h cval.c trace.c trace.h)
include_directories(${CURL_INCLUDE_DIR})
target_link_libraries(Connery PRIVATE /usr/lib/x86_64-linux-gnu/libedit.so ${CURL_LIBRARIES})
diff --git a/src/cval.c b/src/cval.c
index b4610dd..4f28899 100644
--- a/src/cval.c
+++ b/src/cval.c
@@ -1,10 +1,14 @@
#include "cval.h"
+#include "util.h"
+#include "trace.h"
#include
#include
#include
#include
+#include
-#define ENV_HASH_TABLE_SIZE 1000
+#define ENV_HASH_TABLE_SIZE 10000
+#define SYSTEM_LANG 1
#define CASSERT(args, cond, fmt, ...) \
if (!(cond)) {\
@@ -24,135 +28,115 @@ if (!(cond)) {\
func, args->count, num)
-cval *cval_pop(cval *value, int i);
+cval* cval_pop(cval* value, int i);
+cval* cval_evaluate(cenv* env,cval* value);
+cval* cval_take(cval* value, int i);
-cval *cval_evaluate(cenv *env, cval *value);
-
-cval *cval_take(cval *value, int i);
-
-char *ctype_name(int t) {
- switch (t) {
- case CVAL_FUNCTION:
- return "Function";
- case CVAL_NUMBER:
- return "Number";
- case CVAL_ERROR:
- return "Error";
- case CVAL_SYMBOL:
- return "Symbol";
- case CVAL_S_EXPRESSION:
- return "S-Expression";
- case CVAL_Q_EXPRESSION:
- return "Q-Expression";
- case CVAL_STRING:
- return "String";
- case CVAL_FLOAT:
- return "Float";
- case CVAL_BOOLEAN:
- return "Boolean";
- case CVAL_NULL:
- return "Null";
- default:
- return "Unknown Type";
+char* ctype_name(int t) {
+ switch(t) {
+ case CVAL_FUNCTION: return "Function";
+ case CVAL_NUMBER: return "Number";
+ case CVAL_ERROR: return "Error";
+ case CVAL_SYMBOL: return "Symbol";
+ case CVAL_S_EXPRESSION: return "S-Expression";
+ case CVAL_Q_EXPRESSION: return "Q-Expression";
+ case CVAL_STRING: return "String";
+ case CVAL_FLOAT: return "Float";
+ case CVAL_BOOLEAN: return "Boolean";
+ default: return "Unknown Type";
}
}
-cval *cval_function(cbuiltin func) {
- cval *v = malloc(sizeof(cval));
+cval* cval_function(cbuiltin func) {
+ cval* v = malloc(sizeof(cval));
v->type = CVAL_FUNCTION;
v->builtin = func;
return v;
}
-cval *cval_number(long x) {
+cval *cval_boolean(bool b) {
cval *value = malloc(sizeof(cval));
+ value->type = CVAL_BOOLEAN;
+ value->boolean = b;
+ value->count = 0;
+ value->cell = NULL;
+ return value;
+}
+
+cval* cval_number(long x) {
+ cval* value = malloc(sizeof(cval));
value->type = CVAL_NUMBER;
value->num = x;
return value;
}
-cval *cval_float(long double x) {
- cval *value = malloc(sizeof(cval));
+cval* cval_float(long double x) {
+ cval* value = malloc(sizeof(cval));
value->type = CVAL_FLOAT;
value->fnum = x;
return value;
}
-cval *cval_string(char *s) {
- cval *v = malloc(sizeof(cval));
+cval* cval_string (char* s) {
+ cval* v = malloc(sizeof(cval));
v->type = CVAL_STRING;
v->str = malloc(strlen(s) + 1);
strcpy(v->str, s);
return v;
}
-cval *cval_error(char *fmt, ...) {
- cval *value = malloc(sizeof(cval));
+cval* cval_error(char* fmt, ...) {
+ cval* value = malloc(sizeof(cval));
value->type = CVAL_ERROR;
va_list va;
va_start(va, fmt);
value->err = malloc(512);
vsnprintf(value->err, 511, fmt, va);
- value->err = realloc(value->err, strlen(value->err) + 1);
+ value->err = realloc(value->err, strlen(value->err)+1);
va_end(va);
return value;
}
-cval *cval_symbol(char *s) {
- cval *value = malloc(sizeof(cval));
+cval* cval_symbol(char* s) {
+ cval* value = malloc(sizeof(cval));
value->type = CVAL_SYMBOL;
value->sym = malloc(strlen(s) + 1);
strcpy(value->sym, s);
return value;
}
-cval *cval_s_expression(void) {
- cval *value = malloc(sizeof(cval));
+cval* cval_s_expression(void) {
+ cval* value = malloc(sizeof(cval));
value->type = CVAL_S_EXPRESSION;
value->count = 0;
value->cell = NULL;
return value;
}
-cval *cval_q_expression(void) {
- cval *value = malloc(sizeof(cval));
+cval* cval_q_expression(void) {
+ cval* value = malloc(sizeof(cval));
value->type = CVAL_Q_EXPRESSION;
value->count = 0;
value->cell = NULL;
return value;
}
-cval *cval_boolean(bool b) {
- cval *value = malloc(sizeof(cval));
- value->type = CVAL_BOOLEAN;
- value->boolean = b;
- value->count = 0;
- value->cell = NULL;
- return value;
-}
-cval *cval_null() {
- cval *value = malloc(sizeof(cval));
- value->type = CVAL_NULL;
- value->count = 0;
- value->cell = NULL;
- return value;
-}
-cenv *cenv_new(void) {
- cenv *e = malloc(sizeof(cenv));
+cenv* cenv_new(void) {
+ cenv* e = malloc(sizeof(cenv));
e->par = NULL;
e->ht = hash_table_create(ENV_HASH_TABLE_SIZE);
return e;
}
-void cenv_delete(cenv *e) {
+void cenv_delete(cenv* e) {
hash_table_destroy(e->ht);
free(e);
}
-void cval_delete(cval *value) {
- switch (value->type) {
+void cval_delete(cval* value) {
+ switch(value->type) {
case CVAL_NUMBER:
break;
@@ -192,41 +176,41 @@ void cval_delete(cval *value) {
free(value);
}
-cval *cval_take(cval *value, int i) {
- cval *x = cval_pop(value, i);
+cval* cval_take(cval* value, int i) {
+ cval* x = cval_pop(value, i);
cval_delete(value);
return x;
}
-cval *cval_pop(cval *value, int i) {
- cval *x = value->cell[i];
- memmove(&value->cell[i], &value->cell[i + 1],
- sizeof(cval *) * (value->count - i - 1));
+cval* cval_pop(cval* value, int i) {
+ cval* x = value->cell[i];
+ memmove(&value->cell[i], &value->cell[i+1],
+ sizeof(cval*) * (value->count-i-1));
value->count--;
- value->cell = realloc(value->cell, sizeof(cval *) * value->count);
+ value->cell = realloc(value->cell, sizeof(cval*) * value->count);
return x;
}
-cval *builtin_eval(cenv *e, cval *a) {
+cval* builtin_eval(cenv* e, cval* a) {
CASSERT_NUM("eval", a, 1);
CASSERT_TYPE("eval", a, 0, CVAL_Q_EXPRESSION);
- cval *x = cval_take(a, 0);
+ cval* x = cval_take(a, 0);
x->type = CVAL_S_EXPRESSION;
return cval_evaluate(e, x);
}
-cenv *cenv_copy(cenv *e) {
- cenv *n = malloc(sizeof(cenv));
+cenv* cenv_copy(cenv* e) {
+ cenv* n = malloc(sizeof(cenv));
n->par = e->par;
n->ht = hash_table_copy(e->ht);
return n;
}
-cval *cval_copy(cval *v) {
- cval *x = malloc(sizeof(cval));
+cval* cval_copy(cval* v) {
+ cval* x = malloc(sizeof(cval));
x->type = v->type;
switch (v->type) {
@@ -262,7 +246,7 @@ cval *cval_copy(cval *v) {
case CVAL_S_EXPRESSION:
case CVAL_Q_EXPRESSION:
x->count = v->count;
- x->cell = malloc(sizeof(cval *) * x->count);
+ x->cell = malloc(sizeof(cval*) * x->count);
for (int i = 0; i < x->count; i++) {
x->cell[i] = cval_copy(v->cell[i]);
}
@@ -273,45 +257,45 @@ cval *cval_copy(cval *v) {
strcpy(x->str, v->str);
break;
+
case CVAL_BOOLEAN:
x->boolean = v->boolean;
break;
-
}
return x;
}
-void cenv_put(cenv *e, cval *k, cval *v) {
+void cenv_put(cenv* e, cval* k, cval* v) {
hash_table_set(e->ht, k->sym, v);
}
-cval *builtin_list(cenv *e, cval *a) {
+cval* builtin_list(cenv* e, cval* a) {
a->type = CVAL_Q_EXPRESSION;
return a;
}
-cval *cval_add(cval *v, cval *x) {
+cval* cval_add(cval* v, cval* x) {
v->count++;
- v->cell = realloc(v->cell, sizeof(cval *) * v->count);
- v->cell[v->count - 1] = x;
+ v->cell = realloc(v->cell, sizeof(cval*) * v->count);
+ v->cell[v->count-1] = x;
return v;
}
-cval *cval_call(cenv *e, cval *f, cval *a) {
- if (f->builtin) { return f->builtin(e, a); }
+cval* cval_call(cenv* e, cval* f, cval* a) {
+ if (f->builtin) {return f->builtin(e, a);}
int given = a->count;
int total = f->formals->count;
while (a->count) {
- if (f->formals->count == 0) {
+ if(f->formals->count == 0) {
cval_delete(a);
return cval_error("Function pashed too many argumentsh. Got %i, Expected %s", given, total);
}
- cval *sym = cval_pop(f->formals, 0);
+ cval* sym = cval_pop(f->formals, 0);
if (strcmp(sym->sym, "&") == 0) {
@@ -320,14 +304,14 @@ cval *cval_call(cenv *e, cval *f, cval *a) {
return cval_error("Function format invalid. shymbol '&' not followed by shingle shymbol.");
}
- cval *nsym = cval_pop(f->formals, 0);
+ cval* nsym = cval_pop(f->formals, 0);
cenv_put(f->env, nsym, builtin_list(e, a));
cval_delete(sym);
cval_delete(nsym);
break;
}
- cval *val = cval_pop(a, 0);
+ cval* val = cval_pop(a, 0);
cenv_put(f->env, sym, val);
cval_delete(sym);
@@ -344,8 +328,8 @@ cval *cval_call(cenv *e, cval *f, cval *a) {
cval_delete(cval_pop(f->formals, 0));
- cval *sym = cval_pop(f->formals, 0);
- cval *val = cval_q_expression();
+ cval* sym = cval_pop(f->formals, 0);
+ cval* val = cval_q_expression();
cenv_put(f->env, sym, val);
cval_delete(sym);
@@ -355,19 +339,20 @@ cval *cval_call(cenv *e, cval *f, cval *a) {
if (f->formals->count == 0) {
f->env->par = e;
return builtin_eval(f->env, cval_add(cval_s_expression(), cval_copy(f->body)));
- } else {
+ }
+ else {
return cval_copy(f);
}
}
-cval *cval_evaluate_s_expression(cenv *env, cval *value) {
+cval* cval_evaluate_s_expression(cenv* env, cval* value) {
for (int i = 0; i < value->count; i++) {
value->cell[i] = cval_evaluate(env, value->cell[i]);
}
for (int i = 0; i < value->count; i++) {
- if (value->cell[i]->type == CVAL_ERROR) { return cval_take(value, i); }
+ if (value->cell[i]->type == CVAL_ERROR) {return cval_take(value, i);}
}
if (value->count == 0) {
@@ -378,22 +363,20 @@ cval *cval_evaluate_s_expression(cenv *env, cval *value) {
return cval_evaluate(env, cval_take(value, 0));
}
- cval *f = cval_pop(value, 0);
+ cval* f = cval_pop(value, 0);
if (f->type != CVAL_FUNCTION) {
-// cval *err = cval_error("S-Expression starts with incorrect type. Got %s, Expected %s", ctype_name(f->type),
-// ctype_name(CVAL_FUNCTION));
- cval_delete(f);
- cval_delete(value);
- return cval_null();
- }
+ if (f->type == CVAL_S_EXPRESSION) {
+ return cval_evaluate_s_expression(env, f);
+ }
+ }
- cval *result = cval_call(env, f, value);
+ cval* result = cval_call(env, f, value);
cval_delete(f);
return result;
}
-cval *cenv_get(cenv *e, cval *k) {
- cval *value = hash_table_get(e->ht, k->sym);
+cval* cenv_get(cenv* e, cval* k) {
+ cval* value = hash_table_get(e->ht, k->sym);
if (value != NULL) {
return cval_copy(value);
}
@@ -405,9 +388,9 @@ cval *cenv_get(cenv *e, cval *k) {
}
}
-cval *cval_evaluate(cenv *env, cval *value) {
+cval* cval_evaluate(cenv* env, cval* value) {
if (value->type == CVAL_SYMBOL) {
- cval *x = cenv_get(env, value);
+ cval* x = cenv_get(env, value);
cval_delete(value);
return x;
}
@@ -418,40 +401,39 @@ cval *cval_evaluate(cenv *env, cval *value) {
return value;
}
-void cenv_add_builtin(cenv *e, char *name, cbuiltin func) {
- cval *k = cval_symbol(name);
- cval *v = cval_function(func);
+void cenv_add_builtin(cenv* e, char* name, cbuiltin func) {
+ cval* k = cval_symbol(name);
+ cval* v = cval_function(func);
cenv_put(e, k, v);
cval_delete(k);
cval_delete(v);
}
-void cenv_def(cenv *e, cval *k, cval *v) {
+
+void cenv_def(cenv* e, cval* k, cval* v) {
while (e->par) {
e = e->par;
}
- cenv_put(e, k, v);
+ cenv_put(e, k , v);
}
-cval *builtin_var(cenv *e, cval *a, char *func) {
+cval* builtin_var(cenv* e, cval* a, char* func) {
CASSERT_TYPE("def", a, 0, CVAL_Q_EXPRESSION)
- cval *syms = a->cell[0];
+ cval* syms = a->cell[0];
for (int i = 0; i < syms->count; i++) {
CASSERT_TYPE("def", syms, i, CVAL_SYMBOL)
}
- CASSERT(a, (syms->count == a->count - 1),
- "Function '%s' pashed too many arguments for symbols. Got %i, Expected %i", func, syms->count,
- a->count - 1);
+ CASSERT(a, (syms->count == a->count-1), "Function '%s' pashed too many arguments for symbols. Got %i, Expected %i", func, syms->count, a->count-1);
for (int i = 0; i < syms->count; i++) {
if (strcmp(func, "def") == 0) {
- cenv_def(e, syms->cell[i], a->cell[i + 1]);
+ cenv_def(e, syms->cell[i], a->cell[i+1]);
}
if (strcmp(func, "=") == 0) {
- cenv_put(e, syms->cell[i], a->cell[i + 1]);
+ cenv_put(e, syms->cell[i], a->cell[i+1]);
}
}
@@ -459,15 +441,15 @@ cval *builtin_var(cenv *e, cval *a, char *func) {
return cval_s_expression();
}
-cval *builtin_put(cenv *e, cval *a) {
+cval* builtin_put(cenv* e, cval* a) {
return builtin_var(e, a, "=");
}
-cval *builtin_def(cenv *e, cval *a) {
+cval* builtin_def(cenv* e, cval* a) {
return builtin_var(e, a, "def");
}
-cval *cval_join(cval *x, cval *y) {
+cval* cval_join(cval* x, cval* y) {
for (int i = 0; i < y->count; i++) {
x = cval_add(x, y->cell[i]);
}
@@ -484,26 +466,26 @@ cval *cval_read_boolean(mpc_ast_t *t) {
return cval_boolean(false);
}
-cval *cval_read_num(mpc_ast_t *t) {
+cval* cval_read_num(mpc_ast_t* t) {
errno = 0;
long x = strtol(t->contents, NULL, 10);
return errno != ERANGE ?
cval_number(x) : cval_error("that'sh an invalid number");
}
-cval *cval_read_float(mpc_ast_t *t) {
+cval* cval_read_float(mpc_ast_t* t) {
errno = 0;
long double x = strtold(t->contents, NULL);
return errno != ERANGE ?
cval_float(x) : cval_error("that'sh a invalid float");
}
-cval *cval_read_string(mpc_ast_t *t) {
- t->contents[strlen(t->contents) - 1] = '\0';
- char *unescaped = malloc(strlen(t->contents + 1) + 1);
- strcpy(unescaped, t->contents + 1);
+cval* cval_read_string(mpc_ast_t* t) {
+ t->contents[strlen(t->contents)-1] = '\0';
+ char* unescaped = malloc(strlen(t->contents+1)+1);
+ strcpy(unescaped, t->contents+1);
unescaped = mpcf_unescape(unescaped);
- cval *str = cval_string(unescaped);
+ cval* str = cval_string(unescaped);
free(unescaped);
return str;
}
@@ -514,18 +496,17 @@ cval *cval_read_symbol(char *symbol) {
return cval_boolean(true);
} else if (strcmp(symbol, "False") == 0) {
return cval_boolean(false);
- } else if (strcmp(symbol, "Null") == 0) {
- return cval_null();
} else {
return cval_symbol(symbol);
}
}
-cval *cval_read(mpc_ast_t *t) {
+cval* cval_read(mpc_ast_t* t) {
if (strstr(t->tag, "boolean")) {
return cval_read_boolean(t);
}
+
if (strstr(t->tag, "number")) {
return cval_read_num(t);
}
@@ -538,7 +519,7 @@ cval *cval_read(mpc_ast_t *t) {
return cval_read_symbol(t->contents);
}
- cval *x = NULL;
+ cval* x = NULL;
if (strcmp(t->tag, ">") == 0) {
x = cval_s_expression();
}
@@ -553,22 +534,22 @@ cval *cval_read(mpc_ast_t *t) {
}
for (int i = 0; i < t->children_num; i++) {
- if (strcmp(t->children[i]->contents, "(") == 0) {
+ if (strcmp(t->children[i]->contents, "(") == 0){
continue;
}
if (strstr(t->children[i]->tag, "comment")) {
continue;
}
- if (strcmp(t->children[i]->contents, ")") == 0) {
+ if (strcmp(t->children[i]->contents, ")") == 0){
continue;
}
- if (strcmp(t->children[i]->contents, "}") == 0) {
+ if (strcmp(t->children[i]->contents, "}") == 0){
continue;
}
- if (strcmp(t->children[i]->contents, "{") == 0) {
+ if (strcmp(t->children[i]->contents, "{") == 0){
continue;
}
- if (strcmp(t->children[i]->tag, "regex") == 0) {
+ if (strcmp(t->children[i]->tag, "regex") == 0){
continue;
}
x = cval_add(x, cval_read(t->children[i]));
@@ -577,40 +558,43 @@ cval *cval_read(mpc_ast_t *t) {
}
-void cval_print_str(cval *v) {
- char *escaped = malloc(strlen(v->str) + 1);
+void cval_print_str(cval* v) {
+ char* escaped = malloc(strlen(v->str)+1);
strcpy(escaped, v->str);
escaped = mpcf_escape(escaped);
- printf("\"%s\"", escaped);
+ printf("%s", v->str);
free(escaped);
}
-void cval_print_ht_str(cval *v, char *key) {
- char *escaped = malloc(strlen(v->str) + 1);
+void cval_print_ht_str(cval* v, char* key) {
+ char* escaped = malloc(strlen(v->str)+1);
strcpy(escaped, v->str);
escaped = mpcf_escape(escaped);
printf("%s : \"%s\"", key, escaped);
free(escaped);
}
-void cval_expr_print(cval *value, char open, char close) {
+bool cval_expr_print(cval* value, char open, char close) {
+ if (value->count >= 1) {
putchar(open);
for (int i = 0; i < value->count; i++) {
cval_print(value->cell[i]);
- if (i != (value->count - 1)) {
+ if (i != (value->count-1)) {
putchar(' ');
}
}
putchar(close);
+ return true;}
+ return false;
}
-void cval_expr_ht_print(cval *value, char open, char close, char *key) {
+void cval_expr_ht_print(cval* value, char open, char close, char* key) {
fputs(key, stdout);
fputs(" : ", stdout);
putchar(open);
for (int i = 0; i < value->count; i++) {
cval_print(value->cell[i]);
- if (i != (value->count - 1)) {
+ if (i != (value->count-1)) {
putchar(' ');
}
}
@@ -618,8 +602,9 @@ void cval_expr_ht_print(cval *value, char open, char close, char *key) {
}
-void cval_print(cval *value) {
+bool cval_print(cval* value) {
switch (value->type) {
+
case CVAL_BOOLEAN:
if (value->boolean) {
printf("True");
@@ -628,6 +613,7 @@ void cval_print(cval *value) {
}
break;
+
case CVAL_NUMBER:
printf("%li", value->num);
break;
@@ -649,7 +635,11 @@ void cval_print(cval *value) {
break;
case CVAL_ERROR:
+#if SYSTEM_LANG==0
printf("shtirred: %s", value->err);
+#else
+ printf("error: %s", value->err);
+#endif
break;
case CVAL_SYMBOL:
@@ -657,8 +647,7 @@ void cval_print(cval *value) {
break;
case CVAL_S_EXPRESSION:
- cval_expr_print(value, '(', ')');
- break;
+ return cval_expr_print(value, '(', ')');
case CVAL_Q_EXPRESSION:
cval_expr_print(value, '{', '}');
@@ -668,11 +657,11 @@ void cval_print(cval *value) {
cval_print_str(value);
break;
}
-}
-void cval_print_line(cval *value) {
- cval_print(value);
- if (value->type != CVAL_NULL) {
+ return true;
+}
+void cval_print_line(cval* value) {
+ if (cval_print(value)) {
putchar('\n'); }
}
diff --git a/src/cval.h b/src/cval.h
index 942530d..f81f66a 100644
--- a/src/cval.h
+++ b/src/cval.h
@@ -1,9 +1,9 @@
#ifndef CONNERY_CVAL_H
#define CONNERY_CVAL_H
+#include
#include "mpc.h"
#include "hashtable.h"
-#include
typedef struct cval cval;
typedef struct cenv cenv;
@@ -13,7 +13,7 @@ typedef cval *(*cbuiltin)(cenv *, cval *);
enum {
CVAL_NUMBER, CVAL_ERROR, CVAL_SYMBOL, CVAL_FUNCTION,
CVAL_S_EXPRESSION, CVAL_Q_EXPRESSION, CVAL_STRING, CVAL_FLOAT,
- CVAL_BOOLEAN, CVAL_NULL
+ CVAL_BOOLEAN
};
struct cval {
@@ -25,6 +25,7 @@ struct cval {
char *sym;
char *str;
bool boolean;
+ hash_table *ht;
cbuiltin builtin;
cenv *env;
@@ -56,8 +57,6 @@ cval *cval_symbol(char *s);
cval *cval_boolean(bool b);
-cval *cval_null();
-
cval *cval_s_expression(void);
cval *cval_q_expression(void);
@@ -88,9 +87,9 @@ cval *cval_read(mpc_ast_t *t);
void cval_print_line(cval *value);
-void cval_expr_print(cval *value, char open, char close);
+bool cval_expr_print(cval *value, char open, char close);
-void cval_print(cval *value);
+bool cval_print(cval *value);
void cval_print_ht_str(cval *v, char *key);
diff --git a/src/hashtable.c b/src/hashtable.c
index 8d2a1cc..269349e 100644
--- a/src/hashtable.c
+++ b/src/hashtable.c
@@ -168,8 +168,9 @@ hash_table *hash_table_copy(hash_table *target_hash_table) {
return new_hash_table;
}
-void hash_table_print(hash_table *target_hash_table) {
+int hash_table_print(hash_table *target_hash_table) {
int first_row = 1;
+ int count = 0;
for (long i = 0; i < target_hash_table->table_size; i++) {
@@ -227,4 +228,7 @@ void hash_table_print(hash_table *target_hash_table) {
}
+ printf("\ntotal items: ");
+ return target_hash_table -> items;
+
}
\ No newline at end of file
diff --git a/src/hashtable.h b/src/hashtable.h
index 22b8ab4..72e2455 100644
--- a/src/hashtable.h
+++ b/src/hashtable.h
@@ -27,6 +27,6 @@ hash_table *hash_table_copy(hash_table *target_hash_table);
void hash_table_entry_delete(hash_table *target_hash_table, const char *key);
-void hash_table_print(hash_table *target_hash_table);
+int hash_table_print(hash_table *target_hash_table);
#endif //CONNERY_HASHTABLE_H
diff --git a/src/main.c b/src/main.c
index 68df50f..ab49281 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5,6 +5,13 @@
#include "mpc.h"
#include "util.h"
#include "cval.h"
+#include "hashtable.h"
+#include "trace.h"
+
+#define SYSTEM_LANG 0
+#define CONNERY_VERSION "0.0.2"
+#define CONNERY_VER_INT 2
+#define LOG_LEVEL 4
#ifdef _WIN32
#include
@@ -24,7 +31,6 @@ void add_history(char* unused) {}
#else
#include
-#include
#endif
mpc_parser_t *Number;
@@ -43,16 +49,31 @@ if (!(cond)) {\
cval_delete(args); \
return err;}
+#if SYSTEM_LANG==0
#define CASSERT_TYPE(func, args, index, expect) \
CASSERT(args, args->cell[index]->type == expect, \
"Function '%s' pashed incorrect type for argument %i. " \
"Got %s, Expected %s.", \
func, index, ctype_name(args->cell[index]->type), ctype_name(expect))
+#else
+#define CASSERT_TYPE(func, args, index, expect) \
+ CASSERT(args, args->cell[index]->type == expect, \
+ "Function '%s' passed incorrect type for argument %i. " \
+ "Got %s, Expected %s.", \
+ func, index, ctype_name(args->cell[index]->type), ctype_name(expect))
+#endif
+#if SYSTEM_LANG==0
#define CASSERT_NUM(func, args, num) \
CASSERT(args, args->count == num, \
"function '%s' pashed incorrect number of argumentsh. got %i, expected %i.", \
func, args->count, num)
+#else
+#define CASSERT_NUM(func, args, num) \
+CASSERT(args, args->count == num, \
+ "function '%s' passed incorrect number of arguments. got %i, expected %i.", \
+ func, args->count, num)
+#endif
cval *builtin_op(cenv *e, cval *a, char *op) {
int float_support = 0;
@@ -107,7 +128,11 @@ cval *builtin_op(cenv *e, cval *a, char *op) {
if (y->fnum == 0) {
cval_delete(x);
cval_delete(y);
+#if SYSTEM_LANG==0
x = cval_error("Divishion by zero");
+#else
+ x = cval_error("Division by zero");
+#endif
break;
}
x->fnum /= y->fnum;
@@ -115,7 +140,11 @@ cval *builtin_op(cenv *e, cval *a, char *op) {
if (y->num == 0) {
cval_delete(x);
cval_delete(y);
+#if SYSTEM_LANG==0
x = cval_error("Divishion by zero");
+#else
+ x = cval_error("Division by zero");
+#endif
break;
}
x->fnum /= y->num;
@@ -125,14 +154,22 @@ cval *builtin_op(cenv *e, cval *a, char *op) {
if (strcmp(op, "mod") == 0) {
cval_delete(x);
cval_delete(y);
+#if SYSTEM_LANG==0
x = cval_error("mod not shupported on floatsh!");
+#else
+ x = cval_error("mod not supported on floats!");
+#endif
break;
}
if (strcmp(op, "pow") == 0) {
cval_delete(x);
cval_delete(y);
+#if SYSTEM_LANG==0
x = cval_error("pow not shupported on floatsh!");
+#else
+ x = cval_error("pow not supported on floats!");
+#endif
break;
}
@@ -167,7 +204,11 @@ cval *builtin_op(cenv *e, cval *a, char *op) {
if (y->num == 0) {
cval_delete(x);
cval_delete(y);
+#if SYSTEM_LANG==0
x = cval_error("Divishion by zero");
+#else
+ x = cval_error("Division by zero");
+#endif
break;
}
x->num /= y->num;
@@ -214,7 +255,11 @@ cval *builtin_head(cenv *e, cval *a) {
}
if (a->cell[0]->type == CVAL_Q_EXPRESSION) {
+#if SYSTEM_LANG==0
CASSERT(a, a->cell[0]->count != 0, "Function 'head' pashed empty list!");
+#else
+ CASSERT(a, a->cell[0]->count != 0, "Function 'head' passed empty list!");
+#endif
cval *v = cval_take(a, 0);
@@ -226,7 +271,24 @@ cval *builtin_head(cenv *e, cval *a) {
}
cval_delete(a);
+#if SYSTEM_LANG==0
return cval_error("Function 'head' pashed unshupported type!");
+#else
+ return cval_error("Function 'head' passed unsupported type!");
+#endif
+
+}
+
+cval *set_trace_data(cenv *e, trace *t) {
+ hash_table_set(e ->ht, "__STATEMENT_NUMBER__", cval_number(t->current->position));
+
+ if (t->current->position > 2) {
+ hash_table_set(e->ht, "__PREV_PREV_EXPRESSION__", hash_table_get(e->ht, "__PREV_EXPRESSION__")); }
+
+ if (t->current->position > 1) {
+ hash_table_set(e->ht, "__PREV_EXPRESSION__", t->current->prev->data); }
+
+ hash_table_set(e->ht, "__EXPRESSION__", t->current->data);
}
cval *builtin_tail(cenv *e, cval *a) {
@@ -240,12 +302,19 @@ cval *builtin_tail(cenv *e, cval *a) {
str++;
return (cval_string(str));
}
+#if SYSTEM_LANG==0
return (cval_error("Function 'tail' pashed empty shtring!"));
+#else
+ return (cval_error("Function 'tail' passed empty string!"));
+#endif
}
if (a->cell[0]->type == CVAL_Q_EXPRESSION) {
+#if SYSTEM_LANG==0
CASSERT(a, a->cell[0]->count != 0, "Function 'tail' pashed empty list!");
-
+#else
+ CASSERT(a, a->cell[0]->count != 0, "Function 'tail' passed empty list!");
+#endif
cval *v = cval_take(a, 0);
cval_delete(cval_pop(v, 0));
@@ -266,7 +335,11 @@ cval *builtin_tail(cenv *e, cval *a) {
cval_delete(a);
if (init_digits == 1) {
+#if SYSTEM_LANG==0
return cval_error("Function 'tail' pashed shingle digit number!");
+#else
+ return cval_error("Function 'tail' passed single digit number!");
+#endif
}
factor = get_factor(init_digits);
@@ -286,7 +359,11 @@ cval *builtin_tail(cenv *e, cval *a) {
}
cval_delete(a);
+#if SYSTEM_LANG==0
return cval_error("Function 'head' pashed unshupported type!");
+#else
+ return cval_error("Function 'head' passed unsupported type!");
+#endif
}
cval *builtin_rand(cenv *e, cval *a) {
@@ -306,7 +383,6 @@ cval *builtin_rand(cenv *e, cval *a) {
cval *builtin_join(cenv *e, cval *a) {
-
if (a->cell[0]->type == CVAL_STRING) {
unsigned long new_str_length = 0;
@@ -529,21 +605,69 @@ cval *builtin_lambda(cenv *e, cval *a) {
return cval_lambda(formals, body);
}
+
cval *builtin_load(cenv *e, cval *a) {
CASSERT_NUM("load", a, 1)
CASSERT_TYPE("load", a, 0, CVAL_STRING)
+ trace* t = start_trace(a->cell[0]->str);
+
+ mpc_result_t r;
+ if (mpc_parse_contents(a->cell[0]->str, Connery, &r)) {
+ cval *expr = cval_read(r.output);
+ mpc_ast_delete(r.output);
+
+
+ while (expr->count) {
+ cval *expression = cval_pop(expr, 0);
+ record_trace(t, expression);
+ set_trace_data(e, t);
+
+ cval *x = cval_evaluate(e, expression);
+
+ if (x->type == CVAL_ERROR) {
+ cval_print_line(x);
+ }
+
+ cval_delete(x);
+
+ }
+
+ cval_delete(expr);
+ cval_delete(a);
+
+ return cval_s_expression();
+ } else {
+ char *err_msg = mpc_err_string(r.error);
+ mpc_err_delete(r.error);
+
+ cval *err = cval_error("Could not load library '%s'", err_msg);
+ free(err_msg);
+ cval_delete(a);
+ return err;
+ }
+}
+
+cval *builtin_traced_load(cenv *e, cval *a,trace* t ) {
+ CASSERT_NUM("traced_load", a, 1)
+ CASSERT_TYPE("traced_load", a, 0, CVAL_STRING)
+
mpc_result_t r;
if (mpc_parse_contents(a->cell[0]->str, Connery, &r)) {
cval *expr = cval_read(r.output);
mpc_ast_delete(r.output);
while (expr->count) {
- cval *x = cval_evaluate(e, cval_pop(expr, 0));
+ cval *expression = cval_pop(expr, 0);
+ record_trace(t, expression);
+ set_trace_data(e, t);
+
+ cval *x = cval_evaluate(e, expression);
if (x->type == CVAL_ERROR) {
cval_print_line(x);
}
+
cval_delete(x);
}
@@ -560,6 +684,8 @@ cval *builtin_load(cenv *e, cval *a) {
cval_delete(a);
return err;
}
+
+
}
cval *builtin_print(cenv *e, cval *a) {
@@ -574,9 +700,9 @@ cval *builtin_print(cenv *e, cval *a) {
return cval_s_expression();
}
-cval *builtin_error(cenv *e, cval *a) {
- CASSERT_NUM("error", a, 1);
- CASSERT_TYPE("error", a, 0, CVAL_STRING);
+cval *builtin_fault(cenv *e, cval *a) {
+ CASSERT_NUM("fault", a, 1);
+ CASSERT_TYPE("fault", a, 0, CVAL_STRING);
cval *err = cval_error(a->cell[0]->str);
@@ -629,7 +755,7 @@ cval *builtin_file(cenv *e, cval *a) {
if (success) {
fclose(file);
cval_delete(a);
- return cval_boolean(true);
+ return cval_number(1);
}
}
cval_delete(a);
@@ -647,7 +773,7 @@ cval *builtin_file(cenv *e, cval *a) {
if (success) {
fclose(file);
cval_delete(a);
- return cval_boolean(true);
+ return cval_number(1);
}
}
cval_delete(a);
@@ -695,7 +821,7 @@ cval *builtin_find(cenv *e, cval *a) {
return cval_number(pos - org);
} else {
cval_delete(a);
- return cval_boolean(false);
+ return cval_number(0);
}
}
@@ -759,7 +885,12 @@ cval *builtin_length(cenv *e, cval *a) {
}
cval_delete(a);
+#if SYSTEM_LANG==0
return cval_error("Function 'length' pashed unshupported type!");
+#else
+ return cval_error("Function 'length' passed unsupported type!");
+#endif
+
}
cval *builtin_type(cenv *e, cval *a) {
@@ -785,14 +916,8 @@ cval *builtin_type(cenv *e, cval *a) {
case CVAL_SYMBOL:
return cval_number(5);
- case CVAL_FLOAT:
- return cval_number(6);
-
case CVAL_BOOLEAN:
- return cval_number(7);
-
- case CVAL_NULL:
- return cval_number(8);
+ return cval_number(6);
default:
return cval_error("Type not defined!");
@@ -822,8 +947,10 @@ cval *builtin_http(cenv *e, cval *a) {
struct curl_slist *chunk = NULL;
curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_response_writer);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Connery");
+ curl_easy_setopt(curl, CURLOPT_HEADER, 1L);
for (int i = 0; i < request_headers->count; i++) {
CASSERT_TYPE("http_request_headers", request_headers, i, CVAL_STRING);
@@ -835,46 +962,8 @@ cval *builtin_http(cenv *e, cval *a) {
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, a->cell[3]->str);
}
- if (strstr(type, "DOWN")) {
- CASSERT_TYPE("http", a, 3, CVAL_STRING);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_download_writer);
- } else {
- curl_easy_setopt(curl, CURLOPT_HEADER, 1L);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_response_writer);
- }
-
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
- if (strstr(type, "DOWN")) {
- bool success = false;
- struct stat st = {0};
- char* full_path = malloc(strlen(a->cell[3]->str));
- char* path = malloc(strlen(a->cell[3]->str));
- memcpy(full_path, a->cell[3]->str, strlen(a->cell[3]->str)+1);
-
- char* pos = strrchr(a->cell[3]->str, '/');
- memcpy(path, a->cell[3]->str, pos-a->cell[3]->str);
-
- if (stat(path, &st) == -1) {
- mkpath(path, 0700);
- }
-
- FILE *pagefile;
- pagefile = fopen(full_path, "wb");
-
- if (pagefile) {
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, pagefile);
- curl_easy_perform(curl);
- fclose(pagefile);
- success = true;}
-
- cval_delete(a);
- curl_easy_cleanup(curl);
- free(full_path);
- free(path);
-
- return cval_boolean(success);
- }
res = curl_easy_perform(curl);
if (res == CURLE_OK) {
@@ -891,7 +980,6 @@ cval *builtin_http(cenv *e, cval *a) {
multi_tok_t x = multiTok_init();
char *header = multi_tok(headers, &x, "\r\n");
-
while (header != NULL) {
cval_add(headers_list, cval_string(header));
header = multi_tok(NULL, &x, "\r\n");
@@ -900,13 +988,15 @@ cval *builtin_http(cenv *e, cval *a) {
cval_add(response_list, headers_list);
cval_add(response_list, cval_string(strstr(s.body, "\r\n\r\n") + 4));
} else {
- cval_delete(a);
cval_delete(response_list);
+#if SYSTEM_LANG==0
response_list = cval_error("unable to accesh url!");
+#else
+ response_list = cval_error("unable to access url!");
+#endif
}
free(s.body);
curl_easy_cleanup(curl);
- cval_delete(a);
}
return response_list;
}
@@ -917,57 +1007,52 @@ cval *builtin_input(cenv *e, cval *a) {
return cval_string(input);
}
-cval *builtin_exit(cenv *e, cval *a) {
- CASSERT_TYPE("exit", a, 0, CVAL_NUMBER);
+cval *builtin_convert_string(cenv *e, cval *a) {
+ if (a->cell[0]->type == CVAL_NUMBER) {
+ int length = snprintf( NULL, 0, "%ld", a->cell[0]->num );
+ char* str = malloc( length + 1 );
+ snprintf( str, length + 1, "%ld", a->cell[0]->num );
- int exit_code = a->cell[0]->num;
- cval_delete(a);
+ return cval_string(str);
+ }
- mpc_cleanup(9, Number, Float, Symbol, String, Comment, Sexpr, Qexpr, Expr, Connery);
- cenv_delete(e);
- exit(exit_code);
}
-cval *builtin_mkdir(cenv *e, cval *a) {
- CASSERT_NUM("mkdir", a, 1);
- CASSERT_TYPE("mkdir", a, 0, CVAL_STRING);
- char *path = a->cell[0]->str;
- struct stat st = {0};
- int result;
+cval *builtin_sys(cenv *e, cval *a) {
+ CASSERT_TYPE("stats", a, 0, CVAL_STRING);
+ CASSERT_NUM("stats", a, 1);
- if (stat(path, &st) == -1) {
- result = mkpath(path, 0700);
- } else {
- result = -1;
+ char *cmd = a->cell[0]->str;
+
+ if (strcmp(cmd, "VERSION") == 0) {
+ return cval_string(CONNERY_VERSION);
}
- cval_delete(a);
+ if (strcmp(cmd, "VERSION_INT") == 0) {
+ return cval_number(CONNERY_VER_INT);
+ }
- if (result == 1) {
- return cval_boolean(true);
- } else {
- return cval_boolean(false);
+ if (strcmp(cmd, "PRINT_ENV") == 0) {;
+ return cval_number(hash_table_print(e->ht));
}
-}
-cval *builtin_chkdir(cenv *e, cval *a) {
- CASSERT_NUM("chkdir", a, 1);
- CASSERT_TYPE("chkdir", a, 0, CVAL_STRING);
- struct stat st = {0};
+ if (strcmp(cmd, "HARD_EXIT") == 0) {
+ exit(1);
+ }
- char *path = a->cell[0]->str;
- cval* result;
+ if (strcmp(cmd, "SOFT_EXIT") == 0) {
+ exit(0);
+ }
- if (stat(path, &st) == -1) {
- result = cval_boolean(false);
- } else {
- result = cval_boolean(true);
+ if (strcmp(cmd, "SYSTEM_LANGUAGE_INT") == 0) {
+ return cval_number(SYSTEM_LANG);
}
- cval_delete(a);
- return result;
+ return cval_error("invalid input to stats");
}
+
+
void cenv_add_builtins(cenv *e) {
cenv_add_builtin(e, "\\", builtin_lambda);
cenv_add_builtin(e, "def", builtin_def);
@@ -978,12 +1063,12 @@ void cenv_add_builtins(cenv *e) {
cenv_add_builtin(e, "tail", builtin_tail);
cenv_add_builtin(e, "eval", builtin_eval);
cenv_add_builtin(e, "join", builtin_join);
- cenv_add_builtin(e, "def", builtin_def);
cenv_add_builtin(e, "length", builtin_length);
cenv_add_builtin(e, "input", builtin_input);
cenv_add_builtin(e, "replace", builtin_replace);
cenv_add_builtin(e, "find", builtin_find);
cenv_add_builtin(e, "split", builtin_split);
+ cenv_add_builtin(e, "sys", builtin_sys);
cenv_add_builtin(e, "+", builtin_add);
cenv_add_builtin(e, "-", builtin_sub);
@@ -1002,15 +1087,14 @@ void cenv_add_builtins(cenv *e) {
cenv_add_builtin(e, "<=", builtin_less_than_or_equal);
cenv_add_builtin(e, "load", builtin_load);
- cenv_add_builtin(e, "error", builtin_error);
cenv_add_builtin(e, "print", builtin_print);
cenv_add_builtin(e, "type", builtin_type);
cenv_add_builtin(e, "http", builtin_http);
+
cenv_add_builtin(e, "file", builtin_file);
- cenv_add_builtin(e, "exit", builtin_exit);
+ cenv_add_builtin(e, "convert_string", builtin_convert_string);
- cenv_add_builtin(e, "mkdir", builtin_mkdir);
- cenv_add_builtin(e, "chkdir", builtin_chkdir);
+ cenv_add_builtin(e, "__FAULT__", builtin_fault);
}
void load_standard_lib(cenv *e) {
@@ -1033,23 +1117,23 @@ int main(int argc, char **argv) {
Connery = mpc_new("connery");
mpca_lang(MPCA_LANG_DEFAULT,
- " \
- float : /-?[0-9]*\\.[0-9]+/ ; \
- number : /-?[0-9]+/ ; \
- symbol : /[a-zA-Z0-9_+\\-*\\/\\\\=<>!&]+/ \
- |'+' | '-' | '*' | '/' ; \
- sexpr : '(' * ')' ; \
- qexpr : '{' * '}' ; \
- string : /\"(\\\\.|[^\"])*\"/; \
- comment : /;[^\\r\\n]*/ ; \
- expr : | | \
- | | | | ; \
- connery : /^/ * /$/ ; \
+ " \
+ float : /-?[0-9]*\\.[0-9]+/ ; \
+ number : /-?[0-9]+/ ; \
+ symbol : /[a-zA-Z0-9_+\\-*\\/\\\\=<>!&]+/ \
+ |'+' | '-' | '*' | '/' ; \
+ sexpr : '(' * ')' ; \
+ qexpr : '{' * '}' ; \
+ string : /\"(\\\\.|[^\"])*\"/; \
+ comment : /;[^\\r\\n]*/ ; \
+ expr : | | \
+ | | | | ;\
+ connery : /^/ * /$/ ; \
",
- Float, Number, Symbol, Sexpr, Qexpr, Expr, String,
- Comment, Connery);
+ Float, Number, Symbol, Sexpr, Qexpr, Expr, String, Comment, Connery);
cenv *e = cenv_new();
+
cenv_add_builtins(e);
load_standard_lib(e);
@@ -1059,14 +1143,25 @@ int main(int argc, char **argv) {
"/ /___/ /_/ / / / / / / / __/ / / /_/ / \n"
"\\____/\\____/_/ /_/_/ /_/\\___/_/ \\__, / \n"
" /____/ ");
- puts("+----- Version 0.0.1 ------+\n");
+#if SYSTEM_LANG==1
+ puts("_____________ English Mode _____________");
+#endif
+
+ puts(" Version "CONNERY_VERSION);
puts(" ConneryLang.org \n");
+ hash_table_set(e ->ht, "__LOG_LEVEL__", cval_number(LOG_LEVEL));
+
if (argc == 1) {
+ hash_table_set(e ->ht, "__SOURCE__", cval_string("INTERACTIVE"));
+ trace* trace = start_trace("interactive");
while (1) {
char *input = readline("connery> ");
add_history(input);
+ record_trace(trace, cval_string(input));
+ set_trace_data(e, trace);
+
mpc_result_t result;
if (mpc_parse("", input, Connery, &result)) {
cval *output = cval_evaluate(e, cval_read(result.output));
@@ -1083,9 +1178,12 @@ int main(int argc, char **argv) {
}
if (argc >= 2) {
+ hash_table_set(e ->ht, "__SOURCE__", cval_string("FILE"));
+ trace* trace = start_trace("FILE");
for (int i = 1; i < argc; i++) {
cval *args = cval_add(cval_s_expression(), cval_string(argv[i]));
- cval *x = builtin_load(e, args);
+ hash_table_set(e ->ht, "__SOURCE_FILE__", cval_string(argv[i]));
+ cval *x = builtin_traced_load(e, args, trace);
if (x->type == CVAL_ERROR) {
cval_print_line(x);
@@ -1094,7 +1192,7 @@ int main(int argc, char **argv) {
}
}
- mpc_cleanup(9, Number, Float, Symbol, String, Comment, Sexpr, Qexpr, Expr, Connery);
+ mpc_cleanup(8, Number, Float, Symbol, String, Comment, Sexpr, Qexpr, Expr, Connery);
cenv_delete(e);
return 0;
}
\ No newline at end of file
diff --git a/src/mpc.c b/src/mpc.c
index fc6bea7..2eab5a1 100644
--- a/src/mpc.c
+++ b/src/mpc.c
@@ -2482,11 +2482,10 @@ mpc_val_t *mpcf_strtrim(mpc_val_t *x) {
static const char mpc_escape_input_c[] = {
'\a', '\b', '\f', '\n', '\r',
- '\t', '\v', '\\', '\'', '\"', '\0'};
+ '\t', '\v', '\0'};
static const char *mpc_escape_output_c[] = {
- "\\a", "\\b", "\\f", "\\n", "\\r", "\\t",
- "\\v", "\\\\", "\\'", "\\\"", "\\0", NULL};
+ "\\a", "\\b", "\\f", "\\n", "\\r", "\\t", NULL};
static const char mpc_escape_input_raw_re[] = { '/' };
static const char *mpc_escape_output_raw_re[] = { "\\/", NULL };
diff --git a/src/stdlib/Q.connery b/src/stdlib/Q.connery
deleted file mode 100644
index 0f1d4a4..0000000
--- a/src/stdlib/Q.connery
+++ /dev/null
@@ -1,26 +0,0 @@
-(def {__Q_package_location__} "Q")
-(def {__Q_location__} "http://q.connerylang.org")
-(def {__Q_package_list_url_slug__} "/packages/packages_list.csv")
-(def {__Q_packages__} Null)
-
-(mkdir __Q_package_location__)
-
-(fun {__Q_package_scan__ packages package_name} {
- if (>= (length packages) 1)
- {if (== (first (first (head packages))) package_name)
- {first (head packages)}
- {__Q_package_scan__ (tail packages) package_name}}
- {Null}
-})
-
-(fun {Q package_name} {
- (if (is_null __Q_packages__)
- {def {__Q_packages__} (tail (csv (third (http_get (join __Q_location__ __Q_package_list_url_slug__)))))}
- {})
-
- (= {__package_result__} (__Q_package_scan__ __Q_packages__ package_name))
-
- (if (is_null __package_result__)
- {error (join "Package " package_name " not found!")}
- {print "False"})
-})
\ No newline at end of file
diff --git a/src/stdlib/constants.connery b/src/stdlib/constants.connery
index d6eb4aa..a601f3d 100644
--- a/src/stdlib/constants.connery
+++ b/src/stdlib/constants.connery
@@ -4,5 +4,6 @@
(def {Otherwise} True)
(def {std_lib_main_location} "stdlib/main.connery")
+
; Easter Egg
(def {best_kid} "Alice Imogen Cipriano")
\ No newline at end of file
diff --git a/src/stdlib/csv.connery b/src/stdlib/csv.connery
deleted file mode 100644
index d0876e7..0000000
--- a/src/stdlib/csv.connery
+++ /dev/null
@@ -1,9 +0,0 @@
-(fun {__parse_csv_loop__ csv_lines output}{
- if (== 0 (length csv_lines))
- {output}
- {__parse_csv_loop__ (tail csv_lines) (join output (list (delimit "," (eval (head csv_lines)))))}
-})
-
-(fun {csv csv_string} {
- __parse_csv_loop__ (delimit "\n" csv_string) None
-})
\ No newline at end of file
diff --git a/src/stdlib/errors.connery b/src/stdlib/errors.connery
new file mode 100644
index 0000000..a1747ea
--- /dev/null
+++ b/src/stdlib/errors.connery
@@ -0,0 +1,63 @@
+(fun {__STANDARD_ERROR_HANDLER__ msg critical} {
+
+(if (!= connery_system_lang "Connery Classic")
+ {(if (!= __STATEMENT_NUMBER__ -1)
+ {(if (== __SOURCE__ "FILE")
+ {log_error (join (join (join "during statement: " (convert_string __STATEMENT_NUMBER__)) (join " while attempting to load file: " __SOURCE_FILE__)) (join " with cause: " msg))}
+ {log_error (join (join "during statement: " (convert_string __STATEMENT_NUMBER__)) (join " with cause: " msg))})}
+ {(if (== __SOURCE__ "FILE")
+ {log_error (join (join "during file: " __SOURCE_FILE__) (join " with cause: " msg))}
+ {log_error (join "with cause: " msg)})})}
+
+ {(if (!= __STATEMENT_NUMBER__ -1)
+ {(if (== __SOURCE__ "FILE")
+ {log_error (join (join (join "during shtatement: " (convert_string __STATEMENT_NUMBER__)) (join " while attempting to load file: " __SOURCE_FILE__)) (join " with caushe: " msg))}
+ {log_error (join (join "during shtatement: " (convert_string __STATEMENT_NUMBER__)) (join " with caushe: " msg))})}
+ {(if (== __SOURCE__ "FILE")
+ {log_error (join (join "during file: " __SOURCE_FILE__) (join " with caushe: " msg))}
+ {log_error (join "with caushe: " msg)})})})
+
+ (if (>= log_level 4)
+ {
+ (print "TRACE: ")
+
+ (if (>= __STATEMENT_NUMBER__ 3) {
+ (print __PREV_PREV_EXPRESSION__)
+ }{})
+
+ (if (>= __STATEMENT_NUMBER__ 2) {
+ (print __PREV_EXPRESSION__)
+ }{})
+
+ (if (>= __STATEMENT_NUMBER__ 1) {
+ (print __EXPRESSION__)
+ }{}) }
+ {})
+
+(if (== critical 1) {(log_fatal "critical error") (sys "HARD_EXIT")} {})
+})
+
+(fun {__NOOP_ERROR_HANDLER__ msg critical} { })
+
+(def {standard_error_handler} __STANDARD_ERROR_HANDLER__)
+
+(fun {__ERROR__ msg critical} {
+(standard_error_handler msg critical)
+})
+
+(fun {mistakes mistake_bool} {
+if (mistake_bool)
+ {def {standard_error_handler} __STANDARD_ERROR_HANDLER__}
+ {def {standard_error_handler} __NOOP_ERROR_HANDLER__}})
+
+(fun {panic msg} {
+if (is_str msg)
+ {__ERROR__ msg 1}
+ {__ERROR__ (string_convert msg) 1}
+})
+
+(fun {error msg} {
+if (is_str msg)
+ {__ERROR__ msg 0}
+ {__ERROR__ (string_convert msg) 0}
+})
\ No newline at end of file
diff --git a/src/stdlib/functional.connery b/src/stdlib/functional.connery
index e0ed151..bc04457 100644
--- a/src/stdlib/functional.connery
+++ b/src/stdlib/functional.connery
@@ -12,4 +12,12 @@
{if (first (first cs))
{second (first cs)}
{unpack case (tail cs)}}
-})
\ No newline at end of file
+})
+
+; Currying
+(fun {unpack f l} {
+ eval (join (list f) l)
+})
+(fun {pack f & xs} {f xs})
+(def {curry} unpack)
+(def {uncurry} pack)
\ No newline at end of file
diff --git a/src/stdlib/logs.connery b/src/stdlib/logs.connery
new file mode 100644
index 0000000..9bc8c93
--- /dev/null
+++ b/src/stdlib/logs.connery
@@ -0,0 +1,58 @@
+(fun {__log_level_num__ i}
+ {case
+ {(== i 1) "ERROR"}
+ {(== i 2) "WARN"}
+ {(== i 3) "INFO"}
+ {(== i 4) "DEBUG"}
+ {(== i 5) "TRACE"}
+ {Otherwise "FATAL"}})
+
+(fun {__log_level_connery_num__ i}
+ {case
+ {(== i 1) "Mishtake"}
+ {(== i 2) "Shtired"}
+ {(== i 3) "For Your Eyesh Only"}
+ {(== i 4) "Shocking"}
+ {(== i 5) "Without A Trashe"}
+ {Otherwise "Lishenshe To Kill"}})
+
+(fun {__LEVELED_STANDARD_OUTPUT_LOG_HANDLER__ level msg} {
+if (>= log_level level)
+ {
+ (if (!= connery_system_lang "Connery Classic")
+ {(print (join (join (__log_level_num__ level) ": ") msg))}
+ {(print (join (join (__log_level_connery_num__ level) ": ") msg))})
+ }
+ {}
+})
+
+(fun {__NOOP_LOG_HANDLER__ level msg} {})
+
+(def {__DEFAULT_LOGGER__} __LEVELED_STANDARD_OUTPUT_LOG_HANDLER__)
+(def {interpreter_log_handler} __DEFAULT_LOGGER__)
+(def {__LOGGER_INIT_COMPLETE__} False)
+
+(fun {__LOG__ level msg} {
+if (__LOGGER_INIT_COMPLETE__) {
+interpreter_log_handler level msg
+} {
+(def {log_level} __LOG_LEVEL__)
+(interpreter_log_handler level msg)
+(def {__LOGGER_INIT_COMPLETE__} True)
+}})
+
+(fun {go_loud loud_bool} {
+(if (loud_bool)
+ {def {interpreter_log_handler} __DEFAULT_LOGGER__}
+ {def {interpreter_log_handler} __NOOP_LOG_HANDLER__})
+(if (loud_bool)
+ {if (< log_level 4) {(if (> __LOG_LEVEL__ 4) {(def {log_level} __LOG_LEVEL__)} {def {log_level} 4})} {}}
+ {if (> log_level 3) {(if (< __LOG_LEVEL__ 3) {(def {log_level} __LOG_LEVEL__)} {def {log_level} 3})} {}}
+)})
+
+(fun {log_fatal msg} {__LOG__ 0 msg})
+(fun {log_error msg} {__LOG__ 1 msg})
+(fun {log_warn msg} {__LOG__ 2 msg})
+(fun {log_info msg} {__LOG__ 3 msg})
+(fun {log_debug msg} {__LOG__ 4 msg})
+(fun {log_trace msg} {__LOG__ 5 msg})
\ No newline at end of file
diff --git a/src/stdlib/main.connery b/src/stdlib/main.connery
index b5737fd..fc55ad3 100644
--- a/src/stdlib/main.connery
+++ b/src/stdlib/main.connery
@@ -5,7 +5,18 @@
(load "stdlib/logic.connery")
(load "stdlib/lists.connery")
(load "stdlib/strings.connery")
+(load "stdlib/logs.connery")
+(load "stdlib/errors.connery")
(load "stdlib/io.connery")
(load "stdlib/http.connery")
-(load "stdlib/csv.connery")
-(load "stdlib/Q.connery")
\ No newline at end of file
+
+
+(load "stdlib/versions.connery")
+(def {CONNERY_VERSION_INT} (sys "VERSION_INT"))
+(def {CONNERY_VERSION} (sys "VERSION"))
+(def {connery_version} (connery_version_num CONNERY_VERSION_INT))
+(def {CONNERY_SYSTEM_LANG_INT} (sys "SYSTEM_LANGUAGE_INT"))
+(def {connery_system_lang} (system_lang_version_num CONNERY_SYSTEM_LANG_INT))
+
+
+
diff --git a/src/stdlib/versions.connery b/src/stdlib/versions.connery
new file mode 100644
index 0000000..2ac051f
--- /dev/null
+++ b/src/stdlib/versions.connery
@@ -0,0 +1,15 @@
+(fun {connery_version_num i} {
+ case
+ {(== i 0) "Connery - Unspecified Version"}
+ {(== i 1) "Connery - 0.0.1 - The Legend Begins"}
+ {(== i 2) "Connery - 0.0.2"}
+ {(== i 9999) "Connery - Future Version"}
+ {Otherwise (error "Connery version is undefined.")}
+})
+
+(fun {system_lang_version_num i} {
+ case
+ {(== i 0) "Connery Classic"}
+ {(== i 1) "English"}
+ {Otherwise (error "Connery lang version is undefined.")}
+})
\ No newline at end of file
diff --git a/src/trace.c b/src/trace.c
new file mode 100644
index 0000000..2c20ca6
--- /dev/null
+++ b/src/trace.c
@@ -0,0 +1,51 @@
+#include "cval.h"
+#include "trace.h"
+
+trace* start_trace(char* s) {
+
+ trace *tr = malloc(sizeof(trace) * 1);
+ trace_entry *te = malloc(sizeof(trace_entry) * 1);
+
+ te->position=0;
+ te->data=cval_string("initialization of trace");
+
+ tr->current=te;
+ tr->first=te;
+ tr->source=cval_string(s);
+
+ return tr;
+}
+
+void record_trace(trace* t, cval* data) {
+ trace_entry *te = malloc(sizeof(trace_entry) * 1);
+
+ te->position=t->current->position + 1;
+ te->prev=t->current;
+ te->data=cval_copy(data);
+
+ t->current->next=te;
+ t->current=te;
+}
+
+void record_str_trace(trace* t, char* data) {
+ record_trace(t, cval_string(data));
+}
+
+cval* fetch_traceback_data(trace* t, int x) {
+ trace_entry* cur_te = t->current;
+ cval* traceback = cval_q_expression();
+ int y = 0;
+
+ if (x > t->current->position) {
+ x = t->current->position;
+ }
+
+ while (y <= x) {
+ cval_add(traceback, cur_te->data);
+ cur_te = t->current->prev;
+ y += 1;
+ }
+
+ return traceback;
+}
+
diff --git a/src/trace.h b/src/trace.h
new file mode 100644
index 0000000..48af14b
--- /dev/null
+++ b/src/trace.h
@@ -0,0 +1,26 @@
+#ifndef CONNERY_TRACE_H
+#define CONNERY_TRACE_H
+#include "cval.h"
+
+typedef struct cval cval;
+
+typedef struct trace_entry {
+ int position;
+ cval* data;
+ struct trace_entry* next;
+ struct trace_entry* prev;
+} trace_entry;
+
+typedef struct trace {
+ cval* source;
+ struct trace_entry* first;
+ struct trace_entry* current;
+} trace;
+
+trace* start_trace(char* s);
+void record_trace(trace* t, cval* data);
+void record_str_trace(trace* t, char* data);
+cval* fetch_traceback_data(trace* t, int x);
+
+#endif //CONNERY_TRACE_H
+
diff --git a/src/util.c b/src/util.c
index 66d6960..bb098d0 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,14 +1,11 @@
#include
#include
#include
-#include
-#include
-#include
#include "util.h"
void init_http_response(struct http_response *s) {
s->len = 0;
- s->body = malloc(s->len + 1);
+ s->body = malloc(s->len+1);
if (s->body == NULL) {
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
@@ -16,24 +13,19 @@ void init_http_response(struct http_response *s) {
s->body[0] = '\0';
}
-size_t http_response_writer(void *ptr, size_t size, size_t nmemb, struct http_response *s) {
- size_t new_len = s->len + size * nmemb;
- s->body = realloc(s->body, new_len + 1);
+size_t http_response_writer(void *ptr, size_t size, size_t nmemb, struct http_response *s)
+{
+ size_t new_len = s->len + size*nmemb;
+ s->body = realloc(s->body, new_len+1);
if (s->body == NULL) {
fprintf(stderr, "realloc() failed\n");
exit(EXIT_FAILURE);
}
- memcpy(s->body + s->len, ptr, size * nmemb);
+ memcpy(s->body+s->len, ptr, size*nmemb);
s->body[new_len] = '\0';
s->len = new_len;
- return size * nmemb;
-}
-
-size_t http_download_writer(void *ptr, size_t size, size_t nmemb, void *stream)
-{
- size_t written = fwrite(ptr, size, nmemb, (FILE *)stream);
- return written;
+ return size*nmemb;
}
typedef char *multi_tok_t;
@@ -74,15 +66,17 @@ char *concatenateThree(const char *a, const char *b, const char *c) {
return res;
}
-long long_power(long x, long exponent) {
+long long_power(long x,long exponent)
+{
int i;
int number = 1;
for (i = 0; i < exponent; ++i)
number *= x;
- return (number);
+ return(number);
}
-int count_digits(long n) {
+int count_digits(long n)
+{
if (n == 0)
return 0;
return 1 + count_digits(n / 10);
@@ -132,31 +126,4 @@ long get_factor(int init_digits) {
}
}
-int mkpath(const char *path, mode_t mode) {
- char tmp[PATH_MAX];
- char *p = NULL;
- size_t len;
-
- snprintf(tmp, sizeof(tmp), "%s", path);
- len = strlen(tmp);
- if (tmp[len - 1] == '/')
- tmp[len - 1] = 0;
- for (p = tmp + 1; *p; p++)
- if (*p == '/') {
- *p = 0;
-#if defined(_WIN32)
- if (_mkdir(tmp) < 0 && errno != EEXIST)
-#else
- if (mkdir(tmp, mode) < 0 && errno != EEXIST)
-#endif
- return -1;
- *p = '/';
- }
-#if defined(_WIN32)
- if (_mkdir(tmp) < 0 && errno != EEXIST)
-#else
- if (mkdir(tmp, mode) < 0 && errno != EEXIST)
-#endif
- return -1;
- return 1;
-}
\ No newline at end of file
+
diff --git a/src/util.h b/src/util.h
index 4dbee17..6b1e7a6 100644
--- a/src/util.h
+++ b/src/util.h
@@ -1,7 +1,3 @@
-//
-// Created by dev on 8/15/20.
-//
-
#ifndef CONNERY_UTIL_H
#define CONNERY_UTIL_H
@@ -24,6 +20,7 @@ char *concatenateThree(const char *a, const char *b, const char *c);
long long_power(long x,long exponent);
int count_digits(long n);
long get_factor(int init_digits);
+char *replace_str(char *str, char *orig, char *rep);
//mkpath
int mkpath(const char *path, mode_t mode);