Browse Source

Sol Part 63: DO YOU THINK THIS IS A GAME?

Version bump to 0.3a4!
Graham Northup 4 years ago
parent
commit
0822b69fb2
Signed by: Graham Northup <grissess@nexusg.org> GPG Key ID: 5D000E6F539376FB
18 changed files with 9311 additions and 8167 deletions
  1. 1
    0
      .gitignore
  2. 38
    5
      Makefile
  3. 5
    0
      RECIPES
  4. 59
    6
      builtins.c
  5. 164
    159
      lex.yy.c
  6. 7454
    7197
      parser.output
  7. 714
    690
      parser.tab.c
  8. 60
    59
      parser.tab.h
  9. 39
    20
      parser.y
  10. 671
    0
      programs/chip8.sol
  11. 9
    3
      programs/interp.sol
  12. 10
    5
      runtime.c
  13. 4
    0
      ser.c
  14. 11
    5
      sol.h
  15. 6
    0
      solrun.c
  16. 36
    18
      state.c
  17. 28
    0
      tests/lang_elseif.sol
  18. 2
    0
      tokenizer.lex

+ 1
- 0
.gitignore View File

@@ -14,3 +14,4 @@ _build
14 14
 doxyxml
15 15
 valgrind.log
16 16
 *_INFO
17
+prof

+ 38
- 5
Makefile View File

@@ -1,6 +1,6 @@
1
-CFLAGS= -g $(BUILD_DEFINES)
2
-LDFLAGS= -lfl -lm -ldl -lreadline
3
-OBJ= lex.yy.o parser.tab.o dsl/seq.o dsl/list.o dsl/array.o dsl/generic.o astprint.o runtime.o gc.o object.o state.o builtins.o solrun.o ser.o sol_help.o
1
+override CFLAGS:= -g $(BUILD_DEFINES) $(CFLAGS)
2
+override LDFLAGS:= -lfl -lm -ldl -lreadline $(LDFLAGS)
3
+OBJ= lex.yy.o parser.tab.o dsl/seq.o dsl/list.o dsl/array.o dsl/generic.o astprint.o runtime.o gc.o object.o state.o builtins.o solrun.o ser.o
4 4
 
5 5
 ifndef CC
6 6
 	CC:= gcc
@@ -18,12 +18,22 @@ ifndef DESTDIR
18 18
 	DESTDIR:= /usr/local/
19 19
 endif
20 20
 
21
+ifdef NO_HELP
22
+	override CFLAGS+= -DNO_HELP
23
+else
24
+	OBJ+= sol_help.o
25
+endif
26
+
27
+ifndef STDOUT_FILENAME
28
+	STDOUT_FILENAME:=/dev/fd/1
29
+endif
30
+
21 31
 include VERSION_INFO
22 32
 include ARCH_INFO
23 33
 
24 34
 BUILD_DEFINES:= -DSOL_BUILD_HOST="\"$(shell uname -n)\"" -DSOL_BUILD_KERNEL="\"$(shell uname -s)\"" -DSOL_BUILD_ARCH="\"$(shell uname -m)\"" -DSOL_BUILD_REV="\"$(shell git rev-parse --short HEAD)$(shell git diff-index --quiet HEAD || echo '-dirty')\""
25 35
 
26
-SOL_VER:=$(MAJOR).$(MINOR)$(RELEASE)$(PATCH)
36
+SOL_VER:=$(MAJOR).$(MINOR)$(RELEASE)$(PATCH)$(SUFFIX)
27 37
 LINKED_VERS:=sol sol$(MAJOR) sol$(MAJOR).$(MINOR)
28 38
 
29 39
 .PHONY: install install_bin install_bindir install_lib install_libdir uninstall uninstall_bin uninstall_lib all test clean docs
@@ -66,7 +76,30 @@ test_%: tests/%.sol
66 76
 	./sol r $?
67 77
 
68 78
 testcomp_%: tests/%.sol
