|
|
@ -50,7 +50,7 @@ struct ast_container { |
|
|
|
struct allocator block_scope_allocator; |
|
|
|
struct allocator symbol_allocator; |
|
|
|
struct ast_node *main_function; |
|
|
|
bool killed; /* flag to check if this is already destroyed */ |
|
|
|
bool killed; /* flag to check if this is already destroyed */ |
|
|
|
}; |
|
|
|
|
|
|
|
struct ast_node; |
|
|
@ -93,16 +93,16 @@ struct lua_symbol { |
|
|
|
struct block_scope *block; |
|
|
|
} label; |
|
|
|
struct { |
|
|
|
struct lua_symbol *var; /* variable reference */ |
|
|
|
struct lua_symbol *var; /* variable reference */ |
|
|
|
struct ast_node *function; /* Where the upvalue lives */ |
|
|
|
} upvalue; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
struct block_scope { |
|
|
|
struct ast_node *function; /* function owning this block - of type FUNCTION_EXPR */ |
|
|
|
struct block_scope *parent; /* parent block, may belong to parent function */ |
|
|
|
struct lua_symbol_list *symbol_list; /* symbols defined in this block */ |
|
|
|
struct ast_node *function; /* function owning this block - of type FUNCTION_EXPR */ |
|
|
|
struct block_scope *parent; /* parent block, may belong to parent function */ |
|
|
|
struct lua_symbol_list *symbol_list; /* symbols defined in this block */ |
|
|
|
}; |
|
|
|
|
|
|
|
enum ast_node_type { |
|
|
@ -164,14 +164,14 @@ struct ast_node { |
|
|
|
struct ast_node *function_expr; /* Function's AST */ |
|
|
|
} function_stmt; |
|
|
|
struct { |
|
|
|
struct block_scope *scope; /* The do statement only creates a new scope */ |
|
|
|
struct block_scope *scope; /* The do statement only creates a new scope */ |
|
|
|
struct ast_node_list *do_statement_list; /* statements in this block */ |
|
|
|
} do_stmt; |
|
|
|
struct { |
|
|
|
struct ast_node *condition; |
|
|
|
struct block_scope *test_then_scope; |
|
|
|
struct ast_node_list *test_then_statement_list; /* statements in this block */ |
|
|
|
} test_then_block; /* Used internally in if_stmt, not an independent AST node */ |
|
|
|
} test_then_block; /* Used internally in if_stmt, not an independent AST node */ |
|
|
|
struct { |
|
|
|
struct ast_node_list *if_condition_list; /* Actually a list of test_then_blocks */ |
|
|
|
struct block_scope *else_block; |
|
|
@ -187,7 +187,7 @@ struct ast_node { |
|
|
|
struct ast_node_list *expressions; |
|
|
|
struct block_scope *for_body; |
|
|
|
struct ast_node_list *for_statement_list; /* statements in this block */ |
|
|
|
} for_stmt; /* Used for both generic and numeric for loops */ |
|
|
|
} for_stmt; /* Used for both generic and numeric for loops */ |
|
|
|
struct { |
|
|
|
struct var_type type; |
|
|
|
} common_expr; /* To access the type field common to all expr objects */ |
|
|
@ -222,12 +222,12 @@ struct ast_node { |
|
|
|
struct var_type type; |
|
|
|
unsigned int is_vararg : 1; |
|
|
|
unsigned int is_method : 1; |
|
|
|
struct ast_node *parent_function; /* parent function or NULL if main chunk */ |
|
|
|
struct block_scope *main_block; /* the function's main block */ |
|
|
|
struct ast_node *parent_function; /* parent function or NULL if main chunk */ |
|
|
|
struct block_scope *main_block; /* the function's main block */ |
|
|
|
struct ast_node_list *function_statement_list; /* statements in this block */ |
|
|
|
struct lua_symbol_list *args; /* arguments, also must be part of the function block's symbol list */ |
|
|
|
struct ast_node_list *child_functions; /* child functions declared in this function */ |
|
|
|
struct lua_symbol_list *upvalues; /* List of upvalues */ |
|
|
|
struct lua_symbol_list *upvalues; /* List of upvalues */ |
|
|
|
} function_expr; /* a literal expression whose result is a value of type function */ |
|
|
|
struct { |
|
|
|
struct var_type type; |
|
|
@ -303,7 +303,8 @@ static int testnext(LexState *ls, int c) { |
|
|
|
} |
|
|
|
|
|
|
|
static void check(LexState *ls, int c) { |
|
|
|
if (ls->t.token != c) error_expected(ls, c); |
|
|
|
if (ls->t.token != c) |
|
|
|
error_expected(ls, c); |
|
|
|
} |
|
|
|
|
|
|
|
static void checknext(LexState *ls, int c) { |
|
|
@ -325,9 +326,12 @@ static int block_follow(LexState *ls, int withuntil) { |
|
|
|
case TK_ELSE: |
|
|
|
case TK_ELSEIF: |
|
|
|
case TK_END: |
|
|
|
case TK_EOS: return 1; |
|
|
|
case TK_UNTIL: return withuntil; |
|
|
|
default: return 0; |
|
|
|
case TK_EOS: |
|
|
|
return 1; |
|
|
|
case TK_UNTIL: |
|
|
|
return withuntil; |
|
|
|
default: |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -413,17 +417,20 @@ static struct lua_symbol *search_for_variable_in_block(struct block_scope *scope |
|
|
|
FOR_EACH_PTR_REVERSE(scope->symbol_list, symbol) { |
|
|
|
switch (symbol->symbol_type) { |
|
|
|
case SYM_LOCAL: { |
|
|
|
if (varname == symbol->var.var_name) { return symbol; } |
|
|
|
if (varname == symbol->var.var_name) { |
|
|
|
return symbol; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
default: break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
END_FOR_EACH_PTR_REVERSE(symbol); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
//static struct lua_symbol *search_for_label_in_block(struct block_scope *scope, const TString *name) { |
|
|
|
// static struct lua_symbol *search_for_label_in_block(struct block_scope *scope, const TString *name) { |
|
|
|
// struct lua_symbol *symbol; |
|
|
|
// // Lookup in reverse order so that we discover the |
|
|
|
// // most recently added local symbol - as Lua allows same |
|
|
@ -449,15 +456,18 @@ static struct lua_symbol *search_for_variable_in_block(struct block_scope *scope |
|
|
|
static struct lua_symbol *search_upvalue_in_function(struct ast_node *function, const TString *name) { |
|
|
|
struct lua_symbol *symbol; |
|
|
|
FOR_EACH_PTR(function->function_expr.upvalues, symbol) { |
|
|
|
switch (symbol->symbol_type) { |
|
|
|
case SYM_UPVALUE: { |
|
|
|
assert(symbol->upvalue.var->symbol_type == SYM_LOCAL); |
|
|
|
if (name == symbol->upvalue.var->var.var_name) { return symbol; } |
|
|
|
break; |
|
|
|
switch (symbol->symbol_type) { |
|
|
|
case SYM_UPVALUE: { |
|
|
|
assert(symbol->upvalue.var->symbol_type == SYM_LOCAL); |
|
|
|
if (name == symbol->upvalue.var->var.var_name) { |
|
|
|
return symbol; |
|
|
|
} |
|
|
|
default: break; |
|
|
|
break; |
|
|
|
} |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
END_FOR_EACH_PTR(symbol); |
|
|
|
return NULL; |
|
|
|
} |
|
|
@ -468,15 +478,18 @@ static struct lua_symbol *search_upvalue_in_function(struct ast_node *function, |
|
|
|
static bool add_upvalue_in_function(struct parser_state *parser, struct ast_node *function, struct lua_symbol *sym) { |
|
|
|
struct lua_symbol *symbol; |
|
|
|
FOR_EACH_PTR(function->function_expr.upvalues, symbol) { |
|
|
|
switch (symbol->symbol_type) { |
|
|
|
case SYM_UPVALUE: { |
|
|
|
assert(symbol->upvalue.var->symbol_type == SYM_LOCAL); |
|
|
|
if (sym == symbol->upvalue.var) { return false; } |
|
|
|
break; |
|
|
|
switch (symbol->symbol_type) { |
|
|
|
case SYM_UPVALUE: { |
|
|
|
assert(symbol->upvalue.var->symbol_type == SYM_LOCAL); |
|
|
|
if (sym == symbol->upvalue.var) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
default: break; |
|
|
|
break; |
|
|
|
} |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
END_FOR_EACH_PTR(symbol); |
|
|
|
struct lua_symbol *upvalue = dmrC_allocator_allocate(&parser->container->symbol_allocator, 0); |
|
|
|
upvalue->symbol_type = SYM_UPVALUE; |
|
|
@ -487,7 +500,6 @@ static bool add_upvalue_in_function(struct parser_state *parser, struct ast_node |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Searches for a variable starting from current scope, going up the |
|
|
|
* scope chain within the current function. If the variable is not found in any scope of the function, then |
|
|
|
* search the function's upvalue list. Repeat the exercise in parent function until either |
|
|
@ -501,12 +513,14 @@ static struct lua_symbol *search_for_variable(struct parser_state *parser, const |
|
|
|
struct ast_node *current_function = current_scope->function; |
|
|
|
while (current_scope && current_function == current_scope->function) { |
|
|
|
struct lua_symbol *symbol = search_for_variable_in_block(current_scope, varname); |
|
|
|
if (symbol) return symbol; |
|
|
|
if (symbol) |
|
|
|
return symbol; |
|
|
|
current_scope = current_scope->parent; |
|
|
|
} |
|
|
|
// search upvalues in the function |
|
|
|
struct lua_symbol *symbol = search_upvalue_in_function(current_function, varname); |
|
|
|
if (symbol) return symbol; |
|
|
|
if (symbol) |
|
|
|
return symbol; |
|
|
|
// try in parent function |
|
|
|
} |
|
|
|
return NULL; |
|
|
@ -514,7 +528,7 @@ static struct lua_symbol *search_for_variable(struct parser_state *parser, const |
|
|
|
|
|
|
|
/* Searches for a label in current function |
|
|
|
*/ |
|
|
|
//static struct lua_symbol *search_for_label(struct parser_state *parser, const TString *name) { |
|
|
|
// static struct lua_symbol *search_for_label(struct parser_state *parser, const TString *name) { |
|
|
|
// struct block_scope *current_scope = parser->current_scope; |
|
|
|
// while (current_scope && current_scope->function == parser->current_function) { |
|
|
|
// struct lua_symbol *symbol = search_for_label_in_block(current_scope, name); |
|
|
@ -528,7 +542,8 @@ static struct lua_symbol *search_for_variable(struct parser_state *parser, const |
|
|
|
* exists as a local or an upvalue. If the symbol is found in a function's upvalue list then there is no need to |
|
|
|
* check parent functions. |
|
|
|
*/ |
|
|
|
static void add_upvalue_in_levels_upto(struct parser_state *parser, struct ast_node *current_function, struct ast_node *var_function, struct lua_symbol *symbol) { |
|
|
|
static void add_upvalue_in_levels_upto(struct parser_state *parser, struct ast_node *current_function, |
|
|
|
struct ast_node *var_function, struct lua_symbol *symbol) { |
|
|
|
assert(current_function != var_function); |
|
|
|
while (current_function && current_function != var_function) { |
|
|
|
bool added = add_upvalue_in_function(parser, current_function, symbol); |
|
|
@ -570,7 +585,7 @@ static struct ast_node *new_symbol_reference(struct parser_state *parser) { |
|
|
|
global->symbol_type = SYM_GLOBAL; |
|
|
|
global->var.var_name = varname; |
|
|
|
global->var.block = NULL; |
|
|
|
set_type(global->value_type, RAVI_TANY); // Globals are always ANY type |
|
|
|
set_type(global->value_type, RAVI_TANY); // Globals are always ANY type |
|
|
|
// We don't add globals to any scope so that they are |
|
|
|
// always looked up |
|
|
|
symbol = global; |
|
|
@ -701,7 +716,8 @@ static struct ast_node *parse_table_constructor(struct parser_state *parser) { |
|
|
|
table_expr->table_expr.expr_list = NULL; |
|
|
|
table_expr->type = AST_TABLE_EXPR; |
|
|
|
do { |
|
|
|
if (ls->t.token == '}') break; |
|
|
|
if (ls->t.token == '}') |
|
|
|
break; |
|
|
|
struct ast_node *field_expr = parse_field(parser); |
|
|
|
add_ast_node(parser->container, &table_expr->table_expr.expr_list, field_expr); |
|
|
|
} while (testnext(ls, ',') || testnext(ls, ';')); |
|
|
@ -781,7 +797,7 @@ static struct lua_symbol *declare_local_variable(struct parser_state *parser) { |
|
|
|
/* default is a userdata type */ |
|
|
|
tt = RAVI_TUSERDATA; |
|
|
|
typename = user_defined_type_name(ls, typename); |
|
|
|
//str = getstr(typename); |
|
|
|
// str = getstr(typename); |
|
|
|
pusertype = typename; |
|
|
|
} |
|
|
|
if (tt == RAVI_TNUMFLT || tt == RAVI_TNUMINT) { |
|
|
@ -815,7 +831,8 @@ static bool parse_parameter_list(struct parser_state *parser, struct lua_symbol_ |
|
|
|
is_vararg = true; /* declared vararg */ |
|
|
|
break; |
|
|
|
} |
|
|
|
default: luaX_syntaxerror(ls, "<name> or '...' expected"); |
|
|
|
default: |
|
|
|
luaX_syntaxerror(ls, "<name> or '...' expected"); |
|
|
|
} |
|
|
|
} while (!is_vararg && testnext(ls, ',')); |
|
|
|
} |
|
|
@ -961,7 +978,8 @@ static struct ast_node *parse_suffixed_expression(struct parser_state *parser) { |
|
|
|
add_ast_node(parser->container, &suffixed_expr->suffixed_expr.suffix_list, suffix); |
|
|
|
break; |
|
|
|
} |
|
|
|
default: return suffixed_expr; |
|
|
|
default: |
|
|
|
return suffixed_expr; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -1015,7 +1033,8 @@ static struct ast_node *parse_simple_expression(struct parser_state *parser) { |
|
|
|
expr = NULL; |
|
|
|
break; |
|
|
|
} |
|
|
|
case '{': { /* constructor */ return parse_table_constructor(parser); |
|
|
|
case '{': { /* constructor */ |
|
|
|
return parse_table_constructor(parser); |
|
|
|
} |
|
|
|
case TK_FUNCTION: { |
|
|
|
luaX_next(ls); |
|
|
@ -1033,46 +1052,81 @@ static struct ast_node *parse_simple_expression(struct parser_state *parser) { |
|
|
|
|
|
|
|
static UnOpr get_unary_opr(int op) { |
|
|
|
switch (op) { |
|
|
|
case TK_NOT: return OPR_NOT; |
|
|
|
case '-': return OPR_MINUS; |
|
|
|
case '~': return OPR_BNOT; |
|
|
|
case '#': return OPR_LEN; |
|
|
|
case TK_TO_INTEGER: return OPR_TO_INTEGER; |
|
|
|
case TK_TO_NUMBER: return OPR_TO_NUMBER; |
|
|
|
case TK_TO_INTARRAY: return OPR_TO_INTARRAY; |
|
|
|
case TK_TO_NUMARRAY: return OPR_TO_NUMARRAY; |
|
|
|
case TK_TO_TABLE: return OPR_TO_TABLE; |
|
|
|
case TK_TO_STRING: return OPR_TO_STRING; |
|
|
|
case TK_TO_CLOSURE: return OPR_TO_CLOSURE; |
|
|
|
case '@': return OPR_TO_TYPE; |
|
|
|
default: return OPR_NOUNOPR; |
|
|
|
case TK_NOT: |
|
|
|
return OPR_NOT; |
|
|
|
case '-': |
|
|
|
return OPR_MINUS; |
|
|
|
case '~': |
|
|
|
return OPR_BNOT; |
|
|
|
case '#': |
|
|
|
return OPR_LEN; |
|
|
|
case TK_TO_INTEGER: |
|
|
|
return OPR_TO_INTEGER; |
|
|
|
case TK_TO_NUMBER: |
|
|
|
return OPR_TO_NUMBER; |
|
|
|
case TK_TO_INTARRAY: |
|
|
|
return OPR_TO_INTARRAY; |
|
|
|
case TK_TO_NUMARRAY: |
|
|
|
return OPR_TO_NUMARRAY; |
|
|
|
case TK_TO_TABLE: |
|
|
|
return OPR_TO_TABLE; |
|
|
|
case TK_TO_STRING: |
|
|
|
return OPR_TO_STRING; |
|
|
|
case TK_TO_CLOSURE: |
|
|
|
return OPR_TO_CLOSURE; |
|
|
|
case '@': |
|
|
|
return OPR_TO_TYPE; |
|
|
|
default: |
|
|
|
return OPR_NOUNOPR; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static BinOpr get_binary_opr(int op) { |
|
|
|
switch (op) { |
|
|
|
case '+': return OPR_ADD; |
|
|
|
case '-': return OPR_SUB; |
|
|
|
case '*': return OPR_MUL; |
|
|
|
case '%': return OPR_MOD; |
|
|
|
case '^': return OPR_POW; |
|
|
|
case '/': return OPR_DIV; |
|
|
|
case TK_IDIV: return OPR_IDIV; |
|
|
|
case '&': return OPR_BAND; |
|
|
|
case '|': return OPR_BOR; |
|
|
|
case '~': return OPR_BXOR; |
|
|
|
case TK_SHL: return OPR_SHL; |
|
|
|
case TK_SHR: return OPR_SHR; |
|
|
|
case TK_CONCAT: return OPR_CONCAT; |
|
|
|
case TK_NE: return OPR_NE; |
|
|
|
case TK_EQ: return OPR_EQ; |
|
|
|
case '<': return OPR_LT; |
|
|
|
case TK_LE: return OPR_LE; |
|
|
|
case '>': return OPR_GT; |
|
|
|
case TK_GE: return OPR_GE; |
|
|
|
case TK_AND: return OPR_AND; |
|
|
|
case TK_OR: return OPR_OR; |
|
|
|
default: return OPR_NOBINOPR; |
|
|
|
case '+': |
|
|
|
return OPR_ADD; |
|
|
|
case '-': |
|
|
|
return OPR_SUB; |
|
|
|
case '*': |
|
|
|
return OPR_MUL; |
|
|
|
case '%': |
|
|
|
return OPR_MOD; |
|
|
|
case '^': |
|
|
|
return OPR_POW; |
|
|
|
case '/': |
|
|
|
return OPR_DIV; |
|
|
|
case TK_IDIV: |
|
|
|
return OPR_IDIV; |
|
|
|
case '&': |
|
|
|
return OPR_BAND; |
|
|
|
case '|': |
|
|
|
return OPR_BOR; |
|
|
|
case '~': |
|
|
|
return OPR_BXOR; |
|
|
|
case TK_SHL: |
|
|
|
return OPR_SHL; |
|
|
|
case TK_SHR: |
|
|
|
return OPR_SHR; |
|
|
|
case TK_CONCAT: |
|
|
|
return OPR_CONCAT; |
|
|
|
case TK_NE: |
|
|
|
return OPR_NE; |
|
|
|
case TK_EQ: |
|
|
|
return OPR_EQ; |
|
|
|
case '<': |
|
|
|
return OPR_LT; |
|
|
|
case TK_LE: |
|
|
|
return OPR_LE; |
|
|
|
case '>': |
|
|
|
return OPR_GT; |
|
|
|
case TK_GE: |
|
|
|
return OPR_GE; |
|
|
|
case TK_AND: |
|
|
|
return OPR_AND; |
|
|
|
case TK_OR: |
|
|
|
return OPR_OR; |
|
|
|
default: |
|
|
|
return OPR_NOBINOPR; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -1198,7 +1252,8 @@ static struct ast_node *parse_goto_statment(struct parser_state *parser) { |
|
|
|
/* skip no-op statements */ |
|
|
|
static void skip_noop_statements(struct parser_state *parser) { |
|
|
|
LexState *ls = parser->ls; |
|
|
|
while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) parse_statement(parser); |
|
|
|
while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) |
|
|
|
parse_statement(parser); |
|
|
|
} |
|
|
|
|
|
|
|
static struct ast_node *generate_label(struct parser_state *parser, TString *label) { |
|
|
@ -1321,7 +1376,8 @@ static struct ast_node *parse_for_statement(struct parser_state *parser, int lin |
|
|
|
stmt->type = AST_FORIN_STMT; |
|
|
|
parse_for_list(parser, stmt, varname); |
|
|
|
break; |
|
|
|
default: luaX_syntaxerror(ls, "'=' or 'in' expected"); |
|
|
|
default: |
|
|
|
luaX_syntaxerror(ls, "'=' or 'in' expected"); |
|
|
|
} |
|
|
|
check_match(ls, TK_END, TK_FOR, line); |
|
|
|
end_scope(parser); |
|
|
@ -1374,7 +1430,8 @@ static struct ast_node *parse_if_statement(struct parser_state *parser, int line |
|
|
|
test_then_block = parse_if_cond_then_block(parser); /* ELSEIF cond THEN block */ |
|
|
|
add_ast_node(parser->container, &stmt->if_stmt.if_condition_list, test_then_block); |
|
|
|
} |
|
|
|
if (testnext(ls, TK_ELSE)) stmt->if_stmt.else_block = parse_block(parser, &stmt->if_stmt.else_statement_list); /* 'else' part */ |
|
|
|
if (testnext(ls, TK_ELSE)) |
|
|
|
stmt->if_stmt.else_block = parse_block(parser, &stmt->if_stmt.else_statement_list); /* 'else' part */ |
|
|
|
check_match(ls, TK_END, TK_IF, line); |
|
|
|
return stmt; |
|
|
|
} |
|
|
@ -1407,7 +1464,8 @@ static struct ast_node *parse_local_statement(struct parser_state *parser) { |
|
|
|
struct lua_symbol *symbol = declare_local_variable(parser); |
|
|
|
add_symbol(parser->container, &node->local_stmt.vars, symbol); |
|
|
|
nvars++; |
|
|
|
if (nvars >= MAXVARS) luaX_syntaxerror(ls, "too many local variables"); |
|
|
|
if (nvars >= MAXVARS) |
|
|
|
luaX_syntaxerror(ls, "too many local variables"); |
|
|
|
} while (testnext(ls, ',')); |
|
|
|
if (testnext(ls, '=')) /* nexps = */ |
|
|
|
parse_expression_list(parser, &node->local_stmt.exprlist); |
|
|
@ -1432,7 +1490,9 @@ static struct ast_node *parse_function_name(struct parser_state *parser) { |
|
|
|
while (ls->t.token == '.') { |
|
|
|
add_ast_node(parser->container, &function_stmt->function_stmt.selectors, parse_field_selector(parser)); |
|
|
|
} |
|
|
|
if (ls->t.token == ':') { function_stmt->function_stmt.methodname = parse_field_selector(parser); } |
|
|
|
if (ls->t.token == ':') { |
|
|
|
function_stmt->function_stmt.methodname = parse_field_selector(parser); |
|
|
|
} |
|
|
|
return function_stmt; |
|
|
|
} |
|
|
|
|
|
|
@ -1509,17 +1569,29 @@ static struct ast_node *parse_statement(struct parser_state *parser) { |
|
|
|
luaX_next(ls); /* skip ';' */ |
|
|
|
break; |
|
|
|
} |
|
|
|
case TK_IF: { /* stat -> ifstat */ stmt = parse_if_statement(parser, line); break; |
|
|
|
case TK_IF: { /* stat -> ifstat */ |
|
|
|
stmt = parse_if_statement(parser, line); |
|
|
|
break; |
|
|
|
} |
|
|
|
case TK_WHILE: { /* stat -> whilestat */ stmt = parse_while_statement(parser, line); break; |
|
|
|
case TK_WHILE: { /* stat -> whilestat */ |
|
|
|
stmt = parse_while_statement(parser, line); |
|
|
|
break; |
|
|
|
} |
|
|
|
case TK_DO: { /* stat -> DO block END */ stmt = parse_do_statement(parser, line); break; |
|
|
|
case TK_DO: { /* stat -> DO block END */ |
|
|
|
stmt = parse_do_statement(parser, line); |
|
|
|
break; |
|
|
|
} |
|
|
|
case TK_FOR: { /* stat -> forstat */ stmt = parse_for_statement(parser, line); break; |
|
|
|
case TK_FOR: { /* stat -> forstat */ |
|
|
|
stmt = parse_for_statement(parser, line); |
|
|
|
break; |
|
|
|
} |
|
|
|
case TK_REPEAT: { /* stat -> repeatstat */ stmt = parse_repeat_statement(parser, line); break; |
|
|
|
case TK_REPEAT: { /* stat -> repeatstat */ |
|
|
|
stmt = parse_repeat_statement(parser, line); |
|
|
|
break; |
|
|
|
} |
|
|
|
case TK_FUNCTION: { /* stat -> funcstat */ stmt = parse_function_statement(parser, line); break; |
|
|
|
case TK_FUNCTION: { /* stat -> funcstat */ |
|
|
|
stmt = parse_function_statement(parser, line); |
|
|
|
break; |
|
|
|
} |
|
|
|
case TK_LOCAL: { /* stat -> localstat */ |
|
|
|
luaX_next(ls); /* skip LOCAL */ |
|
|
@ -1539,10 +1611,14 @@ static struct ast_node *parse_statement(struct parser_state *parser) { |
|
|
|
stmt = parse_return_statement(parser); |
|
|
|
break; |
|
|
|
} |
|
|
|
case TK_BREAK: /* stat -> breakstat */ |
|
|
|
case TK_GOTO: { /* stat -> 'goto' NAME */ stmt = parse_goto_statment(parser); break; |
|
|
|
case TK_BREAK: /* stat -> breakstat */ |
|
|
|
case TK_GOTO: { /* stat -> 'goto' NAME */ |
|
|
|
stmt = parse_goto_statment(parser); |
|
|
|
break; |
|
|
|
} |
|
|
|
default: { /* stat -> func | assignment */ stmt = parse_expression_statement(parser); break; |
|
|
|
default: { /* stat -> func | assignment */ |
|
|
|
stmt = parse_expression_statement(parser); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
return stmt; |
|
|
@ -1555,8 +1631,10 @@ static void parse_statement_list(struct parser_state *parser, struct ast_node_li |
|
|
|
while (!block_follow(ls, 1)) { |
|
|
|
bool was_return = ls->t.token == TK_RETURN; |
|
|
|
struct ast_node *stmt = parse_statement(parser); |
|
|
|
if (stmt) add_ast_node(parser->container, list, stmt); |
|
|
|
if (was_return) break; /* 'return' must be last statement */ |
|
|
|
if (stmt) |
|
|
|
add_ast_node(parser->container, list, stmt); |
|
|
|
if (was_return) |
|
|
|
break; /* 'return' must be last statement */ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -1569,12 +1647,13 @@ static struct block_scope *new_scope(struct parser_state *parser) { |
|
|
|
struct ast_container *container = parser->container; |
|
|
|
struct block_scope *scope = dmrC_allocator_allocate(&container->block_scope_allocator, 0); |
|
|
|
scope->symbol_list = NULL; |
|
|
|
//scope->do_statement_list = NULL; |
|
|
|
// scope->do_statement_list = NULL; |
|
|
|
scope->function = parser->current_function; |
|
|
|
assert(scope->function && scope->function->type == AST_FUNCTION_EXPR); |
|
|
|
scope->parent = parser->current_scope; |
|
|
|
parser->current_scope = scope; |
|
|
|
if (!parser->current_function->function_expr.main_block) parser->current_function->function_expr.main_block = scope; |
|
|
|
if (!parser->current_function->function_expr.main_block) |
|
|
|
parser->current_function->function_expr.main_block = scope; |
|
|
|
return scope; |
|
|
|
} |
|
|
|
|
|
|
@ -1713,8 +1792,7 @@ static void print_ast_node_list(membuff_t *buf, struct ast_node_list *list, int |
|
|
|
END_FOR_EACH_PTR(node); |
|
|
|
} |
|
|
|
|
|
|
|
static void print_statement_list(membuff_t *buf, struct ast_node_list *statement_list, |
|
|
|
int level) { |
|
|
|
static void print_statement_list(membuff_t *buf, struct ast_node_list *statement_list, int level) { |
|
|
|
print_ast_node_list(buf, statement_list, level + 1, NULL); |
|
|
|
} |
|
|
|
|
|
|
@ -1738,7 +1816,8 @@ static void print_symbol(membuff_t *buf, struct lua_symbol *sym, int level) { |
|
|
|
get_as_str(sym->upvalue.var->value_type.type_name)); |
|
|
|
break; |
|
|
|
} |
|
|
|
default: assert(0); |
|
|
|
default: |
|
|
|
assert(0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -1757,46 +1836,81 @@ static void print_symbol_list(membuff_t *buf, struct lua_symbol_list *list, int |
|
|
|
|
|
|
|
static const char *get_unary_opr_str(UnOpr op) { |
|
|
|
switch (op) { |
|
|
|
case OPR_NOT: return "not"; |
|
|
|
case OPR_MINUS: return "-"; |
|
|
|
case OPR_BNOT: return "~"; |
|
|
|
case OPR_LEN: return "#"; |
|
|
|
case OPR_TO_INTEGER: return "@integer"; |
|
|
|
case OPR_TO_NUMBER: return "@number"; |
|
|
|
case OPR_TO_INTARRAY: return "@integer[]"; |
|
|
|
case OPR_TO_NUMARRAY: return "@number[]"; |
|
|
|
case OPR_TO_TABLE: return "@table"; |
|
|
|
case OPR_TO_CLOSURE: return "@closure"; |
|
|
|
case OPR_TO_STRING: return "@string"; |
|
|
|
case OPR_TO_TYPE: return "@<usertype>"; |
|
|
|
default: return ""; |
|
|
|
case OPR_NOT: |
|
|
|
return "not"; |
|
|
|
case OPR_MINUS: |
|
|
|
return "-"; |
|
|
|
case OPR_BNOT: |
|
|
|
return "~"; |
|
|
|
case OPR_LEN: |
|
|
|
return "#"; |
|
|
|
case OPR_TO_INTEGER: |
|
|
|
return "@integer"; |
|
|
|
case OPR_TO_NUMBER: |
|
|
|
return "@number"; |
|
|
|
case OPR_TO_INTARRAY: |
|
|
|
return "@integer[]"; |
|
|
|
case OPR_TO_NUMARRAY: |
|
|
|
return "@number[]"; |
|
|
|
case OPR_TO_TABLE: |
|
|
|
return "@table"; |
|
|
|
case OPR_TO_CLOSURE: |
|
|
|
return "@closure"; |
|
|
|
case OPR_TO_STRING: |
|
|
|
return "@string"; |
|
|
|
case OPR_TO_TYPE: |
|
|
|
return "@<usertype>"; |
|
|
|
default: |
|
|
|
return ""; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static const char *get_binary_opr_str(BinOpr op) { |
|
|
|
switch (op) { |
|
|
|
case OPR_ADD: return "+"; |
|
|
|
case OPR_SUB: return "-"; |
|
|
|
case OPR_MUL: return "*"; |
|
|
|
case OPR_MOD: return "%"; |
|
|
|
case OPR_POW: return "^"; |
|
|
|
case OPR_DIV: return "/"; |
|
|
|
case OPR_IDIV: return "//"; |
|
|
|
case OPR_BAND: return "&"; |
|
|
|
case OPR_BOR: return "|"; |
|
|
|
case OPR_BXOR: return "~"; |
|
|
|
case OPR_SHL: return "<<"; |
|
|
|
case OPR_SHR: return ">>"; |
|
|
|
case OPR_CONCAT: return ".."; |
|
|
|
case OPR_NE: return "~="; |
|
|
|
case OPR_EQ: return "=="; |
|
|
|
case OPR_LT: return "<"; |
|
|
|
case OPR_LE: return "<="; |
|
|
|
case OPR_GT: return ">"; |
|
|
|
case OPR_GE: return ">="; |
|
|
|
case OPR_AND: return "and"; |
|
|
|
case OPR_OR: return "or"; |
|
|
|
default: return ""; |
|
|
|
case OPR_ADD: |
|
|
|
return "+"; |
|
|
|
case OPR_SUB: |
|
|
|
return "-"; |
|
|
|
case OPR_MUL: |
|
|
|
return "*"; |
|
|
|
case OPR_MOD: |
|
|
|
return "%"; |
|
|
|
case OPR_POW: |
|
|
|
return "^"; |
|
|
|
case OPR_DIV: |
|
|
|
return "/"; |
|
|
|
case OPR_IDIV: |
|
|
|
return "//"; |
|
|
|
case OPR_BAND: |
|
|
|
return "&"; |
|
|
|
case OPR_BOR: |
|
|
|
return "|"; |
|
|
|
case OPR_BXOR: |
|
|
|
return "~"; |
|
|
|
case OPR_SHL: |
|
|
|
return "<<"; |
|
|
|
case OPR_SHR: |
|
|
|
return ">>"; |
|
|
|
case OPR_CONCAT: |
|
|
|
return ".."; |
|
|
|
case OPR_NE: |
|
|
|
return "~="; |
|
|
|
case OPR_EQ: |
|
|
|
return "=="; |
|
|
|
case OPR_LT: |
|
|
|
return "<"; |
|
|
|
case OPR_LE: |
|
|
|
return "<="; |
|
|
|
case OPR_GT: |
|
|
|
return ">"; |
|
|
|
case OPR_GE: |
|
|
|
return ">="; |
|
|
|
case OPR_AND: |
|
|
|
return "and"; |
|
|
|
case OPR_OR: |
|
|
|
return "or"; |
|
|
|
default: |
|
|
|
return ""; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -1817,7 +1931,8 @@ static void print_ast_node(membuff_t *buf, struct ast_node *node, int level) { |
|
|
|
printf_buf(buf, "%pend\n", level); |
|
|
|
break; |
|
|
|
} |
|
|
|
case AST_NONE: break; |
|
|
|
case AST_NONE: |
|
|
|
break; |
|
|
|
case AST_RETURN_STMT: { |
|
|
|
printf_buf(buf, "%preturn\n", level); |
|
|
|
print_ast_node_list(buf, node->return_stmt.exprlist, level + 1, ","); |
|
|
@ -1978,12 +2093,23 @@ static void print_ast_node(membuff_t *buf, struct ast_node *node, int level) { |
|
|
|
case AST_LITERAL_EXPR: { |
|
|
|
printf_buf(buf, "%p", level); |
|
|
|
switch (node->literal_expr.type.type_code) { |
|
|
|
case RAVI_TNIL: printf_buf(buf, "nil"); break; |
|
|
|
case RAVI_TBOOLEAN: printf_buf(buf, "%b", node->literal_expr.u.i); break; |
|
|
|
case RAVI_TNUMINT: printf_buf(buf, "%i", node->literal_expr.u.i); break; |
|
|
|
case RAVI_TNUMFLT: printf_buf(buf, "%f", node->literal_expr.u.n); break; |
|
|
|
case RAVI_TSTRING: printf_buf(buf, "'%t'", node->literal_expr.u.s); break; |
|
|
|
default: assert(0); |
|
|
|
case RAVI_TNIL: |
|
|
|
printf_buf(buf, "nil"); |
|
|
|
break; |
|
|
|
case RAVI_TBOOLEAN: |
|
|
|
printf_buf(buf, "%b", node->literal_expr.u.i); |
|
|
|
break; |
|
|
|
case RAVI_TNUMINT: |
|
|
|
printf_buf(buf, "%i", node->literal_expr.u.i); |
|
|
|
break; |
|
|
|
case RAVI_TNUMFLT: |
|
|
|
printf_buf(buf, "%f", node->literal_expr.u.n); |
|
|
|
break; |
|
|
|
case RAVI_TSTRING: |
|
|
|
printf_buf(buf, "'%t'", node->literal_expr.u.s); |
|
|
|
break; |
|
|
|
default: |
|
|
|
assert(0); |
|
|
|
} |
|
|
|
printf_buf(buf, "\n"); |
|
|
|
break; |
|
|
@ -2022,7 +2148,9 @@ static void print_ast_node(membuff_t *buf, struct ast_node *node, int level) { |
|
|
|
printf_buf(buf, "%p} %c\n", level, "[table constructor end]"); |
|
|
|
break; |
|
|
|
} |
|
|
|
default: printf_buf(buf, "%pUnsupported node type %d\n", level, node->type); assert(0); |
|
|
|
default: |
|
|
|
printf_buf(buf, "%pUnsupported node type %d\n", level, node->type); |
|
|
|
assert(0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -2120,7 +2248,8 @@ static int protected_ast_builder(lua_State *L, ZIO *z, const char *name, const c |
|
|
|
static int build_ast_from_reader(lua_State *L, lua_Reader reader, void *data, const char *chunkname, const char *mode) { |
|
|
|
ZIO z; |
|
|
|
int status; |
|
|
|
if (!chunkname) chunkname = "?"; |
|
|
|
if (!chunkname) |
|
|
|
chunkname = "?"; |
|
|
|
luaZ_init(L, &z, reader, data); |
|
|
|
status = protected_ast_builder(L, &z, chunkname, mode); |
|
|
|
return status; |
|
|
@ -2164,7 +2293,8 @@ typedef struct string_buffer { |
|
|
|
static const char *string_reader(lua_State *L, void *ud, size_t *size) { |
|
|
|
String_buffer *ls = (String_buffer *)ud; |
|
|
|
(void)L; /* not used */ |
|
|
|
if (ls->size == 0) return NULL; |
|
|
|
if (ls->size == 0) |
|
|
|
return NULL; |
|
|
|
*size = ls->size; |
|
|
|
ls->size = 0; |
|
|
|
return ls->s; |
|
|
@ -2201,8 +2331,8 @@ static int build_ast(lua_State *L) { |
|
|
|
} |
|
|
|
if (status != 0) { |
|
|
|
lua_pushnil(L); |
|
|
|
lua_insert(L, -2); /* put before error message */ |
|
|
|
return 2; /* return nil plus error message */ |
|
|
|
lua_insert(L, -2); /* put before error message */ |
|
|
|
return 2; /* return nil plus error message */ |
|
|
|
} |
|
|
|
return 1; |
|
|
|
} |
|
|
|