Browse Source

Fixed Memory Leaks. :)

master
Felix Brendel 6 years ago
parent
commit
bb1cfcd3c3
19 changed files with 203 additions and 177 deletions
  1. +1
    -1
      3rd/ftb
  2. +12
    -12
      bin/pre.slime.expanded
  3. +1
    -1
      bin/tests/class_macro.slime.expanded
  4. +3
    -3
      build.sh
  5. +8
    -9
      include/define_macros.hpp
  6. +1
    -1
      include/libslime.h
  7. +29
    -49
      src/built_ins.cpp
  8. +8
    -9
      src/define_macros.hpp
  9. +1
    -1
      src/error.cpp
  10. +23
    -14
      src/eval.cpp
  11. +3
    -3
      src/gc.cpp
  12. +33
    -36
      src/io.cpp
  13. +4
    -3
      src/libslime.cpp
  14. +19
    -1
      src/lisp_object.cpp
  15. +3
    -2
      src/main.cpp
  16. +34
    -15
      src/memory.cpp
  17. +17
    -14
      src/parse.cpp
  18. +2
    -2
      src/structs.cpp
  19. +1
    -1
      src/testing.cpp

+ 1
- 1
3rd/ftb

@@ -1 +1 @@
Subproject commit 43da71f8094e24c544c12352e02eb76c746e1c93
Subproject commit abbd0b6280738332e195d5c37430feae1dbd0d5e

+ 12
- 12
bin/pre.slime.expanded View File

@@ -4,35 +4,35 @@


(define (hm/get-or-nil hm key) (mytry (hm/get hm key) ())) (define (hm/get-or-nil hm key) (mytry (hm/get hm key) ()))


(define-syntax (pe expr) `(print ',expr "evaluates to" ,expr))
(define-syntax (pe expr) (quasiquote (print (quote (unquote expr)) "evaluates to" (unquote expr))))


(define the-empty-stream ()) (define the-empty-stream ())


(define (stream-null? s) (if s t ())) (define (stream-null? s) (if s t ()))


(define-syntax (delay expr) `(,lambda () ,expr))
(define-syntax (delay expr) (quasiquote ((unquote lambda) () (unquote expr))))


(define (force promise) (promise)) (define (force promise) (promise))


(define-syntax (when condition . body) :doc "Special form for when multiple actions should be done if a\ncondition is true.\n\n{{{example_start}}}\n(when (not ())\n (print "Hello ")\n (print "from ")\n (print "when!"))\n\n(when ()\n (print "Goodbye ")\n (print "World!"))\n{{{example_end}}}\n" (if (= (rest body) ()) `(if ,condition (unquote-splicing body) nil) `(if ,condition (begin (unquote-splicing body)) nil)))
(define-syntax (when condition . body) :doc "Special form for when multiple actions should be done if a\ncondition is true.\n\n{{{example_start}}}\n(when (not ())\n (print "Hello ")\n (print "from ")\n (print "when!"))\n\n(when ()\n (print "Goodbye ")\n (print "World!"))\n{{{example_end}}}\n" (if (= (rest body) ()) (quasiquote (if (unquote condition) (unquote-splicing body) nil)) (quasiquote (if (unquote condition) (begin (unquote-splicing body)) nil))))


(define-syntax (unless condition . body) :doc "Special form for when multiple actions should be done if a\ncondition is false." (if (= (rest body) ()) `(if ,condition nil (unquote-splicing body)) `(if ,condition nil (begin (unquote-splicing body)))))
(define-syntax (unless condition . body) :doc "Special form for when multiple actions should be done if a\ncondition is false." (if (= (rest body) ()) (quasiquote (if (unquote condition) nil (unquote-splicing body))) (quasiquote (if (unquote condition) nil (begin (unquote-splicing body))))))


(define-syntax (n-times times action) :doc "Executes action times times." (define (repeat times elem) (unless (> 1 times) (pair elem (repeat (- times 1) elem)))) `(begin (unquote-splicing (repeat times action))))
(define-syntax (n-times times action) :doc "Executes action times times." (define (repeat times elem) (unless (> 1 times) (pair elem (repeat (- times 1) elem)))) (quasiquote (begin (unquote-splicing (repeat times action)))))


(define-syntax (let bindings . body) (define (unzip lists) (when lists (define (iter lists l1 l2) (define elem (first lists)) (if elem (iter (rest lists) (pair (first elem) l1) (pair (first (rest elem)) l2)) (list l1 l2)))) (iter lists () ())) (define unzipped (unzip bindings)) `((,lambda ,(first unzipped) (unquote-splicing body)) (unquote-splicing (first (rest unzipped)))))
(define-syntax (let bindings . body) (define (unzip lists) (when lists (define (iter lists l1 l2) (define elem (first lists)) (if elem (iter (rest lists) (pair (first elem) l1) (pair (first (rest elem)) l2)) (list l1 l2)))) (iter lists () ())) (define unzipped (unzip bindings)) (quasiquote (((unquote lambda) (unquote (first unzipped)) (unquote-splicing body)) (unquote-splicing (first (rest unzipped))))))