69
-	./sol rc $? /dev/fd/1 | ./sol C
79
+	./sol rc $? $(STDOUT_FILENAME) | ./sol C
80
+
81
+profile: all prof profile-boot $(sort $(patsubst tests/%.sol,profile_%,$(wildcard tests/*.sol))) profilecomp-boot $(sort $(patsubst tests/%.sol,profilecomp_%,$(wildcard tests/*.sol)))
82
+
83
+prof:
84
+	mkdir prof
85
+
86
+profile-boot: programs/test.sol
87
+	LLVM_PROFILE_FILE=prof/boot.prof ./sol r $?
88
+
89
+profile_%: tests/%.sol
90
+	LLVM_PROFILE_FILE=prof/sol.$(basename $(notdir $?)).prof ./sol r $?
91
+
92
+profilecomp-boot: programs/test.sol
93
+	LLVM_PROFILE_FILE=prof/bootcomp.comp.prof ./sol rc $? $(STDOUT_FILENAME) | LLVM_PROFILE_FILE=prof/bootcomp.run.prof ./sol C
94
+
95
+profilecomp_%: tests/%.sol
96
+	LLVM_PROFILE_FILE=prof/solcomp.$(basename $(notdir $?)).comp.prof ./sol rc $? $(STDOUT_FILENAME) | LLVM_PROFILE_FILE=prof/solcomp.$(basename $(notdir $?)).run.prof ./sol C
97
+
98
+prof/sol.html: profile
99
+	llvm-profdata merge -sparse prof/*.prof -o prof/sol.prof.merged
100
+	llvm-cov show -instr-profile prof/sol.prof.merged ./sol -format=html > $@
101
+
102
+all-profile: prof/sol.html
70 103
 
71 104
 dsl:
72 105
 	git submodule init && git submodule sync && git submodule update

+ 5
- 0
RECIPES View File

@@ -0,0 +1,5 @@
1
+WASM/asm.js:
2
+make CC=emcc CFLAGS=-DNO_READLINE NO_HELP=1
3
+
4
+clang for profiling:
5
+make CC=clang CFLAGS="-fprofile-instr-generate -fcoverage-mapping"

+ 59
- 6
builtins.c View File

@@ -4,8 +4,12 @@
4 4
 #include <math.h>
5 5
 #include <stdint.h>
6 6
 #include <dlfcn.h>
7
+#ifndef NO_READLINE
7 8
 #include <readline/readline.h>
8 9
 #include <readline/history.h>
10
+#endif
11
+#include <termios.h>
12
+#include <sys/ioctl.h>
9 13
 #include "ast.h"
10 14
 #include "dsl/dsl.h"
11 15
 
@@ -484,6 +488,7 @@ sol_object_t *sol_f_debug_scopes(sol_state_t *state, sol_object_t *args) {
484 488
 	return sol_incref(state->scopes);
485 489
 }
486 490
 
491
+#ifndef NO_READLINE
487 492
 sol_object_t *sol_f_readline_readline(sol_state_t *state, sol_object_t *args) {
488 493
 	sol_object_t *obj, *objstr, *res;
489 494
 	char *line;
@@ -512,6 +517,7 @@ sol_object_t *sol_f_readline_add_history(sol_state_t *state, sol_object_t *args)
512 517
 	sol_obj_free(line);
513 518
 	return sol_incref(state->None);
514 519
 }
520
+#endif
515 521
 
516 522
 void _sol_freef_seq_iter(void *iter, size_t sz) {
517 523
 	dsl_free_seq_iter((dsl_seq_iter *) iter);
@@ -1290,6 +1296,30 @@ sol_object_t *sol_f_list_filter(sol_state_t *state, sol_object_t *args) {
1290 1296
 	return list;
1291 1297
 }
1292 1298
 
1299
+sol_object_t *sol_f_list_reduce(sol_state_t *state, sol_object_t *args) {
1300
+	sol_object_t *list = sol_list_get_index(state, args, 0), *func = sol_list_get_index(state, args, 1);
1301
+	sol_object_t *val = sol_list_get_index(state, args, 2), *newval;
1302
+	sol_object_t *fargs = sol_new_list(state), *item;
1303
+	int idx = 0, len = sol_list_len(state, list);
1304
+	sol_list_insert(state, fargs, 0, func);
1305
+	sol_list_insert(state, fargs, 1, state->None);
1306
+	sol_list_insert(state, fargs, 2, state->None);
1307
+	while(idx < len) {
1308
+		item = sol_list_get_index(state, list, idx);
1309
+		sol_list_set_index(state, fargs, 1, val);
1310
+		sol_list_set_index(state, fargs, 2, item);
1311
+		sol_obj_free(item);
1312
+		newval = CALL_METHOD(state, func, call, fargs);
1313
+		sol_obj_free(val);
1314
+		val = newval;
1315
+		idx++;
1316
+	}
1317
+	sol_obj_free(list);
1318
+	sol_obj_free(func);
1319
+	sol_obj_free(fargs);
1320
+	return val;
1321
+}
1322
+
1293 1323
 sol_object_t *sol_f_map_add(sol_state_t *state, sol_object_t *args) {
1294 1324
 	sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *map;
1295 1325
 	if(!sol_is_map(b)) {
@@ -1592,7 +1622,13 @@ sol_object_t *sol_f_func_tostring(sol_state_t *state, sol_object_t *args) {
1592 1622
 
1593 1623
 sol_object_t *sol_f_cfunc_call(sol_state_t *state, sol_object_t *args) {
1594 1624
 	sol_object_t *func = sol_list_get_index(state, args, 0), *fargs = sol_list_sublist(state, args, 1);
1595
-	sol_object_t *res = func->cfunc(state, fargs);
1625
+	sol_object_t *res = NULL, *tmp = NULL;
1626
+	sol_list_insert(state, state->fnstack, 0, func);
1627
+	res = func->cfunc(state, fargs);
1628
+	tmp = sol_list_remove(state, state->fnstack, 0);
1629
+	if(tmp != func) {
1630
+		printf("ERROR: Function stack imbalance\n");
1631
+	}
1596 1632
 	sol_obj_free(func);
1597 1633
 	sol_obj_free(fargs);
1598 1634
 	return res;
@@ -2642,7 +2678,7 @@ sol_object_t *sol_f_stream_write(sol_state_t *state, sol_object_t *args) {
2642 2678
 	return sol_new_int(state, sz);
2643 2679
 }
2644 2680
 
2645
-sol_object_t *sol_f_stream_read(sol_state_t *state, sol_object_t *args) {
2681
+sol_object_t *sol_f_stream_read_buffer(sol_state_t *state, sol_object_t *args) {
2646 2682
 	sol_object_t *stream = sol_list_get_index(state, args, 0), *amt = sol_list_get_index(state, args, 1), *iamt, *res;
2647 2683
 	char *s = NULL, *p;
2648 2684
 	size_t count = 0, max = 0, pos, end;
@@ -2660,22 +2696,21 @@ sol_object_t *sol_f_stream_read(sol_state_t *state, sol_object_t *args) {
2660 2696
 				sol_obj_free(amt);
2661 2697
 				return sol_set_error_string(state, "IO read error");
2662 2698
 			}
2663
-			s[end - pos] = '\0';
2699
+			count = end - pos;
2664 2700
 		} else if(sol_string_eq(state, amt, "LINE")) {
2665 2701
 			s = malloc(STDIO_CHUNK_SIZE * sizeof(char));
2666 2702
 			sol_stream_fgets(state, stream, s, STDIO_CHUNK_SIZE);
2703
+			count = strlen(s);
2667 2704
 		}
2668 2705
 	} else {
2669 2706
 		iamt = sol_cast_int(state, amt);
2670 2707
 		s = malloc((iamt->ival + 1) * sizeof(char));
2671 2708
 		count = sol_stream_fread(state, stream, s, sizeof(char), iamt->ival);
2672
-		s[count] = '\0';
2673 2709
 		sol_obj_free(iamt);
2674 2710
 	}
2675 2711
 	if(s) {
2676 2712
 		//printf("IO: Read result: %s\n", s);
2677
-		res = sol_new_string(state, s);
2678
-		free(s);
2713
+		res = sol_new_buffer(state, s, count, OWN_FREE, NULL, NULL);
2679 2714
 	} else {
2680 2715
 		//printf("IO: No read result!\n");
2681 2716
 		res = sol_incref(state->None);
@@ -2685,6 +2720,13 @@ sol_object_t *sol_f_stream_read(sol_state_t *state, sol_object_t *args) {
2685 2720
 	return res;
2686 2721
 }
2687 2722
 
2723
+sol_object_t *sol_f_stream_read(sol_state_t *state, sol_object_t *args) {
2724
+	sol_object_t *buf = sol_f_stream_read_buffer(state, args);
2725
+	sol_object_t *str = sol_new_string(state, buf->buffer);
2726
+	sol_obj_free(buf);
2727
+	return str;
2728
+}
2729
+
2688 2730
 sol_object_t *sol_f_stream_seek(sol_state_t *state, sol_object_t *args) {
2689 2731
 	sol_object_t *stream = sol_list_get_index(state, args, 0), *offset = sol_list_get_index(state, args, 1), *whence = sol_list_get_index(state, args, 2);
2690 2732
 	sol_object_t *ioffset = sol_cast_int(state, offset), *iwhence = sol_cast_int(state, whence);
@@ -2715,6 +2757,17 @@ sol_object_t *sol_f_stream_eof(sol_state_t *state, sol_object_t *args) {
2715 2757
 	return res;
2716 2758
 }
2717 2759
 
2760
+sol_object_t *sol_f_stream_ioctl(sol_state_t *state, sol_object_t *args) {
2761
+	sol_object_t *stream = sol_list_get_index(state, args, 0), *buf = sol_list_get_index(state, args, 2);
2762
+	sol_object_t *req = sol_list_get_index(state, args, 1), *ireq = sol_cast_int(state, req);
2763
+	sol_object_t *res = sol_new_int(state, ioctl(fileno(stream->stream), (unsigned long) ireq->ival, buf->buffer));
2764
+	sol_obj_free(stream);
2765
+	sol_obj_free(buf);
2766
+	sol_obj_free(req);
2767
+	sol_obj_free(ireq);
2768
+	return res;
2769
+}
2770
+
2718 2771
 static char *sol_FileModes[] = {
2719 2772
 	NULL,
2720 2773
 	"r",

+ 164
- 159
lex.yy.c View File

@@ -431,8 +431,8 @@ static void yynoreturn yy_fatal_error ( const char* msg  );
431 431
 	(yy_hold_char) = *yy_cp; \
432 432
 	*yy_cp = '\0'; \
433 433
 	(yy_c_buf_p) = yy_cp;
434
-#define YY_NUM_RULES 73
435
-#define YY_END_OF_BUFFER 74
434
+#define YY_NUM_RULES 74
435
+#define YY_END_OF_BUFFER 75
436 436
 /* This struct is not used in this scanner,
437 437
    but its presence is necessary. */
438 438
 struct yy_trans_info
@@ -440,25 +440,25 @@ struct yy_trans_info
440 440
 	flex_int32_t yy_verify;
441 441
 	flex_int32_t yy_nxt;
442 442
 	};
443
-static const flex_int16_t yy_accept[152] =
443
+static const flex_int16_t yy_accept[154] =
444 444
     {   0,
445
-        0,    0,   74,   73,   72,   34,   73,   68,   23,   26,
446
-       73,   62,   63,   21,   19,   67,   20,   64,   22,    2,
447
-       65,   66,   51,   40,   52,   70,   70,   70,   70,   59,
448
-       60,   28,   70,   70,   70,   70,   70,   70,   70,   70,
449
-       70,   70,   70,   70,   70,   70,   57,   27,   58,   29,
450
-       72,   61,   72,    0,   50,    0,    3,   30,   46,    0,
451
-        4,   25,   43,   41,    0,   42,   44,    1,    2,   56,
452
-       53,   49,   54,   55,   70,   70,   70,   70,   48,   70,
453
-       70,   70,   11,   70,   70,   70,   70,   70,    5,   10,
454
-       70,   70,   70,   33,   70,   70,   70,   70,   47,   32,
455
-
456
-       72,   61,   69,   45,    0,   71,    1,   70,   70,   70,
457
-       31,   70,   70,   70,   17,   70,    9,   70,   70,   24,
458
-       35,   70,   70,   70,   70,   70,   18,   37,   70,   70,
459
-        7,   70,   12,   70,   70,    6,   36,   70,   39,   15,
460
-       70,   38,   70,   70,    8,   70,   13,   14,   70,   16,
461
-        0
445
+        0,    0,   75,   74,   73,   35,   74,   69,   24,   27,
446
+       74,   63,   64,   22,   20,   68,   21,   65,   23,    2,
447
+       66,   67,   52,   41,   53,   71,   71,   71,   71,   60,
448
+       61,   29,   71,   71,   71,   71,   71,   71,   71,   71,
449
+       71,   71,   71,   71,   71,   71,   58,   28,   59,   30,
450
+       73,   62,   73,    0,   51,    0,    3,   31,   47,    0,
451
+        4,   26,   44,   42,    0,   43,   45,    1,    2,   57,
452
+       54,   50,   55,   56,   71,   71,   71,   71,   49,   71,
453
+       71,   71,   12,   71,   71,   71,   71,   71,    5,   11,
454
+       71,   71,   71,   34,   71,   71,   71,   71,   48,   33,
455
+
456
+       73,   62,   70,   46,    0,   72,    1,   71,   71,   71,
457
+       32,   71,   71,   71,   18,   71,   10,   71,   71,   25,
458
+       36,   71,   71,   71,   71,   71,   19,   38,   71,   71,
459
+        7,   71,   13,   71,   71,    6,   37,   71,   40,   16,
460
+       71,   71,   39,   71,   71,    9,   71,    8,   14,   15,
461
+       71,   17,    0
462 462
     } ;
463 463
 
464 464
 static const YY_CHAR yy_ec[256] =
@@ -503,49 +503,49 @@ static const YY_CHAR yy_meta[53] =
503 503
         1,    1
504 504
     } ;
505 505
 
506
-static const flex_int16_t yy_base[156] =
506
+static const flex_int16_t yy_base[158] =
507 507
     {   0,
508
-        0,   51,  169,  170,   52,   52,  163,  170,  170,   49,
509
-      158,  170,  170,   46,  144,  170,   44,  170,  143,   44,
510
-      170,  170,   42,  142,   47,    0,  132,  119,  117,  170,
511
-      170,  138,  117,  114,  114,  113,   25,   41,   37,  124,
512
-      111,  110,  108,  116,   38,  113,  170,   54,  170,  170,
513
-       75,  170,   78,  145,  170,  143,  170,  170,  170,  138,
514
-      170,  124,  170,  170,  142,  170,  170,  126,   71,  170,
515
-      170,  170,  170,  170,    0,  103,  100,   94,  170,  106,
516
-      104,   96,    0,   92,  102,   95,   90,   91,    0,    0,
517
-       91,   97,   84,    0,   83,   93,   80,   88,  170,  170,
518
-
519
-       88,  170,  170,  170,  122,  170,  106,   78,   87,   86,
520
-        0,   89,   73,   83,    0,   72,    0,   83,   83,    0,
521
-        0,   67,   71,   77,   71,   68,    0,    0,   63,   63,
522
-        0,   65,    0,   65,   53,    0,    0,   61,    0,    0,
523
-       53,    0,   63,   51,    0,   45,    0,    0,   51,    0,
524
-      170,  104,  106,   81,  108
508
+        0,   51,  171,  172,   52,   52,  165,  172,  172,   49,
509
+      160,  172,  172,   46,  146,  172,   44,  172,  145,   44,
510
+      172,  172,   42,  144,   47,    0,  134,  121,  119,  172,
511
+      172,  140,  119,  116,  116,  115,   25,   41,   37,  126,
512
+      113,  112,  110,  118,   38,  115,  172,   54,  172,  172,
513
+       75,  172,   78,  147,  172,  145,  172,  172,  172,  140,
514
+      172,  126,  172,  172,  144,  172,  172,  128,   71,  172,
515
+      172,  172,  172,  172,    0,  105,  102,   96,  172,  108,
516
+      106,   98,    0,   94,  104,   97,   92,   93,    0,    0,
517
+       93,   99,   86,    0,   85,   95,   82,   90,  172,  172,
518
+
519
+       88,  172,  172,  172,  124,  172,  108,   80,   89,   88,
520
+        0,   91,   75,   85,    0,   74,    0,   85,   85,    0,
521
+        0,   69,   73,   79,   73,   77,    0,    0,   72,   65,
522
+       64,   66,    0,   66,   55,    0,    0,   62,    0,    0,
523
+       54,   59,    0,   63,   51,    0,   45,    0,    0,    0,
524
+       51,    0,  172,  104,  106,   81,  108
525 525
     } ;
526 526
 
527
-static const flex_int16_t yy_def[156] =
527
+static const flex_int16_t yy_def[158] =
528 528
     {   0,
529
-      151,    1,  151,  151,  151,  151,  152,  151,  151,  151,
530
-      153,  151,  151,  151,  151,  151,  151,  151,  151,  151,
531
-      151,  151,  151,  151,  151,  154,  154,  154,  154,  151,
532
-      151,  151,  154,  154,  154,  154,  154,  154,  154,  154,
533
-      154,  154,  154,  154,  154,  154,  151,  151,  151,  151,
534
-      151,  151,  151,  151,  151,  152,  151,  151,  151,  153,
535
-      151,  151,  151,  151,  155,  151,  151,  151,  151,  151,
536
-      151,  151,  151,  151,  154,  154,  154,  154,  151,  154,
537
-      154,  154,  154,  154,  154,  154,  154,  154,  154,  154,
538
-      154,  154,  154,  154,  154,  154,  154,  154,  151,  151,
539
-
540
-      151,  151,  151,  151,  155,  151,  151,  154,  154,  154,
541
-      154,  154,  154,  154,  154,  154,  154,  154,  154,  154,
542
-      154,  154,  154,  154,  154,  154,  154,  154,  154,  154,
543
-      154,  154,  154,  154,  154,  154,  154,  154,  154,  154,
544
-      154,  154,  154,  154,  154,  154,  154,  154,  154,  154,
545
-        0,  151,  151,  151,  151
529
+      153,    1,  153,  153,  153,  153,  154,  153,  153,  153,
530
+      155,  153,  153,  153,  153,  153,  153,  153,  153,  153,
531
+      153,  153,  153,  153,  153,  156,  156,  156,  156,  153,
532
+      153,  153,  156,  156,  156,  156,  156,  156,  156,  156,
533
+      156,  156,  156,  156,  156,  156,  153,  153,  153,  153,
534
+      153,  153,  153,  153,  153,  154,  153,  153,  153,  155,
535
+      153,  153,  153,  153,  157,  153,  153,  153,  153,  153,
536
+      153,  153,  153,  153,  156,  156,  156,  156,  153,  156,
537
+      156,  156,  156,  156,  156,  156,  156,  156,  156,  156,
538
+      156,  156,  156,  156,  156,  156,  156,  156,  153,  153,
539
+
540
+      153,  153,  153,  153,  157,  153,  153,  156,  156,  156,
541
+      156,  156,  156,  156,  156,  156,  156,  156,  156,  156,
542
+      156,  156,  156,  156,  156,  156,  156,  156,  156,  156,
543
+      156,  156,  156,  156,  156,  156,  156,  156,  156,  156,
544
+      156,  156,  156,  156,  156,  156,  156,  156,  156,  156,
545
+      156,  156,    0,  153,  153,  153,  153
546 546
     } ;
547 547
 
548
-static const flex_int16_t yy_nxt[223] =
548
+static const flex_int16_t yy_nxt[225] =
549 549
     {   0,
550 550
         4,    5,    5,    6,    7,    8,    9,   10,   11,   12,
551 551
        13,   14,   15,   16,   17,   18,   19,   20,   21,   22,
@@ -555,26 +555,26 @@ static const flex_int16_t yy_nxt[223] =
555 555
        49,   50,   51,   53,   53,   54,   58,   62,   65,   68,
556 556
        52,   69,   70,   71,   84,   66,   85,   63,   73,   74,
557 557
        59,   86,   89,   55,   96,   99,  101,   53,   90,   53,
558
-       53,   97,   75,   87,  102,  150,   68,   88,   69,  101,
559
-       53,  149,  148,  147,  146,  145,  144,  102,  143,  142,
560
-
561
-      141,  140,  139,  100,   56,   56,   60,   60,  105,  105,
562
-      138,  137,  136,  135,  134,  133,  132,  131,  130,  129,
563
-      128,  127,  126,  107,  106,  125,  124,  123,  122,  121,
564
-      120,  119,  118,  117,  116,  115,  114,  113,  112,  111,
565
-      110,  109,  108,  107,  106,  104,   61,   57,  103,   98,
566
-       95,   94,   93,   92,   91,   83,   82,   81,   80,   79,
567
-       78,   77,   76,   72,   67,   64,   61,   57,  151,    3,
568
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
569
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
570
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
571
-
572
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
573
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
574
-      151,  151
558
+       53,   97,   75,   87,  102,  152,   68,   88,   69,  101,
559
+       53,  151,  150,  149,  148,  147,  146,  102,  145,  144,
560
+
561
+      143,  142,  141,  100,   56,   56,   60,   60,  105,  105,
562
+      140,  139,  138,  137,  136,  135,  134,  133,  132,  131,
563
+      130,  129,  128,  127,  126,  107,  106,  125,  124,  123,
564
+      122,  121,  120,  119,  118,  117,  116,  115,  114,  113,
565
+      112,  111,  110,  109,  108,  107,  106,  104,   61,   57,
566
+      103,   98,   95,   94,   93,   92,   91,   83,   82,   81,
567
+       80,   79,   78,   77,   76,   72,   67,   64,   61,   57,
568
+      153,    3,  153,  153,  153,  153,  153,  153,  153,  153,
569
+      153,  153,  153,  153,  153,  153,  153,  153,  153,  153,
570
+      153,  153,  153,  153,  153,  153,  153,  153,  153,  153,
571
+
572
+      153,  153,  153,  153,  153,  153,  153,  153,  153,  153,
573
+      153,  153,  153,  153,  153,  153,  153,  153,  153,  153,
574
+      153,  153,  153,  153
575 575
     } ;
576 576
 
577
-static const flex_int16_t yy_chk[223] =
577
+static const flex_int16_t yy_chk[225] =
578 578
     {   0,
579 579
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
580 580
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -584,23 +584,23 @@ static const flex_int16_t yy_chk[223] =
584 584
         1,    1,    2,    5,    5,    6,   10,   14,   17,   20,
585 585
         2,   20,   23,   23,   37,   17,   37,   14,   25,   25,
586 586
        10,   38,   39,    6,   45,   48,   51,   51,   39,   53,
587
-       53,   45,  154,   38,   51,  149,   69,   38,   69,  101,
588
-      101,  146,  144,  143,  141,  138,  135,  101,  134,  132,
589
-
590
-      130,  129,  126,   48,  152,  152,  153,  153,  155,  155,
591
-      125,  124,  123,  122,  119,  118,  116,  114,  113,  112,
592
-      110,  109,  108,  107,  105,   98,   97,   96,   95,   93,
593
-       92,   91,   88,   87,   86,   85,   84,   82,   81,   80,
594
-       78,   77,   76,   68,   65,   62,   60,   56,   54,   46,
595
-       44,   43,   42,   41,   40,   36,   35,   34,   33,   32,
596
-       29,   28,   27,   24,   19,   15,   11,    7,    3,  151,
597
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
598
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
599
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
600
-
601
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
602
-      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
603
-      151,  151
587
+       53,   45,  156,   38,   51,  151,   69,   38,   69,  101,
588
+      101,  147,  145,  144,  142,  141,  138,  101,  135,  134,
589
+
590
+      132,  131,  130,   48,  154,  154,  155,  155,  157,  157,
591
+      129,  126,  125,  124,  123,  122,  119,  118,  116,  114,
592
+      113,  112,  110,  109,  108,  107,  105,   98,   97,   96,
593
+       95,   93,   92,   91,   88,   87,   86,   85,   84,   82,
594
+       81,   80,   78,   77,   76,   68,   65,   62,   60,   56,
595
+       54,   46,   44,   43,   42,   41,   40,   36,   35,   34,
596
+       33,   32,   29,   28,   27,   24,   19,   15,   11,    7,
597
+        3,  153,  153,  153,  153,  153,  153,  153,  153,  153,
598
+      153,  153,  153,  153,  153,  153,  153,  153,  153,  153,
599
+      153,  153,  153,  153,  153,  153,  153,  153,  153,  153,
600
+
601
+      153,  153,  153,  153,  153,  153,  153,  153,  153,  153,
602
+      153,  153,  153,  153,  153,  153,  153,  153,  153,  153,
603
+      153,  153,  153,  153
604 604
     } ;
605 605
 
606 606
 static yy_state_type yy_last_accepting_state;
@@ -962,13 +962,13 @@ yy_match:
962 962
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
963 963
 				{
964 964
 				yy_current_state = (int) yy_def[yy_current_state];
965
-				if ( yy_current_state >= 152 )
965
+				if ( yy_current_state >= 154 )
966 966
 					yy_c = yy_meta[yy_c];
967 967
 				}
968 968
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
969 969
 			++yy_cp;
970 970
 			}
