This commit is contained in:
FelixBrendel
2018-10-23 08:27:42 +02:00
parent ce28d94a9a
commit 65b97fe535
3 changed files with 71 additions and 52 deletions
+52 -16
View File
@@ -1,5 +1,37 @@
(define nil ()) (define nil ())
(define pe
(macro (expr)
(print expr)
(print " evaluates to -> ")
(print (eval expr))
(print "
")
nil))
(define apply
(lambda (fun seq)
(eval (pair fun seq))))
(define defun
(macro (name params :rest body)
(printf "name" params "params" params "body" body)
(define name
(lambda (params) body))))
(define when
(macro (test :rest body)
(if (eval test)
(apply prog body)
nil)))
(define unless
(macro (test :rest body)
(if (eval test)
nil
(apply prog body))))
(define nil? (define nil?
(lambda (x) (lambda (x)
"Checks if the argument is nil." "Checks if the argument is nil."
@@ -41,14 +73,14 @@ defined by the key 'from' and ends with the number defined in
nil))) nil)))
(define map (define map
(lambda (function sequence) (lambda (fun seq)
"Takes a sequence and a function as arguments and returns a "Takes a sequence and a function as arguments and returns a
new sequence which contains the results of using the first new sequence which contains the results of using the first
sequences elemens as argument to that function." sequences elemens as argument to that function."
(if (nil? sequence) (if (nil? seq)
sequence seq
(pair (function (first sequence)) (pair (fun (first seq))
(map (rest sequence) function))))) (map fun (rest seq))))))
(define reduce (define reduce
(lambda (function sequence) (lambda (function sequence)
@@ -56,7 +88,7 @@ sequences elemens as argument to that function."
function to the argument sequence. This only works correctly if the function to the argument sequence. This only works correctly if the
given function accepts a variable amount of parameters. If your given function accepts a variable amount of parameters. If your
funciton is limited to two arguments, use `reduce-binary' instead." funciton is limited to two arguments, use `reduce-binary' instead."
(eval (pair function sequence)))) (apply function sequence)))
(define reduce-binary (define reduce-binary
(lambda (function sequence) (lambda (function sequence)
@@ -78,15 +110,19 @@ as compared to `reduce'."
(filter (rest sequence) function)) (filter (rest sequence) function))
(filter (rest sequence) function))))) (filter (rest sequence) function)))))
(define printf (define printf-quoted
(lambda (:keys sep :defaults-to " " end :defaults-to "\n" :rest args) (macro (:keys sep :defaults-to " " end :defaults-to "\n" :rest args)
(if (and (nil? (first args)) (nil? (rest args))) (if (nil? args)
(print end) (prog (print (eval end)) nil)
(prog (prog
(print (first args)) (print (first args))
(if (not (nil? (rest args))) (when (not (nil? (rest args))) (print (eval sep)))
(print sep)) (define command-args (list :sep (eval sep) :end (eval end)))
;; TODO(Felix): later we should use `extend' here: (append command-args (rest args))
;; (eval (extend (quote (printf :sep sep :end end)) (rest args))) (apply printf-quoted command-args)))))
(eval (extend '(printf :sep sep :end end) (rest args)))
nil)))) (define printf
(lambda (:keys sep :defaults-to " " end :defaults-to "\n" :rest args)
(define command-args (list :sep (eval sep) :end (eval end)))
(append command-args args)
(apply printf-quoted command-args)))
+4
View File
@@ -97,6 +97,7 @@ void append_to_keyword_argument_list(Keyword_Arguments* args,
typedef struct { typedef struct {
bool is_macro;
char* docstring; char* docstring;
Positional_Arguments* positional_arguments; Positional_Arguments* positional_arguments;
Keyword_Arguments* keyword_arguments; Keyword_Arguments* keyword_arguments;
@@ -126,6 +127,7 @@ typedef enum {
Built_In_Define, Built_In_Define,
Built_In_Mutate, Built_In_Mutate,
Built_In_Lambda, Built_In_Lambda,
Built_In_Macro,
Built_In_Eval, Built_In_Eval,
Built_In_Quote, Built_In_Quote,
Built_In_Prog, Built_In_Prog,
@@ -159,6 +161,7 @@ char* Built_In_Name_to_string(Built_In_Name name) {
case Built_In_Less_Equal: return "<="; case Built_In_Less_Equal: return "<=";
case Built_In_List: return "list"; case Built_In_List: return "list";
case Built_In_Load: return "load"; case Built_In_Load: return "load";
case Built_In_Macro: return "macro";
case Built_In_Multiplication: return "*"; case Built_In_Multiplication: return "*";
case Built_In_Mutate: return "mutate"; case Built_In_Mutate: return "mutate";
case Built_In_Not: return "not"; case Built_In_Not: return "not";
@@ -265,6 +268,7 @@ Ast_Node* create_ast_node_built_in_function(char* name) {
else if (string_equal(name, "define")) type = Built_In_Define; else if (string_equal(name, "define")) type = Built_In_Define;
else if (string_equal(name, "mutate")) type = Built_In_Mutate; else if (string_equal(name, "mutate")) type = Built_In_Mutate;
else if (string_equal(name, "lambda")) type = Built_In_Lambda; else if (string_equal(name, "lambda")) type = Built_In_Lambda;
else if (string_equal(name, "macro")) type = Built_In_Macro;
else if (string_equal(name, "eval")) type = Built_In_Eval; else if (string_equal(name, "eval")) type = Built_In_Eval;
else if (string_equal(name, "quote")) type = Built_In_Quote; else if (string_equal(name, "quote")) type = Built_In_Quote;
else if (string_equal(name, "prog")) type = Built_In_Prog; else if (string_equal(name, "prog")) type = Built_In_Prog;
+13 -34
View File
@@ -308,37 +308,6 @@ int list_length(Ast_Node* node) {
return 0; return 0;
} }
/**
Copies a list, in that it creates a new list, however the items are
the same as in the original (same pointers). This is needed to copy
a list when evaluating a parameters list, but not wanting to change
the parameters list. This happens if you have someting like:
(define a 10)
(define condition (quote (= a 10)))
(eval condition)
> 1.00000
If we wouldn't copy the parameters list, after calling eval would
be baked into the quoted list. So even after changing a, the result
of (eval condition) would be 1.00000.
**/
/* Ast_Node* copy_list(Ast_Node* node) { */
/* // we don't copy immutables in here */
/* if (node->type != Ast_Node_Type_Pair) { */
/* return node; */
/* } */
/* Ast_Node* result = new(Ast_Node); */
/* result->type = Ast_Node_Type_Pair; */
/* result->value.pair = new(Pair); */
/* result->value.pair->first = copy_list(node->value.pair->first); */
/* result->value.pair->rest = copy_list(node->value.pair->rest); */
/* return result; */
/* } */
bool is_truthy (Ast_Node* expression, Environment* env); bool is_truthy (Ast_Node* expression, Environment* env);
Ast_Node* extract_keyword_value(char* keyword, Parsed_Arguments* args) { Ast_Node* extract_keyword_value(char* keyword, Parsed_Arguments* args) {
@@ -385,6 +354,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
create_error(_type, node); \ create_error(_type, node); \
return nullptr; \ return nullptr; \
} }
if (error) if (error)
return nullptr; return nullptr;
@@ -422,6 +392,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
// check for special form // check for special form
if (operator->type == Ast_Node_Type_Built_In_Function) { if (operator->type == Ast_Node_Type_Built_In_Function) {
switch (operator->value.built_in_function->type) { switch (operator->value.built_in_function->type) {
case Built_In_Macro:
case Built_In_Lambda: { case Built_In_Lambda: {
/* /*
* (lambda ()) * (lambda ())
@@ -435,6 +406,12 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
Function* function = new(Function); Function* function = new(Function);
if (operator->value.built_in_function->type == Built_In_Macro) {
function->is_macro = true;
} else {
function->is_macro = false;
}
// if parameters were specified // if parameters were specified
if (arguments->value.pair->first->type != Ast_Node_Type_Nil) { if (arguments->value.pair->first->type != Ast_Node_Type_Nil) {
try { try {
@@ -739,10 +716,14 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
} }
// assume it's lambda function and evaluate the arguments // assume it's lambda function and evaluate the arguments
if (operator->type == Ast_Node_Type_Function) {
if (!operator->value.function->is_macro) {
try { try {
arguments = eval_arguments(arguments, env, &arguments_length); arguments = eval_arguments(arguments, env, &arguments_length);
} }
if (operator->type == Ast_Node_Type_Function) { }
Ast_Node* result; Ast_Node* result;
try { try {
result = apply_arguments_to_function(arguments, operator->value.function, env); result = apply_arguments_to_function(arguments, operator->value.function, env);
@@ -750,9 +731,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
return result; return result;
} }
} }
default: { default: {
printf("wtf???????????");
report_error(Error_Type_Not_A_Function); report_error(Error_Type_Not_A_Function);
} }
} }