Browse Source

Sol Part 60: I AM A CARPENTER

master
Graham Northup 5 years ago
parent
commit
0e6a437a42
Signed by: grissess GPG Key ID: 5D000E6F539376FB
  1. 1
      .gitignore
  2. 8
      Makefile
  3. 56
      ast.h
  4. 2
      astprint.c
  5. 294
      lex.yy.c
  6. 2
      runtime.c
  7. 642
      ser.c
  8. 34
      solrun.c

1
.gitignore

@ -9,6 +9,7 @@ gclog.txt
gcstat.txt
iss*
/*.sol
*.slc
_build
doxyxml
valgrind.log

8
Makefile

@ -1,6 +1,6 @@
CFLAGS= -g
LDFLAGS= -lm -ldl -lreadline
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
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
.PHONY: all test
@ -9,11 +9,15 @@ all: dsl sol
sol: $(OBJ)
gcc $(CFLAGS) $? $(LDFLAGS) -o sol
test: all $(sort $(patsubst tests/%.sol,test_%,$(wildcard tests/*.sol)))
test: all $(sort $(patsubst tests/%.sol,test_%,$(wildcard tests/*.sol))) $(sort $(patsubst tests/%.sol,testcomp_%,$(wildcard tests/*.sol)))
test_%: tests/%.sol
./sol r $?
testcomp_%: tests/%.sol
./sol rc $? /dev/fd/1 | ./sol C
dsl:
git submodule init && git submodule sync && git submodule update

56
ast.h

@ -213,6 +213,42 @@ typedef struct tag_stmt_node {
};
} stmt_node;
typedef enum {
BC_NULL,
BC_ST_EXPR,
BC_ST_LIST,
BC_ST_RET,
BC_ST_CONT,
BC_ST_BREAK,
BC_EX_LIT,
BC_EX_LISTGEN,
BC_EX_MAPGEN,
BC_EX_BINOP,
BC_EX_UNOP,
BC_EX_INDEX,
BC_EX_SETINDEX,
BC_EX_ASSIGN,
BC_EX_REF,
BC_EX_CALL,
BC_EX_FUNCDECL,
BC_EX_IFELSE,
BC_EX_LOOP,
BC_EX_ITER,
BC_LIT_INT,
BC_LIT_FLOAT,
BC_LIT_STRING,
BC_LIT_NONE,
BC_INT,
BC_FLOAT,
BC_STRING,
BC_LIST_ST,
BC_LIST_EX,
BC_LIST_AS,
BC_LIST_ID,
BC_LIST_PM,
BC_ENDLIST,
} bytecode;
#define AS_ST(arg) ((stmt_node *) (arg))
#define AS_EX(arg) ((expr_node *) (arg))
#define AS(arg, tp) ((tp *) (arg))
@ -284,4 +320,24 @@ void ob_print(sol_object_t *);
sol_object_t *sol_eval(sol_state_t *, expr_node *);
void sol_exec(sol_state_t *, stmt_node *);
// ser.c
void sol_ser_stmt(FILE *, stmt_node *);
void sol_ser_expr(FILE *, expr_node *);
void sol_ser_stl(FILE *, stmtlist_node *);
void sol_ser_exl(FILE *, exprlist_node *);
void sol_ser_asl(FILE *, assoclist_node *);
void sol_ser_idl(FILE *, identlist_node *);
void sol_ser_pl(FILE *, paramlist_node *);
void sol_ser_lit(FILE *, lit_node *);
void sol_ser_int(FILE *, long);
void sol_ser_float(FILE *, double);
void sol_ser_str(FILE *, const char *);
void *sol_deser(FILE *);
void *sol_deser_checked(FILE *, bytecode);
void *sol_deser_stmt(FILE *);
void *sol_deser_expr(FILE *);
void *sol_deser_lit(FILE *);
#endif

2
astprint.c

@ -261,7 +261,7 @@ void prex(sol_state_t *state, expr_node *node, int lev) {
lev++;
prlev(state, lev, "Expr:");
prex(state, node->call->expr, lev + 1);
prlev(state, lev, "Method: %s\n", node->call->method);
prlev(state, lev, "Method: %s", node->call->method);
prlev(state, lev, "Args:");
cure = node->call->args;
while(cure && cure->expr) {

294
lex.yy.c

@ -1,5 +1,5 @@
#line 3 "lex.yy.c"
#line 2 "lex.yy.c"
#define YY_INT_ALIGNED short int
@ -8,11 +8,97 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
#define YY_FLEX_SUBMINOR_VERSION 1
#define YY_FLEX_SUBMINOR_VERSION 3
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
#define yy_create_buffer yy_create_buffer
#define yy_delete_buffer yy_delete_buffer
#define yy_scan_buffer yy_scan_buffer
#define yy_scan_string yy_scan_string
#define yy_scan_bytes yy_scan_bytes
#define yy_init_buffer yy_init_buffer
#define yy_flush_buffer yy_flush_buffer
#define yy_load_buffer_state yy_load_buffer_state
#define yy_switch_to_buffer yy_switch_to_buffer
#define yypush_buffer_state yypush_buffer_state
#define yypop_buffer_state yypop_buffer_state
#define yyensure_buffer_stack yyensure_buffer_stack
#define yylex yylex
#define yyrestart yyrestart
#define yylex_init yylex_init
#define yylex_init_extra yylex_init_extra
#define yylex_destroy yylex_destroy
#define yyget_debug yyget_debug
#define yyset_debug yyset_debug
#define yyget_extra yyget_extra
#define yyset_extra yyset_extra
#define yyget_in yyget_in
#define yyset_in yyset_in
#define yyget_out yyget_out
#define yyset_out yyset_out
#define yyget_leng yyget_leng
#define yyget_text yyget_text
#define yyget_lineno yyget_lineno
#define yyset_lineno yyset_lineno
#define yywrap yywrap
#define yyget_lval yyget_lval
#define yyset_lval yyset_lval
#define yyget_lloc yyget_lloc
#define yyset_lloc yyset_lloc
#define yyalloc yyalloc
#define yyrealloc yyrealloc
#define yyfree yyfree
#define yytext yytext
#define yyleng yyleng
#define yyin yyin
#define yyout yyout
#define yy_flex_debug yy_flex_debug
#define yylineno yylineno
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
@ -99,32 +185,26 @@ typedef unsigned int flex_uint32_t;
/* Returned upon end-of-file. */
#define YY_NULL 0
/* Promotes a possibly negative, possibly signed char to an unsigned
* integer for use as an array index. If the signed char is negative,
* we want to instead treat it as an 8-bit unsigned char, hence the
* double cast.
/* Promotes a possibly negative, possibly signed char to an
* integer in range [0..255] for use as an array index.
*/
#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
/* Enter a start condition. This macro really ought to take a parameter,
* but we do it the disgusting crufty way forced on us by the ()-less
* definition of BEGIN.
*/
#define BEGIN (yy_start) = 1 + 2 *
/* Translate the current start state into a value that can be later handed
* to BEGIN to return to the state. The YYSTATE alias is for lex
* compatibility.
*/
#define YY_START (((yy_start) - 1) / 2)
#define YYSTATE YY_START
/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
/* Special action meaning "start processing a new file". */
#define YY_NEW_FILE yyrestart(yyin )
#define YY_END_OF_BUFFER_CHAR 0
/* Size of default input buffer. */
@ -161,7 +241,7 @@ extern FILE *yyin, *yyout;
#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2
#define YY_LESS_LINENO(n)
#define YY_LINENO_REWIND_TO(ptr)
@ -178,7 +258,6 @@ extern FILE *yyin, *yyout;
YY_DO_BEFORE_ACTION; /* set up yytext again */ \
} \
while ( 0 )
#define unput(c) yyunput( c, (yytext_ptr) )
#ifndef YY_STRUCT_YY_BUFFER_STATE
@ -221,7 +300,7 @@ struct yy_buffer_state
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
@ -260,7 +339,6 @@ static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */
#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
? (yy_buffer_stack)[(yy_buffer_stack_top)] \
: NULL)
/* Same as previous macro, but useful when we know that the buffer stack is not
* NULL or when we need an lvalue. For internal use only.
*/
@ -281,30 +359,28 @@ static int yy_start = 0; /* start state number */
*/
static int yy_did_buffer_switch_on_eof;
void yyrestart (FILE *input_file );
void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer );
YY_BUFFER_STATE yy_create_buffer (FILE *file,int size );
void yy_delete_buffer (YY_BUFFER_STATE b );
void yy_flush_buffer (YY_BUFFER_STATE b );
void yypush_buffer_state (YY_BUFFER_STATE new_buffer );
void yypop_buffer_state (void );
static void yyensure_buffer_stack (void );
static void yy_load_buffer_state (void );
static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
void yyrestart ( FILE *input_file );
void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer );
YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size );
void yy_delete_buffer ( YY_BUFFER_STATE b );
void yy_flush_buffer ( YY_BUFFER_STATE b );
void yypush_buffer_state ( YY_BUFFER_STATE new_buffer );
void yypop_buffer_state ( void );
static void yyensure_buffer_stack ( void );
static void yy_load_buffer_state ( void );
static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file );
#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len );
YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size );
YY_BUFFER_STATE yy_scan_string ( const char *yy_str );
YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len );
void *yyalloc (yy_size_t );
void *yyrealloc (void *,yy_size_t );
void yyfree (void * );
void *yyalloc ( yy_size_t );
void *yyrealloc ( void *, yy_size_t );
void yyfree ( void * );
#define yy_new_buffer yy_create_buffer
#define yy_set_interactive(is_interactive) \
{ \
if ( ! YY_CURRENT_BUFFER ){ \
@ -314,7 +390,6 @@ void yyfree (void * );
} \
YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
}
#define yy_set_bol(at_bol) \
{ \
if ( ! YY_CURRENT_BUFFER ){\
@ -324,19 +399,16 @@ void yyfree (void * );
} \
YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
}
#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
/* Begin user sect3 */
typedef unsigned char YY_CHAR;
typedef flex_uint8_t YY_CHAR;
FILE *yyin = NULL, *yyout = NULL;
typedef int yy_state_type;
extern int yylineno;
int yylineno = 1;
extern char *yytext;
@ -345,10 +417,10 @@ extern char *yytext;
#endif
#define yytext_ptr yytext
static yy_state_type yy_get_previous_state (void );
static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
static int yy_get_next_buffer (void );
static void yynoreturn yy_fatal_error (yyconst char* msg );
static yy_state_type yy_get_previous_state ( void );
static yy_state_type yy_try_NUL_trans ( yy_state_type current_state );
static int yy_get_next_buffer ( void );
static void yynoreturn yy_fatal_error ( const char* msg );
/* Done after the current pattern has been matched and before the
* corresponding action - sets up yytext.
@ -359,7 +431,6 @@ static void yynoreturn yy_fatal_error (yyconst char* msg );
(yy_hold_char) = *yy_cp; \
*yy_cp = '\0'; \
(yy_c_buf_p) = yy_cp;
#define YY_NUM_RULES 73
#define YY_END_OF_BUFFER 74
/* This struct is not used in this scanner,
@ -369,7 +440,7 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
static yyconst flex_int16_t yy_accept[152] =
static const flex_int16_t yy_accept[152] =
{ 0,
0, 0, 74, 73, 72, 34, 73, 68, 23, 26,
73, 62, 63, 21, 19, 67, 20, 64, 22, 2,
@ -390,7 +461,7 @@ static yyconst flex_int16_t yy_accept[152] =
0
} ;
static yyconst YY_CHAR yy_ec[256] =
static const YY_CHAR yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@ -422,7 +493,7 @@ static yyconst YY_CHAR yy_ec[256] =
1, 1, 1, 1, 1
} ;
static yyconst YY_CHAR yy_meta[53] =
static const YY_CHAR yy_meta[53] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 2, 1, 1,
@ -432,7 +503,7 @@ static yyconst YY_CHAR yy_meta[53] =
1, 1
} ;
static yyconst flex_uint16_t yy_base[156] =
static const flex_int16_t yy_base[156] =
{ 0,
0, 51, 169, 170, 52, 52, 163, 170, 170, 49,
158, 170, 170, 46, 144, 170, 44, 170, 143, 44,
@ -453,7 +524,7 @@ static yyconst flex_uint16_t yy_base[156] =
170, 104, 106, 81, 108
} ;
static yyconst flex_int16_t yy_def[156] =
static const flex_int16_t yy_def[156] =
{ 0,
151, 1, 151, 151, 151, 151, 152, 151, 151, 151,
153, 151, 151, 151, 151, 151, 151, 151, 151, 151,
@ -474,7 +545,7 @@ static yyconst flex_int16_t yy_def[156] =
0, 151, 151, 151, 151
} ;
static yyconst flex_uint16_t yy_nxt[223] =
static const flex_int16_t yy_nxt[223] =
{ 0,
4, 5, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
@ -503,7 +574,7 @@ static yyconst flex_uint16_t yy_nxt[223] =
151, 151
} ;
static yyconst flex_int16_t yy_chk[223] =
static const flex_int16_t yy_chk[223] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@ -606,6 +677,7 @@ static void update_loc(YYLTYPE *yylloc, char *yytext){
#define YY_USER_ACTION update_loc(yylloc, yytext);
#line 680 "lex.yy.c"
/* This is the right way to do it, but it keeps generating token $undefined.
%x STRING
@ -621,7 +693,7 @@ static void update_loc(YYLTYPE *yylloc, char *yytext){
<STRING>. { str_putc(*yytext); }
*/
#line 625 "lex.yy.c"
#line 696 "lex.yy.c"
#define INITIAL 0
@ -637,44 +709,44 @@ static void update_loc(YYLTYPE *yylloc, char *yytext){
#define YY_EXTRA_TYPE void *
#endif
static int yy_init_globals (void );
static int yy_init_globals ( void );
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
int yylex_destroy (void );
int yylex_destroy ( void );
int yyget_debug (void );
int yyget_debug ( void );
void yyset_debug (int debug_flag );
void yyset_debug ( int debug_flag );
YY_EXTRA_TYPE yyget_extra (void );
YY_EXTRA_TYPE yyget_extra ( void );
void yyset_extra (YY_EXTRA_TYPE user_defined );
void yyset_extra ( YY_EXTRA_TYPE user_defined );
FILE *yyget_in (void );
FILE *yyget_in ( void );
void yyset_in (FILE * _in_str );
void yyset_in ( FILE * _in_str );
FILE *yyget_out (void );
FILE *yyget_out ( void );
void yyset_out (FILE * _out_str );
void yyset_out ( FILE * _out_str );
int yyget_leng (void );
int yyget_leng ( void );
char *yyget_text (void );
char *yyget_text ( void );
int yyget_lineno (void );
int yyget_lineno ( void );
void yyset_lineno (int _line_number );
void yyset_lineno ( int _line_number );
YYSTYPE * yyget_lval (void );
YYSTYPE * yyget_lval ( void );
void yyset_lval (YYSTYPE * yylval_param );
void yyset_lval ( YYSTYPE * yylval_param );
YYLTYPE *yyget_lloc (void );
YYLTYPE *yyget_lloc ( void );
void yyset_lloc (YYLTYPE * yylloc_param );
void yyset_lloc ( YYLTYPE * yylloc_param );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@ -682,32 +754,31 @@ void yyset_lval (YYSTYPE * yylval_param );
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
extern "C" int yywrap (void );
extern "C" int yywrap ( void );
#else
extern int yywrap (void );
extern int yywrap ( void );
#endif
#endif
#ifndef YY_NO_UNPUT
static void yyunput (int c,char *buf_ptr );
static void yyunput ( int c, char *buf_ptr );
#endif
#ifndef yytext_ptr
static void yy_flex_strncpy (char *,yyconst char *,int );
static void yy_flex_strncpy ( char *, const char *, int );
#endif
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * );
static int yy_flex_strlen ( const char * );
#endif
#ifndef YY_NO_INPUT
#ifdef __cplusplus
static int yyinput (void );
static int yyinput ( void );
#else
static int input (void );
static int input ( void );
#endif
#endif
@ -738,7 +809,7 @@ static int input (void );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
size_t n; \
int n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@ -751,7 +822,7 @@ static int input (void );
else \
{ \
errno=0; \
while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
{ \
if( errno != EINTR) \
{ \
@ -793,7 +864,7 @@ static int input (void );
#define YY_DECL_IS_OURS 1
extern int yylex \
(YYSTYPE * yylval_param,YYLTYPE * yylloc_param );
(YYSTYPE * yylval_param, YYLTYPE * yylloc_param );
#define YY_DECL int yylex \
(YYSTYPE * yylval_param, YYLTYPE * yylloc_param )
@ -863,7 +934,7 @@ YY_DECL
#line 85 "tokenizer.lex"
#line 867 "lex.yy.c"
#line 937 "lex.yy.c"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
@ -892,9 +963,9 @@ yy_match:
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 152 )
yy_c = yy_meta[(unsigned int) yy_c];
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
while ( yy_base[yy_current_state] != 170 );
@ -1290,7 +1361,7 @@ YY_RULE_SETUP
#line 231 "tokenizer.lex"
ECHO;
YY_BREAK
#line 1294 "lex.yy.c"
#line 1364 "lex.yy.c"
case YY_STATE_EOF(INITIAL):
yyterminate();
@ -1435,7 +1506,7 @@ static int yy_get_next_buffer (void)
{
char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
char *source = (yytext_ptr);
yy_size_t number_to_move, i;
int number_to_move, i;
int ret_val;
if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
@ -1464,7 +1535,7 @@ static int yy_get_next_buffer (void)
/* Try to read more data. */
/* First move last chars to start of buffer. */
number_to_move = (yy_size_t) ((yy_c_buf_p) - (yytext_ptr)) - 1;
number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1);
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
@ -1500,7 +1571,7 @@ static int yy_get_next_buffer (void)
b->yy_ch_buf = (char *)
/* Include room in for 2 EOB chars. */
yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
yyrealloc((void *) b->yy_ch_buf,(yy_size_t) (b->yy_buf_size + 2) );
}
else
/* Can't grow it, we don't own it. */
@ -1546,10 +1617,10 @@ static int yy_get_next_buffer (void)
else
ret_val = EOB_ACT_CONTINUE_SCAN;
if ((int) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */
int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,(yy_size_t) new_size );
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
}
@ -1585,9 +1656,9 @@ static int yy_get_next_buffer (void)
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 152 )
yy_c = yy_meta[(unsigned int) yy_c];
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
}
return yy_current_state;
@ -1613,9 +1684,9 @@ static int yy_get_next_buffer (void)
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 152 )
yy_c = yy_meta[(unsigned int) yy_c];
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
yy_is_jam = (yy_current_state == 151);
return yy_is_jam ? 0 : yy_current_state;
@ -1686,7 +1757,7 @@ static int yy_get_next_buffer (void)
else
{ /* need more input */
int offset = (yy_c_buf_p) - (yytext_ptr);
int offset = (int) ((yy_c_buf_p) - (yytext_ptr));
++(yy_c_buf_p);
switch ( yy_get_next_buffer( ) )
@ -1813,12 +1884,12 @@ static void yy_load_buffer_state (void)
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
b->yy_buf_size = (yy_size_t)size;
b->yy_buf_size = size;
/* yy_ch_buf has to be 2 characters longer than the size given because
* we need to put in 2 end-of-buffer characters.
*/
b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 );
b->yy_ch_buf = (char *) yyalloc((yy_size_t) (b->yy_buf_size + 2) );
if ( ! b->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
@ -1960,7 +2031,7 @@ void yypop_buffer_state (void)
*/
static void yyensure_buffer_stack (void)
{
int num_to_alloc;
yy_size_t num_to_alloc;
if (!(yy_buffer_stack)) {
@ -1974,9 +2045,9 @@ static void yyensure_buffer_stack (void)
);
if ( ! (yy_buffer_stack) )
YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
(yy_buffer_stack_max) = num_to_alloc;
(yy_buffer_stack_top) = 0;
return;
@ -2005,7 +2076,7 @@ static void yyensure_buffer_stack (void)
* @param base the character buffer
* @param size the size in bytes of the character buffer
*
* @return the newly allocated buffer state object.
* @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
{
@ -2021,7 +2092,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */
b->yy_buf_pos = b->yy_ch_buf = base;
b->yy_is_our_buffer = 0;
b->yy_input_file = NULL;
@ -2044,7 +2115,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
* @note If you want to scan bytes that may contain NUL values, then use
* yy_scan_bytes() instead.
*/
YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
YY_BUFFER_STATE yy_scan_string (const char * yystr )
{
return yy_scan_bytes(yystr,(int) strlen(yystr) );
@ -2057,15 +2128,15 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
*
* @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len )
YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len )
{
YY_BUFFER_STATE b;
char *buf;
yy_size_t n;
yy_size_t i;
int i;
/* Get memory for full buffer, including space for trailing EOB's. */
n = (yy_size_t) _yybytes_len + 2;
n = (yy_size_t) (_yybytes_len + 2);
buf = (char *) yyalloc(n );
if ( ! buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
@ -2091,7 +2162,7 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len )
#define YY_EXIT_FAILURE 2
#endif
static void yynoreturn yy_fatal_error (yyconst char* msg )
static void yynoreturn yy_fatal_error (const char* msg )
{
(void) fprintf( stderr, "%s\n", msg );
exit( YY_EXIT_FAILURE );
@ -2121,7 +2192,7 @@ static void yynoreturn yy_fatal_error (yyconst char* msg )
*/
int yyget_lineno (void)
{
return yylineno;
}
@ -2249,7 +2320,7 @@ int yylex_destroy (void)
*/
#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
static void yy_flex_strncpy (char* s1, const char * s2, int n )
{
int i;
@ -2259,7 +2330,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
#endif
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * s )
static int yy_flex_strlen (const char * s )
{
int n;
for ( n = 0; s[n]; ++n )
@ -2297,7 +2368,6 @@ void yyfree (void * ptr )
#line 231 "tokenizer.lex"
int yywrap(void) {
return 1;
}
@ -2317,7 +2387,7 @@ stmt_node *sol_compile(const char *prgstr) {
stmt_node *sol_compile_file(FILE *prgfile) {
stmt_node *program = NULL;
YY_BUFFER_STATE buf = yy_create_buffer(prgfile,YY_BUF_SIZE);
YY_BUFFER_STATE buf = yy_create_buffer(prgfile, YY_BUF_SIZE);
yy_switch_to_buffer(buf);
yyparse(&program);
yy_delete_buffer(buf);

2
runtime.c

@ -46,7 +46,7 @@ stmt_node *st_copy(stmt_node *old) {
case ST_BREAK:
new->brk = NEW(break_node);
new->brk->val = ex_copy(old->cont->val);
new->brk->val = ex_copy(old->brk->val);
break;
default:

642
ser.c

@ -0,0 +1,642 @@
#include <string.h>
#include <stdlib.h>
#include "ast.h"
extern int yydebug;
char *sol_BytecodeNames[] = {
"BC_NULL",
"BC_ST_EXPR",
"BC_ST_LIST",
"BC_ST_RET",
"BC_ST_CONT",
"BC_ST_BREAK",
"BC_EX_LIT",
"BC_EX_LISTGEN",
"BC_EX_MAPGEN",
"BC_EX_BINOP",
"BC_EX_UNOP",
"BC_EX_INDEX",
"BC_EX_SETINDEX",
"BC_EX_ASSIGN",
"BC_EX_REF",
"BC_EX_CALL",
"BC_EX_FUNCDECL",
"BC_EX_IFELSE",
"BC_EX_LOOP",
"BC_EX_ITER",
"BC_LIT_INT",
"BC_LIT_FLOAT",
"BC_LIT_STRING",
"BC_LIT_NONE",
"BC_INT",
"BC_FLOAT",
"BC_STRING",
"BC_LIST_ST",
"BC_LIST_EX",
"BC_LIST_AS",
"BC_LIST_ID",
"BC_LIST_PM",
"BC_ENDLIST",
};
void sol_ser_stmt(FILE *io, stmt_node *st) {
if(!st) {
fputc(BC_NULL, io);
return;
}
switch(st->type) {
case ST_EXPR:
fputc(BC_ST_EXPR, io);
sol_ser_expr(io, st->expr);
break;
case ST_LIST:
fputc(BC_ST_LIST, io);
sol_ser_stl(io, st->stmtlist);
break;
case ST_RET:
fputc(BC_ST_RET, io);
sol_ser_expr(io, st->ret->ret);
break;
case ST_CONT:
fputc(BC_ST_CONT, io);
sol_ser_expr(io, st->cont->val);
break;
case ST_BREAK:
fputc(BC_ST_BREAK, io);
sol_ser_expr(io, st->brk->val);
break;
default:
printf("WARNING: Unknown statement type to serialize: %d\n", st->type);
break;
}
}
void sol_ser_stl(FILE *io, stmtlist_node *stl) {
fputc(BC_LIST_ST, io);
while(stl) {
sol_ser_stmt(io, stl->stmt);
stl = stl->next;
}
fputc(BC_ENDLIST, io);
}
void sol_ser_expr(FILE *io, expr_node *ex) {
if(!ex) {
fputc(BC_NULL, io);
return;
}
switch(ex->type) {
case EX_LIT:
fputc(BC_EX_LIT, io);
sol_ser_lit(io, ex->lit);
break;
case EX_LISTGEN:
fputc(BC_EX_LISTGEN, io);
sol_ser_exl(io, ex->listgen->list);
break;
case EX_MAPGEN:
fputc(BC_EX_MAPGEN, io);
sol_ser_asl(io, ex->mapgen->map);
break;
case EX_BINOP:
fputc(BC_EX_BINOP, io);
fputc(ex->binop->type - OP_ADD, io);
sol_ser_expr(io, ex->binop->left);
sol_ser_expr(io, ex->binop->right);
break;
case EX_UNOP:
fputc(BC_EX_UNOP, io);
fputc(ex->unop->type - OP_NEG, io);
sol_ser_expr(io, ex->unop->expr);
break;
case EX_INDEX:
fputc(BC_EX_INDEX, io);
sol_ser_expr(io, ex->index->expr);
sol_ser_expr(io, ex->index->index);
break;
case EX_SETINDEX:
fputc(BC_EX_SETINDEX, io);
sol_ser_expr(io, ex->setindex->expr);
sol_ser_expr(io, ex->setindex->index);
sol_ser_expr(io, ex->setindex->value);
break;
case EX_ASSIGN:
fputc(BC_EX_ASSIGN, io);
sol_ser_str(io, ex->assign->ident);
sol_ser_expr(io, ex->assign->value);
break;
case EX_REF:
fputc(BC_EX_REF, io);
sol_ser_str(io, ex->ref->ident);
break;
case EX_CALL:
fputc(BC_EX_CALL, io);
sol_ser_expr(io, ex->call->expr);
sol_ser_exl(io, ex->call->args);
sol_ser_str(io, ex->call->method);
break;
case EX_FUNCDECL:
fputc(BC_EX_FUNCDECL, io);
sol_ser_str(io, ex->funcdecl->name);
sol_ser_pl(io, ex->funcdecl->params);
sol_ser_expr(io, ex->funcdecl->anno);
sol_ser_stmt(io, ex->funcdecl->body);
break;
case EX_IFELSE:
fputc(BC_EX_IFELSE, io);
sol_ser_expr(io, ex->ifelse->cond);
sol_ser_stmt(io, ex->ifelse->iftrue);
sol_ser_stmt(io, ex->ifelse->iffalse);
break;
case EX_LOOP:
fputc(BC_EX_LOOP, io);
sol_ser_expr(io, ex->loop->cond);
sol_ser_stmt(io, ex->loop->loop);
break;
case EX_ITER:
fputc(BC_EX_ITER, io);
sol_ser_str(io, ex->iter->var);
sol_ser_expr(io, ex->iter->iter);
sol_ser_stmt(io, ex->iter->loop);
break;
default:
printf("WARNING: Unknown expression type to serialize: %d\n", ex->type);
break;
}
}
void sol_ser_exl(FILE *io, exprlist_node *exn) {
fputc(BC_LIST_EX, io);
while(exn) {
sol_ser_expr(io, exn->expr);
exn = exn->next;
}
fputc(BC_ENDLIST, io);
}
void sol_ser_asl(FILE *io, assoclist_node *asl) {
fputc(BC_LIST_AS, io);
while(asl) {
if(asl->item) {
sol_ser_expr(io, asl->item->key);
sol_ser_expr(io, asl->item->value);
}
asl = asl->next;
}
fputc(BC_ENDLIST, io);
}
void sol_ser_idl(FILE *io, identlist_node *idl) {
fputc(BC_LIST_ID, io);
while(idl) {
sol_ser_str(io, idl->ident);
idl = idl->next;
}
fputc(BC_ENDLIST, io);
}
void sol_ser_pl(FILE *io, paramlist_node *pl) {
if(!pl) {
fputc(BC_NULL, io);
return;
}
fputc(BC_LIST_PM, io);
sol_ser_idl(io, pl->args);
sol_ser_exl(io, pl->annos);
sol_ser_idl(io, pl->clkeys);
sol_ser_exl(io, pl->clvalues);
sol_ser_str(io, pl->rest);
fputc(BC_ENDLIST, io);
}
void sol_ser_lit(FILE *io, lit_node *lit) {
if(!lit) {
fputc(BC_NULL, io);
return;
}
switch(lit->type) {
case LIT_INT:
fputc(BC_LIT_INT, io);
sol_ser_int(io, lit->ival);
break;
case LIT_FLOAT:
fputc(BC_LIT_FLOAT, io);
sol_ser_float(io, lit->fval);
break;
case LIT_STRING:
fputc(BC_LIT_STRING, io);
sol_ser_str(io, lit->str);
break;
case LIT_NONE:
fputc(BC_LIT_NONE, io);
break;
default:
printf("WARNING: Unknown literal type to serialize: %d\n", lit->type);
break;
}
}
void sol_ser_str(FILE *io, const char *s) {
size_t len;
if(!s) {
fputc(BC_NULL, io);
return;
}
fputc(BC_STRING, io);
len = strlen(s);
fwrite(&len, sizeof(size_t), 1, io);
fwrite(s, sizeof(char), len, io);
}
void sol_ser_int(FILE *io, long i) {
fputc(BC_INT, io);
fwrite(&i, sizeof(long), 1, io);
}
void sol_ser_float(FILE *io, double f) {
fputc(BC_FLOAT, io);
fwrite(&f, sizeof(double), 1, io);
}
void *sol_deser_checked(FILE *io, bytecode b) {
int c = fgetc(io);
if(c != b && c != BC_NULL) {
printf("WARNING: Deserialization failed; expected %d, got %d\n", b, c);
}
ungetc(c, io);
return sol_deser(io);
}
void *sol_deser_stmt(FILE *io) {
int c = fgetc(io);
switch(c) {
default:
printf("WARNING: Deserialization failed; expected stmt type, got %d\n", c);
break;
case BC_NULL:
case BC_ST_EXPR:
case BC_ST_LIST:
case BC_ST_RET:
case BC_ST_CONT:
case BC_ST_BREAK:
;
}
ungetc(c, io);
return sol_deser(io);
}
void *sol_deser_expr(FILE *io) {
int c = fgetc(io);
switch(c) {
default:
printf("WARNING: Deserialization failed; expected expr type, got %d\n", c);
break;
case BC_NULL:
case BC_EX_LIT:
case BC_EX_LISTGEN:
case BC_EX_MAPGEN:
case BC_EX_BINOP:
case BC_EX_UNOP:
case BC_EX_INDEX:
case BC_EX_SETINDEX:
case BC_EX_ASSIGN:
case BC_EX_REF:
case BC_EX_CALL:
case BC_EX_FUNCDECL:
case BC_EX_IFELSE:
case BC_EX_LOOP:
case BC_EX_ITER:
;
}
ungetc(c, io);
return sol_deser(io);
}
void *sol_deser_lit(FILE *io) {
int c = fgetc(io);
switch(c) {
default:
printf("WARNING: Deserialization failed; expected lit type, got %d\n", c);
break;
case BC_NULL:
case BC_LIT_INT:
case BC_LIT_FLOAT:
case BC_LIT_STRING:
case BC_LIT_NONE:
;
}
ungetc(c, io);
return sol_deser(io);
}
void *sol_deser(FILE *io) {
bytecode b = fgetc(io);
void *obj = NULL, *node = NULL;
if(yydebug) {
fprintf(stderr, "Encountered BC %s", sol_BytecodeNames[b]);
}
switch(b) {
case BC_NULL:
return NULL;
break;
case BC_ST_EXPR:
obj = NEW(stmt_node);
AS_ST(obj)->type = ST_EXPR;
AS_ST(obj)->expr = sol_deser_expr(io);
return obj;
break;
case BC_ST_LIST:
obj = NEW(stmt_node);
AS_ST(obj)->type = ST_LIST;
AS_ST(obj)->stmtlist = sol_deser_checked(io, BC_LIST_ST);
return obj;
case BC_ST_RET:
obj = NEW(stmt_node);
AS_ST(obj)->type = ST_RET;
AS_ST(obj)->ret = NEW(ret_node);
AS_ST(obj)->ret->ret = sol_deser_expr(io);
return obj;
case BC_ST_CONT:
obj = NEW(stmt_node);
AS_ST(obj)->type = ST_CONT;
AS_ST(obj)->cont = NEW(cont_node);
AS_ST(obj)->cont->val = sol_deser_expr(io);
return obj;
case BC_ST_BREAK:
obj = NEW(stmt_node);
AS_ST(obj)->type = ST_BREAK;
AS_ST(obj)->brk = NEW(break_node);
AS_ST(obj)->brk->val = sol_deser_expr(io);
return obj;
case BC_EX_LIT:
obj = NEW(expr_node);
AS_EX(obj)->type = EX_LIT;
AS_EX(obj)->lit = sol_deser_lit(io);
return obj;
case BC_EX_LISTGEN:
obj = NEW(expr_node);
AS_EX(obj)->type = EX_LISTGEN;
AS_EX(obj)->listgen = NEW(listgen_node);
AS_EX(obj)->listgen->list = sol_deser_checked(io, BC_LIST_EX);
return obj;
case BC_EX_MAPGEN:
obj = NEW(expr_node);
AS_EX(obj)->type = EX_MAPGEN;
AS_EX(obj)->mapgen = NEW(mapgen_node);
AS_EX(obj)->mapgen->map = sol_deser_checked(io, BC_LIST_AS);
return obj;
case BC_EX_BINOP:
obj = NEW(expr_node);
AS_EX(obj)->type = EX_BINOP;
AS_EX(obj)->binop = NEW(binop_node);
AS_EX(obj)->binop->type = OP_ADD + fgetc(io);
AS_EX(obj)->binop->left = sol_deser_expr(io);
AS_EX(obj)->binop->right = sol_deser_expr(io);
return obj;
case BC_EX_UNOP:
obj = NEW(expr_node);
AS_EX(obj)->type = EX_UNOP;
AS_EX(obj)->unop = NEW(unop_node);
AS_EX(obj)->unop->type = OP_NEG + fgetc(io);
AS_EX(obj)->unop->expr = sol_deser_expr(io);
return obj;
case BC_EX_INDEX:
obj = NEW(expr_node);
AS_EX(obj)->type = EX_INDEX;
AS_EX(obj)->index = NEW(index_node);
AS_EX(obj)->index->expr = sol_deser_expr(io);
AS_EX(obj)->index->index = sol_deser_expr(io);
return obj;
case BC_EX_SETINDEX:
obj = NEW(expr_node);
AS_EX(obj)->type = EX_SETINDEX;
AS_EX(obj)->setindex = NEW(setindex_node);
AS_EX(obj)->setindex->expr = sol_deser_expr(io);
AS_EX(obj)->setindex->index = sol_deser_expr(io);
AS_EX(obj)->setindex->value = sol_deser_expr(io);
return obj;
case BC_EX_ASSIGN:
obj = NEW(expr_node);
AS_EX(obj)->type = EX_ASSIGN;
AS_EX(obj)->assign = NEW(assign_node);
AS_EX(obj)->assign->ident = sol_deser_checked(io, BC_STRING);
AS_EX(obj)->assign->value = sol_deser_expr(io);
return obj;
case BC_EX_REF:
obj = NEW(expr_node);
AS_EX(obj)->type = EX_REF;
AS_EX(obj)->ref = NEW(ref_node);
AS_EX(obj)->ref->ident = sol_deser_checked(io, BC_STRING);
return obj;
case BC_EX_CALL:
obj = NEW(expr_node);
AS_EX(obj)->type = EX_CALL;
AS_EX(obj)->call = NEW(call_node);
AS_EX(obj)->call->expr = sol_deser_expr(io);
AS_EX(obj)->call->args = sol_deser_checked(io, BC_LIST_EX);
AS_EX(obj)->call->method = sol_deser_checked(io, BC_STRING);
return obj;
case BC_EX_FUNCDECL:
obj = NEW(expr_node);
AS_EX(obj)->type = EX_FUNCDECL;
AS_EX(obj)->funcdecl = NEW(funcdecl_node);
AS_EX(obj)->funcdecl->name = sol_deser_checked(io, BC_STRING);
AS_EX(obj)->funcdecl->params = sol_deser_checked(io, BC_LIST_PM);
AS_EX(obj)->funcdecl->anno = sol_deser_expr(io);
AS_EX(obj)->funcdecl->body = sol_deser_stmt(io);
return obj;
case BC_EX_IFELSE:
obj = NEW(expr_node);
AS_EX(obj)->type = EX_IFELSE;
AS_EX(obj)->ifelse = NEW(ifelse_node);
AS_EX(obj)->ifelse->cond = sol_deser_expr(io);
AS_EX(obj)->ifelse->iftrue = sol_deser_stmt(io);
AS_EX(obj)->ifelse->iffalse = sol_deser_stmt(io);
return obj;
case BC_EX_LOOP:
obj = NEW(expr_node);
AS_EX(obj)->type = EX_LOOP;
AS_EX(obj)->loop = NEW(loop_node);
AS_EX(obj)->loop->cond = sol_deser_expr(io);
AS_EX(obj)->loop->loop = sol_deser_stmt(io);
return obj;
case BC_EX_ITER:
obj = NEW(expr_node);
AS_EX(obj)->type = EX_ITER;
AS_EX(obj)->iter = NEW(iter_node);
AS_EX(obj)->iter->var = sol_deser_checked(io, BC_STRING);
AS_EX(obj)->iter->iter = sol_deser_expr(io);
AS_EX(obj)->iter->loop = sol_deser_stmt(io);
return obj;
case BC_LIT_INT:
obj = NEW(lit_node);
AS(obj, lit_node)->type = LIT_INT;
node = sol_deser_checked(io, BC_INT);
AS(obj, lit_node)->ival = *AS(node, long);
free(node);
return obj;
case BC_LIT_FLOAT:
obj = NEW(lit_node);
AS(obj, lit_node)->type = LIT_FLOAT;
node = sol_deser_checked(io, BC_FLOAT);
AS(obj, lit_node)->fval = *AS(node, double);
free(node);
return obj;
case BC_LIT_STRING:
obj = NEW(lit_node);
AS(obj, lit_node)->type = LIT_STRING;
AS(obj, lit_node)->str = sol_deser_checked(io, BC_STRING);
return obj;
case BC_LIT_NONE:
obj = NEW(lit_node);
AS(obj, lit_node)->type = LIT_NONE;
return obj;
case BC_INT:
obj = NEW(long);
fread(obj, sizeof(long), 1, io);
return obj;
case BC_FLOAT:
obj = NEW(double);
fread(obj, sizeof(double), 1, io);
return obj;
case BC_STRING:
node = NEW(size_t);
fread(node, sizeof(size_t), 1, io);
obj = malloc(*AS(node, size_t) + 1);
fread(obj, sizeof(char), *AS(node, size_t), io);
AS(obj, char)[*AS(node, size_t)] = 0;
free(node);
return obj;
case BC_LIST_ST:
while((b = fgetc(io)) != BC_ENDLIST) {
ungetc(b, io);
if(!node) {
node = NEW(stmtlist_node);
obj = node;
} else {
AS(node, stmtlist_node)->next = NEW(stmtlist_node);
node = AS(node, stmtlist_node)->next;
}
AS(node, stmtlist_node)->stmt = sol_deser_stmt(io);
}
return obj;
case BC_LIST_EX:
while((b = fgetc(io)) != BC_ENDLIST) {
ungetc(b, io);
if(!node) {
node = NEW(exprlist_node);
obj = node;
} else {
AS(node, exprlist_node)->next = NEW(exprlist_node);
node = AS(node, exprlist_node)->next;
}
AS(node, exprlist_node)->expr = sol_deser_expr(io);
}
return obj;
case BC_LIST_AS:
while((b = fgetc(io)) != BC_ENDLIST) {
ungetc(b, io);
if(!node) {
node = NEW(assoclist_node);
obj = node;
} else {
AS(node, assoclist_node)->next = NEW(assoclist_node);
node = AS(node, assoclist_node)->next;
}
AS(node, assoclist_node)->item = NEW(associtem_node);
AS(node, assoclist_node)->item->key = sol_deser_expr(io);
AS(node, assoclist_node)->item->value = sol_deser_expr(io);
}
return obj;
case BC_LIST_ID:
while((b = fgetc(io)) != BC_ENDLIST) {
ungetc(b,