971
-		while ( yy_base[yy_current_state] != 170 );
971
+		while ( yy_base[yy_current_state] != 172 );
972 972
 
973 973
 yy_find_action:
974 974
 		yy_act = yy_accept[yy_current_state];
@@ -1032,82 +1032,82 @@ YY_RULE_SETUP
1032 1032
 case 8:
1033 1033
 YY_RULE_SETUP
1034 1034
 #line 101 "tokenizer.lex"
1035
-{ return WHILE; }
1035
+{ return ELSEIF; }
1036 1036
 	YY_BREAK
1037 1037
 case 9:
1038 1038
 YY_RULE_SETUP
1039 1039
 #line 103 "tokenizer.lex"
1040
-{ return FOR; }
1040
+{ return WHILE; }
1041 1041
 	YY_BREAK
1042 1042
 case 10:
1043 1043
 YY_RULE_SETUP
1044 1044
 #line 105 "tokenizer.lex"
1045
-{ return IN; }
1045
+{ return FOR; }
1046 1046
 	YY_BREAK
1047 1047
 case 11:
1048 1048
 YY_RULE_SETUP
1049 1049
 #line 107 "tokenizer.lex"
1050
-{ return DO; }
1050
+{ return IN; }
1051 1051
 	YY_BREAK
1052 1052
 case 12:
1053 1053
 YY_RULE_SETUP
1054 1054
 #line 109 "tokenizer.lex"
1055
-{ return FUNC; }
1055
+{ return DO; }
1056 1056
 	YY_BREAK
1057 1057
 case 13:
1058 1058
 YY_RULE_SETUP
1059 1059
 #line 111 "tokenizer.lex"
1060
-{ return LAMBDA; }
1060
+{ return FUNC; }
1061 1061
 	YY_BREAK
1062 1062
 case 14:
1063 1063
 YY_RULE_SETUP
1064 1064
 #line 113 "tokenizer.lex"
1065
-{ return RETURN; }
1065
+{ return LAMBDA; }
1066 1066
 	YY_BREAK
1067 1067
 case 15:
1068 1068
 YY_RULE_SETUP
1069 1069
 #line 115 "tokenizer.lex"
1070
-{ return BREAK; }
1070
+{ return RETURN; }
1071 1071
 	YY_BREAK
1072 1072
 case 16:
1073 1073
 YY_RULE_SETUP
1074 1074
 #line 117 "tokenizer.lex"
1075
-{ return CONTINUE; }
1075
+{ return BREAK; }
1076 1076
 	YY_BREAK
1077 1077
 case 17:
1078 1078
 YY_RULE_SETUP
1079 1079
 #line 119 "tokenizer.lex"
1080
-{ return END; }
1080
+{ return CONTINUE; }
1081 1081
 	YY_BREAK
1082 1082
 case 18:
1083 1083
 YY_RULE_SETUP
1084 1084
 #line 121 "tokenizer.lex"
1085
-{ return NONE; }
1085
+{ return END; }
1086 1086
 	YY_BREAK
1087 1087
 case 19:
1088 1088
 YY_RULE_SETUP
1089 1089
 #line 123 "tokenizer.lex"
1090
-{ return PLUS; }
1090
+{ return NONE; }
1091 1091
 	YY_BREAK
1092 1092
 case 20:
1093 1093
 YY_RULE_SETUP
1094 1094
 #line 125 "tokenizer.lex"
1095
-{ return MINUS; }
1095
+{ return PLUS; }
1096 1096
 	YY_BREAK
1097 1097
 case 21:
1098 1098
 YY_RULE_SETUP
1099 1099
 #line 127 "tokenizer.lex"
1100
-{ return STAR; }
1100
+{ return MINUS; }
1101 1101
 	YY_BREAK
1102 1102
 case 22:
1103 1103
 YY_RULE_SETUP
1104 1104
 #line 129 "tokenizer.lex"
1105
-{ return SLASH; }
1105
+{ return STAR; }
1106 1106
 	YY_BREAK
1107 1107
 case 23:
1108 1108
 YY_RULE_SETUP
1109 1109
 #line 131 "tokenizer.lex"
1110
-{ return PERCENT; }
1110
+{ return SLASH; }
1111 1111
 	YY_BREAK
1112 1112
 case 24:
1113 1113
 YY_RULE_SETUP
@@ -1117,32 +1117,32 @@ YY_RULE_SETUP
1117 1117
 case 25:
1118 1118
 YY_RULE_SETUP
1119 1119
 #line 135 "tokenizer.lex"
1120
-{ return DSTAR; }
1120
+{ return PERCENT; }
1121 1121
 	YY_BREAK
1122 1122
 case 26:
1123 1123
 YY_RULE_SETUP
1124 1124
 #line 137 "tokenizer.lex"
1125
-{ return BAND; }
1125
+{ return DSTAR; }
1126 1126
 	YY_BREAK
1127 1127
 case 27:
1128 1128
 YY_RULE_SETUP
1129 1129
 #line 139 "tokenizer.lex"
1130
-{ return BOR; }
1130
+{ return BAND; }
1131 1131
 	YY_BREAK
1132 1132
 case 28:
1133 1133
 YY_RULE_SETUP
1134 1134
 #line 141 "tokenizer.lex"
1135
-{ return BXOR; }
1135
+{ return BOR; }
1136 1136
 	YY_BREAK
1137 1137
 case 29:
1138 1138
 YY_RULE_SETUP
1139 1139
 #line 143 "tokenizer.lex"
1140
-{ return BNOT; }
1140
+{ return BXOR; }
1141 1141
 	YY_BREAK
1142 1142
 case 30:
1143 1143
 YY_RULE_SETUP
1144 1144
 #line 145 "tokenizer.lex"
1145
-{ return LAND; }
1145
+{ return BNOT; }
1146 1146
 	YY_BREAK
1147 1147
 case 31:
1148 1148
 YY_RULE_SETUP
@@ -1152,7 +1152,7 @@ YY_RULE_SETUP
1152 1152
 case 32:
1153 1153
 YY_RULE_SETUP
1154 1154
 #line 149 "tokenizer.lex"
1155
-{ return LOR; }
1155
+{ return LAND; }
1156 1156
 	YY_BREAK
1157 1157
 case 33:
1158 1158
 YY_RULE_SETUP
@@ -1162,7 +1162,7 @@ YY_RULE_SETUP
1162 1162
 case 34:
1163 1163
 YY_RULE_SETUP
1164 1164
 #line 153 "tokenizer.lex"
1165
-{ return LNOT; }
1165
+{ return LOR; }
1166 1166
 	YY_BREAK
1167 1167
 case 35:
1168 1168
 YY_RULE_SETUP
@@ -1172,7 +1172,7 @@ YY_RULE_SETUP
1172 1172
 case 36:
1173 1173
 YY_RULE_SETUP
1174 1174
 #line 157 "tokenizer.lex"
1175
-{ *yylval = malloc(sizeof(long)); *((long *) *yylval) = 1; return INT;  }
1175
+{ return LNOT; }
1176 1176
 	YY_BREAK
1177 1177
 case 37:
1178 1178
 YY_RULE_SETUP
@@ -1182,7 +1182,7 @@ YY_RULE_SETUP
1182 1182
 case 38:
1183 1183
 YY_RULE_SETUP
1184 1184
 #line 161 "tokenizer.lex"
1185
-{ *yylval = malloc(sizeof(long)); *((long *) *yylval) = 0; return INT;  }
1185
+{ *yylval = malloc(sizeof(long)); *((long *) *yylval) = 1; return INT;  }
1186 1186
 	YY_BREAK
1187 1187
 case 39:
1188 1188
 YY_RULE_SETUP
@@ -1192,176 +1192,181 @@ YY_RULE_SETUP
1192 1192
 case 40:
1193 1193
 YY_RULE_SETUP
1194 1194
 #line 165 "tokenizer.lex"
1195
-{ return ASSIGN; }
1195
+{ *yylval = malloc(sizeof(long)); *((long *) *yylval) = 0; return INT;  }
1196 1196
 	YY_BREAK
1197 1197
 case 41:
1198 1198
 YY_RULE_SETUP
1199 1199
 #line 167 "tokenizer.lex"
1200
-{ return ASSIGNPLUS; }
1200
+{ return ASSIGN; }
1201 1201
 	YY_BREAK
1202 1202
 case 42:
1203 1203
 YY_RULE_SETUP
1204 1204
 #line 169 "tokenizer.lex"
1205
-{ return ASSIGNMINUS; }
1205
+{ return ASSIGNPLUS; }
1206 1206
 	YY_BREAK
1207 1207
 case 43:
1208 1208
 YY_RULE_SETUP
1209 1209
 #line 171 "tokenizer.lex"
1210
-{ return ASSIGNSTAR; }
1210
+{ return ASSIGNMINUS; }
1211 1211
 	YY_BREAK
1212 1212
 case 44:
1213 1213
 YY_RULE_SETUP
1214 1214
 #line 173 "tokenizer.lex"
1215
-{ return ASSIGNSLASH; }
1215
+{ return ASSIGNSTAR; }
1216 1216
 	YY_BREAK
1217 1217
 case 45:
1218 1218
 YY_RULE_SETUP
1219 1219
 #line 175 "tokenizer.lex"
1220
-{ return ASSIGNDSTAR; }
1220
+{ return ASSIGNSLASH; }
1221 1221
 	YY_BREAK
1222 1222
 case 46:
1223 1223
 YY_RULE_SETUP
1224 1224
 #line 177 "tokenizer.lex"
1225
-{ return ASSIGNBAND; }
1225
+{ return ASSIGNDSTAR; }
1226 1226
 	YY_BREAK
1227 1227
 case 47:
1228 1228
 YY_RULE_SETUP
1229 1229
 #line 179 "tokenizer.lex"
1230
-{ return ASSIGNBOR; }
1230
+{ return ASSIGNBAND; }
1231 1231
 	YY_BREAK
1232 1232
 case 48:
1233 1233
 YY_RULE_SETUP
1234 1234
 #line 181 "tokenizer.lex"
1235
-{ return ASSIGNBXOR; }
1235
+{ return ASSIGNBOR; }
1236 1236
 	YY_BREAK
1237 1237
 case 49:
1238 1238
 YY_RULE_SETUP
1239 1239
 #line 183 "tokenizer.lex"
1240
-{ return EQUAL; }
1240
+{ return ASSIGNBXOR; }
1241 1241
 	YY_BREAK
1242 1242
 case 50:
1243 1243
 YY_RULE_SETUP
1244 1244
 #line 185 "tokenizer.lex"
1245
-{ return NEQUAL; }
1245
+{ return EQUAL; }
1246 1246
 	YY_BREAK
1247 1247
 case 51:
1248 1248
 YY_RULE_SETUP
1249 1249
 #line 187 "tokenizer.lex"
1250
-{ return LESS; }
1250
+{ return NEQUAL; }
1251 1251
 	YY_BREAK
1252 1252
 case 52:
1253 1253
 YY_RULE_SETUP
1254 1254
 #line 189 "tokenizer.lex"
1255
-{ return GREATER; }
1255
+{ return LESS; }
1256 1256
 	YY_BREAK
1257 1257
 case 53:
1258 1258
 YY_RULE_SETUP
1259 1259
 #line 191 "tokenizer.lex"
1260
-{ return LESSEQ; }
1260
+{ return GREATER; }
1261 1261
 	YY_BREAK
1262 1262
 case 54:
1263 1263
 YY_RULE_SETUP
1264 1264
 #line 193 "tokenizer.lex"
1265
-{ return GREATEREQ; }
1265
+{ return LESSEQ; }
1266 1266
 	YY_BREAK
