mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-10-29 05:40:25 -04:00 
			
		
		
		
	Added float number support
Replaced 'int' with 'long' (integer type) Improved garbage collect
This commit is contained in:
		
							parent
							
								
									b5c2327ce7
								
							
						
					
					
						commit
						b3e3c349ce
					
				
					 3 changed files with 392 additions and 102 deletions
				
			
		|  | @ -2,11 +2,14 @@ | |||
| (princ "One " 1 "\n") | ||||
| (princ "Two " (+ 1 1) "\n") | ||||
| 
 | ||||
| (defun myprinc (o) (princ o)) | ||||
| (defun myprinc (o) (progn (princ o))) | ||||
| (myprinc "Printed via myprinc function!\n") | ||||
| 
 | ||||
| (defun printnum (from to) (while (<= from to) (princ " " from) (setq from (+ from 1)))) | ||||
| (princ "Numbers 1-10: ") (printnum 1 10) (princ "\n") | ||||
| 
 | ||||
| (defun factorial (n) (when (> n 0) (* n (factorial (- n 1))))) | ||||
| (defun factorial (n) (if (> n 1) (* n (factorial (- n 1))) 1)) | ||||
| (princ "Factorial of 10: " (factorial 10) "\n") | ||||
| 
 | ||||
| (princ "Float test 1.1 + 1.35 = " (+ 1.1 1.35) "\n") | ||||
| (princ "Factorial of 10.0: " (factorial 10.0) "\n") | ||||
|  |  | |||
|  | @ -28,6 +28,7 @@ | |||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <ctype.h> | ||||
| #include <math.h> | ||||
| #include <err.h> | ||||
| 
 | ||||
| #include "local.h" | ||||
|  | @ -39,6 +40,7 @@ struct alisp_object alsa_lisp_t; | |||
| 
 | ||||
| /* parser prototypes */ | ||||
| static struct alisp_object * parse_object(struct alisp_instance *instance, int havetoken); | ||||
| static void princ_cons(snd_output_t *out, struct alisp_object * p); | ||||
| static void princ_object(snd_output_t *out, struct alisp_object * p); | ||||
| static struct alisp_object * eval(struct alisp_instance *instance, struct alisp_object * p); | ||||
| 
 | ||||
|  | @ -133,7 +135,7 @@ static struct alisp_object * new_object(struct alisp_instance *instance, int typ | |||
| 		p->value.c.car = &alsa_lisp_nil; | ||||
| 		p->value.c.cdr = &alsa_lisp_nil; | ||||
| 	} | ||||
| 	p->gc = 0; | ||||
| 	p->gc = 1; | ||||
| 
 | ||||
| 	++instance->used_objs; | ||||
| 
 | ||||