(define-syntax (cond . clauses) (define (rec clauses) (if (= nil clauses) nil (if (= (first (first clauses)) 'else) (begin (if (not (= (rest clauses) ())) (error :syntax-error "There are additional clauses after the else clause!") (pair 'begin (rest (first clauses))))) `(if ,(first (first clauses)) (begin (unquote-splicing (rest (first clauses)))) ,(rec (rest clauses)))))) (rec clauses))
(define-syntax (cond . clauses) (define (rec clauses) (if (= nil clauses) nil (if (= (first (first clauses)) (quote else)) (begin (if (not (= (rest clauses) ())) (error :syntax-error "There are additional clauses after the else clause!") (pair (quote begin) (rest (first clauses))))) (quasiquote (if (unquote (first (first clauses))) (begin (unquote-splicing (rest (first clauses)))) (unquote (rec (rest clauses)))))))) (rec clauses))


(define-syntax (case var . clauses) (define (rec clauses) (if (= nil clauses) nil (if (= (first (first clauses)) 'else) (begin (if (not (= (rest clauses) ())) (error :syntax-error "There are additional clauses after the else clause!") (pair 'begin (rest (first clauses))))) `(if (member? ,var ',(first (first clauses))) (begin (unquote-splicing (rest (first clauses)))) ,(rec (rest clauses)))))) (rec clauses))
(define-syntax (case var . clauses) (define (rec clauses) (if (= nil clauses) nil (if (= (first (first clauses)) (quote else)) (begin (if (not (= (rest clauses) ())) (error :syntax-error "There are additional clauses after the else clause!") (pair (quote begin) (rest (first clauses))))) (quasiquote (if (member? (unquote var) (quote (unquote (first (first clauses))))) (begin (unquote-splicing (rest (first clauses)))) (unquote (rec (rest clauses)))))))) (rec clauses))


(define-syntax (construct-list . body) :doc "\n{{{example_start}}}\n(construct-list\n i <- '(1 2 3 4 5)\n yield (* i i))\n{{{example_end}}}\n\n(construct-list\n i <- '(1 2 3 4)\n j <- '(A B)\n yield (pair i j))\n\n(construct-list\n i <- '(1 2 3 4 5 6 7 8)\n if (= 0 (% i 2))\n yield i)\n" (define (append-map f ll) (unless (= ll ()) (define val (f (first ll))) (if (= (first val) ()) (append-map f (rest ll)) (extend val (append-map f (rest ll)))))) (define (rec body) (cond ((= () body) ()) ((= () (rest body)) (first body)) ((= (first (rest body)) '<-) `(,append-map (lambda (,(first body)) (list ,(rec (rest (rest (rest body)))))) ,(first (rest (rest body))))) ((= (first body) 'if) `(when ,(first (rest body)) ,(rec (rest (rest body))))) ((= (first (rest body)) 'yield) (first (rest body))) (else (error :syntax-error "Not a do-able expression")))) (rec body))
(define-syntax (construct-list . body) :doc "\n{{{example_start}}}\n(construct-list\n i <- '(1 2 3 4 5)\n yield (* i i))\n{{{example_end}}}\n\n(construct-list\n i <- '(1 2 3 4)\n j <- '(A B)\n yield (pair i j))\n\n(construct-list\n i <- '(1 2 3 4 5 6 7 8)\n if (= 0 (% i 2))\n yield i)\n" (define (append-map f ll) (unless (= ll ()) (define val (f (first ll))) (if (= (first val) ()) (append-map f (rest ll)) (extend val (append-map f (rest ll)))))) (define (rec body) (cond ((= () body) ()) ((= () (rest body)) (first body)) ((= (first (rest body)) (quote <-)) (quasiquote ((unquote append-map) (lambda ((unquote (first body))) (list (unquote (rec (rest (rest (rest body))))))) (unquote (first (rest (rest body))))))) ((= (first body) (quote if)) (quasiquote (when (unquote (first (rest body))) (unquote (rec (rest (rest body))))))) ((= (first (rest body)) (quote yield)) (first (rest body))) (else (error :syntax-error "Not a do-able expression")))) (rec body))


(define-syntax (define-typed args . body) (define (get-arg-names args) (when args (pair (first args) (get-arg-names (rest (rest args)))))) (let ((name (first args)) (lambda-list (rest args)) (arg-names (get-arg-names (rest args)))) `(define (,name (unquote-splicing arg-names)) (assert-types= (unquote-splicing lambda-list)) (unquote-splicing body))))
(define-syntax (define-typed args . body) (define (get-arg-names args) (when args (pair (first args) (get-arg-names (rest (rest args)))))) (let ((name (first args)) (lambda-list (rest args)) (arg-names (get-arg-names (rest args)))) (quasiquote (define ((unquote name) (unquote-splicing arg-names)) (assert-types= (unquote-splicing lambda-list)) (unquote-splicing body)))))


(define-syntax (define-module module-name (:imports ()) :exports . body) (let ((module-prefix (concat-strings (symbol->string module-name) "::"))) (eval `(begin (unquote-splicing (map (lambda (x) `(,import ,x)) imports)) (unquote-splicing body))) (pair 'begin (map (lambda (orig-export-name) (let ((export-name (string->symbol (concat-strings module-prefix (symbol->string orig-export-name))))) `(define ,export-name ,(mytry (eval orig-export-name) (error :module-error "The module does not contain a key it tries to export"))))) exports))))
(define-syntax (define-module module-name (:imports ()) :exports . body) (let ((module-prefix (concat-strings (symbol->string module-name) "::"))) (eval (quasiquote (begin (unquote-splicing (map (lambda (x) (quasiquote ((unquote import) (unquote x)))) imports)) (unquote-splicing body)))) (pair (quote begin) (map (lambda (orig-export-name) (let ((export-name (string->symbol (concat-strings module-prefix (symbol->string orig-export-name))))) (quasiquote (define (unquote export-name) (unquote (mytry (eval orig-export-name) (error :module-error "The module does not contain a key it tries to export"))))))) exports))))


(define-syntax (generic-extend args . body) (let ((fun-name (first args)) (params (rest args)) (types ()) (names ())) (define (process-params params) (when params (let ((_name (first params)) (_type (first (rest params)))) (assert (symbol? _name)) (assert (keyword? _type)) (set! types (append types _type)) (set! names (append names _name)) (process-params (rest (rest params)))))) (process-params params) (let ((generic-map-name (string->symbol (concat-strings "generic-" (symbol->string fun-name) "-map")))) (unless (bound? generic-map-name) (define generic-map-name (create-hash-map))) (hm/set! generic-map-name types (eval `(,lambda ,names (unquote-splicing body)))) (if (bound? fun-name) (let ((exisiting-fun (eval fun-name))) (unless (type=? exisiting-fun :generic-procedure) (unless (procedure? exisiting-fun) (error :macro-expand-error "can only generic-extend procedures.")) (define orig-proc exisiting-fun) (define fun-name (eval `(,lambda args (let ((fun (hm/get (map type args)))) (if (procedure? fun) (fun . args) (,orig-proc . args))))))))))))
(define-syntax (generic-extend args . body) (let ((fun-name (first args)) (params (rest args)) (types ()) (names ())) (define (process-params params) (when params (let ((_name (first params)) (_type (first (rest params)))) (assert (symbol? _name)) (assert (keyword? _type)) (set! types (append types _type)) (set! names (append names _name)) (process-params (rest (rest params)))))) (process-params params) (let ((generic-map-name (string->symbol (concat-strings "generic-" (symbol->string fun-name) "-map")))) (unless (bound? generic-map-name) (define generic-map-name (create-hash-map))) (hm/set! generic-map-name types (eval (quasiquote ((unquote lambda) (unquote names) (unquote-splicing body))))) (if (bound? fun-name) (let ((exisiting-fun (eval fun-name))) (unless (type=? exisiting-fun :generic-procedure) (unless (procedure? exisiting-fun) (error :macro-expand-error "can only generic-extend procedures.")) (define orig-proc exisiting-fun) (define fun-name (eval (quasiquote ((unquote lambda) args (let ((fun (hm/get (map type args)))) (if (procedure? fun) (fun . args) ((unquote orig-proc) . args)))))))))))))


(define (null? x) :doc "Checks if the argument is =nil=." (= x ())) (define (null? x) :doc "Checks if the argument is =nil=." (= x ()))




+ 1
- 1
bin/tests/class_macro.slime.expanded View File

@@ -8,7 +8,7 @@


(assert (= (type v1) (type v2) :vector3)) (assert (= (type v1) (type v2) :vector3))


(assert (= (v1 'scalar-product v2) 10))
(assert (= (v1 (quote scalar-product) v2) 10))


(assert (-> (-> v1 cross-product v2) equal? (make-vector3 -4 8 -4))) (assert (-> (-> v1 cross-product v2) equal? (make-vector3 -4 8 -4)))



+ 3
- 3
build.sh View File

@@ -19,17 +19,17 @@ echo "----------------------"
echo "" echo ""


# time g++ -fpermissive src/main.cpp -g -o ./bin/slime --std=c++17 || exit 1 # time g++ -fpermissive src/main.cpp -g -o ./bin/slime --std=c++17 || exit 1
time clang++ -D_DEBUG -D_PROFILING -D_DONT_BREAK_ON_ERRORS \
time clang++ -D_DEBUG -D_DONT_BREAK_ON_ERRORS \
src/main.cpp -g -o ./bin/slime --std=c++17 \ src/main.cpp -g -o ./bin/slime --std=c++17 \
-I3rd/ || exit 1 -I3rd/ || exit 1
# time clang++ -O3 -D_DONT_BREAK_ON_ERRORS \ # time clang++ -O3 -D_DONT_BREAK_ON_ERRORS \
# src/main.cpp -g -o ./bin/slime --std=c++17 \ # src/main.cpp -g -o ./bin/slime --std=c++17 \
# -I3rd/ || exit 1 # -I3rd/ || exit 1



echo "" echo ""
pushd ./bin > /dev/null pushd ./bin > /dev/null
time ./slime --run-tests
time valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ./slime --run-tests
# time ./slime --run-tests


popd > /dev/null popd > /dev/null
popd > /dev/null popd > /dev/null


+ 8
- 9
include/define_macros.hpp View File

@@ -101,11 +101,14 @@
)(__VA_ARGS__) )(__VA_ARGS__)
#endif #endif


// NOTE(Felix): we have to copy the string because we need
// it to be mutable for the parser to work, because the
// parser relys on being able to temporaily put in markers
// in the code
// NOTE(Felix): we have to copy the string because we need it to be
// mutable for the parser to work, because the parser relys on being
// able to temporaily put in markers in the code and also it will fill
// out the source code location
#define _define_helper(def, docs, special) \ #define _define_helper(def, docs, special) \
Parser::parser_file = file_name_built_ins; \
Parser::parser_line = __LINE__; \
Parser::parser_col = 0; \
auto label(params,__LINE__) = Parser::parse_single_expression( \ auto label(params,__LINE__) = Parser::parse_single_expression( \
Memory::get_c_str(Memory::create_string(#def))); \ Memory::get_c_str(Memory::create_string(#def))); \
if_error_log_location_and_return(); \ if_error_log_location_and_return(); \
@@ -115,13 +118,9 @@
auto label(sfun,__LINE__) = Memory::create_lisp_object_cfunction(special); \ auto label(sfun,__LINE__) = Memory::create_lisp_object_cfunction(special); \
create_arguments_from_lambda_list_and_inject(label(params,__LINE__)->value.pair.rest, label(sfun,__LINE__)); \ create_arguments_from_lambda_list_and_inject(label(params,__LINE__)->value.pair.rest, label(sfun,__LINE__)); \
if_error_log_location_and_return(); \ if_error_log_location_and_return(); \
label(sfun,__LINE__)->sourceCodeLocation = new(Source_Code_Location); \
label(sfun,__LINE__)->sourceCodeLocation->file = file_name_built_ins; \
label(sfun,__LINE__)->sourceCodeLocation->line = __LINE__; \
label(sfun,__LINE__)->sourceCodeLocation->column = 0; \
label(sfun,__LINE__)->docstring = Memory::create_string(docs); \ label(sfun,__LINE__)->docstring = Memory::create_string(docs); \
define_symbol(label(sym,__LINE__), label(sfun,__LINE__)); \ define_symbol(label(sym,__LINE__), label(sfun,__LINE__)); \
label(sfun,__LINE__)->value.cFunction->body = (std::function<Lisp_Object* ()>)[&]() -> Lisp_Object*
label(sfun,__LINE__)->value.cFunction->body = []() -> Lisp_Object*


#define define(def, docs) _define_helper(def, docs, false) #define define(def, docs) _define_helper(def, docs, false)
#define define_special(def, docs) _define_helper(def, docs, true) #define define_special(def, docs) _define_helper(def, docs, true)


+ 1
- 1
include/libslime.h View File

@@ -1,6 +1,6 @@
#pragma once #pragma once


#include <functional>
// #include <functional>
#include "ftb/arraylist.hpp" #include "ftb/arraylist.hpp"
#include "ftb/hashmap.hpp" #include "ftb/hashmap.hpp"




+ 29
- 49
src/built_ins.cpp View File

@@ -83,6 +83,7 @@ proc built_in_load(String* file_name) -> Lisp_Object* {
try result = eval_expr(program->data[i]); try result = eval_expr(program->data[i]);
} }
delete program; delete program;
free(file_content);


return result; return result;
} }
@@ -315,18 +316,6 @@ proc load_built_ins_into_environment() -> void {
define_special((define-syntax form (:doc "") . body), "TODO") { define_special((define-syntax form (:doc "") . body), "TODO") {
fetch(form, doc, body); fetch(form, doc, body);


// static Lisp_Object *form_symbol = Memory::get_or_create_lisp_object_symbol("form");
// static Lisp_Object *doc_symbol = Memory::get_or_create_lisp_object_symbol("doc");
// static Lisp_Object *body_symbol = Memory::get_or_create_lisp_object_symbol("body");

// printf("\n\nin define-syntax:: envi stack depth: %d\n",
// Globals::Current_Execution::envi_stack.next_index);
// print_environment(get_current_environment());

// Lisp_Object *form = lookup_symbol(form_symbol, get_current_environment());
// Lisp_Object *doc = lookup_symbol(doc_symbol, get_current_environment());
// Lisp_Object *body = lookup_symbol(body_symbol, get_current_environment());

try assert_type(doc, Lisp_Object_Type::String); try assert_type(doc, Lisp_Object_Type::String);
// if no doc string, we dont have to store it // if no doc string, we dont have to store it
if (Memory::get_c_str(doc)[0] == '\0') { if (Memory::get_c_str(doc)[0] == '\0') {
@@ -343,20 +332,19 @@ proc load_built_ins_into_environment() -> void {


// creating new lisp object and setting type // creating new lisp object and setting type
Lisp_Object* func; Lisp_Object* func;
try func = Memory::create_lisp_object();
Memory::set_type(func, Lisp_Object_Type::Function);
func->value.function.type = Function_Type::Macro;
new((&func->value.function.args.positional.symbols)) Array_List<Environment*>(16);
new((&func->value.function.args.keyword.keywords)) Array_List<Environment*>(16);
new((&func->value.function.args.keyword.values)) Array_List<Environment*>(16);
try func = Memory::create_lisp_object_function(Function_Type::Macro);


// Lisp_Object* func;
// try func = Memory::create_lisp_object();
// Memory::set_type(func, Lisp_Object_Type::Function);
// func->value.function->type = Function_Type::Macro;
if (doc) func->docstring = doc->value.string; if (doc) func->docstring = doc->value.string;


in_caller_env { in_caller_env {
// setting parent env // setting parent env
func->value.function.parent_environment = get_current_environment();
func->value.function->parent_environment = get_current_environment();
create_arguments_from_lambda_list_and_inject(lambdalist, func); create_arguments_from_lambda_list_and_inject(lambdalist, func);
func->value.function.body = maybe_wrap_body_in_begin(body);
func->value.function->body = maybe_wrap_body_in_begin(body);
define_symbol(symbol, func); define_symbol(symbol, func);
} }
return Memory::nil; return Memory::nil;
@@ -394,21 +382,16 @@ proc load_built_ins_into_environment() -> void {


// creating new lisp object and setting type // creating new lisp object and setting type
Lisp_Object* func; Lisp_Object* func;
try func = Memory::create_lisp_object();
Memory::set_type(func, Lisp_Object_Type::Function);
func->value.function.type = Function_Type::Lambda;
new((&func->value.function.args.positional.symbols)) Array_List<Environment*>(16);
new((&func->value.function.args.keyword.keywords)) Array_List<Environment*>(16);
new((&func->value.function.args.keyword.values)) Array_List<Environment*>(16);
try func = Memory::create_lisp_object_function(Function_Type::Lambda);


if (doc) if (doc)
func->docstring = doc->value.string; func->docstring = doc->value.string;


in_caller_env { in_caller_env {
// setting parent env // setting parent env
func->value.function.parent_environment = get_current_environment();
func->value.function->parent_environment = get_current_environment();
create_arguments_from_lambda_list_and_inject(lambdalist, func); create_arguments_from_lambda_list_and_inject(lambdalist, func);
func->value.function.body = maybe_wrap_body_in_begin(body);
func->value.function->body = maybe_wrap_body_in_begin(body);
define_symbol(symbol, func); define_symbol(symbol, func);
} }


@@ -536,12 +519,10 @@ proc load_built_ins_into_environment() -> void {
Lisp_Object* quasiquote_sym = Memory::get_or_create_lisp_object_symbol("quasiquote"); Lisp_Object* quasiquote_sym = Memory::get_or_create_lisp_object_symbol("quasiquote");
Lisp_Object* unquote_sym = Memory::get_or_create_lisp_object_symbol("unquote"); Lisp_Object* unquote_sym = Memory::get_or_create_lisp_object_symbol("unquote");
Lisp_Object* unquote_splicing_sym = Memory::get_or_create_lisp_object_symbol("unquote-splicing"); Lisp_Object* unquote_splicing_sym = Memory::get_or_create_lisp_object_symbol("unquote-splicing");
/* recursive lambdas in lambdas yay!! */
// NOTE(Felix): first we have to initialize the variable // NOTE(Felix): first we have to initialize the variable
// with a garbage lambda, so that we can then overwrite it // with a garbage lambda, so that we can then overwrite it
// a recursive lambda // a recursive lambda
std::function<Lisp_Object*(Lisp_Object*)> unquoteSomeExpressions; // = [] (Lisp_Object* expr) -> Lisp_Object* {return nullptr;};
unquoteSomeExpressions = [&] (Lisp_Object* expr) -> Lisp_Object* {
const auto unquoteSomeExpressions = [&] (const auto & self, Lisp_Object* expr) -> Lisp_Object* {
// if it is an atom, return it // if it is an atom, return it
if (Memory::get_type(expr) != Lisp_Object_Type::Pair) if (Memory::get_type(expr) != Lisp_Object_Type::Pair)
return Memory::copy_lisp_object(expr); return Memory::copy_lisp_object(expr);
@@ -584,7 +565,7 @@ proc load_built_ins_into_environment() -> void {
if (Memory::get_type(head->value.pair.first) == Lisp_Object_Type::Pair && if (Memory::get_type(head->value.pair.first) == Lisp_Object_Type::Pair &&
head->value.pair.first->value.pair.first == unquote_splicing_sym) head->value.pair.first->value.pair.first == unquote_splicing_sym)
{ {
Lisp_Object* spliced = unquoteSomeExpressions(head->value.pair.first);
Lisp_Object* spliced = self(self, head->value.pair.first);


if (spliced == Memory::nil) { if (spliced == Memory::nil) {
head = head->value.pair.rest; head = head->value.pair.rest;
@@ -615,7 +596,7 @@ proc load_built_ins_into_environment() -> void {
try newPairHead->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil); try newPairHead->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
newPairHead = newPairHead->value.pair.rest; newPairHead = newPairHead->value.pair.rest;
} }
newPairHead->value.pair.first = unquoteSomeExpressions(head->value.pair.first);
newPairHead->value.pair.first = self(self, head->value.pair.first);
} }


// if (Memory::get_type(head->value.pair.rest) != Lisp_Object_Type::Pair) { // if (Memory::get_type(head->value.pair.rest) != Lisp_Object_Type::Pair) {
@@ -630,7 +611,7 @@ proc load_built_ins_into_environment() -> void {
return newPair; return newPair;
}; };


expr = unquoteSomeExpressions(expr);
expr = unquoteSomeExpressions(unquoteSomeExpressions, expr);
return expr; return expr;
}; };
define_special((and . args), "TODO") { define_special((and . args), "TODO") {
@@ -694,18 +675,17 @@ proc load_built_ins_into_environment() -> void {
define_special((lambda args . body), "TODO") { define_special((lambda args . body), "TODO") {
fetch(args, body); fetch(args, body);


Lisp_Object* fun;
try fun = Memory::create_lisp_object();
Memory::set_type(fun, Lisp_Object_Type::Function);
fun->value.function.type = Function_Type::Lambda;
// creating new lisp object and setting type
Lisp_Object* func;
try func = Memory::create_lisp_object_function(Function_Type::Lambda);


in_caller_env { in_caller_env {
fun->value.function.parent_environment = get_current_environment();
func->value.function->parent_environment = get_current_environment();
} }


try create_arguments_from_lambda_list_and_inject(args, fun);
fun->value.function.body = maybe_wrap_body_in_begin(body);
return fun;
try create_arguments_from_lambda_list_and_inject(args, func);
func->value.function->body = maybe_wrap_body_in_begin(body);
return func;
}; };
// define_special((special-lambda args . body), "TODO") { // define_special((special-lambda args . body), "TODO") {
// fetch(args, body); // fetch(args, body);
@@ -713,14 +693,14 @@ proc load_built_ins_into_environment() -> void {
// Lisp_Object* fun; // Lisp_Object* fun;
// try fun = Memory::create_lisp_object(); // try fun = Memory::create_lisp_object();
// Memory::set_type(fun, Lisp_Object_Type::Function); // Memory::set_type(fun, Lisp_Object_Type::Function);
// fun->value.function.type = Function_Type::Special_Lambda;
// fun->value.function->type = Function_Type::Special_Lambda;


// in_caller_env { // in_caller_env {
// fun->value.function.parent_environment = get_current_environment();
// fun->value.function->parent_environment = get_current_environment();
// } // }


// try create_arguments_from_lambda_list_and_inject(args, fun); // try create_arguments_from_lambda_list_and_inject(args, fun);
// fun->value.function.body = maybe_wrap_body_in_begin(body);
// fun->value.function->body = maybe_wrap_body_in_begin(body);
// return fun; // return fun;
// }; // };
define((apply fun args), "TODO") { define((apply fun args), "TODO") {
@@ -834,7 +814,7 @@ proc load_built_ins_into_environment() -> void {
case Lisp_Object_Type::Continuation: return Memory::get_or_create_lisp_object_keyword("continuation"); case Lisp_Object_Type::Continuation: return Memory::get_or_create_lisp_object_keyword("continuation");
case Lisp_Object_Type::CFunction: return Memory::get_or_create_lisp_object_keyword("cfunction"); case Lisp_Object_Type::CFunction: return Memory::get_or_create_lisp_object_keyword("cfunction");
case Lisp_Object_Type::Function: { case Lisp_Object_Type::Function: {
Function* fun = &n->value.function;
Function* fun = n->value.function;
if (fun->type == Function_Type::Lambda) if (fun->type == Function_Type::Lambda)
return Memory::get_or_create_lisp_object_keyword("lambda"); return Memory::get_or_create_lisp_object_keyword("lambda");
// else if (fun->type == Function_Type::Special_Lambda) // else if (fun->type == Function_Type::Special_Lambda)
@@ -892,7 +872,7 @@ proc load_built_ins_into_environment() -> void {
{ {
Arguments* args; Arguments* args;
if (Memory::get_type(val) == Lisp_Object_Type::Function) if (Memory::get_type(val) == Lisp_Object_Type::Function)
args = &val->value.function.args;
args = &val->value.function->args;
else else
args = &val->value.cFunction->args; args = &val->value.cFunction->args;


@@ -941,10 +921,10 @@ proc load_built_ins_into_environment() -> void {
try assert_type(n, Lisp_Object_Type::Function); try assert_type(n, Lisp_Object_Type::Function);


puts("body:\n"); puts("body:\n");
print(n->value.function.body);
print(n->value.function->body);
puts("\n"); puts("\n");
printf("parent_env: %lld\n", printf("parent_env: %lld\n",
(long long)n->value.function.parent_environment);
(long long)n->value.function->parent_environment);


return Memory::nil; return Memory::nil;
}; };


+ 8
- 9
src/define_macros.hpp View File

@@ -101,11 +101,14 @@
)(__VA_ARGS__) )(__VA_ARGS__)
#endif #endif


// NOTE(Felix): we have to copy the string because we need
// it to be mutable for the parser to work, because the
// parser relys on being able to temporaily put in markers
// in the code
// NOTE(Felix): we have to copy the string because we need it to be
// mutable for the parser to work, because the parser relys on being
// able to temporaily put in markers in the code and also it will fill
// out the source code location
#define _define_helper(def, docs, special) \ #define _define_helper(def, docs, special) \
Parser::parser_file = file_name_built_ins; \
Parser::parser_line = __LINE__; \
Parser::parser_col = 0; \
auto label(params,__LINE__) = Parser::parse_single_expression( \ auto label(params,__LINE__) = Parser::parse_single_expression( \
Memory::get_c_str(Memory::create_string(#def))); \ Memory::get_c_str(Memory::create_string(#def))); \
if_error_log_location_and_return(); \ if_error_log_location_and_return(); \
@@ -115,13 +118,9 @@
auto label(sfun,__LINE__) = Memory::create_lisp_object_cfunction(special); \ auto label(sfun,__LINE__) = Memory::create_lisp_object_cfunction(special); \
create_arguments_from_lambda_list_and_inject(label(params,__LINE__)->value.pair.rest, label(sfun,__LINE__)); \ create_arguments_from_lambda_list_and_inject(label(params,__LINE__)->value.pair.rest, label(sfun,__LINE__)); \
if_error_log_location_and_return(); \ if_error_log_location_and_return(); \
label(sfun,__LINE__)->sourceCodeLocation = new(Source_Code_Location); \
label(sfun,__LINE__)->sourceCodeLocation->file = file_name_built_ins; \
label(sfun,__LINE__)->sourceCodeLocation->line = __LINE__; \
label(sfun,__LINE__)->sourceCodeLocation->column = 0; \
label(sfun,__LINE__)->docstring = Memory::create_string(docs); \ label(sfun,__LINE__)->docstring = Memory::create_string(docs); \
define_symbol(label(sym,__LINE__), label(sfun,__LINE__)); \ define_symbol(label(sym,__LINE__), label(sfun,__LINE__)); \
label(sfun,__LINE__)->value.cFunction->body = (std::function<Lisp_Object* ()>)[&]() -> Lisp_Object*
label(sfun,__LINE__)->value.cFunction->body = []() -> Lisp_Object*


#define define(def, docs) _define_helper(def, docs, false) #define define(def, docs) _define_helper(def, docs, false)
#define define_special(def, docs) _define_helper(def, docs, true) #define define_special(def, docs) _define_helper(def, docs, true)


+ 1
- 1
src/error.cpp View File

@@ -30,7 +30,7 @@ proc create_error(const char* c_func_name,const char* c_file_name, int c_file_li
} }
// visualize_lisp_machine(); // visualize_lisp_machine();
using Globals::error; using Globals::error;
error = new(Error);
error = (Error*)malloc(sizeof(Error)) ;
error->type = type; error->type = type;
error->message = message; error->message = message;




+ 23
- 14
src/eval.cpp View File

@@ -17,8 +17,8 @@ proc create_extended_environment_for_function_application(
new_env = Memory::create_child_environment(get_root_environment()); new_env = Memory::create_child_environment(get_root_environment());
arg_spec = &function->value.cFunction->args; arg_spec = &function->value.cFunction->args;
} else { } else {
new_env = Memory::create_child_environment(function->value.function.parent_environment);
arg_spec = &function->value.function.args;
new_env = Memory::create_child_environment(function->value.function->parent_environment);
arg_spec = &function->value.function->args;
} }
if (should_evaluate) { if (should_evaluate) {
try arguments = eval_arguments(arguments); try arguments = eval_arguments(arguments);
@@ -51,7 +51,7 @@ proc create_extended_environment_for_function_application(
// NOTE(Felix): We have to copy all the arguments, // NOTE(Felix): We have to copy all the arguments,
// otherwise we change the program code. XXX(Felix): T C // otherwise we change the program code. XXX(Felix): T C
// functions we pass by reference... // functions we pass by reference...
try_void sym = arg_spec->positional.symbols.data[i];
sym = arg_spec->positional.symbols.data[i];
if (is_c_function) { if (is_c_function) {
define_symbol(sym, arguments->value.pair.first); define_symbol(sym, arguments->value.pair.first);
} else { } else {
@@ -240,7 +240,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Lisp_Object* function,
if (Memory::get_type(function) == Lisp_Object_Type::CFunction) if (Memory::get_type(function) == Lisp_Object_Type::CFunction)
try result = function->value.cFunction->body(); try result = function->value.cFunction->body();
else // if lisp function else // if lisp function
try result = eval_expr(function->value.function.body);
try result = eval_expr(function->value.function->body);


return result; return result;
} }
@@ -256,16 +256,14 @@ proc create_arguments_from_lambda_list_and_inject(Lisp_Object* arguments, Lisp_O
if (Memory::get_type(function) == Lisp_Object_Type::CFunction) { if (Memory::get_type(function) == Lisp_Object_Type::CFunction) {
result = &function->value.cFunction->args; result = &function->value.cFunction->args;
} else { } else {
result = &function->value.function.args;
result = &function->value.function->args;
} }


::new (&result->positional.symbols) Array_List<Lisp_Object*>;
::new (&result->keyword.keywords) Array_List<Lisp_Object*>;
::new (&result->keyword.values) Array_List<Lisp_Object*>;
// ::new (&result->positional.symbols) Array_List<Lisp_Object*>;
// ::new (&result->keyword.keywords) Array_List<Lisp_Object*>;
// ::new (&result->keyword.values) Array_List<Lisp_Object*>;


// first init the fields // first init the fields
// result->positional = create_positional_argument_list(16);
// result->keyword = create_keyword_argument_list(16);
result->rest = nullptr; result->rest = nullptr;


// okay let's try to read some positional arguments // okay let's try to read some positional arguments
@@ -357,6 +355,11 @@ proc list_length(Lisp_Object* node) -> int {
return 0; return 0;
} }


proc copy_scl(Source_Code_Location*) -> Source_Code_Location* {
// TODO(Felix):
return nullptr;
}

proc eval_arguments(Lisp_Object* arguments) -> Lisp_Object* { proc eval_arguments(Lisp_Object* arguments) -> Lisp_Object* {
profile_this; profile_this;
// int my_out_arguments_length = 0; // int my_out_arguments_length = 0;
@@ -374,7 +377,8 @@ proc eval_arguments(Lisp_Object* arguments) -> Lisp_Object* {
while (Memory::get_type(current_head) == Lisp_Object_Type::Pair) { while (Memory::get_type(current_head) == Lisp_Object_Type::Pair) {
try evaluated_arguments_head->value.pair.first = eval_expr(current_head->value.pair.first); try evaluated_arguments_head->value.pair.first = eval_expr(current_head->value.pair.first);


evaluated_arguments_head->value.pair.first->sourceCodeLocation = current_head->value.pair.first->sourceCodeLocation;
evaluated_arguments_head->value.pair.first->sourceCodeLocation =
copy_scl(current_head->value.pair.first->sourceCodeLocation);
current_head = current_head->value.pair.rest; current_head = current_head->value.pair.rest;


if (Memory::get_type(current_head) == Lisp_Object_Type::Pair) { if (Memory::get_type(current_head) == Lisp_Object_Type::Pair) {
@@ -451,7 +455,7 @@ proc eval_expr(Lisp_Object* node) -> Lisp_Object* {
try result = apply_arguments_to_function( try result = apply_arguments_to_function(
arguments, arguments,
lispOperator, lispOperator,
lispOperator->value.function.type == Function_Type::Lambda);
lispOperator->value.function->type == Function_Type::Lambda);


// NOTE(Felix): The parser does not understnad (import ..) // NOTE(Felix): The parser does not understnad (import ..)
// so it cannot expand imported macros at read time // so it cannot expand imported macros at read time
@@ -460,15 +464,20 @@ proc eval_expr(Lisp_Object* node) -> Lisp_Object* {
// stray macros fying around, in that case, we expand them // stray macros fying around, in that case, we expand them
// and bake them in, so they do not have to be expanded // and bake them in, so they do not have to be expanded
// later again. We will call this "lazy macro expansion" // later again. We will call this "lazy macro expansion"
if (lispOperator->value.function.type == Function_Type::Macro) {
if (lispOperator->value.function->type == Function_Type::Macro) {
// bake in the macro expansion: // bake in the macro expansion:
*node = *result;
*node = *Memory::copy_lisp_object(result);
result->sourceCodeLocation = copy_scl(result->sourceCodeLocation);
// eval again because macro // eval again because macro
try result = eval_expr(result); try result = eval_expr(result);
} }


return result; return result;
} }

create_generic_error("The first element of the pair was not a function but: %s",
Lisp_Object_Type_to_string(Memory::get_type(lispOperator)));
return nullptr;
} }
default: { default: {
create_generic_error("%s is not a function.", Lisp_Object_Type_to_string(Memory::get_type(node))); create_generic_error("%s is not a function.", Lisp_Object_Type_to_string(Memory::get_type(node)));


+ 3
- 3
src/gc.cpp View File

@@ -46,10 +46,10 @@ namespace GC {
// NOTE(Felix): We dont have to mark the symbols, keywords // NOTE(Felix): We dont have to mark the symbols, keywords
// for parameter names, as symbols and keywords are never // for parameter names, as symbols and keywords are never
// garbage collected // garbage collected
maybe_mark(node->value.function.parent_environment);
maybe_mark(node->value.function.body);
maybe_mark(node->value.function->parent_environment);
maybe_mark(node->value.function->body);
// mark the default arguemnt values: // mark the default arguemnt values:
for (auto it : node->value.function.args.keyword.values) {
for (auto it : node->value.function->args.keyword.values) {
if (it) if (it)
maybe_mark(it); maybe_mark(it);
} }


+ 33
- 36
src/io.cpp View File

@@ -64,9 +64,8 @@ proc escape_string(char* in) -> char* {
return ret; return ret;
} }


proc unescape_string(char* in) -> bool {
if (!in)
return true;
proc unescape_string(char* in) -> int {
if (!in) return 0;


char *out = in, *p = in; char *out = in, *p = in;
const char *int_err = nullptr; const char *int_err = nullptr;
@@ -117,9 +116,7 @@ proc unescape_string(char* in) -> bool {


/* Set the end of string. */ /* Set the end of string. */
*out = '\0'; *out = '\0';
if (int_err)
return false;
return true;
return out - in;
} }


proc read_entire_file(char* filename) -> char* { proc read_entire_file(char* filename) -> char* {
@@ -358,11 +355,11 @@ proc print(Lisp_Object* node, bool print_repr, FILE* file) -> void {
fprintf(file, "[%s]", Memory::get_c_str(node->userType->value.symbol.identifier)); fprintf(file, "[%s]", Memory::get_c_str(node->userType->value.symbol.identifier));
break; break;
} }
if (node->value.function.type == Function_Type::Lambda)
if (node->value.function->type == Function_Type::Lambda)
fputs("[lambda]", file); fputs("[lambda]", file);
// else if (node->value.function.type == Function_Type::Special_Lambda)
// else if (node->value.function->type == Function_Type::Special_Lambda)
// fputs("[special-lambda]", file); // fputs("[special-lambda]", file);
else if (node->value.function.type == Function_Type::Macro)
else if (node->value.function->type == Function_Type::Macro)
fputs("[macro]", file); fputs("[macro]", file);
else else
assert(false); assert(false);
@@ -372,33 +369,33 @@ proc print(Lisp_Object* node, bool print_repr, FILE* file) -> void {


// first check if it is a quotation form, in that case we want // first check if it is a quotation form, in that case we want
// to print it prettier // to print it prettier
if (Memory::get_type(head->value.pair.first) == Lisp_Object_Type::Symbol) {
String* identifier = head->value.pair.first->value.symbol.identifier;
auto symbol = head->value.pair.first;
auto quote_sym = Memory::get_or_create_lisp_object_symbol("quote");
auto unquote_sym = Memory::get_or_create_lisp_object_symbol("unquote");
auto quasiquote_sym = Memory::get_or_create_lisp_object_symbol("quasiquote");
if (symbol == quote_sym || symbol == unquote_sym)
{
putc(symbol == quote_sym
? '\''
: ',', file);
assert_type(head->value.pair.rest, Lisp_Object_Type::Pair);
assert(head->value.pair.rest->value.pair.rest == Memory::nil);
print(head->value.pair.rest->value.pair.first, print_repr, file);
break;
}
else if (symbol == quasiquote_sym) {
putc('`', file);
assert_type(head->value.pair.rest, Lisp_Object_Type::Pair);
print(head->value.pair.rest->value.pair.first, print_repr, file);
break;
}
}
// if (Memory::get_type(head->value.pair.first) == Lisp_Object_Type::Symbol) {
// String* identifier = head->value.pair.first->value.symbol.identifier;
// auto symbol = head->value.pair.first;
// auto quote_sym = Memory::get_or_create_lisp_object_symbol("quote");
// auto unquote_sym = Memory::get_or_create_lisp_object_symbol("unquote");
// auto quasiquote_sym = Memory::get_or_create_lisp_object_symbol("quasiquote");
// if (symbol == quote_sym || symbol == unquote_sym)
// {
// putc(symbol == quote_sym
// ? '\''
// : ',', file);
// assert_type(head->value.pair.rest, Lisp_Object_Type::Pair);
// assert(head->value.pair.rest->value.pair.rest == Memory::nil);
// print(head->value.pair.rest->value.pair.first, print_repr, file);
// break;
// }
// else if (symbol == quasiquote_sym) {
// putc('`', file);
// assert_type(head->value.pair.rest, Lisp_Object_Type::Pair);
// print(head->value.pair.rest->value.pair.first, print_repr, file);
// break;
// }
// }


putc('(', file); putc('(', file);




+ 4
- 3
src/libslime.cpp View File

@@ -3,7 +3,6 @@


#define _CRTDBG_MAP_ALLOC #define _CRTDBG_MAP_ALLOC
#include <stdlib.h> #include <stdlib.h>
#include <crtdbg.h>


#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
@@ -11,12 +10,14 @@
#include <cmath> #include <cmath>
#include <ctype.h> #include <ctype.h>
#include <stdarg.h> #include <stdarg.h>
#include <functional>
#include <errno.h>
#include <new>
// #include <functional>


#ifdef _MSC_VER #ifdef _MSC_VER
# include <crtdbg.h>
# include <direct.h> # include <direct.h>
# include <windows.h> # include <windows.h>

#else #else
# include <unistd.h> # include <unistd.h>
# include <signal.h> # include <signal.h>


+ 19
- 1
src/lisp_object.cpp View File

@@ -41,7 +41,25 @@ proc append_to_keyword_argument_list(Keyword_Arguments* args,
} }


Lisp_Object::~Lisp_Object() { Lisp_Object::~Lisp_Object() {
if (Memory::get_type(this) == Lisp_Object_Type::HashMap) {
free(sourceCodeLocation);
sourceCodeLocation = 0;

switch (Memory::get_type(this)) {
case Lisp_Object_Type::HashMap: {
this->value.hashMap.~Hash_Map(); this->value.hashMap.~Hash_Map();
} break;
case Lisp_Object_Type::CFunction: {
this->value.cFunction->args.positional.symbols.~Array_List();
this->value.cFunction->args.keyword.keywords.~Array_List();
this->value.cFunction->args.keyword.values.~Array_List();
delete this->value.cFunction;
} break;
case Lisp_Object_Type::Function:{
this->value.function->args.positional.symbols.~Array_List();
this->value.function->args.keyword.keywords.~Array_List();
this->value.function->args.keyword.values.~Array_List();
delete this->value.function;
} break;
default: break;
} }
} }

+ 3
- 2
src/main.cpp View File

@@ -1,13 +1,14 @@
#include "libslime.cpp" #include "libslime.cpp"



int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if (argc > 1) { if (argc > 1) {
if (Slime::string_equal(argv[1], "--run-tests")) { if (Slime::string_equal(argv[1], "--run-tests")) {
int res = Slime::run_all_tests(); int res = Slime::run_all_tests();
Slime::Memory::free_everything();
// Slime::interprete_file((char*)"generate-docs.slime"); // Slime::interprete_file((char*)"generate-docs.slime");
#ifdef _MSC_VER
_CrtDumpMemoryLeaks(); _CrtDumpMemoryLeaks();
#endif
return res ? 0 : 1; return res ? 0 : 1;
} }




+ 34
- 15
src/memory.cpp View File

@@ -11,12 +11,12 @@ namespace Memory {
// ------------------ // ------------------
// lisp_objects // lisp_objects
// ------------------ // ------------------
Bucket_Allocator<Lisp_Object, 1024> object_memory;
Bucket_Allocator<Lisp_Object> object_memory(1024, 8);


// ------------------ // ------------------
// environments // environments
// ------------------ // ------------------
Bucket_Allocator<Environment, 1024> environment_memory;
Bucket_Allocator<Environment> environment_memory(1024, 8);


// ------------------ // ------------------
// strings // strings
@@ -146,6 +146,12 @@ namespace Memory {


proc free_everything() -> void { proc free_everything() -> void {
free(string_memory); free(string_memory);
object_memory.for_each([](Lisp_Object* lo){
lo->~Lisp_Object();
});
environment_memory.for_each([](Environment* env){
env->~Environment();
});
} }


proc init(int sms) -> void { proc init(int sms) -> void {
@@ -183,18 +189,24 @@ namespace Memory {
global_keyword_table.~Hash_Map(); global_keyword_table.~Hash_Map();
file_to_env_map.~Hash_Map(); file_to_env_map.~Hash_Map();


::new(&global_symbol_table) Hash_Map<char*, Lisp_Object*>;
::new(&global_keyword_table) Hash_Map<char*, Lisp_Object*>;
::new(&file_to_env_map) Hash_Map<char*, Lisp_Object*>;
new(&global_symbol_table) Hash_Map<char*, Lisp_Object*>;
new(&global_keyword_table) Hash_Map<char*, Lisp_Object*>;
new(&file_to_env_map) Hash_Map<char*, Lisp_Object*>;


try_void Parser::standard_in = create_string("stdin"); try_void Parser::standard_in = create_string("stdin");


object_memory.for_each([](Lisp_Object* lo){
lo->~Lisp_Object();
});
environment_memory.for_each([](Environment* env){
env->~Environment();
});


object_memory.~Bucket_Allocator(); object_memory.~Bucket_Allocator();
// environment_memory.~Bucket_Allocator();
environment_memory.~Bucket_Allocator();


::new(&object_memory) Bucket_Allocator<Lisp_Object, 1024>;
::new(&environment_memory) Bucket_Allocator<Environment, 1024>;
::new(&object_memory) Bucket_Allocator<Lisp_Object>(1024, 8);
::new(&environment_memory) Bucket_Allocator<Environment>(1024, 8);


next_free_spot_in_string_memory = string_memory; next_free_spot_in_string_memory = string_memory;


@@ -342,16 +354,20 @@ namespace Memory {
Lisp_Object* node; Lisp_Object* node;
try node = create_lisp_object(); try node = create_lisp_object();
set_type(node, Lisp_Object_Type::CFunction); set_type(node, Lisp_Object_Type::CFunction);
// node->value.lambdaWrapper = new Lambda_Wrapper(function);
node->value.cFunction = new(cFunction);
node->value.cFunction->args = {};
new((&node->value.cFunction->args.positional.symbols)) Array_List<Environment*>(16);
new((&node->value.cFunction->args.keyword.keywords)) Array_List<Environment*>(16);
new((&node->value.cFunction->args.keyword.values)) Array_List<Environment*>(16);
node->value.cFunction = new cFunction;
node->value.cFunction->is_special_form = is_special; node->value.cFunction->is_special_form = is_special;
return node; return node;
} }


proc create_lisp_object_function(Function_Type ft) -> Lisp_Object* {
Lisp_Object* func;
try func = Memory::create_lisp_object();
Memory::set_type(func, Lisp_Object_Type::Function);
func->value.function = new Function;
func->value.function->type = ft;
return func;
}

proc create_lisp_object_pair(Lisp_Object* first, Lisp_Object* rest) -> Lisp_Object* { proc create_lisp_object_pair(Lisp_Object* first, Lisp_Object* rest) -> Lisp_Object* {
Lisp_Object* node; Lisp_Object* node;
try node = create_lisp_object(); try node = create_lisp_object();
@@ -368,7 +384,9 @@ namespace Memory {
// we don't copy singleton objects // we don't copy singleton objects
if (n == Memory::nil || n == Memory::t || if (n == Memory::nil || n == Memory::t ||
Memory::get_type(n) == Lisp_Object_Type::Symbol || Memory::get_type(n) == Lisp_Object_Type::Symbol ||
Memory::get_type(n) == Lisp_Object_Type::Keyword)
Memory::get_type(n) == Lisp_Object_Type::Keyword ||
Memory::get_type(n) == Lisp_Object_Type::Function ||
Memory::get_type(n) == Lisp_Object_Type::CFunction)
{ {
return n; return n;
} }
@@ -376,6 +394,7 @@ namespace Memory {
Lisp_Object* target; Lisp_Object* target;
try target = create_lisp_object(); try target = create_lisp_object();
*target = *n; *target = *n;

return target; return target;
} }




+ 17
- 14
src/parse.cpp View File

@@ -31,7 +31,7 @@ namespace Parser {
} }


proc inject_scl(Lisp_Object* lo) -> void { proc inject_scl(Lisp_Object* lo) -> void {
lo->sourceCodeLocation = new(Source_Code_Location);
lo->sourceCodeLocation = (Source_Code_Location*)malloc(sizeof(Source_Code_Location));
lo->sourceCodeLocation->file = parser_file; lo->sourceCodeLocation->file = parser_file;
lo->sourceCodeLocation->line = parser_line; lo->sourceCodeLocation->line = parser_line;
lo->sourceCodeLocation->column = parser_col; lo->sourceCodeLocation->column = parser_col;
@@ -65,7 +65,6 @@ namespace Parser {
++parser_col; ++parser_col;
++(*index_in_text); ++(*index_in_text);
} }

} }


proc eat_until_code(char* text, int* index_in_text) -> void { proc eat_until_code(char* text, int* index_in_text) -> void {
@@ -120,7 +119,7 @@ namespace Parser {
Lisp_Object* ret; Lisp_Object* ret;
try ret = Memory::create_lisp_object_number(number); try ret = Memory::create_lisp_object_number(number);


inject_scl(ret);
// inject_scl(ret);
return ret; return ret;
} }


@@ -132,7 +131,7 @@ namespace Parser {
Lisp_Object* ret; Lisp_Object* ret;
try ret = Memory::get_or_create_lisp_object_keyword(str_keyword); try ret = Memory::get_or_create_lisp_object_keyword(str_keyword);


inject_scl(ret);
// inject_scl(ret);
return ret; return ret;
} }


@@ -142,7 +141,7 @@ namespace Parser {
Lisp_Object* ret; Lisp_Object* ret;
try ret = Memory::get_or_create_lisp_object_symbol(str_symbol); try ret = Memory::get_or_create_lisp_object_symbol(str_symbol);


inject_scl(ret);
// inject_scl(ret);
return ret; return ret;
} }


@@ -157,7 +156,7 @@ namespace Parser {
Lisp_Object* ret; Lisp_Object* ret;
try ret = Memory::create_lisp_object_string( try ret = Memory::create_lisp_object_string(
Memory::create_string("", 0)); Memory::create_string("", 0));
inject_scl(ret);
// inject_scl(ret);


// plus one because we want to go after the quotes // plus one because we want to go after the quotes
*index_in_text += 1; *index_in_text += 1;
@@ -169,10 +168,10 @@ namespace Parser {
// okay so the first letter was not actually closing the string... // okay so the first letter was not actually closing the string...
int string_length = 0; int string_length = 0;
bool escaping = false; bool escaping = false;
while (!(text[*index_in_text+string_length] == '"' && !escaping))
{
if (escaping)
while (escaping || text[*index_in_text+string_length] != '"') {
if (escaping) {
escaping = false; escaping = false;
}
else else
if (text[*index_in_text+string_length] == '\\') if (text[*index_in_text+string_length] == '\\')
escaping = true; escaping = true;
@@ -186,9 +185,10 @@ namespace Parser {
// NOTE(Felix): Tactic: Through unescaping the string will // NOTE(Felix): Tactic: Through unescaping the string will
// only get shorter, so we replace it inplace and later jump // only get shorter, so we replace it inplace and later jump
// to the original end of the string. // to the original end of the string.
try unescape_string(text+(*index_in_text));
int new_len;
try new_len = unescape_string(text+(*index_in_text));


String* string = Memory::create_string("", string_length);
String* string = Memory::create_string("", new_len);


// TODO(Felix): manually copy to parse control sequences // TODO(Felix): manually copy to parse control sequences
// correctly without the need to unescape the string, also // correctly without the need to unescape the string, also
@@ -196,6 +196,7 @@ namespace Parser {
// characters since last new line so we can update the parser // characters since last new line so we can update the parser
// location more easily // location more easily
strcpy(&string->data, text+(*index_in_text)); strcpy(&string->data, text+(*index_in_text));
// printf("------ %s\n", &string->data);


text[*index_in_text+string_length] = '"'; text[*index_in_text+string_length] = '"';


@@ -218,7 +219,7 @@ namespace Parser {
Lisp_Object* ret; Lisp_Object* ret;
try ret = Memory::create_lisp_object_string(string); try ret = Memory::create_lisp_object_string(string);


inject_scl(ret);
// inject_scl(ret);
return ret; return ret;
} }


@@ -285,7 +286,8 @@ namespace Parser {
try ret = Memory::create_list(Memory::get_or_create_lisp_object_symbol("unquote-splicing"), result); try ret = Memory::create_list(Memory::get_or_create_lisp_object_symbol("unquote-splicing"), result);
} }


if (ret) inject_scl(ret);
// if (ret && ret != Memory::nil && ret != Memory::t)
// inject_scl(ret);


return ret; return ret;
} }
@@ -313,7 +315,7 @@ namespace Parser {
Lisp_Object* expression = head; Lisp_Object* expression = head;


while (true) { while (true) {
inject_scl(head);
// inject_scl(head);
if (text[*index_in_text] == '(' || if (text[*index_in_text] == '(' ||
text[*index_in_text] == '\''|| text[*index_in_text] == '\''||
text[*index_in_text] == '`' || text[*index_in_text] == '`' ||
@@ -363,6 +365,7 @@ namespace Parser {
} else { } else {
try head->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil); try head->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
head = head->value.pair.rest; head = head->value.pair.rest;
// inject_scl(head);
} }
} }
return expression; return expression;


+ 2
- 2
src/structs.cpp View File

@@ -118,7 +118,7 @@ struct Function {
}; };


struct cFunction { struct cFunction {
std::function<Lisp_Object* ()> body;
Lisp_Object* (*body)();
Arguments args; Arguments args;
bool is_special_form; bool is_special_form;
}; };
@@ -134,7 +134,7 @@ struct Lisp_Object {
String* string; String* string;
Pair pair; Pair pair;
Vector vector; Vector vector;
Function function;
Function* function;
cFunction* cFunction; cFunction* cFunction;
void* pointer; void* pointer;
Continuation continuation; Continuation continuation;


+ 1
- 1
src/testing.cpp View File

@@ -656,7 +656,7 @@ proc run_all_tests() -> bool {
invoke_test_script("hashmaps"); invoke_test_script("hashmaps");
invoke_test_script("singular_imports"); invoke_test_script("singular_imports");


// Memory::print_status();
// // Memory::print_status();


return result; return result;
} }


Loading…
Cancel
Save