orangeduck / BuildYourOwnLisp

Learn C and build your own programming language in under 1000 lines of code!
http://www.buildyourownlisp.com/
Other
2.9k stars 394 forks source link

Not Isue, help with decimal numbers #164

Open zmmaj opened 3 years ago

zmmaj commented 3 years ago

I hope this will help to someone. To be clear... I do not know Lisp or C.. :( I am GameMaker programmer.. so my intention is to put in this code SDL library, and i have some success.. However, my first issue is to make this code to read and print out decimals. All games needs decimals.. It was very hard for me to find what is going wrong here.. where are decimals.??? So step by step, i found this solution.
First of all change grammar. to mach line below. number : /-?[0-9]+(\.[0-9]*)?/ ; \

That is NOT all . With only this change you can input decimal numbers but output is still wrong eg + 2.2 2 = 4 not 4.2 So, you must change several other thing First number declaration from / Basic / long num; char err; char sym; char* str;

to / Basic / float num; char err; char sym; char* str;

ELSE in function for reading numbers ... lval lval_read_num(mpc_ast_t t) { errno = 0; long x = strtol(t->contents, NULL, 10);

change TO lval lval_read_num(mpc_ast_t t) { errno = 0; float x = atof(t->contents); since strol() convert string to LONG, we need another to convert from string to FLOAT. That is atof().

ELSE: lval lval_num(long x) { lval v = malloc(sizeof(lval)); v->type = LVAL_NUM; v->num = x; return v; } TO lval lval_num(float x) { lval v = malloc(sizeof(lval)); v->type = LVAL_NUM; v->num = x; return v; } Still not finished.. In function: *void lval_print(lval v) { .... you must change how will print numbers on output,,, So, change line case LVAL_NUM: printf("%li", v->num); break; to case LVAL_NUM: printf("%3.2f", v->num); break;**

This -> "%3.2f" is maybe strange, it can be only "%f" ... So find on internet solution who mach your wish how to look output numbers,,, try also and %g ... Now that is all ! Try now. :)

Gaochengzhi commented 2 years ago

It's better to make a distinguish between the integer and double type. The first problem is how to distinguish between integer and double on a regular expression level. It sounds easy but you will meet plenty of problems, in the end my dummy resolution is like: number : /-?[0-9]+/; \ double : /-?[0-9]*\\.?[0-9]+/; \ just wrapper them in the ``. It's safe but also awkward to use. if you have better way please tell me.

The second problem is how to implement basic numeric operation, especially when double mixed with number, like 8 + 1.22, my solution is first convert all the number into double. If any of the operands are double, then the final result should also be double, otherwise convert them into int again.

zmmaj commented 2 years ago

In my way, everything is converted to double on start.. Of course you can change double to number at end if you do not like result with .00