|  | @ -173,6 +175,17 @@ static struct alisp_object * search_object_integer(struct alisp_instance *instan | |||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static struct alisp_object * search_object_float(struct alisp_instance *instance, double in) | ||||
| { | ||||
| 	struct alisp_object * p; | ||||
| 
 | ||||
| 	for (p = instance->used_objs_list; p != NULL; p = p->next) | ||||
| 		if (p->type == ALISP_OBJ_FLOAT && p->value.f == in) | ||||
| 			return p; | ||||
| 
 | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| void alsa_lisp_init_objects(void) __attribute__ ((constructor)); | ||||
| 
 | ||||
| void alsa_lisp_init_objects(void) | ||||
|  | @ -280,7 +293,9 @@ static int gettoken(struct alisp_instance *instance) | |||
| 		case '7': case '8': case '9': | ||||
| 			/* Integer: [0-9]+ */ | ||||
| 			p = instance->token_buffer; | ||||
| 			instance->thistoken = ALISP_INTEGER; | ||||
| 			do { | ||||
| 			      __ok: | ||||
| 				if (p - instance->token_buffer >= instance->token_buffer_max) { | ||||
| 					p = extend_buf(instance, p); | ||||
| 					if (p == NULL) | ||||
|  | @ -288,10 +303,27 @@ static int gettoken(struct alisp_instance *instance) | |||
| 				} | ||||
| 				*p++ = c; | ||||
| 				c = xgetc(instance); | ||||
| 				if (c == '.' && instance->thistoken == ALISP_INTEGER) { | ||||
| 					c = xgetc(instance); | ||||
| 					xungetc(instance, c); | ||||
| 					if (isdigit(c)) { | ||||
| 						instance->thistoken = ALISP_FLOAT; | ||||
| 						c = '.'; | ||||
| 						goto __ok; | ||||
| 					} else { | ||||
| 						c = '.'; | ||||
| 					} | ||||
| 				} else if (c == 'e' && instance->thistoken == ALISP_FLOAT) { | ||||
| 					c = xgetc(instance); | ||||
| 					if (isdigit(c)) { | ||||
| 						instance->thistoken = ALISP_FLOATE; | ||||
| 						goto __ok; | ||||
| 					} | ||||
| 				} | ||||
| 			} while (isdigit(c)); | ||||
| 			xungetc(instance, c); | ||||
| 			*p = '\0'; | ||||
| 			return instance->thistoken = ALISP_INTEGER; | ||||
| 			return instance->thistoken; | ||||
| 
 | ||||
| 		got_id: | ||||
| 		case '_': case '+': case '*': case '/': case '%': | ||||
|  | @ -437,7 +469,6 @@ static struct alisp_object * parse_object(struct alisp_instance *instance, int h | |||
| { | ||||
| 	int thistoken; | ||||
| 	struct alisp_object * p = NULL; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (!havetoken) | ||||
| 		thistoken = gettoken(instance); | ||||
|  | @ -470,14 +501,27 @@ static struct alisp_object * parse_object(struct alisp_instance *instance, int h | |||
| 			} | ||||
| 		} | ||||
| 		break; | ||||
| 	case ALISP_INTEGER: | ||||
| 		i = atoi(instance->token_buffer); | ||||
| 	case ALISP_INTEGER: { | ||||
| 		long i; | ||||
| 		i = atol(instance->token_buffer); | ||||
| 		if ((p = search_object_integer(instance, i)) == NULL) { | ||||
| 			p = new_object(instance, ALISP_OBJ_INTEGER); | ||||
| 			if (p) | ||||
| 				p->value.i = i; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 	case ALISP_FLOAT: | ||||
| 	case ALISP_FLOATE: { | ||||
| 		double f; | ||||
| 		f = atof(instance->token_buffer); | ||||
| 		if ((p = search_object_float(instance, f)) == NULL) { | ||||
| 			p = new_object(instance, ALISP_OBJ_FLOAT); | ||||
| 			if (p) | ||||
| 				p->value.f = f; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 	case ALISP_STRING: | ||||
| 		if ((p = search_object_string(instance, instance->token_buffer)) == NULL) { | ||||
| 			p = new_object(instance, ALISP_OBJ_STRING); | ||||
|  | @ -555,6 +599,14 @@ static void dump_objects(struct alisp_instance *instance, const char *fname) | |||
| 	} | ||||
| 
 | ||||
| 	for (p = instance->setobjs_list; p != NULL; p = p->next) { | ||||
| 		if (p->value->type == ALISP_OBJ_CONS && | ||||
| 		    p->value->value.c.car->type == ALISP_OBJ_IDENTIFIER && | ||||
| 		    !strcmp(p->value->value.c.car->value.id, "lambda")) { | ||||
| 		    	snd_output_printf(out, "(defun %s ", p->name->value.id); | ||||
| 		    	princ_cons(out, p->value->value.c.cdr); | ||||
| 		    	snd_output_printf(out, ")\n"); | ||||
| 		    	continue; | ||||
| 		} | ||||
| 		snd_output_printf(out, "(setq %s '", p->name->value.id); | ||||
|  		princ_object(out, p->value); | ||||
| 		snd_output_printf(out, ")\n"); | ||||
|  | @ -569,6 +621,7 @@ static const char *obj_type_str(struct alisp_object * p) | |||
| 	case ALISP_OBJ_NIL: return "nil"; | ||||
| 	case ALISP_OBJ_T: return "t"; | ||||
| 	case ALISP_OBJ_INTEGER: return "integer"; | ||||
| 	case ALISP_OBJ_FLOAT: return "float"; | ||||
| 	case ALISP_OBJ_IDENTIFIER: return "identifier"; | ||||
| 	case ALISP_OBJ_STRING: return "string"; | ||||
| 	case ALISP_OBJ_CONS: return "cons"; | ||||
|  | @ -637,7 +690,22 @@ static void tag_whole_tree(struct alisp_instance *instance) | |||
| static void do_garbage_collect(struct alisp_instance *instance) | ||||
| { | ||||
| 	struct alisp_object * p, * new_used_objs_list = NULL, * next; | ||||
| 	struct alisp_object_pair * op, * new_set_objs_list = NULL, * onext; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * remove nil variables | ||||
| 	 */ | ||||
| 	for (op = instance->setobjs_list; op != NULL; op = onext) { | ||||
| 		onext = op->next; | ||||
| 		if (op->value->type == ALISP_OBJ_NIL) { | ||||
| 			free(op); | ||||
| 		} else { | ||||
| 			op->next = new_set_objs_list; | ||||
| 			new_set_objs_list = op; | ||||
| 		} | ||||
| 	} | ||||
| 	instance->setobjs_list = new_set_objs_list; | ||||
| 	 | ||||
| 	tag_whole_tree(instance); | ||||
| 
 | ||||
| 	/*
 | ||||
|  | @ -645,7 +713,7 @@ static void do_garbage_collect(struct alisp_instance *instance) | |||
| 	 */ | ||||
| 	for (p = instance->used_objs_list; p != NULL; p = next) { | ||||
| 		next = p->next; | ||||
| 		if (p->gc != instance->gc_id) { | ||||
| 		if (p->gc != instance->gc_id && p->gc > 0) { | ||||
| 			/* Remove unreferenced object. */ | ||||
| 			lisp_debug(instance, "** collecting cons %p", p); | ||||
| 			switch (p->type) { | ||||
|  | @ -731,21 +799,36 @@ static struct alisp_object * F_cdr(struct alisp_instance *instance, struct alisp | |||
| static struct alisp_object * F_add(struct alisp_instance *instance, struct alisp_object * args) | ||||
| { | ||||
| 	struct alisp_object * p = args, * p1; | ||||
| 	int v = 0; | ||||
| 	long v = 0; | ||||
| 	double f = 0; | ||||
| 	int type = ALISP_OBJ_INTEGER; | ||||
| 
 | ||||
| 	do { | ||||
| 		p1 = eval(instance, car(p)); | ||||
| 		if (p1->type == ALISP_OBJ_INTEGER) | ||||
| 			v += p1->value.i; | ||||
| 		else | ||||
| 			lisp_warn(instance, "sum with a non integer operand"); | ||||
| 		if (p1->type == ALISP_OBJ_INTEGER) { | ||||
| 			if (type == ALISP_OBJ_FLOAT) | ||||
| 				f += p1->value.i; | ||||
| 			else | ||||
| 				v += p1->value.i; | ||||
| 		} else if (p1->type == ALISP_OBJ_FLOAT) { | ||||
| 			f += p1->value.f + v; | ||||
| 			v = 0; | ||||
| 			type = ALISP_OBJ_FLOAT; | ||||
| 		} else { | ||||
| 			lisp_warn(instance, "sum with a non integer or float operand"); | ||||
| 		} | ||||
| 		p = cdr(p); | ||||
| 	} while (p != &alsa_lisp_nil); | ||||
| 
 | ||||
| 	p1 = new_object(instance, ALISP_OBJ_INTEGER); | ||||
| 	if (p1) | ||||
| 		p1->value.i = v; | ||||
| 
 | ||||
| 	if (type == ALISP_OBJ_INTEGER) { | ||||
| 		p1 = new_object(instance, ALISP_OBJ_INTEGER); | ||||
| 		if (p1) | ||||
| 			p1->value.i = v; | ||||
| 	} else { | ||||
| 		p1 = new_object(instance, ALISP_OBJ_FLOAT); | ||||
| 		if (p1) | ||||
| 			p1->value.f = f; | ||||
| 	} | ||||
| 	return p1; | ||||
| } | ||||
| 
 | ||||
|  | @ -755,24 +838,45 @@ static struct alisp_object * F_add(struct alisp_instance *instance, struct alisp | |||
| static struct alisp_object * F_sub(struct alisp_instance *instance, struct alisp_object * args) | ||||
| { | ||||
| 	struct alisp_object * p = args, * p1; | ||||
| 	int v = 0; | ||||
| 	long v = 0; | ||||
| 	double f = 0; | ||||
| 	int type = ALISP_OBJ_INTEGER; | ||||
| 
 | ||||
| 	do { | ||||
| 		p1 = eval(instance, car(p)); | ||||
| 		if (p1->type == ALISP_OBJ_INTEGER) { | ||||
| 			if (p == args && cdr(p) != &alsa_lisp_nil) | ||||
| 			if (p == args && cdr(p) != &alsa_lisp_nil) { | ||||
| 				v = p1->value.i; | ||||
| 			else | ||||
| 				v -= p1->value.i; | ||||
| 			} else { | ||||
| 				if (type == ALISP_OBJ_FLOAT) | ||||
| 					f -= p1->value.i; | ||||
| 				else | ||||
| 					v -= p1->value.i; | ||||
| 			} | ||||
| 		} else if (p1->type == ALISP_OBJ_FLOAT) { | ||||
| 			if (type == ALISP_OBJ_INTEGER) { | ||||
| 				f = v; | ||||
| 				type = ALISP_OBJ_FLOAT; | ||||
| 			} | ||||
| 			if (p == args && cdr(p) != &alsa_lisp_nil) | ||||
| 				f = p1->value.f; | ||||
| 			else { | ||||
| 				f -= p1->value.f; | ||||
| 			} | ||||
| 		} else | ||||
| 			lisp_warn(instance, "difference with a non integer operand"); | ||||
| 			lisp_warn(instance, "difference with a non integer or float operand"); | ||||
| 		p = cdr(p); | ||||
| 	} while (p != &alsa_lisp_nil); | ||||
| 
 | ||||
| 	p1 = new_object(instance, ALISP_OBJ_INTEGER); | ||||
| 	if (p1) | ||||
| 		p1->value.i = v; | ||||
| 
 | ||||
| 	if (type == ALISP_OBJ_INTEGER) { | ||||
| 		p1 = new_object(instance, ALISP_OBJ_INTEGER); | ||||
| 		if (p1) | ||||
| 			p1->value.i = v; | ||||
| 	} else { | ||||
| 		p1 = new_object(instance, ALISP_OBJ_FLOAT); | ||||
| 		if (p1) | ||||
| 			p1->value.f = f; | ||||
| 	} | ||||
| 	return p1; | ||||
| } | ||||
| 
 | ||||
|  | @ -782,20 +886,35 @@ static struct alisp_object * F_sub(struct alisp_instance *instance, struct alisp | |||
| static struct alisp_object * F_mul(struct alisp_instance *instance, struct alisp_object * args) | ||||
| { | ||||
| 	struct alisp_object * p = args, * p1; | ||||
| 	int v = 1; | ||||
| 	long v = 1; | ||||
| 	double f = 1; | ||||
| 	int type = ALISP_OBJ_INTEGER; | ||||
| 
 | ||||
| 	do { | ||||
| 		p1 = eval(instance, car(p)); | ||||
| 		if (p1->type == ALISP_OBJ_INTEGER) | ||||
| 			v *= p1->value.i; | ||||
| 		else | ||||
| 			lisp_warn(instance, "product with a non integer operand"); | ||||
| 		if (p1->type == ALISP_OBJ_INTEGER) { | ||||
| 			if (type == ALISP_OBJ_FLOAT) | ||||
| 				f *= p1->value.i; | ||||
| 			else | ||||
| 				v *= p1->value.i; | ||||
| 		} else if (p1->type == ALISP_OBJ_FLOAT) { | ||||
| 			f *= p1->value.f * v; v = 1; | ||||
| 			type = ALISP_OBJ_FLOAT; | ||||
| 		} else { | ||||
| 			lisp_warn(instance, "product with a non integer or float operand"); | ||||
| 		} | ||||
| 		p = cdr(p); | ||||
| 	} while (p != &alsa_lisp_nil); | ||||
| 
 | ||||
| 	p1 = new_object(instance, ALISP_OBJ_INTEGER); | ||||
| 	if (p1) | ||||
| 		p1->value.i = v; | ||||
| 	if (type == ALISP_OBJ_INTEGER) { | ||||
| 		p1 = new_object(instance, ALISP_OBJ_INTEGER); | ||||
| 		if (p1) | ||||
| 			p1->value.i = v; | ||||
| 	} else { | ||||
| 		p1 = new_object(instance, ALISP_OBJ_FLOAT); | ||||
| 		if (p1) | ||||
| 			p1->value.f = f; | ||||
| 	} | ||||
| 
 | ||||
| 	return p1; | ||||
| } | ||||
|  | @ -806,29 +925,58 @@ static struct alisp_object * F_mul(struct alisp_instance *instance, struct alisp | |||
| static struct alisp_object * F_div(struct alisp_instance *instance, struct alisp_object * args) | ||||
| { | ||||
| 	struct alisp_object * p = args, * p1; | ||||
| 	int v = 0; | ||||
| 	long v = 0; | ||||
| 	double f = 0; | ||||
| 	int type = ALISP_OBJ_INTEGER; | ||||
| 
 | ||||
| 	do { | ||||
| 		p1 = eval(instance, car(p)); | ||||
| 		if (p1->type == ALISP_OBJ_INTEGER) { | ||||
| 			if (p == args && cdr(p) != &alsa_lisp_nil) | ||||
| 			if (p == args && cdr(p) != &alsa_lisp_nil) { | ||||
| 				v = p1->value.i; | ||||
| 			else { | ||||
| 			} else { | ||||
| 				if (p1->value.i == 0) { | ||||
| 					lisp_warn(instance, "division by zero"); | ||||
| 					v = 0; | ||||
| 					f = 0; | ||||
| 					break; | ||||
| 				} else | ||||
| 					v /= p1->value.i; | ||||
| 				} else { | ||||
| 					if (type == ALISP_OBJ_FLOAT) | ||||
| 						f /= p1->value.i; | ||||
| 					else | ||||
| 						v /= p1->value.i; | ||||
| 				} | ||||
| 			} | ||||
| 		} else if (p1->type == ALISP_OBJ_FLOAT) { | ||||
| 			if (type == ALISP_OBJ_INTEGER) { | ||||
| 				f = v; | ||||
| 				type = ALISP_OBJ_FLOAT; | ||||
| 			} | ||||
| 			if (p == args && cdr(p) != &alsa_lisp_nil) { | ||||
| 				f = p1->value.f; | ||||
| 			} else { | ||||
| 				if (p1->value.f == 0) { | ||||
| 					lisp_warn(instance, "division by zero"); | ||||
| 					f = 0; | ||||
| 					break; | ||||
| 				} else { | ||||
| 					f /= p1->value.i; | ||||
| 				} | ||||
| 			} | ||||
| 		} else | ||||
| 			lisp_warn(instance, "quotient with a non integer operand"); | ||||
| 			lisp_warn(instance, "quotient with a non integer or float operand"); | ||||
| 		p = cdr(p); | ||||
| 	} while (p != &alsa_lisp_nil); | ||||
| 
 | ||||
| 	p1 = new_object(instance, ALISP_OBJ_INTEGER); | ||||
| 	if (p1) | ||||
| 		p1->value.i = v; | ||||
| 	if (type == ALISP_OBJ_INTEGER) { | ||||
| 		p1 = new_object(instance, ALISP_OBJ_INTEGER); | ||||
| 		if (p1) | ||||
| 			p1->value.i = v; | ||||
| 	} else { | ||||
| 		p1 = new_object(instance, ALISP_OBJ_FLOAT); | ||||
| 		if (p1) | ||||
| 			p1->value.f = f; | ||||
| 	} | ||||
| 
 | ||||
| 	return p1; | ||||
| } | ||||
|  | @ -843,20 +991,34 @@ static struct alisp_object * F_mod(struct alisp_instance *instance, struct alisp | |||
| 	p1 = eval(instance, car(args)); | ||||
| 	p2 = eval(instance, car(cdr(args))); | ||||
| 
 | ||||
| 	if (p1->type != ALISP_OBJ_INTEGER || p2->type != ALISP_OBJ_INTEGER) { | ||||
| 		lisp_warn(instance, "module with a non integer operand"); | ||||
| 	if (p1->type == ALISP_OBJ_INTEGER && p2->type == ALISP_OBJ_INTEGER) { | ||||
| 		p3 = new_object(instance, ALISP_OBJ_INTEGER); | ||||
| 		if (p3 == NULL) | ||||
| 			return NULL; | ||||
| 		if (p2->value.i == 0) { | ||||
| 			lisp_warn(instance, "module by zero"); | ||||
| 			p3->value.i = 0; | ||||
| 		} else | ||||
| 			p3->value.i = p1->value.i % p2->value.i; | ||||
| 	} else if ((p1->type == ALISP_OBJ_INTEGER || p1->type == ALISP_OBJ_FLOAT) && | ||||
| 		   (p2->type == ALISP_OBJ_INTEGER || p2->type == ALISP_OBJ_FLOAT)) { | ||||
| 		double f1, f2; | ||||
| 		p3 = new_object(instance, ALISP_OBJ_FLOAT); | ||||
| 		if (p3 == NULL) | ||||
| 			return NULL; | ||||
| 		f1 = p1->type == ALISP_OBJ_INTEGER ? p1->value.i : p1->value.f; | ||||
| 		f2 = p2->type == ALISP_OBJ_INTEGER ? p2->value.i : p2->value.f; | ||||
| 		f1 = fmod(f1, f2); | ||||
| 		if (f1 == EDOM) { | ||||
| 			lisp_warn(instance, "module by zero"); | ||||
| 			p3->value.f = 0; | ||||
| 		} else | ||||
| 			p3->value.f = f1; | ||||
| 	} else { | ||||
| 		lisp_warn(instance, "module with a non integer or float operand"); | ||||
| 		return &alsa_lisp_nil; | ||||
| 	} | ||||
| 
 | ||||
| 	p3 = new_object(instance, ALISP_OBJ_INTEGER); | ||||
| 	if (p2->value.i == 0) { | ||||
| 		lisp_warn(instance, "module by zero"); | ||||
| 		if (p3) | ||||
| 			p3->value.i = 0; | ||||
| 	} else | ||||
| 		if (p3) | ||||
| 			p3->value.i = p1->value.i % p2->value.i; | ||||
| 
 | ||||
| 	return p3; | ||||
| } | ||||
| 
 | ||||
|  | @ -870,14 +1032,20 @@ static struct alisp_object * F_lt(struct alisp_instance *instance, struct alisp_ | |||
| 	p1 = eval(instance, car(args)); | ||||
| 	p2 = eval(instance, car(cdr(args))); | ||||
| 
 | ||||
| 	if (p1->type != ALISP_OBJ_INTEGER || p2->type != ALISP_OBJ_INTEGER) { | ||||
| 		lisp_warn(instance, "comparison with a non integer operand"); | ||||
| 		return &alsa_lisp_nil; | ||||
| 	if (p1->type == ALISP_OBJ_INTEGER && p2->type == ALISP_OBJ_INTEGER) { | ||||
| 		if (p1->value.i < p2->value.i) | ||||
| 			return &alsa_lisp_t; | ||||
| 	} else if ((p1->type == ALISP_OBJ_INTEGER || p1->type == ALISP_OBJ_FLOAT) && | ||||
| 		 (p2->type == ALISP_OBJ_INTEGER || p2->type == ALISP_OBJ_FLOAT)) { | ||||
| 		double f1, f2; | ||||
| 		f1 = p1->type == ALISP_OBJ_INTEGER ? p1->value.i : p1->value.f; | ||||
| 		f2 = p2->type == ALISP_OBJ_INTEGER ? p2->value.i : p2->value.f; | ||||
| 		if (f1 < f2) | ||||
| 			return &alsa_lisp_t; | ||||
| 	} else { | ||||
| 		lisp_warn(instance, "comparison with a non integer or float operand"); | ||||
| 	} | ||||
| 
 | ||||
| 	if (p1->value.i < p2->value.i) | ||||
| 		return &alsa_lisp_t; | ||||
| 
 | ||||
| 	return &alsa_lisp_nil; | ||||
| } | ||||
| 
 | ||||
|  | @ -891,14 +1059,20 @@ static struct alisp_object * F_gt(struct alisp_instance *instance, struct alisp_ | |||
| 	p1 = eval(instance, car(args)); | ||||
| 	p2 = eval(instance, car(cdr(args))); | ||||
| 
 | ||||
| 	if (p1->type != ALISP_OBJ_INTEGER || p2->type != ALISP_OBJ_INTEGER) { | ||||
| 		lisp_warn(instance, "comparison with a non integer operand"); | ||||
| 		return &alsa_lisp_nil; | ||||
| 	if (p1->type == ALISP_OBJ_INTEGER && p2->type == ALISP_OBJ_INTEGER) { | ||||
| 		if (p1->value.i > p2->value.i) | ||||
| 			return &alsa_lisp_t; | ||||
| 	} else if ((p1->type == ALISP_OBJ_INTEGER || p1->type == ALISP_OBJ_FLOAT) && | ||||
| 		 (p2->type == ALISP_OBJ_INTEGER || p2->type == ALISP_OBJ_FLOAT)) { | ||||
| 		double f1, f2; | ||||
| 		f1 = p1->type == ALISP_OBJ_INTEGER ? p1->value.i : p1->value.f; | ||||
| 		f2 = p2->type == ALISP_OBJ_INTEGER ? p2->value.i : p2->value.f; | ||||
| 		if (f1 > f2) | ||||
| 			return &alsa_lisp_t; | ||||
| 	} else { | ||||
| 		lisp_warn(instance, "comparison with a non integer or float operand"); | ||||
| 	} | ||||
| 
 | ||||
| 	if (p1->value.i > p2->value.i) | ||||
| 		return &alsa_lisp_t; | ||||
| 
 | ||||
| 	return &alsa_lisp_nil; | ||||
| } | ||||
| 
 | ||||
|  | @ -912,13 +1086,20 @@ static struct alisp_object * F_le(struct alisp_instance *instance, struct alisp_ | |||
| 	p1 = eval(instance, car(args)); | ||||
| 	p2 = eval(instance, car(cdr(args))); | ||||
| 
 | ||||
| 	if (p1->type != ALISP_OBJ_INTEGER || p2->type != ALISP_OBJ_INTEGER) { | ||||
| 		lisp_warn(instance, "comparison with a non integer operand"); | ||||
| 		return &alsa_lisp_nil; | ||||
| 	if (p1->type == ALISP_OBJ_INTEGER && p2->type == ALISP_OBJ_INTEGER) { | ||||
| 		if (p1->value.i <= p2->value.i) | ||||
| 			return &alsa_lisp_t; | ||||
| 	} else if ((p1->type == ALISP_OBJ_INTEGER || p1->type == ALISP_OBJ_FLOAT) && | ||||
| 		 (p2->type == ALISP_OBJ_INTEGER || p2->type == ALISP_OBJ_FLOAT)) { | ||||
| 		double f1, f2; | ||||
| 		f1 = p1->type == ALISP_OBJ_INTEGER ? p1->value.i : p1->value.f; | ||||
| 		f2 = p2->type == ALISP_OBJ_INTEGER ? p2->value.i : p2->value.f; | ||||
| 		if (f1 <= f2) | ||||
| 			return &alsa_lisp_t; | ||||
| 	} else { | ||||
| 		lisp_warn(instance, "comparison with a non integer or float operand"); | ||||
| 	} | ||||
| 
 | ||||
| 	if (p1->value.i <= p2->value.i) | ||||
| 		return &alsa_lisp_t; | ||||
| 
 | ||||
| 	return &alsa_lisp_nil; | ||||
| } | ||||
|  | @ -933,14 +1114,20 @@ static struct alisp_object * F_ge(struct alisp_instance *instance, struct alisp_ | |||
| 	p1 = eval(instance, car(args)); | ||||
| 	p2 = eval(instance, car(cdr(args))); | ||||
| 
 | ||||
| 	if (p1->type != ALISP_OBJ_INTEGER || p2->type != ALISP_OBJ_INTEGER) { | ||||
| 		lisp_warn(instance, "comparison with a non integer operand"); | ||||
| 		return &alsa_lisp_nil; | ||||
| 	if (p1->type == ALISP_OBJ_INTEGER && p2->type == ALISP_OBJ_INTEGER) { | ||||
| 		if (p1->value.i >= p2->value.i) | ||||
| 			return &alsa_lisp_t; | ||||
| 	} else if ((p1->type == ALISP_OBJ_INTEGER || p1->type == ALISP_OBJ_FLOAT) && | ||||
| 		 (p2->type == ALISP_OBJ_INTEGER || p2->type == ALISP_OBJ_FLOAT)) { | ||||
| 		double f1, f2; | ||||
| 		f1 = p1->type == ALISP_OBJ_INTEGER ? p1->value.i : p1->value.f; | ||||
| 		f2 = p2->type == ALISP_OBJ_INTEGER ? p2->value.i : p2->value.f; | ||||
| 		if (f1 >= f2) | ||||
| 			return &alsa_lisp_t; | ||||
| 	} else { | ||||
| 		lisp_warn(instance, "comparison with a non integer or float operand"); | ||||
| 	} | ||||
| 
 | ||||
| 	if (p1->value.i >= p2->value.i) | ||||
| 		return &alsa_lisp_t; | ||||
| 
 | ||||
| 	return &alsa_lisp_nil; | ||||
| } | ||||
| 
 | ||||
|  | @ -954,14 +1141,23 @@ static struct alisp_object * F_numeq(struct alisp_instance *instance, struct ali | |||
| 	p1 = eval(instance, car(args)); | ||||
| 	p2 = eval(instance, car(cdr(args))); | ||||
| 
 | ||||
| 	if (p1->type != ALISP_OBJ_INTEGER || p2->type != ALISP_OBJ_INTEGER) { | ||||
| 		lisp_warn(instance, "comparison with a non integer operand"); | ||||
| 		return &alsa_lisp_nil; | ||||
| 	if (p1->type == ALISP_OBJ_INTEGER && p2->type == ALISP_OBJ_INTEGER) { | ||||
| 		if (p1->value.i == p2->value.i) | ||||
| 			return &alsa_lisp_t; | ||||
| 	} else if ((p1->type == ALISP_OBJ_INTEGER || p1->type == ALISP_OBJ_FLOAT) && | ||||
| 		 (p2->type == ALISP_OBJ_INTEGER || p2->type == ALISP_OBJ_FLOAT)) { | ||||
| 		double f1, f2; | ||||
| 		f1 = p1->type == ALISP_OBJ_INTEGER ? p1->value.i : p1->value.f; | ||||
| 		f2 = p2->type == ALISP_OBJ_INTEGER ? p2->value.i : p2->value.f; | ||||
| 		if (f1 == f2) | ||||
| 			return &alsa_lisp_t; | ||||
| 	} else if ((p1->type == ALISP_OBJ_STRING || p2->type == ALISP_OBJ_STRING)) { | ||||
| 		if (!strcmp(p1->value.s, p2->value.s)) | ||||
| 			return &alsa_lisp_t; | ||||
| 	} else { | ||||
| 		lisp_warn(instance, "comparison with a non integer or float operand"); | ||||
| 	} | ||||
| 
 | ||||
| 	if (p1->value.i == p2->value.i) | ||||
| 		return &alsa_lisp_t; | ||||
| 
 | ||||
| 	return &alsa_lisp_nil; | ||||
| } | ||||
| 
 | ||||
|  | @ -984,10 +1180,23 @@ static void princ_string(snd_output_t *out, char *s) | |||
| 	snd_output_putc(out, '"'); | ||||
| } | ||||
| 
 | ||||
| static void princ_cons(snd_output_t *out, struct alisp_object * p) | ||||
| { | ||||
| 	do { | ||||
| 		princ_object(out, p->value.c.car); | ||||
| 		p = p->value.c.cdr; | ||||
| 		if (p != &alsa_lisp_nil) { | ||||
| 			snd_output_putc(out, ' '); | ||||
| 			if (p->type != ALISP_OBJ_CONS) { | ||||
| 				snd_output_printf(out, ". "); | ||||
| 				princ_object(out, p); | ||||
| 			} | ||||
| 		} | ||||
| 	} while (p != &alsa_lisp_nil && p->type == ALISP_OBJ_CONS); | ||||
| } | ||||
| 
 | ||||
| static void princ_object(snd_output_t *out, struct alisp_object * p) | ||||
| { | ||||
| 	struct alisp_object * p1; | ||||
| 
 | ||||
| 	switch (p->type) { | ||||
| 	case ALISP_OBJ_NIL: | ||||
| 		snd_output_printf(out, "nil"); | ||||
|  | @ -1002,22 +1211,14 @@ static void princ_object(snd_output_t *out, struct alisp_object * p) | |||
| 		princ_string(out, p->value.s); | ||||
| 		break; | ||||
| 	case ALISP_OBJ_INTEGER: | ||||
| 		snd_output_printf(out, "%d", p->value.i); | ||||
| 		snd_output_printf(out, "%ld", p->value.i); | ||||
| 		break; | ||||
| 	case ALISP_OBJ_FLOAT: | ||||
| 		snd_output_printf(out, "%f", p->value.f); | ||||
| 		break; | ||||
| 	case ALISP_OBJ_CONS: | ||||
| 		snd_output_putc(out, '('); | ||||
| 		p1 = p; | ||||
| 		do { | ||||
| 			princ_object(out, p1->value.c.car); | ||||
| 			p1 = p1->value.c.cdr; | ||||
| 			if (p1 != &alsa_lisp_nil) { | ||||
| 				snd_output_putc(out, ' '); | ||||
| 				if (p1->type != ALISP_OBJ_CONS) { | ||||
| 					snd_output_printf(out, ". "); | ||||
| 					princ_object(out, p1); | ||||
| 				} | ||||
| 			} | ||||
| 		} while (p1 != &alsa_lisp_nil && p1->type == ALISP_OBJ_CONS); | ||||
| 		princ_cons(out, p); | ||||
| 		snd_output_putc(out, ')'); | ||||
| 	} | ||||
| } | ||||
|  | @ -1122,7 +1323,7 @@ static struct alisp_object * F_eq(struct alisp_instance *instance, struct alisp_ | |||
| 
 | ||||
| 	if (p1->type == p2->type) | ||||
| 		switch (p1->type) { | ||||
| 		case ALISP_IDENTIFIER: | ||||
| 		case ALISP_OBJ_IDENTIFIER: | ||||
| 			if (!strcmp(p1->value.id, p2->value.id)) | ||||
| 				return &alsa_lisp_t; | ||||
| 			return &alsa_lisp_nil; | ||||
|  | @ -1383,7 +1584,7 @@ static struct alisp_object * F_defun(struct alisp_instance *instance, struct ali | |||
| 
 | ||||
| 	lexpr = new_object(instance, ALISP_OBJ_CONS); | ||||
| 	if (lexpr) { | ||||
| 		lexpr->value.c.car = new_object(instance, ALISP_IDENTIFIER); | ||||
| 		lexpr->value.c.car = new_object(instance, ALISP_OBJ_IDENTIFIER); | ||||
| 		if (lexpr->value.c.car == NULL) | ||||
| 			return NULL; | ||||
| 		if ((lexpr->value.c.car->value.id = strdup("lambda")) == NULL) { | ||||
|  | @ -1409,7 +1610,7 @@ static struct alisp_object * eval_func(struct alisp_instance *instance, struct a | |||
| 	int i; | ||||
| 
 | ||||
| 	p1 = car(p); | ||||
| 	if (p1->type == ALISP_IDENTIFIER && !strcmp(p1->value.id, "lambda")) { | ||||
| 	if (p1->type == ALISP_OBJ_IDENTIFIER && !strcmp(p1->value.id, "lambda")) { | ||||
| 		p2 = car(cdr(p)); | ||||
| 		p3 = args; | ||||
| 
 | ||||
|  | @ -1468,6 +1669,84 @@ struct alisp_object * F_gc(struct alisp_instance *instance, struct alisp_object | |||
| 	return &alsa_lisp_t; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Syntax: (int value) | ||||
|  * 'value' can be integer or float type | ||||
|  */ | ||||
| struct alisp_object * F_int(struct alisp_instance *instance, struct alisp_object * args) | ||||
| { | ||||
| 	struct alisp_object * p = eval(instance, car(args)); | ||||
| 
 | ||||
| 	if (p->type == ALISP_INTEGER) | ||||
| 		return p; | ||||
| 	if (p->type == ALISP_FLOAT) { | ||||
| 		struct alisp_object * p1; | ||||
| 		p1 = new_object(instance, ALISP_OBJ_INTEGER); | ||||
| 		if (p1 == NULL) | ||||
| 			return NULL; | ||||
| 		p1->value.i = floor(p->value.f); | ||||
| 		return p1; | ||||
| 	} | ||||
| 
 | ||||
| 	lisp_warn(instance, "expected an integer or float for integer conversion"); | ||||
| 	return &alsa_lisp_nil; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Syntax: (float value) | ||||
|  * 'value' can be integer or float type | ||||
|  */ | ||||
| struct alisp_object * F_float(struct alisp_instance *instance, struct alisp_object * args) | ||||
| { | ||||
| 	struct alisp_object * p = eval(instance, car(args)); | ||||
| 
 | ||||
| 	if (p->type == ALISP_FLOAT) | ||||
| 		return p; | ||||
| 	if (p->type == ALISP_INTEGER) { | ||||
| 		struct alisp_object * p1; | ||||
| 		p1 = new_object(instance, ALISP_OBJ_FLOAT); | ||||
| 		if (p1 == NULL) | ||||
| 			return NULL; | ||||
| 		p1->value.f = p->value.i; | ||||
| 		return p1; | ||||
| 	} | ||||
| 
 | ||||
| 	lisp_warn(instance, "expected an integer or float for integer conversion"); | ||||
| 	return &alsa_lisp_nil; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Syntax: (str value) | ||||
|  * 'value' can be integer, float or string type | ||||
|  */ | ||||
| struct alisp_object * F_str(struct alisp_instance *instance, struct alisp_object * args) | ||||
| { | ||||
| 	struct alisp_object * p = eval(instance, car(args)); | ||||
| 
 | ||||
| 	if (p->type == ALISP_STRING) | ||||
| 		return p; | ||||
| 	if (p->type == ALISP_INTEGER || p->type == ALISP_FLOAT) { | ||||
| 		struct alisp_object * p1; | ||||
| 		char buf[64]; | ||||
| 		p1 = new_object(instance, ALISP_OBJ_STRING); | ||||
| 		if (p1 == NULL) | ||||
| 			return NULL; | ||||
| 		if (p->type == ALISP_INTEGER) { | ||||
| 			snprintf(buf, sizeof(buf), "%ld", p->value.i); | ||||
| 		} else { | ||||
| 			snprintf(buf, sizeof(buf), "%.f", p->value.f); | ||||
| 		} | ||||
| 		if ((p1->value.s = strdup(buf)) == NULL) { | ||||
| 			nomem(); | ||||
| 			return &alsa_lisp_nil; | ||||
| 		} | ||||
| 		return p1; | ||||
| 	} | ||||
| 
 | ||||
| 	lisp_warn(instance, "expected an integer or float for integer conversion"); | ||||
| 	return &alsa_lisp_nil; | ||||
| } | ||||
| 
 | ||||
| static struct alisp_object * F_dump_memory(struct alisp_instance *instance, struct alisp_object * args) | ||||
| { | ||||
| 	struct alisp_object * p = car(args); | ||||
|  | @ -1527,9 +1806,11 @@ static struct intrinsic intrinsics[] = { | |||
| 	{ "defun", F_defun }, | ||||
| 	{ "eq", F_eq }, | ||||
| 	{ "eval", F_eval }, | ||||
| 	{ "float", F_float }, | ||||
| 	{ "garbage-collect", F_gc }, | ||||
| 	{ "gc", F_gc }, | ||||
| 	{ "if", F_if }, | ||||
| 	{ "int", F_int }, | ||||
| 	{ "list", F_list }, | ||||
| 	{ "not", F_not }, | ||||
| 	{ "null", F_not }, | ||||
|  | @ -1542,6 +1823,7 @@ static struct intrinsic intrinsics[] = { | |||
| 	{ "set", F_set }, | ||||
| 	{ "setf", F_setq }, | ||||
| 	{ "setq", F_setq }, | ||||
| 	{ "str", F_str }, | ||||
| 	{ "unless", F_unless }, | ||||
| 	{ "when", F_when }, | ||||
| 	{ "while", F_while }, | ||||
|  | @ -1620,6 +1902,7 @@ int alsa_lisp(struct alisp_cfg *cfg) | |||
| 	instance->eout = cfg->eout; | ||||
| 	instance->wout = cfg->wout; | ||||
| 	instance->dout = cfg->dout; | ||||
| 	instance->gc_id = 1; | ||||
| 	 | ||||
| 	init_lex(instance); | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,6 +24,8 @@ | |||
| enum alisp_tokens { | ||||
| 	ALISP_IDENTIFIER, | ||||
| 	ALISP_INTEGER, | ||||
| 	ALISP_FLOAT, | ||||
| 	ALISP_FLOATE, | ||||
| 	ALISP_STRING | ||||
| }; | ||||
| 
 | ||||
|  | @ -31,6 +33,7 @@ enum alisp_objects { | |||
| 	ALISP_OBJ_NIL, | ||||
| 	ALISP_OBJ_T, | ||||
| 	ALISP_OBJ_INTEGER, | ||||
| 	ALISP_OBJ_FLOAT, | ||||
| 	ALISP_OBJ_IDENTIFIER, | ||||
| 	ALISP_OBJ_STRING, | ||||
| 	ALISP_OBJ_CONS | ||||
|  | @ -42,7 +45,8 @@ struct alisp_object { | |||
| 	union { | ||||
| 		char	*id; | ||||
| 		char	*s; | ||||
| 		int	i; | ||||
| 		long	i; | ||||
| 		double	f; | ||||
| 		struct { | ||||
| 			struct alisp_object *car; | ||||
| 			struct alisp_object *cdr; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jaroslav Kysela
						Jaroslav Kysela