@@ -174,13 +174,13 @@ static Obj *read_list(void *root) {
174174 for (;;) {
175175 * obj = read_expr (root );
176176 if (!* obj )
177- error ("Unclosed parenthesis" , ( * obj ) -> line_num );
177+ error ("Unclosed parenthesis" , filepos . line_num );
178178 if (* obj == Cparen )
179179 return reverse (* head );
180180 if (* obj == Dot ) {
181181 * last = read_expr (root );
182182 if (read_expr (root ) != Cparen )
183- error ("Closed parenthesis expected after dot" , ( * obj ) -> line_num );
183+ error ("Closed parenthesis expected after dot" , filepos . line_num );
184184 Obj * ret = reverse (* head );
185185 (* head )-> cdr = * last ;
186186 return ret ;
@@ -660,77 +660,36 @@ static Obj *prim_reverse(void *root, Obj **env, Obj **list) {
660660 }
661661}
662662
663- // (+ <integer> ...)
664- static Obj * prim_plus (void * root , Obj * * env , Obj * * list ) {
665- long long sum = 0 ;
666- for (Obj * args = eval_list (root , env , list ); args != Nil ; args = args -> cdr ) {
667- if (args -> car -> type != TINT )
668- error ("+ takes only numbers" , (* list )-> line_num );
669- sum += args -> car -> value ;
670- }
671- return make_int (root , sum );
672- }
673-
674- // (* <integer> ...)
675- static Obj * prim_mult (void * root , Obj * * env , Obj * * list ) {
676- long long prod = 1 ;
677- for (Obj * args = eval_list (root , env , list ); args != Nil ; args = args -> cdr ) {
678- if (args -> car -> type != TINT )
679- error ("* takes only numbers" , (* list )-> line_num );
680- prod *= args -> car -> value ;
681- }
682- return make_int (root , prod );
683- }
684-
685- // (/ <integer> ...)
686- static Obj * prim_div (void * root , Obj * * env , Obj * * list ) {
687- Obj * args = eval_list (root , env , list );
688- long long r = args -> car -> value ;
689- for (Obj * p = args -> cdr ; p != Nil ; p = p -> cdr ){
690- if (p -> car -> type != TINT )
691- error ("/ takes only numbers" , (* list )-> line_num );
692- r /= p -> car -> value ;
693- }
694- return make_int (root , r );
663+ #define PRIM_ARITHMETIC_OP (PRIM_OP , OP , OPEQ ) \
664+ static Obj *PRIM_OP(void *root, Obj **env, Obj **list) { \
665+ Obj *args = eval_list(root, env, list); \
666+ long long r = args->car->value; \
667+ for (Obj *p = args->cdr; p != Nil; p = p->cdr) { \
668+ if (p->car->type != TINT) \
669+ error(#OP " takes only numbers", (*list)->line_num); \
670+ r OPEQ p->car->value; \
671+ } \
672+ return make_int(root, r); \
695673}
696674
697- // (% <integer> ...)
698- static Obj * prim_modulo (void * root , Obj * * env , Obj * * list ) {
699- Obj * args = eval_list (root , env , list );
700- long long r = args -> car -> value ;
701- for (Obj * p = args -> cdr ; p != Nil ; p = p -> cdr ){
702- if (p -> car -> type != TINT )
703- error ("mod takes only numbers" , (* list )-> line_num );
704- r %= p -> car -> value ;
705- }
706- return make_int (root , r );
707- }
708-
709- // (- <integer> ...)
710- static Obj * prim_minus (void * root , Obj * * env , Obj * * list ) {
711- Obj * args = eval_list (root , env , list );
712- for (Obj * p = args ; p != Nil ; p = p -> cdr )
713- if (p -> car -> type != TINT )
714- error ("- takes only numbers" , (* list )-> line_num );
715- if (args -> cdr == Nil )
716- return make_int (root , - args -> car -> value );
717- long long r = args -> car -> value ;
718- for (Obj * p = args -> cdr ; p != Nil ; p = p -> cdr )
719- r -= p -> car -> value ;
720- return make_int (root , r );
721- }
675+ // (+ <integer> ...)
676+ PRIM_ARITHMETIC_OP (prim_plus , + , += )
677+ PRIM_ARITHMETIC_OP (prim_minus , - , -= )
678+ PRIM_ARITHMETIC_OP (prim_mult , * , *= )
679+ PRIM_ARITHMETIC_OP (prim_div , /, /= )
680+ PRIM_ARITHMETIC_OP (prim_modulo , %, %= )
722681
723682// (op <integer> <integer>)
724- #define PRIM_COMPARISON_OP (PRIM_OP , OP ) \
725- static Obj *PRIM_OP(void *root, Obj **env, Obj **list) { \
726- Obj *args = eval_list(root, env, list); \
727- if (length(args) != 2) \
728- error(#OP " takes only 2 number", (*list)->line_num);\
729- Obj *x = args->car; \
730- Obj *y = args->cdr->car; \
731- if (x->type != TINT || y->type != TINT) \
732- error(#OP " takes only 2 numbers", (*list)->line_num); \
733- return x->value OP y->value ? True : Nil; \
683+ #define PRIM_COMPARISON_OP (PRIM_OP , OP ) \
684+ static Obj * PRIM_OP (void * root , Obj * * env , Obj * * list ) { \
685+ Obj * args = eval_list (root , env , list ); \
686+ if (length (args ) != 2 ) \
687+ error (#OP " takes only 2 number", (*list)->line_num); \
688+ Obj *x = args->car; \
689+ Obj *y = args->cdr->car; \
690+ if (x->type != TINT || y->type != TINT) \
691+ error(#OP " takes only 2 numbers", (*list)->line_num); \
692+ return x->value OP y->value ? True : Nil; \
734693}
735694
736695PRIM_COMPARISON_OP (prim_num_eq , = = )
0 commit comments