1267 1267
 case 55:
1268 1268
 YY_RULE_SETUP
1269 1269
 #line 195 "tokenizer.lex"
1270
-{ return RSHIFT; }
1270
+{ return GREATEREQ; }
1271 1271
 	YY_BREAK
1272 1272
 case 56:
1273 1273
 YY_RULE_SETUP
1274 1274
 #line 197 "tokenizer.lex"
1275
-{ return LSHIFT; }
1275
+{ return RSHIFT; }
1276 1276
 	YY_BREAK
1277 1277
 case 57:
1278 1278
 YY_RULE_SETUP
1279 1279
 #line 199 "tokenizer.lex"
1280
-{ return LBRACE; }
1280
+{ return LSHIFT; }
1281 1281
 	YY_BREAK
1282 1282
 case 58:
1283 1283
 YY_RULE_SETUP
1284 1284
 #line 201 "tokenizer.lex"
1285
-{ return RBRACE; }
1285
+{ return LBRACE; }
1286 1286
 	YY_BREAK
1287 1287
 case 59:
1288 1288
 YY_RULE_SETUP
1289 1289
 #line 203 "tokenizer.lex"
1290
-{ return LBRACKET; }
1290
+{ return RBRACE; }
1291 1291
 	YY_BREAK
1292 1292
 case 60:
1293 1293
 YY_RULE_SETUP
1294 1294
 #line 205 "tokenizer.lex"
1295
-{ return RBRACKET; }
1295
+{ return LBRACKET; }
1296 1296
 	YY_BREAK
1297 1297
 case 61:
1298 1298
 YY_RULE_SETUP
1299 1299
 #line 207 "tokenizer.lex"
1300
-{ return BLPAREN; } /* "Breaking" paren, not allowed to introduce a call_expr */
1300
+{ return RBRACKET; }
1301 1301
 	YY_BREAK
1302 1302
 case 62:
1303 1303
 YY_RULE_SETUP
1304 1304
 #line 209 "tokenizer.lex"
1305
-{ return LPAREN; } 
1305
+{ return BLPAREN; } /* "Breaking" paren, not allowed to introduce a call_expr */
1306 1306
 	YY_BREAK
1307 1307
 case 63:
1308 1308
 YY_RULE_SETUP
1309 1309
 #line 211 "tokenizer.lex"
1310
-{ return RPAREN; }
1310
+{ return LPAREN; } 
1311 1311
 	YY_BREAK
1312 1312
 case 64:
1313 1313
 YY_RULE_SETUP
1314 1314
 #line 213 "tokenizer.lex"
1315
-{ return DOT; }
1315
+{ return RPAREN; }
1316 1316
 	YY_BREAK
1317 1317
 case 65:
1318 1318
 YY_RULE_SETUP
1319 1319
 #line 215 "tokenizer.lex"
1320
-{ return COLON; }
1320
+{ return DOT; }
1321 1321
 	YY_BREAK
1322 1322
 case 66:
1323 1323
 YY_RULE_SETUP
1324 1324
 #line 217 "tokenizer.lex"
1325
-{ return SEMICOLON; }
1325
+{ return COLON; }
1326 1326
 	YY_BREAK
1327 1327
 case 67:
1328 1328
 YY_RULE_SETUP
1329 1329
 #line 219 "tokenizer.lex"
1330
-{ return COMMA; }
1330
+{ return SEMICOLON; }
1331 1331
 	YY_BREAK
1332 1332
 case 68:
1333 1333
 YY_RULE_SETUP
1334 1334
 #line 221 "tokenizer.lex"
1335
-{ return POUND; }
1335
+{ return COMMA; }
1336 1336
 	YY_BREAK
1337 1337
 case 69:
1338 1338
 YY_RULE_SETUP
1339 1339
 #line 223 "tokenizer.lex"
1340
-{ return TBANG; }
1340
+{ return POUND; }
1341 1341
 	YY_BREAK
1342 1342
 case 70:
1343 1343
 YY_RULE_SETUP
1344 1344
 #line 225 "tokenizer.lex"
1345
-{ *yylval = (void *) strdup(yytext); return IDENT; }
1345
+{ return TBANG; }
1346 1346
 	YY_BREAK
1347 1347
 case 71:
1348
-/* rule 71 can match eol */
1349 1348
 YY_RULE_SETUP
1350 1349
 #line 227 "tokenizer.lex"
1351
-/* Skip comments */
1350
+{ *yylval = (void *) strdup(yytext); return IDENT; }
1352 1351
 	YY_BREAK
1353 1352
 case 72:
1354 1353
 /* rule 72 can match eol */
1355 1354
 YY_RULE_SETUP
1356 1355
 #line 229 "tokenizer.lex"
1357
-/* Skip whitespace */
1356
+/* Skip comments */
1358 1357
 	YY_BREAK
1359 1358
 case 73:
1359
+/* rule 73 can match eol */
1360 1360
 YY_RULE_SETUP
1361 1361
 #line 231 "tokenizer.lex"
1362
+/* Skip whitespace */
1363
+	YY_BREAK
1364
+case 74:
1365
+YY_RULE_SETUP
1366
+#line 233 "tokenizer.lex"
1362 1367
 ECHO;
1363 1368
 	YY_BREAK
1364
-#line 1364 "lex.yy.c"
1369
+#line 1369 "lex.yy.c"
1365 1370
 case YY_STATE_EOF(INITIAL):
1366 1371
 	yyterminate();
1367 1372
 
@@ -1655,7 +1660,7 @@ static int yy_get_next_buffer (void)
1655 1660
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
1656 1661
 			{
1657 1662
 			yy_current_state = (int) yy_def[yy_current_state];
1658
-			if ( yy_current_state >= 152 )
1663
+			if ( yy_current_state >= 154 )
1659 1664
 				yy_c = yy_meta[yy_c];
1660 1665
 			}
1661 1666
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@@ -1683,11 +1688,11 @@ static int yy_get_next_buffer (void)
1683 1688
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
1684 1689
 		{
1685 1690
 		yy_current_state = (int) yy_def[yy_current_state];
1686
-		if ( yy_current_state >= 152 )
1691
+		if ( yy_current_state >= 154 )
1687 1692
 			yy_c = yy_meta[yy_c];
1688 1693
 		}
1689 1694
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
1690
-	yy_is_jam = (yy_current_state == 151);
1695
+	yy_is_jam = (yy_current_state == 153);
1691 1696
 
1692 1697
 		return yy_is_jam ? 0 : yy_current_state;
1693 1698
 }
@@ -2365,7 +2370,7 @@ void yyfree (void * ptr )
2365 2370
 
2366 2371
 #define YYTABLES_NAME "yytables"
2367 2372
 
2368
-#line 231 "tokenizer.lex"
2373
+#line 233 "tokenizer.lex"
2369 2374
 
2370 2375
 
2371 2376
 int yywrap(void) {

+ 7454
- 7197
parser.output
File diff suppressed because it is too large
View File


+ 714
- 690
parser.tab.c
File diff suppressed because it is too large
View File


+ 60
- 59
parser.tab.h View File

@@ -47,65 +47,66 @@ extern int yydebug;
47 47
   {
48 48
     IF = 258,
49 49
     THEN = 259,
50
-    ELSE = 260,
51
-    WHILE = 261,
52
-    FOR = 262,
53
-    IN = 263,
54
-    DO = 264,
55
-    FUNC = 265,
56
-    LAMBDA = 266,
57
-    RETURN = 267,
58
-    BREAK = 268,
59
-    CONTINUE = 269,
60
-    END = 270,
61
-    NONE = 271,
62
-    IDENT = 272,
63
-    INT = 273,
64
-    FLOAT = 274,
65
-    STRING = 275,
66
-    PLUS = 276,
67
-    MINUS = 277,
68
-    STAR = 278,
69
-    SLASH = 279,
70
-    PERCENT = 280,
71
-    DSTAR = 281,
72
-    BAND = 282,
73
-    BOR = 283,
74
-    BXOR = 284,
75
-    BNOT = 285,
76
-    LAND = 286,
77
-    LOR = 287,
78
-    LNOT = 288,
79
-    ASSIGN = 289,
80
-    ASSIGNPLUS = 290,
81
-    ASSIGNMINUS = 291,
82
-    ASSIGNSTAR = 292,
83
-    ASSIGNSLASH = 293,
84
-    ASSIGNDSTAR = 294,
85
-    ASSIGNBAND = 295,
86
-    ASSIGNBOR = 296,
87
-    ASSIGNBXOR = 297,
88
-    EQUAL = 298,
89
-    NEQUAL = 299,
90
-    LESS = 300,
91
-    GREATER = 301,
92
-    LESSEQ = 302,
93
-    GREATEREQ = 303,
94
-    RSHIFT = 304,
95
-    LSHIFT = 305,
96
-    LBRACE = 306,
97
-    RBRACE = 307,
98
-    BLPAREN = 308,
99
-    LPAREN = 309,
100
-    RPAREN = 310,
101
-    LBRACKET = 311,
102
-    RBRACKET = 312,
103
-    DOT = 313,
104
-    COLON = 314,
105
-    SEMICOLON = 315,
106
-    COMMA = 316,
107
-    POUND = 317,
108
-    TBANG = 318
50
+    ELSEIF = 260,
51
+    ELSE = 261,
52
+    WHILE = 262,
53
+    FOR = 263,
54
+    IN = 264,
55
+    DO = 265,
56
+    FUNC = 266,
57
+    LAMBDA = 267,
58
+    RETURN = 268,
59
+    BREAK = 269,
60
+    CONTINUE = 270,
61
+    END = 271,
62
+    NONE = 272,
63
+    IDENT = 273,
64
+    INT = 274,
65
+    FLOAT = 275,
66
+    STRING = 276,
67
+    PLUS = 277,
68
+    MINUS = 278,
69
+    STAR = 279,
70
+    SLASH = 280,
71
+    PERCENT = 281,
72
+    DSTAR = 282,
73
+    BAND = 283,
74
+    BOR = 284,
75
+    BXOR = 285,
76
+    BNOT = 286,
77
+    LAND = 287,
78
+    LOR = 288,
79
+    LNOT = 289,
80
+    ASSIGN = 290,
81
+    ASSIGNPLUS = 291,
82
+    ASSIGNMINUS = 292,
83
+    ASSIGNSTAR = 293,
84
+    ASSIGNSLASH = 294,
85
+    ASSIGNDSTAR = 295,
86
+    ASSIGNBAND = 296,
87
+    ASSIGNBOR = 297,
88
+    ASSIGNBXOR = 298,
89
+    EQUAL = 299,
90
+    NEQUAL = 300,
91
+    LESS = 301,
92
+    GREATER = 302,
93
+    LESSEQ = 303,
94
+    GREATEREQ = 304,
95
+    RSHIFT = 305,
96
+    LSHIFT = 306,
97
+    LBRACE = 307,
98
+    RBRACE = 308,
99
+    BLPAREN = 309,
100
+    LPAREN = 310,
101
+    RPAREN = 311,
102
+    LBRACKET = 312,
103
+    RBRACKET = 313,
104
+    DOT = 314,
105
+    COLON = 315,
106
+    SEMICOLON = 316,
107
+    COMMA = 317,
108
+    POUND = 318,
109
+    TBANG = 319
109 110
   };
110 111
 #endif
111 112
 

+ 39
- 20
parser.y View File

@@ -5,13 +5,23 @@
5 5
 #include <string.h>
6 6
 
7 7
 #define YYSTYPE void *
8
+#define YYLTYPE loc_t
9
+
10
+/* Hacks */
11
+#define first_line line
12
+#define last_line line
13
+#define first_column col
14
+#define last_column col
15
+
16
+int yylex(YYSTYPE *, loc_t *);
17
+void yyerror(loc_t *, stmt_node **, char *);
8 18
 
9 19
 %}
10 20
 
11 21
 %define lr.type ielr
12 22
 %define api.pure full
13 23
 
14
-%token IF THEN ELSE
24
+%token IF THEN ELSEIF ELSE
15 25
 %token WHILE FOR IN DO
16 26
 %token FUNC LAMBDA RETURN BREAK CONTINUE
17 27
 %token END NONE
@@ -71,21 +81,13 @@ expr:
71 81
 ;
72 82
 
73 83
 control_expr:
