diff --git a/bin/test.slime b/bin/test.slime
deleted file mode 100644
index 59506ac..0000000
--- a/bin/test.slime
+++ /dev/null
@@ -1,77 +0,0 @@
-(define-syntax defclass (name members :rest body)
- "Macro for creatating classes."
- (defun underscore (sym)
- (string->symbol (concat-strings "_" (symbol->string sym))))
-
- (define underscored-members (map underscore members))
-
- ;; the wrapping let environment
- (define let-body (list 'let (zip members underscored-members)))
-
- ;; the body
- (map (lambda (fun) (append let-body fun)) body)
-
- ;; the dispatch function
- (append let-body (list 'special-lambda '(message :rest args)
- "This is the docs for the handle"
- '(eval (extend (list message) args))))
-
-
- ;; stuff it all in the constructor function
- (eval (list 'defun (string->symbol (concat-strings "make-" (symbol->string name))) underscored-members
- "This is the handle to an object of the class "
- let-body)))
-
-;; (v1 print)
-;; (v1 length)
-;; (v1 get-x)
-;; (v1 set-x 10)
-
-(defclass vector3 (x y z)
- (defun get-x () x)
- (defun get-y () y)
- (defun get-z () z)
-
- (defun set-x (new-x) (mutate x new-x))
- (defun set-y (new-y) (mutate y new-y))
- (defun set-z (new-z) (mutate z new-z))
-
- (defun length ()
- (** (+ (* x x) (* y y) (* z z)) 0.5))
-
- (defun scale (fac)
- (mutate x (* fac x))
- (mutate y (* fac y))
- (mutate z (* fac z))
- fac)
-
- (defun add (other)
- (make-vector3
- (+ x (other get-x))
- (+ y (other get-y))
- (+ z (other get-z))))
-
- (defun subtract (other)
- (make-vector3
- (- x (other get-x))
- (- y (other get-y))
- (- z (other get-z))))
-
- (defun scalar-product (other)
- (+ (* x (other get-x))
- (* y (other get-y))
- (* z (other get-z))))
-
- (defun cross-product (other)
- (make-vector3
- (- (* y (other get-z)) (* z (other get-y)))
- (- (* z (other get-x)) (* x (other get-z)))
- (- (* x (other get-y)) (* y (other get-x)))))
-
- (defun printout ()
- (printf "[vector3] (" x y z ")"))
- )
-
-(define v1 (make-vector3 1 2 3))
-(define v2 (make-vector3 3 2 1))
-
diff --git a/bin/tests/class_macro.slime b/bin/tests/class_macro.slime
index b74b4f1..0a2fb5d 100644
--- a/bin/tests/class_macro.slime
+++ b/bin/tests/class_macro.slime
@@ -78,4 +78,4 @@
(define v1 (make-vector3 1 2 3))
(define v2 (make-vector3 3 2 1))
-(v1 scalar-product v2)
+(assert (= (v1 scalar-product v2) 10))
diff --git a/bin/tests/lexical_scope.slime b/bin/tests/lexical_scope.slime
new file mode 100644
index 0000000..d953f83
--- /dev/null
+++ b/bin/tests/lexical_scope.slime
@@ -0,0 +1,11 @@
+(defun make-counter ()
+ (let ((var 0))
+ (lambda ()
+ (mutate var (+ 1 var))
+ var)))
+
+(define counter (make-counter))
+
+(assert (= (counter) 1))
+(assert (= (counter) 3))
+(assert (= (counter) 3))
diff --git a/build.bat b/build.bat
index 73fe7ff..6432008 100644
--- a/build.bat
+++ b/build.bat
@@ -17,7 +17,9 @@ if %errorlevel% == 0 (
echo.
echo Done
echo.
- call timecmd slime.exe --run-tests
+ pushd ..\bin
+ call timecmd ..\build\slime.exe --run-tests
+ popd
) else (
echo.
echo Fuckin' ell
diff --git a/src/built_ins.cpp b/src/built_ins.cpp
index c61a695..800d131 100644
--- a/src/built_ins.cpp
+++ b/src/built_ins.cpp
@@ -55,7 +55,7 @@ proc built_in_load(String* file_name, Environment* env) -> Lisp_Object* {
}
return result;
} else {
- create_error(Error_Type::Unknown_Error, nullptr);
+ create_error(Error_Type::File_Not_Found, nullptr);
return nullptr;
}
}
@@ -66,7 +66,7 @@ proc load_built_ins_into_environment(Environment* env) -> void {
#define cLambda [=](Lisp_Object* arguments, Environment* env) mutable -> Lisp_Object*
#define report_error(_type) { \
- create_error(_type, arguments->sourceCodeLocation); \
+ create_error(_type, current_source_code_location); \
return nullptr; \
}
@@ -294,6 +294,23 @@ proc load_built_ins_into_environment(Environment* env) -> void {
return Memory::create_lisp_object_number(pow(base, exponent));
});
+ defun("assert", cLambda {
+ int arguments_length;
+ debug_break();
+ try {
+ arguments = eval_arguments(arguments, env, &arguments_length);
+ }
+
+ if (arguments_length != 1) {
+ report_error(Error_Type::Wrong_Number_Of_Arguments);
+ }
+
+ if (is_truthy(arguments->value.pair->first, env))
+ return Memory::t;
+
+ report_error(Error_Type::Assertion_Error);
+ return nullptr;
+ });
defun("define", cLambda {
try {
arguments_length = list_length(arguments);
@@ -1069,7 +1086,23 @@ proc load_built_ins_into_environment(Environment* env) -> void {
}
report_error(Error_Type::Unknown_Error);
});
+ defun("symbol->keyword", cLambda {
+ try {
+ evaluated_arguments = eval_arguments(arguments, env, &arguments_length);
+ }
+ if (arguments_length != 1) {
+ report_error(Error_Type::Wrong_Number_Of_Arguments);
+ }
+
+ Lisp_Object* source = evaluated_arguments->value.pair->first;
+
+ if (source->type != Lisp_Object_Type::Symbol) {
+ report_error(Error_Type::Type_Missmatch);
+ }
+
+ return Memory::get_or_create_lisp_object_keyword(source->value.string);
+ });
defun("string->symbol", cLambda {
// TODO(Felix): do some sanity checks on the string. For
diff --git a/src/error.cpp b/src/error.cpp
index 80e60ca..0ccdf55 100644
--- a/src/error.cpp
+++ b/src/error.cpp
@@ -18,6 +18,8 @@ proc create_error(Error_Type type, Source_Code_Location* location) -> void {
proc Error_Type_to_string(Error_Type type) -> const char* {
switch (type) {
+ case Error_Type::Assertion_Error: return "Assertion failed";
+ case Error_Type::File_Not_Found: return "File not found";
case Error_Type::Ill_Formed_Arguments: return "Evaluation-error: Ill formed arguments";
case Error_Type::Ill_Formed_Lambda_List: return "Evaluation-error: Ill formed lambda list";
case Error_Type::Ill_Formed_List: return "Evaluation-error: Ill formed list";
@@ -32,7 +34,7 @@ proc Error_Type_to_string(Error_Type type) -> const char* {
case Error_Type::Unknown_Keyword_Argument: return "Evaluation-error: Unknown keyword argument";
case Error_Type::Wrong_Number_Of_Arguments: return "Evaluation-error: Wrong number of arguments";
case Error_Type::Out_Of_Memory: return "Runtime-error: Out of memory";
- default: return "Unknown Error";
+ default: return "this error type doesn't have a desciption..";
}
}
diff --git a/src/eval.cpp b/src/eval.cpp
index 4f28ea8..a7c83d0 100644
--- a/src/eval.cpp
+++ b/src/eval.cpp
@@ -1,3 +1,5 @@
+Source_Code_Location* current_source_code_location = nullptr;
+
proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> Lisp_Object* {
Environment* new_env = Memory::create_child_environment(function->parent_environment);
@@ -330,6 +332,7 @@ proc eval_arguments(Lisp_Object* arguments, Environment* env, int *out_arguments
evaluated_arguments_head->value.pair->first =
eval_expr(current_head->value.pair->first, env);
}
+ evaluated_arguments_head->value.pair->first->sourceCodeLocation = current_head->value.pair->first->sourceCodeLocation;
current_head = current_head->value.pair->rest;
if (current_head->type == Lisp_Object_Type::Pair) {
@@ -368,6 +371,8 @@ proc eval_expr(Lisp_Object* node, Environment* env) -> Lisp_Object* {
return symbol;
}
case Lisp_Object_Type::Pair: {
+ current_source_code_location = node->sourceCodeLocation;
+
Lisp_Object* lispOperator;
if (node->value.pair->first->type != Lisp_Object_Type::CFunction &&
node->value.pair->first->type != Lisp_Object_Type::Function)
@@ -464,7 +469,6 @@ proc interprete_stdin() -> void {
char* line;
built_in_load(Memory::create_string("pre.slime"), env);
- built_in_load(Memory::create_string("test.slime"), env);
if (error) {
log_error();
diff --git a/src/forward_decls.cpp b/src/forward_decls.cpp
index 3653a7c..a1187b8 100644
--- a/src/forward_decls.cpp
+++ b/src/forward_decls.cpp
@@ -1,3 +1,4 @@
+proc built_in_load(String*, Environment*) -> Lisp_Object*;
proc print_environment(Environment*) -> void;
proc eval_arguments(Lisp_Object*, Environment*, int*) -> Lisp_Object*;
proc eval_expr(Lisp_Object*, Environment*) -> Lisp_Object*;
diff --git a/src/io.cpp b/src/io.cpp
index 4156450..205bd04 100644
--- a/src/io.cpp
+++ b/src/io.cpp
@@ -200,7 +200,7 @@ proc read_line() -> char* {
}
(*line)--; // we dont want the \n actually
*line = '\0';
-
+
return linep;
}
diff --git a/src/main.cpp b/src/main.cpp
index 66775d7..5f1ea2e 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -3,8 +3,7 @@
int main(int argc, char* argv[]) {
if (argc > 1) {
if (Slime::string_equal(argv[1], "--run-tests")) {
- Slime::run_all_tests();
- return 0;
+ return Slime::run_all_tests() ? 0 : 1;
}
Slime::interprete_file(argv[1]);
diff --git a/src/parse.cpp b/src/parse.cpp
index b2fbfae..77d3aae 100644
--- a/src/parse.cpp
+++ b/src/parse.cpp
@@ -4,15 +4,15 @@ namespace Parser {
int parser_line;
int parser_col;
// NOTE(Felix): In this environment, the build in functions will
- // be loaded, and the macros will be stroed in form of
+ // be loaded, and the macros will be stored in form of
// special-lambdas, that get executed in this environment at
// read-time. This should always be the global environment.
Environment* environment_for_macros;
proc init(Environment* env) -> void {
// NOTE(Felix): it is important to keep the parser environment
- // up to date with the global environment. When donig tests,
- // or running a programm we have to reaload it.
+ // up to date with the global environment. When doing tests,
+ // or running a programm we have to reload it.
// NOTE(Felix): For now we just allow executing built-ins at
// read-time (while creating macros). If later we want to
@@ -241,18 +241,21 @@ namespace Parser {
}
}
+ Lisp_Object* ret = nullptr;
if (quoteType == '\'')
- return Memory::create_lisp_object_pair(
+ ret = Memory::create_lisp_object_pair(
Memory::get_or_create_lisp_object_symbol("quote"),
Memory::create_lisp_object_pair(result, Memory::nil));
else if (quoteType == '`')
- return Memory::create_lisp_object_pair(
+ ret = Memory::create_lisp_object_pair(
Memory::get_or_create_lisp_object_symbol("quasiquote"),
Memory::create_lisp_object_pair(result, Memory::nil));
- // it has to be an unquote
- return Memory::create_lisp_object_pair(
- Memory::get_or_create_lisp_object_symbol("unquote"),
- Memory::create_lisp_object_pair(result, Memory::nil));
+ else if (quoteType == ',')
+ ret = Memory::create_lisp_object_pair(
+ Memory::get_or_create_lisp_object_symbol("unquote"),
+ Memory::create_lisp_object_pair(result, Memory::nil));
+ inject_scl(ret);
+ return ret;
}
@@ -277,6 +280,7 @@ namespace Parser {
Lisp_Object* expression = head;
while (true) {
+ inject_scl(head);
if (text[*index_in_text] == '(' ||
text[*index_in_text] == '\''||
text[*index_in_text] == '`' ||
diff --git a/src/slime.h b/src/slime.h
index 21baf86..4008d02 100644
--- a/src/slime.h
+++ b/src/slime.h
@@ -18,8 +18,8 @@ namespace Slime {
#include "./io.cpp"
#include "./env.cpp"
#include "./parse.cpp"
-#include "./built_ins.cpp"
#include "./eval.cpp"
+#include "./built_ins.cpp"
#include "./testing.cpp"
#include "./undefines.cpp"
}
diff --git a/src/structs.cpp b/src/structs.cpp
index a397299..bbc6f80 100644
--- a/src/structs.cpp
+++ b/src/structs.cpp
@@ -27,11 +27,14 @@ enum struct Function_Type {
};
enum struct Error_Type {
+ Assertion_Error,
+ File_Not_Found,
Ill_Formed_Arguments,
Ill_Formed_Lambda_List,
Ill_Formed_List,
Not_A_Function,
Not_Yet_Implemented,
+ Out_Of_Memory,
Symbol_Not_Defined,
Syntax_Error,
Trailing_Garbage,
@@ -41,7 +44,6 @@ enum struct Error_Type {
Unknown_Error,
Unknown_Keyword_Argument,
Wrong_Number_Of_Arguments,
- Out_Of_Memory,
};
enum struct Log_Level {
diff --git a/src/testing.cpp b/src/testing.cpp
index 43b142e..75b5fb2 100644
--- a/src/testing.cpp
+++ b/src/testing.cpp
@@ -85,8 +85,9 @@
printf("%spassed%s\n", console_green, console_normal); \
} \
else { \
+ result = false; \
for(int i = -1; i < 70; ++i) \
- printf((i%3==1)? "." : " "); \
+ printf((i%3==1)? "." : " "); \
printf("%sfailed%s\n", console_red, console_normal); \
if(error) { \
free(error); \
@@ -455,16 +456,42 @@ proc test_singular_t_and_nil() -> testresult {
assert_no_error();
assert_not_null(result3);
- assert_equal_int(result3, Memory::t);
return pass;
}
-proc run_all_tests() -> void {
- log_level = Log_Level::None;
+proc test_class_macro() -> testresult {
+ Memory::init();
+ Environment* env = Memory::create_built_ins_environment();
+ Parser::init(env);
+
+ built_in_load(Memory::create_string("pre.slime"), env);
+ Lisp_Object* result = built_in_load(Memory::create_string("tests/class_macro.slime"), env);
+
+ assert_no_error();
+
+ return pass;
+}
+
+proc test_lexical_scope() -> testresult {
+ Memory::init();
+ Environment* env = Memory::create_built_ins_environment();
+ Parser::init(env);
+
+ built_in_load(Memory::create_string("pre.slime"), env);
+ Lisp_Object* result = built_in_load(Memory::create_string("tests/lexical_scope.slime"), env);
+
+ assert_no_error();
+ return pass;
+}
+
+proc run_all_tests() -> bool {
+ // log_level = Log_Level::None;
Memory::init();
Parser::init(Memory::create_built_ins_environment());
+ bool result = true;
+
printf("-- Parsing --\n");
invoke_test(test_parse_atom);
invoke_test(test_parse_expression);
@@ -486,10 +513,13 @@ proc run_all_tests() -> void {
printf("\n-- Memory management --\n");
invoke_test(test_singular_t_and_nil);
- printf("\n-- Lexical scope --\n");
printf("\n-- Macros --\n");
+ printf("\n-- Test Files --\n");
+ invoke_test(test_class_macro);
+ invoke_test(test_lexical_scope);
+ return result;
}
#undef epsilon
diff --git a/vs/slime.sln b/vs/slime.sln
index 043c57f..0eeeea2 100644
--- a/vs/slime.sln
+++ b/vs/slime.sln
@@ -6,16 +6,13 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slime", "slime.vcxproj", "{1A47A3ED-871F-4CB4-875B-8CAA385B1771}"
EndProject
Global
- GlobalSection(Performance) = preSolution
- HasPerformanceSessions = true
- EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
- testfile|x64 = testfile|x64
- testfile|x86 = testfile|x86
+ Tests|x64 = Tests|x64
+ Tests|x86 = Tests|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1A47A3ED-871F-4CB4-875B-8CAA385B1771}.Debug|x64.ActiveCfg = Debug|x64
@@ -26,10 +23,10 @@ Global
{1A47A3ED-871F-4CB4-875B-8CAA385B1771}.Release|x64.Build.0 = Release|x64
{1A47A3ED-871F-4CB4-875B-8CAA385B1771}.Release|x86.ActiveCfg = Release|Win32
{1A47A3ED-871F-4CB4-875B-8CAA385B1771}.Release|x86.Build.0 = Release|Win32
- {1A47A3ED-871F-4CB4-875B-8CAA385B1771}.testfile|x64.ActiveCfg = testfile|x64
- {1A47A3ED-871F-4CB4-875B-8CAA385B1771}.testfile|x64.Build.0 = testfile|x64
- {1A47A3ED-871F-4CB4-875B-8CAA385B1771}.testfile|x86.ActiveCfg = testfile|Win32
- {1A47A3ED-871F-4CB4-875B-8CAA385B1771}.testfile|x86.Build.0 = testfile|Win32
+ {1A47A3ED-871F-4CB4-875B-8CAA385B1771}.Tests|x64.ActiveCfg = Tests|x64
+ {1A47A3ED-871F-4CB4-875B-8CAA385B1771}.Tests|x64.Build.0 = Tests|x64
+ {1A47A3ED-871F-4CB4-875B-8CAA385B1771}.Tests|x86.ActiveCfg = Tests|Win32
+ {1A47A3ED-871F-4CB4-875B-8CAA385B1771}.Tests|x86.Build.0 = Tests|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -40,4 +37,7 @@ Global
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
+ GlobalSection(Performance) = preSolution
+ HasPerformanceSessions = true
+ EndGlobalSection
EndGlobal
diff --git a/vs/slime.vcxproj b/vs/slime.vcxproj
index c0c20d0..95c5bf6 100644
--- a/vs/slime.vcxproj
+++ b/vs/slime.vcxproj
@@ -25,6 +25,14 @@
testfile
x64
+
+ Tests
+ Win32
+
+
+ Tests
+ x64
+
15.0
@@ -72,6 +80,13 @@
true
MultiByte
+
+ v141
+
+
+ v141
+ MultiByte
+
@@ -170,6 +185,13 @@
NotSet
+
+
+ Disabled
+ EnableFastChecks
+ stdcpplatest
+
+