Browse Source

Sol Part 46: POOOOSIX POOOWEEEERRRRRR!!!

Fixes #20
Graham Northup 5 years ago
parent
commit
f08f6a2c62
4 changed files with 424 additions and 103 deletions
  1. 50
    14
      ast.h
  2. 68
    52
      lex.yy.c
  3. 253
    37
      sol.h
  4. 53
    0
      state.c

+ 50
- 14
ast.h View File

@@ -5,6 +5,10 @@
5 5
 
6 6
 #include <stdio.h>
7 7
 
8
+/** Locator structure.
9
+ *
10
+ * Contains the location of a symbol; available on all `stmt_node`s and `expr_node`s as `loc`.
11
+ */
8 12
 typedef struct {
9 13
 	size_t line;
10 14
 	size_t col;
@@ -16,38 +20,70 @@ typedef struct tag_expr_node expr_node;
16 20
 struct tag_stmt_node;
17 21
 typedef struct tag_stmt_node stmt_node;
18 22
 
23
+/** Literal type
24
+ *
25
+ * Defines the types of literals that may appear in a source program.
26
+ */
19 27
 typedef enum {LIT_INT, LIT_FLOAT, LIT_STRING, LIT_NONE} lit_t;
28
+/** Literal node
29
+ *
30
+ * Represents a literal in a source program.
31
+ */
20 32
 typedef struct {
21
-	lit_t type;
33
+	lit_t type; ///< The type of literal.
22 34
 	union {
23
-		long ival;
24
-		double fval;
25
-		char *str;
35
+		long ival; ///< Integer value for `LIT_INT`.
36
+		double fval; ///< Floating-point value for `LIT_FLOAT`.
37
+		char *str; ///< String value for `LIT_STRING`.
26 38
 	};
27 39
 } lit_node;
28 40
 
41
+/** Binary operation type
42
+ *
43
+ * Defines the types of binary operators that may occur in a source program.
44
+ */
29 45
 typedef enum {OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW, OP_BAND, OP_BOR, OP_BXOR, OP_LAND, OP_LOR, OP_EQUAL, OP_NEQUAL, OP_LESS, OP_GREATER, OP_LESSEQ, OP_GREATEREQ, OP_LSHIFT, OP_RSHIFT, OP_TBANG} binop_t;
46
+/** Binary operation node
47
+ *
48
+ * Represents a binary operator in a source program.
49
+ */
30 50
 typedef struct {
31
-	binop_t type;
32
-	expr_node *left;
33
-	expr_node *right;
51
+	binop_t type; ///< The type of binary operation
52
+	expr_node *left; ///< The left hand side.
53
+	expr_node *right; ///< The right hand side.
34 54
 } binop_node;
35 55
 
56
+/** Unary operation type
57
+ *
58
+ * Defines the types of unary operators that may occur in a source program.
59
+ */
36 60
 typedef enum {OP_NEG, OP_BNOT, OP_LNOT, OP_LEN} unop_t;
61
+/** Unary opreation node
62
+ *
63
+ * Represents a unary operator in a source program.
64
+ */
37 65
 typedef struct {
38
-	unop_t type;
39
-	expr_node *expr;
66
+	unop_t type; ///< The type of unary operation.
67
+	expr_node *expr; ///< The value to which it is applied.
40 68
 } unop_node;
41 69
 
70
+/** Index node
71
+ *
72
+ * Represents an index operation in a source program.
73
+ */
42 74
 typedef struct {
43
-	expr_node *expr;
44
-	expr_node *index;
75
+	expr_node *expr; ///< Expression to index.
76
+	expr_node *index; ///< Expression to index by.
45 77
 } index_node;
46 78
 
79
+/** Setindex node
80
+ *
81
+ * Represents a setindex operation in a source program.
82
+ */
47 83
 typedef struct {
48
-	expr_node *expr;
49
-	expr_node *index;
50
-	expr_node *value;
84
+	expr_node *expr; ///< Expression to set the index of.
85
+	expr_node *index; ///< Expression to index by.
86
+	expr_node *value; ///< Value to set said index to.
51 87
 } setindex_node;
52 88
 
53 89
 typedef struct {

+ 68
- 52
lex.yy.c View File

@@ -7,8 +7,8 @@
7 7
 
8 8
 #define FLEX_SCANNER
9 9
 #define YY_FLEX_MAJOR_VERSION 2
10
-#define YY_FLEX_MINOR_VERSION 5
11
-#define YY_FLEX_SUBMINOR_VERSION 39
10
+#define YY_FLEX_MINOR_VERSION 6
11
+#define YY_FLEX_SUBMINOR_VERSION 0
12 12
 #if YY_FLEX_SUBMINOR_VERSION > 0
13 13
 #define FLEX_BETA
14 14
 #endif
@@ -352,11 +352,17 @@ extern int yylineno;
352 352
 int yylineno = 1;
353 353
 
354 354
 extern char *yytext;
355
+#ifdef yytext_ptr
356
+#undef yytext_ptr
357
+#endif
355 358
 #define yytext_ptr yytext
356 359
 
357 360
 static yy_state_type yy_get_previous_state (void );
358 361
 static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
359 362
 static int yy_get_next_buffer (void );
363
+#if defined(__GNUC__) && __GNUC__ >= 3
364
+__attribute__((__noreturn__))
365
+#endif
360 366
 static void yy_fatal_error (yyconst char msg[]  );
361 367
 
362 368
 /* Done after the current pattern has been matched and before the
@@ -398,7 +404,7 @@ static yyconst flex_int16_t yy_accept[148] =
398 404
         8,   69,   13,   14,   69,   16,    0
399 405
     } ;
400 406
 
401
-static yyconst flex_int32_t yy_ec[256] =
407
+static yyconst YY_CHAR yy_ec[256] =
402 408
     {   0,
403 409
         1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
404 410
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -430,7 +436,7 @@ static yyconst flex_int32_t yy_ec[256] =
430 436
         1,    1,    1,    1,    1
431 437
     } ;
432 438
 
433
-static yyconst flex_int32_t yy_meta[53] =
439
+static yyconst YY_CHAR yy_meta[53] =
434 440
     {   0,
435 441
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
436 442
         1,    1,    1,    1,    1,    1,    1,    2,    1,    1,
@@ -440,7 +446,7 @@ static yyconst flex_int32_t yy_meta[53] =
440 446
         1,    1
441 447
     } ;
442 448
 
443
-static yyconst flex_int16_t yy_base[152] =
449
+static yyconst flex_uint16_t yy_base[152] =
444 450
     {   0,
445 451
         0,    0,  161,  162,   51,   51,  155,  162,  162,   48,
446 452
       150,  162,  162,   45,  136,  162,   43,  162,  135,   43,
@@ -482,7 +488,7 @@ static yyconst flex_int16_t yy_def[152] =
482 488
       147
483 489
     } ;
484 490
 
485
-static yyconst flex_int16_t yy_nxt[215] =
491
+static yyconst flex_uint16_t yy_nxt[215] =
486 492
     {   0,
487 493
         4,    5,    5,    6,    7,    8,    9,   10,   11,   12,
488 494
        13,   14,   15,   16,   17,   18,   19,   20,   21,   22,
@@ -627,7 +633,7 @@ static void update_loc(YYLTYPE *yylloc, char *yytext){
627 633
 <STRING>. { str_putc(*yytext); }
628 634
 
629 635
 */
630
-#line 631 "lex.yy.c"
636
+#line 637 "lex.yy.c"
631 637
 
632 638
 #define INITIAL 0
633 639
 
@@ -660,11 +666,11 @@ void yyset_extra (YY_EXTRA_TYPE user_defined  );
660 666
 
661 667
 FILE *yyget_in (void );
662 668
 
663
-void yyset_in  (FILE * in_str  );
669
+void yyset_in  (FILE * _in_str  );
664 670
 
665 671
 FILE *yyget_out (void );
666 672
 
667
-void yyset_out  (FILE * out_str  );
673
+void yyset_out  (FILE * _out_str  );
668 674
 
669 675
 yy_size_t yyget_leng (void );
670 676
 
@@ -672,7 +678,7 @@ char *yyget_text (void );
672 678
 
673 679
 int yyget_lineno (void );
674 680
 
675
-void yyset_lineno (int line_number  );
681
+void yyset_lineno (int _line_number  );
676 682
 
677 683
 YYSTYPE * yyget_lval (void );
678 684
 
@@ -694,8 +700,12 @@ extern int yywrap (void );
694 700
 #endif
695 701
 #endif
696 702
 
703
+#ifndef YY_NO_UNPUT
704
+    
697 705
     static void yyunput (int c,char *buf_ptr  );
698 706
     
707
+#endif
708
+
699 709
 #ifndef yytext_ptr
700 710
 static void yy_flex_strncpy (char *,yyconst char *,int );
701 711
 #endif
@@ -810,7 +820,7 @@ extern int yylex \
810 820
 
811 821
 /* Code executed at the end of each rule. */
812 822
 #ifndef YY_BREAK
813
-#define YY_BREAK break;
823
+#define YY_BREAK /*LINTED*/break;
814 824
 #endif
815 825
 
816 826
 #define YY_RULE_SETUP \
@@ -820,9 +830,9 @@ extern int yylex \
820 830
  */
821 831
 YY_DECL
822 832
 {
823
-	register yy_state_type yy_current_state;
824
-	register char *yy_cp, *yy_bp;
825
-	register int yy_act;
833
+	yy_state_type yy_current_state;
834
+	char *yy_cp, *yy_bp;
835
+	int yy_act;
826 836
     
827 837
         YYSTYPE * yylval;
828 838
     
@@ -862,9 +872,9 @@ YY_DECL
862 872
 #line 85 "tokenizer.lex"
863 873
 
864 874
 
865
-#line 866 "lex.yy.c"
875
+#line 876 "lex.yy.c"
866 876
 
867
-	while ( 1 )		/* loops until end-of-file is reached */
877
+	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
868 878
 		{
869 879
 		yy_cp = (yy_c_buf_p);
870 880
 
@@ -880,7 +890,7 @@ YY_DECL
880 890
 yy_match:
881 891
 		do
882 892
 			{
883
-			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
893
+			YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
884 894
 			if ( yy_accept[yy_current_state] )
885 895
 				{
886 896
 				(yy_last_accepting_state) = yy_current_state;
@@ -1283,7 +1293,7 @@ YY_RULE_SETUP
1283 1293
 #line 229 "tokenizer.lex"
1284 1294
 ECHO;
1285 1295
 	YY_BREAK
1286
-#line 1287 "lex.yy.c"
1296
+#line 1297 "lex.yy.c"
1287 1297
 case YY_STATE_EOF(INITIAL):
1288 1298
 	yyterminate();
1289 1299
 
@@ -1426,9 +1436,9 @@ case YY_STATE_EOF(INITIAL):
1426 1436
  */
1427 1437
 static int yy_get_next_buffer (void)
1428 1438
 {
1429
-    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
1430
-	register char *source = (yytext_ptr);
1431
-	register int number_to_move, i;
1439
+    	char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
1440
+	char *source = (yytext_ptr);
1441
+	yy_size_t number_to_move, i;
1432 1442
 	int ret_val;
1433 1443
 
1434 1444
 	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
@@ -1457,7 +1467,7 @@ static int yy_get_next_buffer (void)
1457 1467
 	/* Try to read more data. */
1458 1468
 
1459 1469
 	/* First move last chars to start of buffer. */
1460
-	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
1470
+	number_to_move = (yy_size_t) ((yy_c_buf_p) - (yytext_ptr)) - 1;
1461 1471
 
1462 1472
 	for ( i = 0; i < number_to_move; ++i )
1463 1473
 		*(dest++) = *(source++);
@@ -1560,14 +1570,14 @@ static int yy_get_next_buffer (void)
1560 1570
 
1561 1571
     static yy_state_type yy_get_previous_state (void)
1562 1572
 {
1563
-	register yy_state_type yy_current_state;
1564
-	register char *yy_cp;
1573
+	yy_state_type yy_current_state;
1574
+	char *yy_cp;
1565 1575
     
1566 1576
 	yy_current_state = (yy_start);
1567 1577
 
1568 1578
 	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
1569 1579
 		{
1570
-		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
1580
+		YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
1571 1581
 		if ( yy_accept[yy_current_state] )
1572 1582
 			{
1573 1583
 			(yy_last_accepting_state) = yy_current_state;
@@ -1592,10 +1602,10 @@ static int yy_get_next_buffer (void)
1592 1602
  */
1593 1603
     static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
1594 1604
 {
1595
-	register int yy_is_jam;
1596
-    	register char *yy_cp = (yy_c_buf_p);
1605
+	int yy_is_jam;
1606
+    	char *yy_cp = (yy_c_buf_p);
1597 1607
 
1598
-	register YY_CHAR yy_c = 1;
1608
+	YY_CHAR yy_c = 1;
1599 1609
 	if ( yy_accept[yy_current_state] )
1600 1610
 		{
1601 1611
 		(yy_last_accepting_state) = yy_current_state;
@@ -1613,9 +1623,11 @@ static int yy_get_next_buffer (void)
1613 1623
 		return yy_is_jam ? 0 : yy_current_state;
1614 1624
 }
1615 1625
 
1616
-    static void yyunput (int c, register char * yy_bp )
1626
+#ifndef YY_NO_UNPUT
1627
+
1628
+    static void yyunput (int c, char * yy_bp )
1617 1629
 {
1618
-	register char *yy_cp;
1630
+	char *yy_cp;
1619 1631
     
1620 1632
     yy_cp = (yy_c_buf_p);
1621 1633
 
@@ -1625,10 +1637,10 @@ static int yy_get_next_buffer (void)
1625 1637
 	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
1626 1638
 		{ /* need to shift things up to make room */
1627 1639
 		/* +2 for EOB chars. */
1628
-		register yy_size_t number_to_move = (yy_n_chars) + 2;
1629
-		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
1640
+		yy_size_t number_to_move = (yy_n_chars) + 2;
1641
+		char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
1630 1642
 					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
1631
-		register char *source =
1643
+		char *source =
1632 1644
 				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
1633 1645
 
1634 1646
 		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
@@ -1650,6 +1662,8 @@ static int yy_get_next_buffer (void)
1650 1662
 	(yy_c_buf_p) = yy_cp;
1651 1663
 }
1652 1664
 
1665
+#endif
1666
+
1653 1667
 #ifndef YY_NO_INPUT
1654 1668
 #ifdef __cplusplus
1655 1669
     static int yyinput (void)
@@ -1799,7 +1813,7 @@ static void yy_load_buffer_state  (void)
1799 1813
 	if ( ! b )
1800 1814
 		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
1801 1815
 
1802
-	b->yy_buf_size = size;
1816
+	b->yy_buf_size = (yy_size_t)size;
1803 1817
 
1804 1818
 	/* yy_ch_buf has to be 2 characters longer than the size given because
1805 1819
 	 * we need to put in 2 end-of-buffer characters.
@@ -1954,7 +1968,7 @@ static void yyensure_buffer_stack (void)
1954 1968
 		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
1955 1969
 		 * immediate realloc on the next call.
1956 1970
          */
1957
-		num_to_alloc = 1;
1971
+		num_to_alloc = 1; // After all that talk, this was set to 1 anyways...
1958 1972
 		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
1959 1973
 								(num_to_alloc * sizeof(struct yy_buffer_state*)
1960 1974
 								);
@@ -1971,7 +1985,7 @@ static void yyensure_buffer_stack (void)
1971 1985
 	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
1972 1986
 
1973 1987
 		/* Increase the buffer to prepare for a possible push. */
1974
-		int grow_size = 8 /* arbitrary grow size */;
1988
+		yy_size_t grow_size = 8 /* arbitrary grow size */;
1975 1989
 
1976 1990
 		num_to_alloc = (yy_buffer_stack_max) + grow_size;
1977 1991
 		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
@@ -2079,7 +2093,7 @@ YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len
2079 2093
 
2080 2094
 static void yy_fatal_error (yyconst char* msg )
2081 2095
 {
2082
-    	(void) fprintf( stderr, "%s\n", msg );
2096
+			(void) fprintf( stderr, "%s\n", msg );
2083 2097
 	exit( YY_EXIT_FAILURE );
2084 2098
 }
2085 2099
 
@@ -2145,29 +2159,29 @@ char *yyget_text  (void)
2145 2159
 }
2146 2160
 
2147 2161
 /** Set the current line number.
2148
- * @param line_number
2162
+ * @param _line_number line number
2149 2163
  * 
2150 2164
  */
2151
-void yyset_lineno (int  line_number )
2165
+void yyset_lineno (int  _line_number )
2152 2166
 {
2153 2167
     
2154
-    yylineno = line_number;
2168
+    yylineno = _line_number;
2155 2169
 }
2156 2170
 
2157 2171
 /** Set the input stream. This does not discard the current
2158 2172
  * input buffer.
2159
- * @param in_str A readable stream.
2173
+ * @param _in_str A readable stream.
2160 2174
  * 
2161 2175
  * @see yy_switch_to_buffer
2162 2176
  */
2163
-void yyset_in (FILE *  in_str )
2177
+void yyset_in (FILE *  _in_str )
2164 2178
 {
2165
-        yyin = in_str ;
2179
+        yyin = _in_str ;
2166 2180
 }
2167 2181
 
2168
-void yyset_out (FILE *  out_str )
2182
+void yyset_out (FILE *  _out_str )
2169 2183
 {
2170
-        yyout = out_str ;
2184
+        yyout = _out_str ;
2171 2185
 }
2172 2186
 
2173 2187
 int yyget_debug  (void)
@@ -2175,9 +2189,9 @@ int yyget_debug  (void)
2175 2189
         return yy_flex_debug;
2176 2190
 }
2177 2191
 
2178
-void yyset_debug (int  bdebug )
2192
+void yyset_debug (int  _bdebug )
2179 2193
 {
2180
-        yy_flex_debug = bdebug ;
2194
+        yy_flex_debug = _bdebug ;
2181 2195
 }
2182 2196
 
2183 2197
 static int yy_init_globals (void)
@@ -2237,7 +2251,8 @@ int yylex_destroy  (void)
2237 2251
 #ifndef yytext_ptr
2238 2252
 static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
2239 2253
 {
2240
-	register int i;
2254
+		
2255
+	int i;
2241 2256
 	for ( i = 0; i < n; ++i )
2242 2257
 		s1[i] = s2[i];
2243 2258
 }
@@ -2246,7 +2261,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
2246 2261
 #ifdef YY_NEED_STRLEN
2247 2262
 static int yy_flex_strlen (yyconst char * s )
2248 2263
 {
2249
-	register int n;
2264
+	int n;
2250 2265
 	for ( n = 0; s[n]; ++n )
2251 2266
 		;
2252 2267
 
@@ -2256,11 +2271,12 @@ static int yy_flex_strlen (yyconst char * s )
2256 2271
 
2257 2272
 void *yyalloc (yy_size_t  size )
2258 2273
 {
2259
-	return (void *) malloc( size );
2274
+			return (void *) malloc( size );
2260 2275
 }
2261 2276
 
2262 2277
 void *yyrealloc  (void * ptr, yy_size_t  size )
2263 2278
 {
2279
+		
2264 2280
 	/* The cast to (char *) in the following accommodates both
2265 2281
 	 * implementations that use char* generic pointers, and those
2266 2282
 	 * that use void* generic pointers.  It works with the latter
@@ -2273,12 +2289,12 @@ void *yyrealloc  (void * ptr, yy_size_t  size )
2273 2289
 
2274 2290
 void yyfree (void * ptr )
2275 2291
 {
2276
-	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
2292
+			free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
2277 2293
 }
2278 2294
 
2279 2295
 #define YYTABLES_NAME "yytables"
2280 2296
 
2281
-#line 228 "tokenizer.lex"
2297
+#line 229 "tokenizer.lex"
2282 2298
 
2283 2299
 
2284 2300
 

+ 253
- 37
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 VERSION "0.2a0"
13
+#define VERSION "0.2a1"
14 14
 /** The hexadecimal version of the project, formatted 0xAAIIRPP where:
15 15
  * 
16 16
  * - AA is the two-digit major version
@@ -20,7 +20,7 @@
20 20
  *
21 21
  * This value is guaranteed to always increase by revision.
22 22
  */
23
-#define HEXVER 0x0002A00
23
+#define HEXVER 0x0002A01
24 24
 
25 25
 #ifndef SOL_ICACHE_MIN
26 26
 /** The smallest integer to cache. */
@@ -380,111 +380,327 @@ typedef struct sol_tag_object_t {
380 380
 typedef enum {SF_NORMAL, SF_BREAKING, SF_CONTINUING} sol_state_flag_t;
381 381
 
382 382
 typedef struct sol_tag_state_t {
383
-	sol_object_t *scopes; // A list of scope maps, innermost out, ending at the global scope
384
-	sol_object_t *ret; // Return value of this function, for early return
385
-	sol_object_t *traceback; // The last stack of statement (nodes) in the last error, or NULL
386
-	sol_state_flag_t sflag; // Used to implement break/continue
387
-	sol_object_t *error; // Some arbitrary error descriptor, None if no error
388
-	sol_object_t *stdout; // Standard output stream object (for print())
389
-	sol_object_t *stdin; // Standard input stream object
390
-	sol_object_t *stderr; // Standard error stream object
391
-	sol_object_t *None;
392
-	sol_object_t *OutOfMemory;
393
-	sol_object_t *StopIteration;
394
-	sol_ops_t NullOps;
395
-	sol_ops_t SingletOps;
396
-	sol_ops_t IntOps;
397
-	sol_ops_t FloatOps;
398
-	sol_ops_t StringOps;
399
-	sol_ops_t ListOps;
400
-	sol_ops_t MapOps;
401
-	sol_ops_t MCellOps;
402
-	sol_ops_t FuncOps;
403
-	sol_ops_t CFuncOps;
404
-	sol_ops_t ASTNodeOps;
405
-	sol_ops_t BufferOps;
406
-	sol_ops_t DyLibOps;
407
-	sol_ops_t DySymOps;
408
-	sol_ops_t StreamOps;
409
-	sol_object_t *modules;
410
-	sol_object_t *methods;
411
-	dsl_object_funcs obfuncs;
412
-	const char *calling_type;
413
-	const char *calling_meth;
383
+	sol_object_t *scopes; ///< A list of scope maps, innermost out, ending at the global scope
384
+	sol_object_t *ret; ///< Return value of this function, for early return
385
+	sol_object_t *traceback; ///< The last stack of statement (nodes) in the last error, or NULL
386
+	sol_state_flag_t sflag; ///< Used to implement break/continue
387
+	sol_object_t *error; ///< Some arbitrary error descriptor, `None` if no error
388
+	sol_object_t *stdout; ///< Standard output stream object (for print(), type `SOL_STREAM`)
389
+	sol_object_t *stdin; ///< Standard input stream object (type `SOL_STREAM`)
390
+	sol_object_t *stderr; ///< Standard error stream object (type `SOL_STREAM`)
391
+	sol_object_t *None; ///< The all-important `None` object
392
+	sol_object_t *OutOfMemory; ///< The semi-important `OutOfMemory` object
393
+	sol_object_t *StopIteration; ///< The somewhat-important `StopIteration` object
394
+	sol_ops_t NullOps; ///< Basic, initialized operations. Not used by any extant object type.
395
+	sol_ops_t SingletOps; ///< Operations on singlets (`None`, `OutOfMemory`, `StopIteration`, etc.)
396
+	sol_ops_t IntOps; ///< Operations on integers
397
+	sol_ops_t FloatOps; ///< Operations on floats
398
+	sol_ops_t StringOps; ///< Operations on strings
399
+	sol_ops_t ListOps; ///< Operations on lists
400
+	sol_ops_t MapOps; ///< Operations on maps
401
+	sol_ops_t MCellOps; ///< Operations on map cells (rarely used)
402
+	sol_ops_t FuncOps; ///< Operations on functions
403
+	sol_ops_t CFuncOps; ///< Operations on C functions
404
+	sol_ops_t ASTNodeOps; ///< Operations on AST nodes
405
+	sol_ops_t BufferOps; ///< Operations on buffers
406
+	sol_ops_t DyLibOps; ///< Operations on dynamic library objects
407
+	sol_ops_t DySymOps; ///< Operations on dynamic symbol objects
408
+	sol_ops_t StreamOps; ///< Operations on streams
409
+	sol_object_t *modules; ///< A map of modules, string name to contents, resolved at "super-global" scope (and thus overrideable)
410
+	sol_object_t *methods; ///< A map of string names to methods (like "list" -> {insert=<CFunction>, remove=<CFunction>, ...}) free for private use by extension developers
411
+	dsl_object_funcs obfuncs; ///< The set of object functions that allows DSL to integrate with Sol's reference counting
412
+	const char *calling_type; ///< Set (during `CALL_METHOD`) to determine the type (ops structure) being invoked for this method (mostly for sol_f_not_impl)
413
+	const char *calling_meth; ///< Set (during `CALL_METHOD`) to determine the method name being invoked (mostly for sol_f_not_impl)
414 414
 #ifdef SOL_ICACHE
415
-	sol_object_t *icache[SOL_ICACHE_MAX - SOL_ICACHE_MIN + 1];
416
-	char icache_bypass;
415
+	sol_object_t *icache[SOL_ICACHE_MAX - SOL_ICACHE_MIN + 1]; ///< The integer cache (holds integers from `SOL_ICACHE_MIN` to `SOL_ICACHE_MAX` indexed by `[i - SOL_ICACHE_MIN]`)
416
+	char icache_bypass; ///< Set to true to bypass caching--needed to avoid infinite recursion when initially populating the cache
417 417
 #endif
418
-	sol_object_t *lastvalue;
419
-	sol_object_t *loopvalue;
418
+	sol_object_t *lastvalue; ///< Holds the value of the last expression evaluated, returned by an `if` expression
419
+	sol_object_t *loopvalue; ///< Holds an initially-empty list appended to by `continue <expr>` or set to another object by `break <expr>`
420 420
 } sol_state_t;
421 421
 
422 422
 // state.c
423 423
 
424
+/** Initializes the state.
425
+ *
426
+ * This should be called once (and only once!) for every state; it does the important
427
+ * work of ensuring that the state is ready to execute code, including:
428
+ * 
429
+ * - Creating the initial singlet values `None`, `OutOfMemory`, and `StopIteration`,
430
+ * - Creating and populating the operations on all internally-defined object types.
431
+ * - Initializing all built-in modules and methods.
432
+ * - Running any "init.sol" files.
433
+ * - Recognizing early-init errors and aborting.
434
+ *
435
+ * It is the singular, monolithic place where most pre-execution occurs, and language
436
+ * developers may thus use it at their discretion. Extension developers should provide
437
+ * their own documented initializers, and embedders should do their own initialization
438
+ * immediately after calling this function.
439
+ */
424 440
 int sol_state_init(sol_state_t *);
441
+/** Cleans up the state.
442
+ *
443
+ * In theory, after calling this, the state should be ready to be released (e.g., freed
444
+ * if it was allocated on the heap). Importantly, it should NOT be used for any code
445
+ * execution after this call (it WILL segfault).
446
+ */
425 447
 void sol_state_cleanup(sol_state_t *);
426 448
 
449
+/** Resolve a name.
450
+ *
451
+ * Technically, a "name" can be anything (any key in a map, more precisely), but the
452
+ * runtime (and most sane code) generally depends on names being strings. It is, however,
453
+ * emphatically possible to populate the scopes with non-string names--for potential use
454
+ * cases, see `programs/monty.sol`
455
+ */
427 456
 sol_object_t *sol_state_resolve(sol_state_t *, sol_object_t *);
457
+/** Resolve a string name, given as a C string.
458
+ *
459
+ * This handles the popular case where a C program would like to resolve the value of a
460
+ * variable by (string) name. In particular, it handles the memory of doing so properly.
461
+ */
428 462
 sol_object_t *sol_state_resolve_name(sol_state_t *, const char *);
463
+/** Assign to a global name.
464
+ *
465
+ * This is rarely used, except in `sol_state_init`. It sets the value of the given name
466
+ * (as an object) in the global (outermost) scope. Code execution generally uses the
467
+ * local scope instead.
468
+ */
429 469
 void sol_state_assign(sol_state_t *, sol_object_t *, sol_object_t *);
470
+/** Assign to a global string name, given as a C string.
471
+ *
472
+ * This is a convenience for `sol_state_assign`, which handles the creation and destruction
473
+ * of the Sol string.
474
+ */
430 475
 void sol_state_assign_name(sol_state_t *, const char *, sol_object_t *);
476
+/** Assign to a local name.
477
+ *
478
+ * Sets the name to the value in the local (innermost) scope. It has the functional equivalent
479
+ * of the Sol code `<name> = <value>` in whatever context the state is in.
480
+ */
431 481
 void sol_state_assign_l(sol_state_t *, sol_object_t *, sol_object_t *);
482
+/** Assign to a local string name, given as a C string.
483
+ *
484
+ * Another convenience for `sol_state_assign_l`.
485
+ */
432 486
 void sol_state_assign_l_name(sol_state_t *, const char *, sol_object_t *);
433 487
 
488
+/** Push a scope.
489
+ *
490
+ * This adds a new (more-local) scope to the scope stack (`state->scopes`). This permits values
491
+ * in such a scope to be manipulated independently of those in enclosing scopes, and their references
492
+ * are discarded during the next `sol_state_pop_scope`. (The values may, of course, be present via
493
+ * other references.)
494
+ *
495
+ * Scope stack manipulation MUST be balanced; egregious errors will occur otherwise.
496
+ * 
497
+ * Scope stack manipulation is generally only necessary where another environment is expected for the
498
+ * code running in that context; e.g., the body of a function, or an AST node from an imported file. In
499
+ * particular, most control structures do NOT introduce scopes, due to the deleterious effects of having
500
+ * no direct influence on enclosing scopes.
501
+ */
434 502
 void sol_state_push_scope(sol_state_t *, sol_object_t *);
503
+/** Pops a scope.
504
+ *
505
+ * Removes and discards the local scope. All names and associated value references are lost.
506
+ *
507
+ * This MUST be balanced with `sol_state_push_scope`.
508
+ */
435 509
 sol_object_t *sol_state_pop_scope(sol_state_t *);
436 510
 
511
+/** Returns the current error.
512
+ *
513
+ * This object is `None` if there is no error. See `sol_has_error`.
514
+ */
437 515
 sol_object_t *sol_get_error(sol_state_t *);
516
+/** Set the current error.
517
+ *
518
+ * Sets the current error object. Clears the error if the object is `None`.
519
+ */
438 520
 sol_object_t *sol_set_error(sol_state_t *, sol_object_t *);
521
+/** Set the current error to a string, given a C string.
522
+ *
523
+ * Conveniently sets the error to a string object created from the given C string.
524
+ */
439 525
 sol_object_t *sol_set_error_string(sol_state_t *, const char *);
526
+/** Clear the current error.
527
+ *
528
+ * Equivalent to `sol_set_error(state, state->None)`.
529
+ */
440 530
 void sol_clear_error(sol_state_t *);
441 531
 
532
+/** Prepares a traceback.
533
+ *
534
+ * Initializes the traceback stack to an empty list in preparation of `sol_add_traceback`.
535
+ * Typically used by the runtime while recovering from an error; the value is ultimately
536
+ * returned as the third element of the return list from `try`.
537
+ */
442 538
 void sol_init_traceback(sol_state_t *);
539
+/** Adds an object to a traceback.
540
+ *
541
+ * This object is usually an ASTNode; typically, it is a statement which was being executed
542
+ * when the relevant error occurred. This object is made the first item of the traceback pair
543
+ * (the second element is the current local scope).
544
+ */
443 545
 void sol_add_traceback(sol_state_t *, sol_object_t *);
546
+/** Gets the traceback.
547
+ *
548
+ * This will be a list of traceback pairs; each such pair will be [<value given to `sol_add_traceback`>,
549
+ * <local scope>].
550
+ */
444 551
 sol_object_t *sol_traceback(sol_state_t *);
445 552
 
553
+/** Registers a module.
554
+ *
555
+ * Creates a module entry by name, referring to its value. Modules resolve after globals, and
556
+ * therefore form a sort of untouchable "super-global" scope. Most built-in modules reside in
557
+ * this namespace.
558
+ */
446 559
 void sol_register_module(sol_state_t *, sol_object_t *, sol_object_t *);
560
+/** Registers a module by string name, given a C string.
561
+ *
562
+ * A convenience for `sol_register_module`.
563
+ */
447 564
 void sol_register_module_name(sol_state_t *, char *, sol_object_t *);
565
+/** Gets a module.
566
+ *
567
+ * Retrieves a module by its given name. Its value will be as it was registered.
568
+ */
448 569
 sol_object_t *sol_get_module(sol_state_t *, sol_object_t *);
570
+/** Gets a module by string name, given a C string.
571
+ *
572
+ * A convenience for `sol_get_module`.
573
+ */
449 574
 sol_object_t *sol_get_module_name(sol_state_t *, char *);
575
+/** Registers methods.
576
+ *
577
+ * Creates a methods entry by name, referring to its value. Methods are never resolved directly
578
+ * by (non-debug) code, but are used liberally throughout the C interface for implementing named
579
+ * methods on objects (such as lists, buffers, etc.) that wouldn't normally resolve names--thus
580
+ * the name. Thus, the mapping forms a sort of private namespace that may freely be used by
581
+ * developers as they see fit.
582
+ */
450 583
 void sol_register_methods(sol_state_t *, sol_object_t *, sol_object_t *);
584
+/** Registers a method by string name, given a C string.
585
+ *
586
+ * A convenience for `sol_register_methods`.
587
+ */
451 588
 void sol_register_methods_name(sol_state_t *, char *, sol_object_t *);
589
+/** Gets methods.
590
+ *
591
+ * Retrieves the methods by its name, returning the value that was registered.
592
+ */
452 593
 sol_object_t *sol_get_methods(sol_state_t *, sol_object_t *);
594
+/** Gets methods by string name, given a C string.
595
+ *
596
+ * A convenience for `sol_get_methods`.
597
+ */
453 598
 sol_object_t *sol_get_methods_name(sol_state_t *, char *);
454 599
 
600
+/** Index operation override for the `io` module.
601
+ *
602
+ * This hook virtually provides `stdin`, `stdout`, and `stderr` by returning the relevant
603
+ * values on the states.
604
+ */
455 605
 sol_object_t *sol_f_io_index(sol_state_t *, sol_object_t *);
606
+/** Setindex operation override for the `io` module.
607
+ *
608
+ * This hook intercepts and specially handles attempts to set `stdin`, `stdout`, and `stderr`
609
+ * by setting the relevant values on the state.
610
+ */
456 611
 sol_object_t *sol_f_io_setindex(sol_state_t *, sol_object_t *);
612
+/** Retrieves the stdin stream.
613
+ *
614
+ * Returns the stream object used to read program input.
615
+ */
457 616
 sol_object_t *sol_get_stdin(sol_state_t *);
617
+/** Retrieves the stdout stream.
618
+ *
619
+ * Returns the stream object used to write program output.
620
+ */
458 621
 sol_object_t *sol_get_stdout(sol_state_t *);
622
+/** Retrieves the stderr stream.
623
+ *
624
+ * Returns the stream object used to write program errors or out-of-band data.
625
+ */
459 626
 sol_object_t *sol_get_stderr(sol_state_t *);
460 627
 
628
+/** Initializes an ops structure.
629
+ *
630
+ * This sets all the fields of a `sol_ops_t` to their sensible defaults. Such an initialized
631
+ * structure is available on the state as `state->NullOps`.
632
+ */
461 633
 void sol_ops_init(sol_ops_t *);
462 634
 
463 635
 // builtins.c
464 636
 
637
+/** Not implemented handler.
638
+ *
639
+ * This raises the "Undefined method" error.
640
+ */
465 641
 sol_object_t *sol_f_not_impl(sol_state_t *, sol_object_t *);
642
+/** !!! handler.
643
+ *
644
+ * Swaps objects by value.
645
+ */
466 646
 sol_object_t *sol_f_tbang(sol_state_t *, sol_object_t *);
647
+/** No operation handler.
648
+ *
649
+ * Does nothing.
650
+ */
467 651
 sol_object_t *sol_f_no_op(sol_state_t *, sol_object_t *);
652
+/** Default comparison handler.
653
+ *
654
+ * Returns 0 (equal) if the references refer to exactly the same object, or
655
+ * 1 (greater) otherwise.
656
+ *
657
+ * Note that this is not a partial order.
658
+ */
468 659
 sol_object_t *sol_f_default_cmp(sol_state_t *, sol_object_t *);
660
+/** Default tostring handler.
661
+ *
662
+ * Returns a string formatted as "<<typename> object at <address>>".
663
+ */
469 664
 sol_object_t *sol_f_default_tostring(sol_state_t *, sol_object_t *);
665
+/** Default torepr handler.
666
+ *
667
+ * Returns tostring(object).
668
+ */
470 669
 sol_object_t *sol_f_default_repr(sol_state_t *, sol_object_t *);
471 670
 
671
+/// Built-in function toint
472 672
 sol_object_t *sol_f_toint(sol_state_t *, sol_object_t *);
673
+/// Built-in function tofloat
473 674
 sol_object_t *sol_f_tofloat(sol_state_t *, sol_object_t *);
675
+/// Built-in function tostring
474 676
 sol_object_t *sol_f_tostring(sol_state_t *, sol_object_t *);
677
+/// Built-in function try
475 678
 sol_object_t *sol_f_try(sol_state_t *, sol_object_t *);
679
+/// Built-in function error
476 680
 sol_object_t *sol_f_error(sol_state_t *, sol_object_t *);
681
+/// Built-in function type
477 682
 sol_object_t *sol_f_type(sol_state_t *, sol_object_t *);
683
+/// Built-in function prepr
478 684
 sol_object_t *sol_f_prepr(sol_state_t *, sol_object_t *);
685
+/// Built-in function print
479 686
 sol_object_t *sol_f_print(sol_state_t *, sol_object_t *);
687
+/// Built-in function rawget
480 688
 sol_object_t *sol_f_rawget(sol_state_t *, sol_object_t *);
689
+/// Built-in function rawset
481 690
 sol_object_t *sol_f_rawset(sol_state_t *, sol_object_t *);
691
+/// Built-in function range
482 692
 sol_object_t *sol_f_range(sol_state_t *, sol_object_t *);
693
+/// Built-in function exec
483 694
 sol_object_t *sol_f_exec(sol_state_t *, sol_object_t *);
695
+/// Built-in function eval
484 696
 sol_object_t *sol_f_eval(sol_state_t *, sol_object_t *);
697
+/// Built-in function execfile
485 698
 sol_object_t *sol_f_execfile(sol_state_t *, sol_object_t *);
699
+/// Built-in function parse
486 700
 sol_object_t *sol_f_parse(sol_state_t *, sol_object_t *);
701
+/// Built-in function ord
487 702
 sol_object_t *sol_f_ord(sol_state_t *, sol_object_t *);
703
+/// Built-in function chr
488 704
 sol_object_t *sol_f_chr(sol_state_t *, sol_object_t *);
489 705
 
490 706
 sol_object_t *sol_f_debug_getref(sol_state_t *, sol_object_t *);

+ 53
- 0
state.c View File

@@ -1,11 +1,31 @@
1 1
 #include <stdint.h>
2 2
 #include <stdio.h>
3
+#include <stdlib.h>
4
+#include <string.h>
3 5
 #include "ast.h"
4 6
 
7
+#define TMP_PATH_SZ 256
8
+
9
+char *sol_AbsInitPaths[] = {
10
+	"/etc/sol/init.sol",
11
+	"/opt/sol/init.sol",
12
+};
13
+
14
+char *sol_HomeInitPaths[] = {
15
+	"/.config/sol/init.sol",
16
+};
17
+
18
+char sol_TempPath[TMP_PATH_SZ];
19
+
20
+#define LENGTH(array) (sizeof(array) / sizeof(array[0]))
21
+
5 22
 int sol_state_init(sol_state_t *state) {
6 23
 	sol_object_t *globals, *mod, *meths;
7 24
 	sol_object_t *btype, *bsize, *bobj;
8 25
 	unsigned long i;
26
+	FILE *fp;
27
+	stmt_node *stmt;
28
+	char *suffix;
9 29
 
10 30
 	sol_mm_initialize(state);
11 31
 
@@ -445,6 +465,39 @@ int sol_state_init(sol_state_t *state) {
445 465
 		goto cleanup;
446 466
 	}
447 467
 
468
+	// Perform initialization based on the user profile, if so requested.
469
+	// TODO: Make this switchable at runtime.
470
+	
471
+	for(i = 0; i < LENGTH(sol_AbsInitPaths); i++) {
472
+		fp = fopen(sol_AbsInitPaths[i], "r");
473
+		if(fp) {
474
+			stmt = sol_compile_file(fp);
475
+			sol_exec(state, stmt);
476
+			st_free(stmt);
477
+			fclose(fp);
478
+		}
479
+	}
480
+
481
+	suffix = getenv("HOME");
482
+	if(suffix) {
483
+		strncpy(sol_TempPath, suffix, TMP_PATH_SZ);
484
+		suffix = sol_TempPath + strlen(sol_TempPath);
485
+		for(i = 0; i < LENGTH(sol_HomeInitPaths); i++) {
486
+			strncpy(suffix, sol_HomeInitPaths[i], TMP_PATH_SZ - (suffix - sol_TempPath));
487
+			fp = fopen(sol_TempPath, "r");
488
+			if(fp) {
489
+				stmt = sol_compile_file(fp);
490
+				sol_exec(state, stmt);
491
+				st_free(stmt);
492
+				fclose(fp);
493
+			}
494
+		}
495
+	}
496
+	
497
+	if(sol_has_error(state)) {
498
+		goto cleanup;
499
+	}
500
+
448 501
 	// We're all set!
449 502
 	return 1;
450 503
 

Loading…
Cancel
Save