74
-  IF expr THEN stmt_list END {
75
-	$$ = NEW_EX();
76
-	AS_EX($$)->type = EX_IFELSE;
77
-	AS_EX($$)->ifelse = NEW(ifelse_node);
78
-	AS_EX($$)->ifelse->cond = $2;
79
-	AS_EX($$)->ifelse->iftrue = $4;
80
-	AS_EX($$)->ifelse->iffalse = NULL;
81
-}
82
-| IF expr THEN stmt_list ELSE stmt_list END {
84
+  IF expr THEN stmt_list if_termin {
83 85
 	$$ = NEW_EX();
84 86
 	AS_EX($$)->type = EX_IFELSE;
85 87
 	AS_EX($$)->ifelse = NEW(ifelse_node);
86 88
 	AS_EX($$)->ifelse->cond = $2;
87 89
 	AS_EX($$)->ifelse->iftrue = $4;
88
-	AS_EX($$)->ifelse->iffalse = $6;
90
+	AS_EX($$)->ifelse->iffalse = $5;
89 91
 }
90 92
 | WHILE expr DO stmt_list END {
91 93
 	$$ = NEW_EX();
@@ -105,6 +107,23 @@ control_expr:
105 107
 | assign_expr { $$ = $1; }
106 108
 ;
107 109
 
110
+if_termin:
111
+	ELSEIF expr THEN stmt_list if_termin {
112
+		$$ = NEW_ST();
113
+		AS_ST($$)->type = ST_EXPR;
114
+		AS_ST($$)->expr = NEW_EX();
115
+		AS_ST($$)->expr->type = EX_IFELSE;
116
+		AS_ST($$)->expr->ifelse = NEW(ifelse_node);
117
+		AS_ST($$)->expr->ifelse->cond = $2;
118
+		AS_ST($$)->expr->ifelse->iftrue = $4;
119
+		AS_ST($$)->expr->ifelse->iffalse = $5;
120
+	}
121
+|	ELSE stmt_list END {
122
+		$$ = $2;
123
+	}
124
+|	END { $$ = NULL; }
125
+;
126
+
108 127
 assign_expr:
109 128
   IDENT ASSIGN expr { $$ = NEW_EX(); AS_EX($$)->type = EX_ASSIGN; AS_EX($$)->assign = NEW(assign_node); AS_EX($$)->assign->ident = $1; AS_EX($$)->assign->value = $3; }
110 129
 | IDENT ASSIGNPLUS expr {
@@ -165,7 +184,7 @@ assign_expr:
165 184
   }
166 185
 | ex_index_expr ASSIGN expr {
167 186
     if(AS_EX($1)->type != EX_INDEX) {
168
-        yyerror("Assigning to non-indexing expression");
187
+        yyerror(&@$, NULL, "Assigning to non-indexing expression");
169 188
         YYABORT;
170 189
     }
171 190
     $$ = NEW_EX();
@@ -178,7 +197,7 @@ assign_expr:
178 197
 }
179 198
 | ex_index_expr ASSIGNPLUS expr {
180 199
     if(AS_EX($1)->type != EX_INDEX) {
181
-        yyerror("Assigning to non-indexing expression");
200
+        yyerror(&@$, NULL, "Assigning to non-indexing expression");
182 201
         YYABORT;
183 202
     }
184 203
     $$ = NEW_EX();
@@ -191,7 +210,7 @@ assign_expr:
191 210
 }
192 211
 | ex_index_expr ASSIGNMINUS expr {
193 212
     if(AS_EX($1)->type != EX_INDEX) {
194
-        yyerror("Assigning to non-indexing expression");
213
+        yyerror(&@$, NULL, "Assigning to non-indexing expression");
195 214
         YYABORT;
196 215
     }
197 216
     $$ = NEW_EX();
@@ -204,7 +223,7 @@ assign_expr:
204 223
 }
205 224
 | ex_index_expr ASSIGNSTAR expr {
206 225
     if(AS_EX($1)->type != EX_INDEX) {
207
-        yyerror("Assigning to non-indexing expression");
226
+        yyerror(&@$, NULL, "Assigning to non-indexing expression");
208 227
         YYABORT;
209 228
     }
210 229
     $$ = NEW_EX();
@@ -217,7 +236,7 @@ assign_expr:
217 236
 }
218 237
 | ex_index_expr ASSIGNSLASH expr {
219 238
     if(AS_EX($1)->type != EX_INDEX) {
220
-        yyerror("Assigning to non-indexing expression");
239
+        yyerror(&@$, NULL, "Assigning to non-indexing expression");
221 240
         YYABORT;
222 241
     }
223 242
     $$ = NEW_EX();
@@ -230,7 +249,7 @@ assign_expr:
230 249
 }
231 250
 | ex_index_expr ASSIGNDSTAR expr {
232 251
     if(AS_EX($1)->type != EX_INDEX) {
233
-        yyerror("Assigning to non-indexing expression");
252
+        yyerror(&@$, NULL, "Assigning to non-indexing expression");
234 253
         YYABORT;
235 254
     }
236 255
     $$ = NEW_EX();
@@ -243,7 +262,7 @@ assign_expr:
243 262
 }
244 263
 | ex_index_expr ASSIGNBAND expr {
245 264
     if(AS_EX($1)->type != EX_INDEX) {
246
-        yyerror("Assigning to non-indexing expression");
265
+        yyerror(&@$, NULL, "Assigning to non-indexing expression");
247 266
         YYABORT;
248 267
     }
249 268
     $$ = NEW_EX();
@@ -256,7 +275,7 @@ assign_expr:
256 275
 }
257 276
 | ex_index_expr ASSIGNBOR expr {
258 277
     if(AS_EX($1)->type != EX_INDEX) {
259
-        yyerror("Assigning to non-indexing expression");
278
+        yyerror(&@$, NULL, "Assigning to non-indexing expression");
260 279
         YYABORT;
261 280
     }
262 281
     $$ = NEW_EX();
@@ -269,7 +288,7 @@ assign_expr:
269 288
 }
270 289
 | ex_index_expr ASSIGNBXOR expr {
271 290
     if(AS_EX($1)->type != EX_INDEX) {
272
-        yyerror("Assigning to non-indexing expression");
291
+        yyerror(&@$, NULL, "Assigning to non-indexing expression");
273 292
         YYABORT;
274 293
     }
275 294
     $$ = NEW_EX();

+ 671
- 0
programs/chip8.sol View File

@@ -0,0 +1,671 @@
1
+chr2hex_t = {}
2
+hex2chr_t = {}
3
+
4
+for i in range(10) do
5
+	c = chr(ord('0') + i)
6
+	chr2hex_t[c] = i
7
+	hex2chr_t[i] = c
8
+end
9
+
10
+for i in [10, 11, 12, 13, 14, 15] do
11
+	c = chr(ord('A') + i - 10)
12
+	chr2hex_t[c] = i
13
+	hex2chr_t[i] = c
14
+end
15
+
16
+func new_reg()
17
+	return {
18
+		V = [0] * 16,
19
+		I = 0,
20
+		IP = 512,
21
+		ST = 0,
22
+		DT = 0,
23
+	}
24
+end
25
+
26
+func new_mem()
27
+	return [
28
+		240, 144, 144, 144, 240,  -- 0
29
+		32, 96, 32, 32, 112,      -- 1
30
+		240, 16, 240, 128, 240,   -- 2
31
+		240, 16, 240, 16, 240,    -- 3
32
+		144, 144, 240, 16, 16,    -- 4
33
+		240, 128, 240, 16, 240,   -- 5
34
+		240, 128, 240, 144, 240,  -- 6
35
+		240, 16, 32, 64, 64,      -- 7
36
+		240, 144, 240, 144, 240,  -- 8
37
+		240, 144, 240, 16, 240,   -- 9
38
+		240, 144, 240, 144, 144,  -- A
39
+		224, 144, 224, 144, 224,  -- B
40
+		240, 128, 128, 128, 240,  -- C
41
+		224, 144, 144, 144, 224,  -- D
42
+		240, 128, 240, 128, 240,  -- E
43
+		240, 128, 240, 128, 128,  -- F
44
+	] + [0] * 4016
45
+end
46
+
47
+func mem_int(mem, i, bytes)
48
+	r = 0
49
+	while (bytes > 0) && (i < 4096) do
50
+		r = (r << 8) | mem[i]
51
+		i += 1
52
+		bytes -= 1
53
+	end
54
+	return r
55
+end
56
+
57
+func load_buffer(mem, addr, s)
58
+	if None == addr then addr = 512 end
59
+	idx = 0
60
+	while (idx < s:size()) && (addr < 4096) do
61
+		mem[addr] = s:get(buffer.type.byte, idx)
62
+		addr += 1
63
+		idx += 1
64
+	end
65
+end
66
+
67
+func load_stream(mem, addr, str)
68
+	load_buffer(mem, addr, str:read_buffer(io.ALL))
69
+end
70
+
71
+func get_bit(v, i)
72
+	return (v >> i) & 1
73
+end
74
+
75
+func new_disp(w, h)
76
+	if w == None then w = 64 end
77
+	if h == None then h = 32 end
78
+	return {
79
+		fb = [0] * (64 * 32),
80
+		w = w,
81
+		h = h,
82
+	}
83
+end
84
+
85
+func disp_blit(b, x, y, v)
86
+	idx = y * (b.w) + x
87
+	changed = 0
88
+	for bit in range(8) do
89
+		if (idx >= 0) && (idx < (b.w) * (b.h)) then
90
+			oldb = b.fb[idx]
91
+			b.fb[idx] ^= if v & 128 then 1 else 0 end
92
+			changed = changed || ((!oldb) && (b.fb[idx]))
93
+			idx += 1
94
+			v = v << 1
95
+		end
96
+	end
97
+	return changed
98
+end
99
+
100
+func print_sprite(m, i, n)
101
+	if None == n then n = 15 end
102
+	fake_fb = new_disp(8, n)
103
+	for idx in range(n) do
104
+		disp_blit(fake_fb, 0, idx, m[i + idx])
105
+	end
106
+	print(disp_render(fake_fb))
107
+end
108
+
109
+NL = chr(10)
110
+CSI = chr(27) + '['
111
+
112
+func clear_screen()
113
+	io.stdout:write(CSI+'H'+CSI+'2J')
114
+end
115
+
116
+func disp_render(d)
117
+	s = ''
118
+	for row in range(d.h) do
119
+		s = s + disp_render_row(d, row) + NL
120
+	end
121
+	return s
122
+end
123
+
124
+func disp_render_row(d, r)
125
+	t = ''
126
+	for col in range(d.w) do
127
+		idx = r * (d.w) + col
128
+		if d.fb[idx] then
129
+			t += '*'
130
+		else
131
+			t += ' '
132
+		end
133
+	end
134
+	return t
135
+end
136
+
137
+func unused_syscall(state, n)
138
+	state:log("unknown syscall " + tostring(n))
139
+end
140
+
141
+func clear_disp(state, n)
142
+	state.disp = new_disp()
143
+end
144
+
145
+func ret(state, n)
146
+	state:jump(state:pop())
147
+end
148
+
149
+func new_sys()
150
+	sys = [unused_syscall] * 4096
151
+	sys[224] = clear_disp
152
+	sys[238] = ret
153
+	return sys
154
+end
155
+
156
+func new_state()
157
+	return {
158
+		reg = new_reg(),
159
+		mem = new_mem(),
160
+		disp = new_disp(),
161
+		sys = new_sys(),
162
+		jumped = false,
163
+		trace = false,
164
+		jump = func(self, ip)
165
+			self.reg.IP = ip
166
+			self.jumped = true
167
+		end,
168
+		skip = func(self)
169
+			self.reg.IP += 2
170
+		end,
171
+		stack = [],
172
+		push = func(self, v)
173
+			self.stack:insert(#(self.stack), v)
174
+			if (#self.stack) > 16 then
175
+				self:log("stack overflow: " + tostring(self.stack))
176
+			end
177
+		end,
178
+		pop = func(self)
179
+			if (#self.stack) == 0 then
180
+				self:log("stack underflow")
181
+				return 0
182
+			end
183
+			return self.stack:remove((#self.stack) - 1)
184
+		end,
185
+		keys = [0] * 16,
186
+		buffer = [],
187
+		log = func(self, msg)
188
+			self.buffer:insert(#(self.buffer), msg)
189
+		end,
190
+		breaks = [],
191
+		-- wchan = None
192
+	}
193
+end
194
+
195
+func new_insn(n)
196
+	return {
197
+		nib = [(n >> 12) & 15, (n >> 8) & 15, (n >> 4) & 15, n & 15],
198
+		byte = {high = (n >> 8) & 255, low = n & 255},
199
+		addr = n & 4095,
200
+		n = n,
201
+	}
202
+end
203
+
204
+func rand(n=0)
205
+	n = ((n * 17) + 1569752) % 3707765549
206
+	n = (n << 1) | (((n >> 3) & 1) ^ ((n >> 6) & 1))
207
+	n = (n << 1) | (((n >> 8) & 1) ^ ((n >> 5) & 1))
208
+	n = ((n * 7) + 67293512) % 3747882443
209
+	n = (n << 1) | (((n >> 7) & 1) ^ ((n >> 2) & 1))
210
+	n = (n << 1) | (((n >> 4) & 1) ^ ((n >> 3) & 1))
211
+	return n
212
+end
213
+
214
+func seed(n)
215
+	rand.closure.n = n
216
+end
217
+
218
+func bad_op(state, ins)
219
+	state:log("bad insn: " + tostring(ins.n) + " " + tostring(ins.nib))
220
+end
221
+
222
+insns = {
223
+	[0] = func insn0(state, ins)
224
+		state.sys[ins.addr](state, ins.addr)
225
+	end,
226
+	[1] = func insn1(state, ins)
227
+		state:jump(ins.addr)
228
+	end,
229
+	[2] = func insn2(state, ins)
230
+		state:push(state.reg.IP + 2)
231
+		state:jump(ins.addr)
232
+	end,
233
+	[3] = func insn3(state, ins)
234
+		if state.reg.V[ins.nib[1]] == ins.byte.low then
235
+			state:skip()
236
+		end
237
+	end,
238
+	[4] = func insn4(state, ins)
239
+		if state.reg.V[ins.nib[1]] != ins.byte.low then
240
+			state:skip()
241
+		end
242
+	end,
243
+	[5] = func insn5(state, ins)
244
+		if state.reg.V[ins.nib[1] ]== state.reg.V[ins.nib[2]] then
245
+			state:skip()
246
+		end
247
+	end,
248
+	[6] = func insn6(state, ins)
249
+		state.reg.V[ins.nib[1]] = ins.byte.low
250
+	end,
251
+	[7] = func insn7(state, ins)
252
+		state.reg.V[ins.nib[1]] = (state.reg.V[ins.nib[1]] + (ins.byte.low)) & 255
253
+	end,
254
+	[8] = func insn8(state, ins)
255
+		{
256
+			[0] = func insn8_0(state, ins)
257
+				state.reg.V[ins.nib[1]] = state.reg.V[ins.nib[2]]
258
+			end,
259
+			[1] = func insn8_1(state, ins)
260
+				state.reg.V[ins.nib[1]] |= state.reg.V[ins.nib[2]]
261
+			end,
262
+			[2] = func insn8_2(state, ins)
263
+				state.reg.V[ins.nib[1]] &= state.reg.V[ins.nib[2]]
264
+			end,
265
+			[3] = func insn8_3(state, ins)
266
+				state.reg.V[ins.nib[1]] ^= state.reg.V[ins.nib[2]]
267
+			end,
268
+			[4] = func insn8_4(state, ins)
269
+				sum = state.reg.V[ins.nib[1]] + (state.reg.V[ins.nib[2]])
270
+				state.reg.V[ins.nib[1]] = sum & 255
271
+				state.reg.V[15] = if (sum >> 8) then 1 else 0 end
272
+			end,
273
+			[5] = func insn8_5(state, ins)
274
+				diff = state.reg.V[ins.nib[1]] - (state.reg.V[ins.nib[2]])
275
+				state.reg.V[ins.nib[1]] = diff & 255
276
+				state.reg.V[15] = if (diff >> 8) then 1 else 0 end
277
+			end,
278
+			[6] = func insn8_6(state, ins)
279
+				state.reg.V[15] = state.reg.V[ins.nib[1]] & 1
280
+				state.reg.V[ins.nib[1]] = (state.reg.V[ins.nib[1]] >> 1)
281
+			end,
282
+			[7] = func insn8_7(state, ins)
283
+				state.reg.V[15] = if state.reg.V[ins.nib[2]] > (state.reg.V[ins.nib[1]]) then 1 else 0 end
284
+				state.reg.V[ins.nib[1]] = (stat.reg.V[ins.nib[2]] - (state.reg.V[ins.nib[1]]))
285
+			end,
286
+			[8] = bad_op, [9] = bad_op, [10] = bad_op, [11] = bad_op, [12] = bad_op, [13] = bad_op,
287
+			[14] = func insn8_14(state, ins)
288
+				state.reg.V[15] = (state.reg.V[ins.nib[1]] & 128) >> 7
289
+				state.reg.V[ins.nib[1]] = (state.reg.V[ins.nib[1]] << 1) & 255
290
+			end,
291
+			[15] = bad_op,
292
+		}[ins.nib[3]](state, ins)
293
+	end,
294
+	[9] = func insn9(state, ins)
295
+		if state.reg.V[ins.nib[1]] != state.reg.V[ins.nib[2]] then
296
+			state:skip()
297
+		end
298
+	end,
299
+	[10] = func insn10(state, ins)
300
+		state.reg.I = ins.addr
301
+	end,
302
+	[11] = func insn11(state, ins)
303
+		state:jump(ins.addr + state.reg.V[0])
304
+	end,
305
+	[12] = func insn12(state, ins)
306
+		state.reg.V[ins.nib[1]] = rand() & ins.byte.low
307
+	end,
308
+	[13] = func insn13(state, ins)
309
+		x = state.reg.V[ins.nib[1]]
310
+		y = state.reg.V[ins.nib[2]]
311
+		n = ins.nib[2]
312
+		i = state.reg.I
313
+		c = 0
314
+		for idx in range(n) do
315
+			if (i >= 0) && (i < 4095) then
316
+				c = c || disp_blit(state.disp, x, y, state.mem[i])
317
+			end
318
+			i += 1
319
+			y += 1
320
+		end
321
+		state.reg.V[15] = c
322
+	end,
323
+	[14] = func insn14(state, ins)
324
+		if ins.byte.low == 158 then
325
+			if state.keys[ins.nib[1]] then
326
+				state:skip()
327
+			end
328
+			return
329
+		end
330
+		if ins.byte.low == 161 then
331
+			if !(state.keys[ins.nib[1]]) then
332
+				state:skip()
333
+			end
334
+			return
335
+		end
336
+		bad_op(state, ins)
337
+	end,
338
+	[15] = func insn15(state, ins)
339
+		if ins.byte.low == 7 then
340
+			state.reg.V[ins.nib[1]] = state.reg.DT
341
+			return
342
+		end
343
+		if ins.byte.low == 10 then
344
+			state:log("waiting on key...")
345
+			state.wchan = {type="key", reg=ins.nib[1]}
346
+			return
347
+		end
348
+		if ins.byte.low == 21 then
349
+			state.reg.DT = state.reg.V[ins.nib[1]]
350
+			return
351
+		end
352
+		if ins.byte.low == 24 then
353
+			state.reg.ST = state.reg.V[ins.nib[1]]
354
+			return
355
+		end
356
+		if ins.byte.low == 30 then
357
+			state.reg.I = (state.reg.I + (state.reg.V[ins.nib[1]])) & 65535
358
+			return
359
+		end
360
+		if ins.byte.low == 41 then
361
+			state.reg.I = 5 * (state.reg.V[ins.nib[1]] & 15)
362
+			return
363
+		end
364
+		if ins.byte.low == 51 then
365
+			if state.reg.I >= 4093 then
366
+				state:log('BCD OOB @' + (state.reg.IP) + ': I=' + (state.reg.I))
367
+				return
368
+			end
369
+			bcd = tostring(state.reg.V[ins.nib[1]])
370
+			while (#bcd) < 3 do bcd = '0' + bcd end
371
+			state.mem[state.reg.I] = ord(bcd[0]) - ord('0')
372
+			state.mem[state.reg.I + 1] = ord(bcd[1]) - ord('0')
373
+			state.mem[state.reg.I + 2] = ord(bcd[2]) - ord('0')
374
+			return
375
+		end
376
+		if (ins.byte.low == 85) || (ins.byte.low == 101)then
377
+			if state.reg.I + (ins.nib[1]) >= 4096 then
378
+				state:log((if ins.byte.low == 85 then 'S' else 'R' end) + 'VC OOB @' + (state.reg.IP) + ': I=' + (state.reg.I) + ', n=' + (ins.nib[1]))
379
+				return
380
+			end
381
+			for n in range(ins.nib[1] + 1) do
382
+				if ins.byte.low == 85 then
383
+					state.mem[state.reg.I + n] = state.reg.V[n]
384
+				else
385
+					state.reg.V[n] = state.mem[state.reg.I + n]
386
+				end
387
+			end
388
+			return
389
+		end
390
+		bad_op(state, ins)
391
+	end,
392
+}
393
+
394
+func bad_disas(state, ins)
395
+	nibs = for n in ins.nib do continue n end
396
+	return '.DB ' + nibs:map(lambda(n) hex2chr_t[n] end):reduce(lambda(x, y) x + y end, "")
397
+end
398
+
399
+disas = {
400
+	[0] = func disas0(state, ins)
401
+		return 'SYS ' + tostring(ins.addr) + '  ; (' + tostring(state.sys[ins.addr]) + ')'
402
+	end,
403
+	[1] = func disas1(state, ins)
404
+		return 'JMP ' + tostring(ins.addr)
405
+	end,
406
+	[2] = func disas2(state, ins)
407
+		return 'CAL ' + tostring(ins.addr)
408
+	end,
409
+	[3] = func disas3(state, ins)
410
+		return 'SKE V' + tostring(ins.nib[1]) + ', ' + tostring(ins.byte.low)
411
+	end,
412
+	[4] = func disas4(state, ins)
413
+		return 'SKN V' + tostring(ins.nib[1]) + ', ' + tostring(ins.byte.low)
414
+	end,
415
+	[5] = func disas5(state, ins)
416
+		return 'SKE V' + tostring(ins.nib[1]) + ', V' + tostring(ins.nib[2])
417
+	end,
418
+	[6] = func disas6(state, ins)
419
+		return 'MOV V' + tostring(ins.nib[1]) + ', ' + tostring(ins.byte.low)
420
+	end,
421
+	[7] = func disas7(state, ins)
422
+		return 'ADD V' + tostring(ins.nib[1]) + ', ' + tostring(ins.byte.low)
423
+	end,
424
+	[8] = func disas8(state, ins)
425
+		return {
426
+			[0] = func disas8_0(state, ins)
427
+				return 'MOV V' + tostring(ins.nib[1]) + ', V' + tostring(ins.nib[2])
428
+			end,
429
+			[1] = func disas8_1(state, ins)
430
+				return 'BOR V' + tostring(ins.nib[1]) + ', V' + tostring(ins.nib[2])
431
+			end,
432
+			[2] = func disas8_2(state, ins)
433
+				return 'BAN V' + tostring(ins.nib[1]) + ', V' + tostring(ins.nib[2])
434
+			end,
435
+			[3] = func disas8_3(state, ins)
436
+				return 'BXR V' + tostring(ins.nib[1]) + ', V' + tostring(ins.nib[2])
437
+			end,
438
+			[4] = func disas8_4(state, ins)
439
+				return 'ADD V' + tostring(ins.nib[1]) + ', V' + tostring(ins.nib[2])
440
+			end,
441
+			[5] = func disas8_5(state, ins)
442
+				return 'SUB V' + tostring(ins.nib[1]) + ', V' + tostring(ins.nib[2])
443
+			end,
444
+			[6] = func disas8_6(state, ins)
445
+				return 'SHR V' + tostring(ins.nib[1])
446
+			end,
447
+			[7] = func disas8_7(state, ins)
448
+				return 'SBR V' + tostring(ins.nib[1]) + ', V' + tostring(ins.nib[2]) + '  ; (SUB V' + tostring(ins.nib[2]) + ', V' + tostring(ins.nib[1]) + ')'
449
+			end,
450
+			[8] = bad_disas, [9] = bad_disas, [10] = bad_disas, [11] = bad_disas, [12] = bad_disas, [13] = bad_disas,
451
+			[14] = func disas8_14(state, ins)
452
+				return 'SHL V' + tostring(ins.nib[1])
453
+			end,
454
+			[15] = bad_disas
455
+		}[ins.nib[3]](state, ins)
456
+	end,
457
+	[9] = func disas9(state, ins)
458
+		return 'SKN V' + tostring(ins.nib[1]) + ', V' + tostring(ins.nib[2])
459
+	end,
460
+	[10] = func disas10(state, ins)
461
+		return 'MOV I, ' + tostring(ins.addr)
462
+	end,
463
+	[11] = func disas11(state, ins)
464
+		return 'JR0 ' + tostring(ins.addr)
465
+	end,
466
+	[12] = func disas12(state, ins)
467
+		return 'RND V' + tostring(ins.nib[1]) + ', ' + tostring(ins.byte.low)
468
+	end,
469
+	[13] = func disas13(state, ins)
470
+		return 'BLT V' + tostring(ins.nib[1]) + ', V' + tostring(ins.nib[2]) + ', ' + tostring(ins.nib[3])
471
+	end,
472
+	[14] = func disas14(state, ins)
473
+		if ins.byte.low == 158 then
474
+			return 'SKK ' + tostring(ins.nib[1])
475
+		end
476
+		if ins.byte.low == 161 then
477
+			return 'SNK ' + tostring(ins.nib[1])
478
+		end
479
+		return bad_disas(state, ins)
480
+	end,
481
+	[15] = func disas15(state, ins)
482
+		if ins.byte.low == 7 then
483
+			return 'MOV V' + tostring(ins.nib[1]) + ', DT'
484
+		end
485
+		if ins.byte.low == 10 then
486
+			return 'WAK V' + tostring(ins.nib[1])
487
+		end
488
+		if ins.byte.low == 21 then
489
+			return 'MOV DT, V' + tostring(ins.nib[1])
490
+		end
491
+		if ins.byte.low == 24 then
492
+			return 'MOV ST, V' + tostring(ins.nib[1])
493
+		end
494
+		if ins.byte.low == 30 then
495
+			return 'ADD I, V' + tostring(ins.nib[1])
496
+		end
497
+		if ins.byte.low == 41 then
498
+			return 'LDF V' + tostring(ins.nib[1])
499
+		end
500
+		if ins.byte.low == 51 then
501
+			return 'BCD V' + tostring(ins.nib[1])
502
+		end
503
+		if ins.byte.low == 85 then
504
+			return 'SVC ' + tostring(ins.nib[1])
505
+		end
506
+		if ins.byte.low == 101 then
507
+			return 'RVC ' + tostring(ins.nib[1])
508
+		end
509
+		return bad_disas(state, ins)
510
+	end,
511
+	__call = func(self, state, ins)
512
+		return self[ins.nib[0]](state, ins)
513
+	end,
514
+}
515
+
516
+func descr_list(l, prf, bias)
517
+	if None == bias then bias = 0 end
518
+	idx = -1
519
+	return (for i in l do idx += 1; continue prf + tostring(idx + bias) + '=' + tostring(i) end):reduce(lambda(x, y) x + " " + y end, ""):sub(1)
520
+end
521
+
522
+func descr_state(state, DESCR_CNT = range(15))
523
+	return 'IP=' + tostring(state.reg.IP) + ' I=' + tostring(state.reg.I) + '	[' + descr_list(for idx in DESCR_CNT do continue state.mem[state.reg.I + idx - 7] end, 'M', state.reg.I - 7) + ']	{' + descr_list(state.reg.V, 'V') + '} DT=' + tostring(state.reg.DT) + ' ST=' + tostring(state.reg.ST) + ' stack=' + tostring(state.stack)
524
+end
525
+
526
+func step_cpu(state, force)
527
+	ins = new_insn(mem_int(state.mem, state.reg.IP, 2))
528
+	if None != force then
529
+		for brk in state.breaks do
530
+			if brk(state, ins) then
531
+				state.wchan = {type="break", brk=brk}
532
+				return
533
+			end
534
+		end
535
+	end
536
+	if state.trace then state:log((for n in ins.nib do continue hex2chr_t[n] end):reduce(lambda(x, y) x + y end, '') + ': ' + disas(state, ins) + '  ;; ' + descr_state(state)) end
537
+	insns[ins.nib[0]](state, ins)
538
+	if !(state.jumped) then
539
+		state.reg.IP += 2
540
+	end
541
+	state.jumped = false
542
+end
543
+
544
+DISP_HEIGHT = (func()
545
+	buf = buffer.new(8)
546
+	io.stdin:ioctl(io.TIOCGWINSZ, buf)
547
+	return buf:get(buffer.type.uint16, 0)
548
+end)()
549
+
550
+DEBUG_VALS = {
551
+	s = lambda() step_cpu(state, true) end,  -- XXX Dynamic scope access
552
+	d = lambda(n) for i in range(n) do
553
+		ridx = i - n / 2
554
+		rip = IP + 2 * ridx
555
+		print(
556
+			if rip == IP then '=>' else '  ' end,
557
+			rip, ':',
558
+			disas(state, new_insn(mem_int(mem, IP + 2 * (i - (n / 2)), 2)))
559
+		)
560
+	end end,
561
+	q = lambda() state.running = false end,
562
+}
563
+
564
+func run_cpu(state, incnt, tmcnt)
565
+	if None == incnt then incnt = 20 end
566
+	if None == tmcnt then tmcnt = 15 end
567
+	icntrange = range(incnt)
568
+	state.running = true
569
+	while state.running do
570
+		if None == state.wchan then
571
+			for ictr in icntrange do
572
+				step_cpu(state)
573
+				if None != state.wchan then break end
574
+			end
575
+		end
576
+		clear_screen()
577
+		print(disp_render(state.disp))
578
+		io.stdout:write(descr_state(state) + ' ')
579
+		if state.reg.DT > 0 then
580
+			state.reg.DT -= tmcnt
581
+			if state.reg.DT < 0 then state.reg.DT = 0 end
582
+		end
583
+		if state.reg.ST > 0 then
584
+			print('***BEEP***')
585
+			state.reg.ST -= tmcnt
586
+			if state.reg.ST < 0 then state.reg.ST = 0 end
587
+		else
588
+			print('')
589
+		end
590
+		if (None != state.wchan) then
591
+			if state.wchan.type == "key" then
592
+				print('waiting on a key (0-15): ')
593
+				v = toint(io.stdin:read(io.LINE))
594
+				state.reg.V[state.wchan.reg] = v & 255
595
+			elseif state.wchan.type == "break" then
596
+				-- NOP
597
+			else
598
+				error('Unknown wait channel!')
599
+			end
600
+		end
601
+		if (#(state.buffer)) > 0 then
602
+			lctr = state.disp.h + 1
603
+			rem = #(state.buffer)
604
+			midx = 0
605
+			for msg in state.buffer do
606
+				if lctr >= DISP_HEIGHT - 1 then
607
+					io.stdout:write('(...and', rem, 'more [Enter/q])')
608
+					if io.stdin:read(io.LINE):sub(0, -1) == 'q' then break end
609
+					lctr = 0
610
+				end
611
+				print(midx, ':', msg)
612
+				rem -= 1
613
+				midx += 1
614
+				lctr += 1
615
+			end
616
+			while true do
617
+				io.stdout:write('(acknowledge/eval?) ')
618
+				ln = io.stdin:read(io.LINE):sub(0, -1)
619
+				if (#ln) > 0 then
620
+					res = try(parse, ln)
621
+					if res[0] then
622
+						res = try(lambda (nd) nd.stmtlist[0].expr(state.reg + state + DEBUG_VALS) end, res[1])
623
+						if res[0] then
624
+							print(res[1])
625
+						else
626
+							print('Exec error:', res[1])
627
+						end
628
+					else
629
+						print('Parse error:', res[1])
630
+					end
631
+				else
632
+					break
633
+				end
634
+			end
635
+			state.buffer = []
636
+		end
637
+	end
638
+end
639
+
640
+SEPARATOR = ('=#' * 38) + '='
641
+
642
+func main()
643
+	print('Enter filename to load: ')
644
+	fname = io.stdin:read(io.LINE):sub(0, -1)
645
+	strm = io.open(fname, io.MODE_READ|io.MODE_BINARY)
646
+	state = new_state()
647
+	load_stream(state.mem, None, strm)
648
+	while true do
649
+		io.stdout:write("(init)> ")
650
+		ln = io.stdin:read(io.LINE):sub(0, -1)
651
+		if (#ln) > 0 then
652
+			print(parse(ln).stmtlist[0].expr(state.reg + state))
653
+		else
654
+			break
655
+		end
656
+	end
657
+	res = try(run_cpu, state)
658
+	if !res[0] then
659
+		print('Error occurred:', res[1])
660
+		print(SEPARATOR)
661
+		print('Buffered logs not dumped before error:')
662
+		for msg in state.buffer do print(msg) end
663
+		print(SEPARATOR)
664
+		print('Starting post-mortem debugger...')
665
+		execfile('solid.sol')
666
+		debst = new_debug_state(res)
667
+		postmortem(debst)
668
+	end
669
+end
670
+
671
+main()

+ 9
- 3
programs/interp.sol View File

@@ -23,8 +23,13 @@ while __interp.running do
23 23
 	else
24 24
 		__interp.prompt = __interp.ps1
25 25
 	end
26
-	__interp.line = readline.readline(__interp.prompt)
27
-	if #__interp.line then readline.add_history(__interp.line) end
26
+	if None != readline then
27
+		__interp.line = readline.readline(__interp.prompt)
28
+		if #__interp.line then readline.add_history(__interp.line) end
29
+	else
30
+		__interp.line = io.stdin:read(io.LINE):sub(0, -1)
31
+	end
32
+	7
28 33
 	--prepr(__interp.line)
29 34
 	--prepr(__interp)
30 35
 	if (__interp.line:sub(-4, None)=="then") then
@@ -64,8 +69,9 @@ while __interp.running do
64 69
 								for ent in __interp.result[2] do
65 70
 									st = ent[0]
66 71
 									scope = ent[1]
72
+									fun = ent[2]
67 73
 									if st.type == ast.ST_LIST then continue end
68
-									print('In', st, 'at', st.loc.line, ',', st.loc.col, ':')
74
+									print('In', fun, 'at', st.loc.line, ',', st.loc.col, ':')
69 75
 									ast.print(st)
70 76
 									print(scope)
71 77
 									print('---')

+ 10
- 5
runtime.c View File

@@ -491,12 +491,12 @@ void pl_free(paramlist_node *list) {
491 491
 	if(list->rest) free(list->rest);
492 492
 }
493 493
 
494
-#define ERR_CHECK(state) do { if(sol_has_error(state)) longjmp(jmp, 1); } while(0)
494
+#define ERR_CHECK(state) do { if(sol_has_error(state)) { sol_add_traceback(state, sol_new_exprnode(state, ex_copy(expr))); longjmp(jmp, 1); } } while(0)
495 495
 sol_object_t *sol_eval_inner(sol_state_t *state, expr_node *expr, jmp_buf jmp) {
496
-	sol_object_t *res, *left, *right, *lint, *rint, *value, *list, *vint, *iter, *item;
497
-	exprlist_node *cure;
498
-	assoclist_node *cura;
499
-	identlist_node *curi;
496
+	sol_object_t *res = NULL, *left = NULL, *right = NULL, *lint = NULL, *rint = NULL, *value = NULL, *list = NULL, *vint = NULL, *iter = NULL, *item = NULL;
497
+	exprlist_node *cure = NULL;
498
+	assoclist_node *cura = NULL;
499
+	identlist_node *curi = NULL;
500 500
 	if(!expr) {
501 501
 		return sol_set_error_string(state, "Evaluate NULL expression");
502 502
 	}
@@ -1025,7 +1025,12 @@ sol_object_t *sol_f_func_call(sol_state_t *state, sol_object_t *args) {
1025 1025
 		sol_obj_free(key);
1026 1026
 	}
1027 1027
 	sol_state_push_scope(state, scope);
1028
+	sol_list_insert(state, state->fnstack, 0, value);
1028 1029
 	sol_exec(state, AS(value->func, stmt_node));
1030
+	key = sol_list_remove(state, state->fnstack, 0);
1031
+	if(key != value) {
1032
+		printf("ERROR: Function stack imbalanced\n");
1033
+	}
1029 1034
 	sol_state_pop_scope(state);
1030 1035
 	sol_map_merge_existing(state, value->closure, scope);
1031 1036
 	if(state->ret) {

+ 4
- 0
ser.c View File

@@ -575,6 +575,7 @@ void *sol_deser(FILE *io) {
575 575
 					node = AS(node, stmtlist_node)->next;
576 576
 				}
577 577
 				AS(node, stmtlist_node)->stmt = sol_deser_stmt(io);
578
+				AS(node, stmtlist_node)->next = NULL;
578 579
 			}
579 580
 			return obj;
580 581
 
@@ -589,6 +590,7 @@ void *sol_deser(FILE *io) {
589 590
 					node = AS(node, exprlist_node)->next;
590 591
 				}
591 592
 				AS(node, exprlist_node)->expr = sol_deser_expr(io);
593
+				AS(node, exprlist_node)->next = NULL;
592 594
 			}
593 595
 			return obj;
594 596
 
@@ -605,6 +607,7 @@ void *sol_deser(FILE *io) {
605 607
 				AS(node, assoclist_node)->item = NEW(associtem_node);
606 608
 				AS(node, assoclist_node)->item->key = sol_deser_expr(io);
607 609
 				AS(node, assoclist_node)->item->value = sol_deser_expr(io);
610
+				AS(node, assoclist_node)->next = NULL;
608 611
 			}
609 612
 			return obj;
610 613
 
@@ -619,6 +622,7 @@ void *sol_deser(FILE *io) {
619 622
 					node = AS(node, identlist_node)->next;
620 623
 				}
621 624
 				AS(node, identlist_node)->ident = sol_deser_checked(io, BC_STRING);
625
+				AS(node, identlist_node)->next = NULL;
622 626
 			}
623 627
 			return obj;
624 628
 

+ 11
- 5
sol.h View File

@@ -10,7 +10,7 @@
10 10
 #include "dsl/dsl.h"
11 11
 
12 12
 /** The version of the project, as made available through `debug.version`. */
13
-#define SOL_VERSION "0.3a2"
13
+#define SOL_VERSION "0.3a4"
14 14
 /** The hexadecimal version of the project, formatted 0xAAIIRPP where:
15 15
  * 
16 16
  * - AA is the two-digit major version
@@ -23,7 +23,7 @@
23 23
  * version shall be available in all versions numerically greater than it
24 24
  * (unless they are later deprecated or removed).
25 25
  */
26
-#define SOL_HEXVER 0x0003A02
26
+#define SOL_HEXVER 0x0003A04
27 27
 
28 28
 #ifndef SOL_BUILD_HOST
29 29
 #define SOL_BUILD_HOST "(unknown host)"
@@ -412,11 +412,12 @@ typedef struct sol_tag_state_t {
412 412
 	sol_object_t *scopes; ///< A list of scope maps, innermost out, ending at the global scope
413 413
 	sol_object_t *ret; ///< Return value of this function, for early return
414 414
 	sol_object_t *traceback; ///< The last stack of statement (nodes) in the last error, or NULL
415
+	sol_object_t *fnstack; ///< The stack of function objects (`SOL_FUNCTION`, `SOL_CFUNCTION`) in the current call stack
415 416
 	sol_state_flag_t sflag; ///< Used to implement break/continue
416 417
 	sol_object_t *error; ///< Some arbitrary error descriptor, `None` if no error
417
-	sol_object_t *stdout; ///< Standard output stream object (for print(), type `SOL_STREAM`)
418
-	sol_object_t *stdin; ///< Standard input stream object (type `SOL_STREAM`)
419
-	sol_object_t *stderr; ///< Standard error stream object (type `SOL_STREAM`)
418
+	sol_object_t *_stdout; ///< Standard output stream object (for print(), type `SOL_STREAM`)
419
+	sol_object_t *_stdin; ///< Standard input stream object (type `SOL_STREAM`)
420
+	sol_object_t *_stderr; ///< Standard error stream object (type `SOL_STREAM`)
420 421
 	sol_object_t *None; ///< The all-important `None` object
421 422
 	sol_object_t *OutOfMemory; ///< The semi-important `OutOfMemory` object
422 423
 	sol_ops_t NullOps; ///< Basic, initialized operations. Not used by any extant object type.
@@ -550,6 +551,8 @@ sol_object_t *sol_get_error(sol_state_t *);
550 551
 /** Set the current error.
551 552
  *
552 553
  * Sets the current error object. Clears the error if the object is `None`.
554
+ *
555
+ * Returns a new reference to `None`, suitable for returning elsewhere.
553 556
  */
554 557
 sol_object_t *sol_set_error(sol_state_t *, sol_object_t *);
555 558
 /** Set the current error to a string, given a C string.
@@ -814,6 +817,7 @@ sol_object_t *sol_f_list_remove(sol_state_t *, sol_object_t *);
814 817
 sol_object_t *sol_f_list_truncate(sol_state_t *, sol_object_t *);
815 818
 sol_object_t *sol_f_list_map(sol_state_t *, sol_object_t *);
816 819
 sol_object_t *sol_f_list_filter(sol_state_t *, sol_object_t *);
820
+sol_object_t *sol_f_list_reduce(sol_state_t *, sol_object_t *);
817 821
 
818 822
 sol_object_t *sol_f_map_add(sol_state_t *, sol_object_t *);
819 823
 sol_object_t *sol_f_map_index(sol_state_t *, sol_object_t *);
@@ -872,10 +876,12 @@ sol_object_t *sol_f_stream_tostring(sol_state_t *, sol_object_t *);
872 876
 
873 877
 sol_object_t *sol_f_stream_write(sol_state_t *, sol_object_t *);
874 878
 sol_object_t *sol_f_stream_read(sol_state_t *, sol_object_t *);
879
+sol_object_t *sol_f_stream_read_buffer(sol_state_t *, sol_object_t *);
875 880
 sol_object_t *sol_f_stream_seek(sol_state_t *, sol_object_t *);
876 881
 sol_object_t *sol_f_stream_tell(sol_state_t *, sol_object_t *);
877 882
 sol_object_t *sol_f_stream_flush(sol_state_t *, sol_object_t *);
878 883
 sol_object_t *sol_f_stream_eof(sol_state_t *, sol_object_t *);
884
+sol_object_t *sol_f_stream_ioctl(sol_state_t *, sol_object_t *);
879 885
 
880 886
 sol_object_t *sol_f_stream_open(sol_state_t *, sol_object_t *);
881 887
 

+ 6
- 0
solrun.c View File

@@ -2,7 +2,9 @@
2 2
 #include "ast.h"
3 3
 #include "parser.tab.h"
4 4
 
5
+#ifndef NO_HELP
5 6
 extern char _binary_sol_help_txt_start, _binary_sol_help_txt_end;
7
+#endif
6 8
 
7 9
 int main(int argc, char **argv) {
8 10
 	stmt_node *program;
@@ -58,12 +60,16 @@ int main(int argc, char **argv) {
58 60
 				case 'V':
59 61
 					printf(SOL_BUILD_ID "\n");
60 62
 				case 'h':
63
+#ifndef NO_HELP
61 64
 					fwrite(
62 65
 						&_binary_sol_help_txt_start,
63 66
 						1,
64 67
 						&_binary_sol_help_txt_end - &_binary_sol_help_txt_start,
65 68
 						stdout
66 69
 					);
70
+#else
71
+					printf("Sorry, no help in this version (-DNO_HELP)!\n");
72
+#endif
67 73
 					return 0;
68 74
 					break;
69 75
 			}

+ 36
- 18
state.c View File

@@ -2,6 +2,8 @@
2 2
 #include <stdio.h>
3 3
 #include <stdlib.h>
4 4
 #include <string.h>
5
+#include <termios.h>
6
+#include <sys/ioctl.h>
5 7
 #include "ast.h"
6 8
 
7 9
 #define TMP_PATH_SZ 256
@@ -228,9 +230,9 @@ int sol_state_init(sol_state_t *state) {
228 230
 		goto cleanup;
229 231
 	}
230 232
 
231
-	state->stdin = sol_new_stream(state, stdin, MODE_READ);
232
-	state->stdout = sol_new_stream(state, stdout, MODE_WRITE);
233
-	state->stderr = sol_new_stream(state, stderr, MODE_WRITE);
233
+	state->_stdin = sol_new_stream(state, stdin, MODE_READ);
234
+	state->_stdout = sol_new_stream(state, stdout, MODE_WRITE);
235
+	state->_stderr = sol_new_stream(state, stderr, MODE_WRITE);
234 236
 
235 237
 	// NB: None is actually a keyword in the language--it doesn't need to be a
236 238
 	// global (see parser.y)
@@ -279,11 +281,13 @@ int sol_state_init(sol_state_t *state) {
279 281
 	sol_register_module_name(state, "iter", mod);
280 282
 	sol_obj_free(mod);
281 283
 
284
+#ifndef NO_READLINE
282 285
 	mod = sol_new_map(state);
283 286
 	sol_map_borrow_name(state, mod, "readline", sol_new_cfunc(state, sol_f_readline_readline, "readline.readline"));
284 287
 	sol_map_borrow_name(state, mod, "add_history", sol_new_cfunc(state, sol_f_readline_add_history, "readline.add_history"));
285 288
 	sol_register_module_name(state, "readline", mod);
286 289
 	sol_obj_free(mod);
290
+#endif
287 291
 
288 292
 	mod = sol_new_map(state);
289 293
 	sol_map_borrow_name(state, mod, "ST_EXPR", sol_new_int(state, ST_EXPR));
@@ -424,6 +428,8 @@ int sol_state_init(sol_state_t *state) {
424 428
 	sol_map_borrow_name(state, mod, "SEEK_END", sol_new_int(state, SEEK_END));
425 429
 	sol_map_borrow_name(state, mod, "ALL", sol_new_string(state, "ALL"));
426 430
 	sol_map_borrow_name(state, mod, "LINE", sol_new_string(state, "LINE"));
431
+	sol_map_borrow_name(state, mod, "TIOCGWINSZ", sol_new_int(state, TIOCGWINSZ));
432
+	sol_map_borrow_name(state, mod, "TIOCSWINSZ", sol_new_int(state, TIOCSWINSZ));
427 433
 	sol_map_borrow_name(state, mod, "open", sol_new_cfunc(state, sol_f_stream_open, "io.open"));
428 434
 	sol_map_borrow_name(state, mod, "__setindex", sol_new_cfunc(state, sol_f_io_setindex, "io.__setindex"));
429 435
 	sol_map_borrow_name(state, mod, "__index", sol_new_cfunc(state, sol_f_io_index, "io.__index"));
@@ -445,16 +451,19 @@ int sol_state_init(sol_state_t *state) {
445 451
 	sol_map_borrow_name(state, meths, "truncate", sol_new_cfunc(state, sol_f_list_truncate, "list.truncate"));
446 452
 	sol_map_borrow_name(state, meths, "map", sol_new_cfunc(state, sol_f_list_map, "list.map"));
447 453
 	sol_map_borrow_name(state, meths, "filter", sol_new_cfunc(state, sol_f_list_filter, "list.filter"));
454
+	sol_map_borrow_name(state, meths, "reduce", sol_new_cfunc(state, sol_f_list_reduce, "list.reduce"));
448 455
 	sol_register_methods_name(state, "list", meths);
449 456
 	sol_obj_free(meths);
450 457
 
451 458
 	meths = sol_new_map(state);
452 459
 	sol_map_borrow_name(state, meths, "read", sol_new_cfunc(state, sol_f_stream_read, "stream.read"));
460
+	sol_map_borrow_name(state, meths, "read_buffer", sol_new_cfunc(state, sol_f_stream_read_buffer, "stream.read_buffer"));
453 461
 	sol_map_borrow_name(state, meths, "write", sol_new_cfunc(state, sol_f_stream_write, "stream.write"));
454 462
 	sol_map_borrow_name(state, meths, "seek", sol_new_cfunc(state, sol_f_stream_seek, "stream.seek"));
455 463
 	sol_map_borrow_name(state, meths, "tell", sol_new_cfunc(state, sol_f_stream_tell, "stream.tell"));
456 464
 	sol_map_borrow_name(state, meths, "flush", sol_new_cfunc(state, sol_f_stream_flush, "stream.flush"));
457 465
 	sol_map_borrow_name(state, meths, "eof", sol_new_cfunc(state, sol_f_stream_eof, "stream.eof"));
466
+	sol_map_borrow_name(state, meths, "ioctl", sol_new_cfunc(state, sol_f_stream_ioctl, "stream.ioctl"));
458 467
 	sol_register_methods_name(state, "stream", meths);
459 468
 	sol_obj_free(meths);
460 469
 
@@ -465,6 +474,8 @@ int sol_state_init(sol_state_t *state) {
465 474
 	sol_register_methods_name(state, "string", meths);
466 475
 	sol_obj_free(meths);
467 476
 
477
+	state->fnstack = sol_new_list(state);
478
+
468 479
 	if(sol_has_error(state)) {
469 480
 		goto cleanup;
470 481
 	}
@@ -547,9 +558,9 @@ void sol_state_cleanup(sol_state_t *state) {
547 558
 	sol_obj_free(state->error);
548 559
 	sol_obj_free(state->None);
549 560
 	sol_obj_free(state->OutOfMemory);
550
-	sol_obj_free(state->stdin);
551
-	sol_obj_free(state->stdout);
552
-	sol_obj_free(state->stderr);
561
+	sol_obj_free(state->_stdin);
562
+	sol_obj_free(state->_stdout);
563
+	sol_obj_free(state->_stderr);
553 564
 	if(state->ret) {
554 565
 		sol_obj_free(state->ret);
555 566
 	}
@@ -717,6 +728,13 @@ void sol_add_traceback(sol_state_t *state, sol_object_t *node) {
717 728
 	sol_list_insert(state, pair, 0, node);
718 729
 	sol_list_insert(state, pair, 1, scope);
719 730
 	sol_obj_free(scope);
731
+	if(sol_list_len(state, state->fnstack) > 0) {
732
+		scope = sol_list_get_index(state, state->fnstack, 0);
733
+		sol_list_insert(state, pair, 2, scope);
734
+		sol_obj_free(scope);
735
+	} else {
736
+		sol_list_insert(state, pair, 2, state->None);
737
+	}
720 738
 	sol_list_insert(state, state->traceback, 0, pair);
721 739
 	sol_obj_free(pair);
722 740
 }
@@ -765,17 +783,17 @@ sol_object_t *sol_f_io_index(sol_state_t *state, sol_object_t *args) {
765 783
 	if(sol_string_eq(state, namestr, "stdin")) {
766 784
 		sol_obj_free(name);
767 785
 		sol_obj_free(namestr);
768
-		return sol_incref(state->stdin);
786
+		return sol_incref(state->_stdin);
769 787
 	}
770 788
 	if(sol_string_eq(state, namestr, "stdout")) {
771 789
 		sol_obj_free(name);
772 790
 		sol_obj_free(namestr);
773
-		return sol_incref(state->stdout);
791
+		return sol_incref(state->_stdout);
774 792
 	}
775 793
 	if(sol_string_eq(state, namestr, "stderr")) {
776 794
 		sol_obj_free(name);
777 795
 		sol_obj_free(namestr);
778
-		return sol_incref(state->stderr);
796
+		return sol_incref(state->_stderr);
779 797
 	}
780 798
 	sol_obj_free(namestr);
781 799
 	res = sol_map_get(state, self, name);
@@ -788,18 +806,18 @@ sol_object_t *sol_f_io_setindex(sol_state_t *state, sol_object_t *args) {
788 806
 	sol_object_t *name = sol_list_get_index(state, args, 1), *value = sol_list_get_index(state, args, 2);
789 807
 	sol_object_t *namestr = sol_cast_string(state, name), *io;
790 808
 	if(sol_string_eq(state, namestr, "stdin")) {
791
-		sol_obj_free(state->stdin);
792
-		state->stdin = sol_incref(value);
809
+		sol_obj_free(state->_stdin);
810
+		state->_stdin = sol_incref(value);
793 811
 		goto done;
794 812
 	}
795 813
 	if(sol_string_eq(state, namestr, "stdout")) {
796
-		sol_obj_free(state->stdout);
797
-		state->stdout = sol_incref(value);
814
+		sol_obj_free(state->_stdout);
815
+		state->_stdout = sol_incref(value);
798 816
 		goto done;
799 817
 	}
800 818
 	if(sol_string_eq(state, namestr, "stderr")) {
801
-		sol_obj_free(state->stderr);
802
-		state->stderr = sol_incref(value);
819
+		sol_obj_free(state->_stderr);
820
+		state->_stderr = sol_incref(value);
803 821
 		goto done;
804 822
 	}
805 823
 	io = sol_list_get_index(state, args, 0);
@@ -813,15 +831,15 @@ done:
813 831
 }
814 832
 
815 833
 sol_object_t *sol_get_stdin(sol_state_t *state) {
816
-	return sol_incref(state->stdin);
834
+	return sol_incref(state->_stdin);
817 835
 }
818 836
 
819 837
 sol_object_t *sol_get_stdout(sol_state_t *state) {
820
-	return sol_incref(state->stdout);
838
+	return sol_incref(state->_stdout);
821 839
 }
822 840
 
823 841
 sol_object_t *sol_get_stderr(sol_state_t *state) {
824
-	return sol_incref(state->stderr);
842
+	return sol_incref(state->_stderr);
825 843
 }
826 844
 
827 845
 void sol_ops_init(sol_ops_t *ops) {

+ 28
- 0
tests/lang_elseif.sol View File

@@ -0,0 +1,28 @@
1
+execfile("tests/_lib.sol")
2
+
3
+f = lambda(x)
4
+	if x == 0 then
5
+		"foo"
6
+	elseif x == 1 then
7
+		"bar"
8
+	else
9
+		"baz"
10
+	end
11
+end
12
+
13
+g = lambda(x)
14
+	if x == 'a' then
15
+		7
16
+	elseif x == 'b' then
17
+		14
18
+	end
19
+end
20
+
21
+assert_eq(f(0), "foo", "if/elseif/else, if branch")
22
+assert_eq(f(1), "bar", "if/elseif/else, elseif branch")
23
+assert_eq(f(2), "baz", "if/elseif/else, else branch 1")
24
+assert_eq(f(7), "baz", "if/elseif/else, else branch 2")
25
+
26
+assert_eq(g('a'), 7, "if/elseif, if branch")
27
+assert_eq(g('b'), 14, "if/elseif, elseif branch")
28
+assert_eq(g(3), None, "if/elseif, no branch")

+ 2
- 0
tokenizer.lex View File

@@ -98,6 +98,8 @@ then { return THEN; }
98 98
 
99 99
 else { return ELSE; }
100 100
 
101
+elseif { return ELSEIF; }
102
+
101 103
 while { return WHILE; }
102 104
 
103 105
 for { return FOR; }

Loading…
Cancel
Save