ast_value *imm_float_zero;
ast_value *imm_float_one;
ast_value *imm_vector_zero;
+ ast_value *nil;
size_t crc_globals;
size_t crc_fields;
*/
ast_label **labels;
ast_goto **gotos;
- const char **loops;
+ const char **breaks;
+ const char **continues;
/* A list of hashtables for each scope */
ht *variables;
break;
case opid1('*'):
if (exprs[0]->expression.vtype != exprs[1]->expression.vtype &&
- exprs[0]->expression.vtype != TYPE_VECTOR &&
- exprs[0]->expression.vtype != TYPE_FLOAT &&
- exprs[1]->expression.vtype != TYPE_VECTOR &&
- exprs[1]->expression.vtype != TYPE_FLOAT)
+ !(exprs[0]->expression.vtype == TYPE_VECTOR &&
+ exprs[1]->expression.vtype == TYPE_FLOAT) &&
+ !(exprs[1]->expression.vtype == TYPE_VECTOR &&
+ exprs[0]->expression.vtype == TYPE_FLOAT)
+ )
{
parseerror(parser, "invalid types used in expression: cannot multiply types %s and %s",
type_name[exprs[1]->expression.vtype],
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
parseerror(parser, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
}
- else if (!ast_compare_type(exprs[0], exprs[1])) {
+ else if (exprs[1]->expression.vtype != TYPE_NIL &&
+ !ast_compare_type(exprs[0], exprs[1]))
+ {
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
const oper_info *olast = NULL;
size_t o;
for (o = 0; o < operator_count; ++o) {
- if ((!(operators[o].flags & OP_PREFIX) == wantop) &&
+ if (((!(operators[o].flags & OP_PREFIX) == !!wantop)) &&
/* !(operators[o].flags & OP_SUFFIX) && / * remove this */
!strcmp(parser_tokval(parser), operators[o].op))
{
return false;
}
- vec_push(parser->loops, label);
+ vec_push(parser->breaks, label);
+ vec_push(parser->continues, label);
rv = parse_while_go(parser, block, out);
if (label)
mem_d(label);
- if (vec_last(parser->loops) != label) {
+ if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) {
parseerror(parser, "internal error: label stack corrupted");
rv = false;
ast_delete(*out);
*out = NULL;
}
- else
- vec_pop(parser->loops);
+ else {
+ vec_pop(parser->breaks);
+ vec_pop(parser->continues);
+ }
return rv;
}
(void)block; /* not touching */
- /* skip the 'while' and check for opening paren */
- if (!parser_next(parser) || parser->tok != '(') {
- parseerror(parser, "expected 'while' condition in parenthesis");
- return false;
- }
/* parse into the expression */
if (!parser_next(parser)) {
parseerror(parser, "expected 'while' condition after opening paren");
}
}
- vec_push(parser->loops, label);
+ vec_push(parser->breaks, label);
+ vec_push(parser->continues, label);
rv = parse_dowhile_go(parser, block, out);
if (label)
mem_d(label);
- if (vec_last(parser->loops) != label) {
+ if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) {
parseerror(parser, "internal error: label stack corrupted");
rv = false;
ast_delete(*out);
*out = NULL;
}
- else
- vec_pop(parser->loops);
+ else {
+ vec_pop(parser->breaks);
+ vec_pop(parser->continues);
+ }
return rv;
}
return false;
}
- vec_push(parser->loops, label);
+ vec_push(parser->breaks, label);
+ vec_push(parser->continues, label);
rv = parse_for_go(parser, block, out);
if (label)
mem_d(label);
- if (vec_last(parser->loops) != label) {
+ if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) {
parseerror(parser, "internal error: label stack corrupted");
rv = false;
ast_delete(*out);
*out = NULL;
}
- else
- vec_pop(parser->loops);
+ else {
+ vec_pop(parser->breaks);
+ vec_pop(parser->continues);
+ }
return rv;
}
static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **out)
static bool parse_break_continue(parser_t *parser, ast_block *block, ast_expression **out, bool is_continue)
{
- size_t i;
+ size_t i;
unsigned int levels = 0;
- lex_ctx ctx = parser_ctx(parser);
+ lex_ctx ctx = parser_ctx(parser);
+ const char **loops = (is_continue ? parser->continues : parser->breaks);
(void)block; /* not touching */
if (!parser_next(parser)) {
if (parser->tok == TOKEN_IDENT) {
if (!OPTS_FLAG(LOOP_LABELS))
parseerror(parser, "labeled loops not activated, try using -floop-labels");
- i = vec_size(parser->loops);
+ i = vec_size(loops);
while (i--) {
- if (parser->loops[i] && !strcmp(parser->loops[i], parser_tokval(parser)))
+ if (loops[i] && !strcmp(loops[i], parser_tokval(parser)))
break;
if (!i) {
parseerror(parser, "no such loop to %s: `%s`",
return true;
}
+static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression **out);
static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **out)
+{
+ bool rv;
+ char *label = NULL;
+
+ /* skip the 'while' and get the body */
+ if (!parser_next(parser)) {
+ if (OPTS_FLAG(LOOP_LABELS))
+ parseerror(parser, "expected loop label or 'switch' operand in parenthesis");
+ else
+ parseerror(parser, "expected 'switch' operand in parenthesis");
+ return false;
+ }
+
+ if (parser->tok == ':') {
+ if (!OPTS_FLAG(LOOP_LABELS))
+ parseerror(parser, "labeled loops not activated, try using -floop-labels");
+ if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
+ parseerror(parser, "expected loop label");
+ return false;
+ }
+ label = util_strdup(parser_tokval(parser));
+ if (!parser_next(parser)) {
+ mem_d(label);
+ parseerror(parser, "expected 'switch' operand in parenthesis");
+ return false;
+ }
+ }
+
+ if (parser->tok != '(') {
+ parseerror(parser, "expected 'switch' operand in parenthesis");
+ return false;
+ }
+
+ vec_push(parser->breaks, label);
+
+ rv = parse_switch_go(parser, block, out);
+ if (label)
+ mem_d(label);
+ if (vec_last(parser->breaks) != label) {
+ parseerror(parser, "internal error: label stack corrupted");
+ rv = false;
+ ast_delete(*out);
+ *out = NULL;
+ }
+ else {
+ vec_pop(parser->breaks);
+ }
+ return rv;
+}
+
+static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression **out)
{
ast_expression *operand;
ast_value *opval;
(void)block; /* not touching */
(void)opval;
- /* parse over the opening paren */
- if (!parser_next(parser) || parser->tok != '(') {
- parseerror(parser, "expected switch operand in parenthesis");
- return false;
- }
-
/* parse into the expression */
if (!parser_next(parser)) {
parseerror(parser, "expected switch operand");
* Also: if there was a prototype, `var` will be deleted and set to `proto` which
* is then filled with the previous definition and the parameter-names replaced.
*/
+ if (!strcmp(var->name, "nil")) {
+ if (OPTS_FLAG(UNTYPED_NIL)) {
+ if (!localblock || !OPTS_FLAG(PERMISSIVE))
+ parseerror(parser, "name `nil` not allowed (try -fpermissive)");
+ } else
+ (void)!parsewarning(parser, WARN_RESERVED_NAMES, "variable name `nil` is reserved");
+ }
if (!localblock) {
/* Deal with end_sys_ vars */
was_end = false;
bool parser_init()
{
+ lex_ctx empty_ctx;
size_t i;
parser = (parser_t*)mem_a(sizeof(parser_t));
vec_push(parser->variables, parser->htglobals = util_htnew(PARSER_HT_SIZE));
vec_push(parser->typedefs, util_htnew(TYPEDEF_HT_SIZE));
vec_push(parser->_blocktypedefs, 0);
+
+ empty_ctx.file = "<internal>";
+ empty_ctx.line = 0;
+ parser->nil = ast_value_new(empty_ctx, "nil", TYPE_NIL);
+ if (OPTS_FLAG(UNTYPED_NIL))
+ util_htset(parser->htglobals, "nil", (void*)parser->nil);
return true;
}
vec_free(parser->labels);
vec_free(parser->gotos);
+ vec_free(parser->breaks);
+ vec_free(parser->continues);
mem_d(parser);
}