Bläddra i källkod

macros

master
FelixBrendel 7 år sedan
förälder
incheckning
65b97fe535
3 ändrade filer med 71 tillägg och 52 borttagningar
  1. +52
    -16
      bin/pre.slime
  2. +4
    -0
      src/ast.c
  3. +15
    -36
      src/eval.c

+ 52
- 16
bin/pre.slime Visa fil

@@ -1,5 +1,37 @@
(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?
(lambda (x)
"Checks if the argument is nil."
@@ -41,14 +73,14 @@ defined by the key 'from' and ends with the number defined in
nil)))

(define map
(lambda (function sequence)
(lambda (fun seq)
"Takes a sequence and a function as arguments and returns a
new sequence which contains the results of using the first
sequences elemens as argument to that function."
(if (nil? sequence)
sequence
(pair (function (first sequence))
(map (rest sequence) function)))))
(if (nil? seq)
seq
(pair (fun (first seq))
(map fun (rest seq))))))

(define reduce
(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
given function accepts a variable amount of parameters. If your
funciton is limited to two arguments, use `reduce-binary' instead."
(eval (pair function sequence))))
(apply function sequence)))

(define reduce-binary
(lambda (function sequence)
@@ -78,15 +110,19 @@ as compared to `reduce'."
(filter (rest sequence) function))
(filter (rest sequence) function)))))

(define printf
(lambda (:keys sep :defaults-to " " end :defaults-to "\n" :rest args)
(if (and (nil? (first args)) (nil? (rest args)))
(print end)
(define printf-quoted
(macro (:keys sep :defaults-to " " end :defaults-to "\n" :rest args)
(if (nil? args)
(prog (print (eval end)) nil)
(prog
(print (first args))
(if (not (nil? (rest args)))
(print sep))
;; TODO(Felix): later we should use `extend' here:
;; (eval (extend (quote (printf :sep sep :end end)) (rest args)))
(eval (extend '(printf :sep sep :end end) (rest args)))
nil))))
(when (not (nil? (rest args))) (print (eval sep)))
(define command-args (list :sep (eval sep) :end (eval end)))
(append command-args (rest args))
(apply printf-quoted command-args)))))

(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
- 0
src/ast.c Visa fil

@@ -97,6 +97,7 @@ void append_to_keyword_argument_list(Keyword_Arguments* args,


typedef struct {
bool is_macro;
char* docstring;
Positional_Arguments* positional_arguments;
Keyword_Arguments* keyword_arguments;
@@ -126,6 +127,7 @@ typedef enum {
Built_In_Define,
Built_In_Mutate,
Built_In_Lambda,
Built_In_Macro,
Built_In_Eval,
Built_In_Quote,
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_List: return "list";
case Built_In_Load: return "load";
case Built_In_Macro: return "macro";
case Built_In_Multiplication: return "*";
case Built_In_Mutate: return "mutate";
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, "mutate")) type = Built_In_Mutate;
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, "quote")) type = Built_In_Quote;
else if (string_equal(name, "prog")) type = Built_In_Prog;


+ 15
- 36
src/eval.c Visa fil

@@ -308,37 +308,6 @@ int list_length(Ast_Node* node) {
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);

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); \
return nullptr; \
}
if (error)
return nullptr;

@@ -422,6 +392,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
// check for special form
if (operator->type == Ast_Node_Type_Built_In_Function) {
switch (operator->value.built_in_function->type) {
case Built_In_Macro:
case Built_In_Lambda: {
/*
* (lambda ())
@@ -435,6 +406,12 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {


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 (arguments->value.pair->first->type != Ast_Node_Type_Nil) {
try {
@@ -739,10 +716,14 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
}

// assume it's lambda function and evaluate the arguments
try {
arguments = eval_arguments(arguments, env, &arguments_length);
}

if (operator->type == Ast_Node_Type_Function) {
if (!operator->value.function->is_macro) {
try {
arguments = eval_arguments(arguments, env, &arguments_length);
}
}

Ast_Node* result;
try {
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;
}
}

default: {
printf("wtf???????????");
report_error(Error_Type_Not_A_Function);
}
}


Laddar…
Avbryt
Spara