| @@ -124,6 +124,17 @@ by the key 'from' and ends with the number defined in 'to'." | |||
| (when (< from to) | |||
| (pair from (range :from (+ 1 from) :to to)))) | |||
| (defun range-while (:keys from :defaults-to 0 to) | |||
| "Returns a sequence of numbers starting with the number defined | |||
| by the key 'from' and ends with the number defined in 'to'." | |||
| (define result (list from)) | |||
| (mutate from (incr from)) | |||
| (while (< from to) | |||
| (prog | |||
| (append result (copy from)) | |||
| (mutate from (incr from)))) | |||
| result) | |||
| (defun map (fun seq) | |||
| "Takes a function and a sequence as arguments and returns a new | |||
| sequence which contains the results of using the first sequences | |||
| @@ -156,6 +156,7 @@ typedef enum { | |||
| Built_In_Read, | |||
| Built_In_Rest, | |||
| Built_In_Subtraction, | |||
| Built_In_Try, | |||
| Built_In_Type, | |||
| Built_In_While, | |||
| } Built_In_Name; | |||
| @@ -198,6 +199,7 @@ char* Built_In_Name_to_string(Built_In_Name name) { | |||
| case Built_In_Read: return "read"; | |||
| case Built_In_Rest: return "rest"; | |||
| case Built_In_Subtraction: return "-"; | |||
| case Built_In_Try: return "try"; | |||
| case Built_In_Type: return "type"; | |||
| case Built_In_While: return "while"; | |||
| } | |||
| @@ -315,6 +317,7 @@ Ast_Node* create_ast_node_built_in_function(char* name) { | |||
| else if (string_equal(name, "quote")) type = Built_In_Quote; | |||
| else if (string_equal(name, "read")) type = Built_In_Read; | |||
| else if (string_equal(name, "rest")) type = Built_In_Rest; | |||
| else if (string_equal(name, "try")) type = Built_In_Try; | |||
| else if (string_equal(name, "type")) type = Built_In_Type; | |||
| else if (string_equal(name, "while")) type = Built_In_While; | |||
| else return nullptr; | |||
| @@ -640,11 +640,21 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { | |||
| if (arguments_length < 2) { | |||
| report_error(Error_Type_Wrong_Number_Of_Arguments); | |||
| } | |||
| Ast_Node* condition = arguments->value.pair->first; | |||
| Ast_Node* condition_part = arguments->value.pair->first; | |||
| Ast_Node* condition; | |||
| Ast_Node* then_part = arguments->value.pair->rest; | |||
| Ast_Node* result = create_ast_node_nil(); | |||
| while (eval_expr(condition, env)->type != Ast_Node_Type_Nil) { | |||
| result = eval_expr(then_part->value.pair->first, env); | |||
| while (true) { | |||
| try { | |||
| condition = eval_expr(condition_part, env); | |||
| } | |||
| if (condition->type == Ast_Node_Type_Nil) { | |||
| break; | |||
| } | |||
| try { | |||
| result = eval_expr(then_part->value.pair->first, env); | |||
| } | |||
| } | |||
| return result; | |||
| @@ -684,6 +694,27 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { | |||
| } | |||
| return arguments->value.pair->first; | |||
| } | |||
| case Built_In_Try: { | |||
| try { | |||
| arguments_length = list_length(arguments); | |||
| } | |||
| if (arguments_length != 2) { | |||
| report_error(Error_Type_Wrong_Number_Of_Arguments); | |||
| } | |||
| Ast_Node* try_part = arguments->value.pair->first; | |||
| Ast_Node* catch_part = arguments->value.pair->rest->value.pair->first; | |||
| Ast_Node* result; | |||
| result = eval_expr(try_part, env); | |||
| if (error) { | |||
| delete_error(); | |||
| try { | |||
| result = eval_expr(catch_part, env); | |||
| } | |||
| } | |||
| return result; | |||
| } | |||
| case Built_In_Macro_Define: | |||
| case Built_In_Define: { | |||
| try { | |||