#define concat_( a, b) a##b #define label(prefix, lnum) concat_(prefix,lnum) #define log_location() \ do { \ if (Globals::log_level == Log_Level::Debug) { \ printf("in"); \ int spacing = 30-(int)strlen(__FILE__); \ if (spacing < 1) spacing = 1; \ for (int i = 0; i < spacing;++i) \ printf(" "); \ printf("%s (%d) ", __FILE__, __LINE__); \ printf("-> %s\n",__FUNCTION__); \ } \ } while(0) #define if_error_log_location_and_return() \ do { \ if (Globals::error) { \ log_location(); \ return; \ } \ } while(0) #ifdef _DEBUG #define try_or_else_return(val) \ if (1) \ goto label(body,__LINE__); \ else \ while (1) \ if (1) { \ if (Globals::error) { \ log_location(); \ return val; \ } \ break; \ } \ else label(body,__LINE__): ; #else #define try_or_else_return(val) #endif #define try_struct try_or_else_return({}) #define try_void try_or_else_return() #define try try_or_else_return(0) #define dont_break_on_errors fluid_let(Globals::breaking_on_errors, false) #define ignore_logging fluid_let(Globals::log_level, Log_Level::None) #define fetch1(var) \ Lisp_Object* var##_symbol = Memory::get_or_create_lisp_object_symbol(#var); \ Lisp_Object* var = lookup_symbol(var##_symbol, get_current_environment()); \ if (Globals::error) printf("in %s:%d\n", __FILE__, __LINE__) #define fetch2(var1, var2) fetch1(var1); fetch1(var2) #define fetch3(var1, var2, var3) fetch2(var1, var2); fetch1(var3) #define fetch4(var1, var2, var3, var4) fetch3(var1, var2, var3); fetch1(var4) #define fetch5(var1, var2, var3, var4, var5) fetch4(var1, var2, var3, var4); fetch1(var5) #define fetch6(var1, var2, var3, var4, var5, var6) fetch5(var1, var2, var3, var4, var5); fetch1(var6) #define fetch7(var1, var2, var3, var4, var5, var6, var7) fetch6(var1, var2, var3, var4, var5, var6); fetch1(var7) #define fetch8(var1, var2, var3, var4, var5, var6, var7, var8) fetch7(var1, var2, var3, var4, var5, var6, var7); fetch1(var8) #define fetch9(var1, var2, var3, var4, var5, var6, var7, var8, var9) fetch8(var1, var2, var3, var4, var5, var6, var7, var8); fetch1(var9) #define fetch10(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10) fetch9(var1, var2, var3, var4, var5, var6, var7, var8, var9); fetch1(var10) #define fetch11(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11) fetch10(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10); fetch1(var11) #define fetch12(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12) fetch11(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11); fetch1(var12) #define fetch13(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13) fetch12(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12); fetch1(var13) #define fetch14(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14) fetch13(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13); fetch1(var14) #define fetch15(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15) fetch14(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14); fetch1(var15) #define fetch16(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16) fetch15(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15); fetch1(var16) #define fetch17(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17) fetch16(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16); fetch1(var17) #define fetch18(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18) fetch17(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17); fetch1(var18) #define fetch19(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18, var19) fetch18(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18); fetch1(var19) #define fetch20(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18, var19, var20) fetch19(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18, var19); fetch1(var20) #define fetch21(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18, var19, var20, var21) fetch20(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18, var19, var20); fetch1(var21) #define fetch22(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18, var19, var20, var21, var22) fetch21(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18, var19, var20, var21); fetch1(var22) #define fetch23(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18, var19, var20, var21, var22, var23) fetch22(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18, var19, var20, var21, var22); fetch1(var23) #define fetch24(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18, var19, var20, var21, var22, var23, var24) fetch23(var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18, var19, var20, var21, var22, var23); fetch1(var24) #define GET_MACRO( \ _1, _2, _3, _4, _5, _6, \ _7, _8, _9, _10, _11, _12, \ _13, _14, _15, _16, _17, _18, \ _19, _20, _21, _22, _23, _24, \ NAME, ...) NAME #ifdef _MSC_VER #define EXPAND( x ) x #define fetch(...) EXPAND( \ GET_MACRO( \ __VA_ARGS__, \ fetch24, fetch23, fetch22, fetch21, fetch20, fetch19, \ fetch18, fetch17, fetch16, fetch15, fetch14, fetch13, \ fetch12, fetch11, fetch10, fetch9, fetch8, fetch7, \ fetch6, fetch5, fetch4, fetch3, fetch2, fetch1 \ )(__VA_ARGS__)) #else #define fetch(...) \ GET_MACRO( \ __VA_ARGS__, \ fetch24, fetch23, fetch22, fetch21, fetch20, fetch19, \ fetch18, fetch17, fetch16, fetch15, fetch14, fetch13, \ fetch12, fetch11, fetch10, fetch9, fetch8, fetch7, \ fetch6, fetch5, fetch4, fetch3, fetch2, fetch1 \ )(__VA_ARGS__) #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 and also it will fill // out the source code location #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( \ Memory::get_c_str(Memory::create_string(#def))); \ if_error_log_location_and_return(); \ assert_type(label(params,__LINE__), Lisp_Object_Type::Pair); \ assert_type(label(params,__LINE__)->value.pair.first, Lisp_Object_Type::Symbol); \ auto label(sym,__LINE__) = label(params,__LINE__)->value.pair.first; \ 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__)); \ if_error_log_location_and_return(); \ label(sfun,__LINE__)->docstring = Memory::create_string(docs); \ define_symbol(label(sym,__LINE__), label(sfun,__LINE__)); \ label(sfun,__LINE__)->value.cFunction->body = []() -> Lisp_Object* #define define(def, docs) _define_helper(def, docs, false) #define define_special(def, docs) _define_helper(def, docs, true) #define in_caller_env fluid_let( \ Globals::Current_Execution::envi_stack.next_index, \ Globals::Current_Execution::envi_stack.next_index-1) /* * iterate over lisp vectors */ #define for_lisp_vector(v) \ if (!v); else \ if (int it_index = 0); else \ for (auto it = v->value.vector.data; \ it_index < v->value.vector.length; \ it=v->value.vector.data+(++it_index)) /* * iterate over lisp lists */ #define for_lisp_list(l) \ if (!l); else \ if (int it_index = 0); else \ for (Lisp_Object* head = l, *it; \ Memory::get_type(head) == Lisp_Object_Type::Pair && (it = head->value.pair.first); \ head = head->value.pair.rest, ++it_index)