View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0000394 | LDMud 3.3 | Compilation, Installation | public | 2005-06-24 07:37 | 2018-01-29 21:57 |
| Reporter | Gnomi | Assigned To | |||
| Priority | normal | Severity | minor | Reproducibility | always |
| Status | closed | Resolution | fixed | ||
| Platform | i686 | OS | Debian GNU/Linux | OS Version | 3.1 |
| Product Version | 3.3 | ||||
| Fixed in Version | 3.3.714 | ||||
| Summary | 0000394: Types mixed up | ||||
| Description | Hi, this is an interesting one. The line int i = to_int(({float})0); which initializes a global variable yields (in 3.2, 3.3 and 3.4) Type mismatch ( private float vs int ) when initializing i. The reason is, that the driver keeps the last type in the global variable current_type and thinks, this is the type of the variable that should be initialized. But ({float}) also overwrites current_type, which then results in this error. Handling '({ })' specially wont help, because in 3.3 and 3.4 the error occurs also with the following line: closure cl = (: int i = 10; :); The cleanest solution would be to get rid of this global variable, but that requires a rewrite of the grammar (drag 'type' from 'def := type name_list' into 'new_name' from 'name_list'). If you're interested I could try to come up with such a patch. Greetings, Gnomi. | ||||
| Tags | No tags attached. | ||||
| Attached Files | 3.3currenttype.diff (35,135 bytes)
Index: src/prolang.y
===================================================================
--- src/prolang.y (Revision 22)
+++ src/prolang.y (Arbeitskopie)
@@ -871,10 +871,6 @@
*/
#endif /* USE_STRUCTS */
-static fulltype_t current_type;
- /* The current basic type (reference not counted).
- */
-
static p_uint last_expression;
/* If >= 0, the address of the last instruction which by itself left
* a value on the stack. If there is no such instruction, the value
@@ -987,6 +983,8 @@
/* Forward declarations */
struct lvalue_s; /* Defined within YYSTYPE aka %union */
+static void define_local_variable (ident_t* name, fulltype_t actual_type, typeflags_t opt_star, struct lvalue_s *lv, Bool redeclare, Bool with_init);
+static void init_local_variable (ident_t* name, struct lvalue_s *lv, int assign_op, fulltype_t type2);
static Bool add_lvalue_code ( struct lvalue_s * lv, int instruction);
static void insert_pop_value(void);
static void arrange_protected_lvalue(p_int, int, p_int, int);
@@ -3406,7 +3404,175 @@
} /* verify_declared() */
/*-------------------------------------------------------------------------*/
+static int
+define_global_variable (ident_t* name, fulltype_t actual_type, typeflags_t opt_star, Bool with_init)
+/* This is called directly from a parser rule: <type> [*] <name>
+ * if with_init is true, then an initialization of this variable will follow.
+ * It creates the global variable and returns its index.
+ */
+{
+ int i;
+
+ variables_defined = MY_TRUE;
+
+ if (!(actual_type.typeflags & (TYPE_MOD_PRIVATE | TYPE_MOD_PUBLIC
+ | TYPE_MOD_PROTECTED)))
+ {
+ actual_type.typeflags |= default_varmod;
+ }
+
+ if (actual_type.typeflags & TYPE_MOD_VARARGS)
+ {
+ yyerror("can't declare a variable as varargs");
+ actual_type.typeflags &= ~TYPE_MOD_VARARGS;
+ }
+
+ actual_type.typeflags |= opt_star;
+
+ if (!pragma_share_variables)
+ actual_type.typeflags |= VAR_INITIALIZED;
+
+ define_variable(name, actual_type);
+ i = verify_declared(name); /* Is the var declared? */
+
+ /* Initialize float values with 0.0. */
+ if (with_init
+ || (!(actual_type.typeflags & TYPE_MOD_POINTER)
+ && (actual_type.typeflags & PRIMARY_TYPE_MASK) == TYPE_FLOAT
+ ))
+ {
+
+ /* Prepare the init code */
+ transfer_init_control();
+
+ /* If this is the first variable initialization and
+ * pragma_share_variables is in effect, insert
+ * the check for blueprint/clone initialisation:
+ * if (clonep(this_object())) return 1;
+ */
+ if (!variables_initialized && pragma_share_variables)
+ {
+ ins_f_code(F_THIS_OBJECT);
+ ins_f_code(F_CLONEP);
+ ins_f_code(F_BRANCH_WHEN_ZERO);
+ ins_byte(2);
+ ins_f_code(F_CONST1);
+ ins_f_code(F_RETURN);
+ }
+
+ /* Initialize floats with 0.0 */
+ if(!with_init)
+ {
+ PREPARE_INSERT(5)
+ /* Must come after the non-local program code inserts! */
+
+ add_f_code(F_FCONST0);
+
+#ifdef DEBUG
+ if (i & VIRTUAL_VAR_TAG)
+ {
+ /* When we want to allow 'late' initializers for
+ * inherited variables, it must have a distinct syntax,
+ * lest name clashs remain undetected, making LPC code
+ * hard to debug.
+ */
+ fatal("Newly declared variable is virtual\n");
+ }
+#endif
+ variables_initialized = MY_TRUE; /* We have __INIT code */
+ if (!pragma_share_variables)
+ VARIABLE(i)->type.typeflags |= VAR_INITIALIZED;
+
+ /* Push the variable reference and create the assignment */
+
+ if (i + num_virtual_variables > 0xff)
+ {
+ add_f_code(F_PUSH_IDENTIFIER16_LVALUE);
+ add_short(i + num_virtual_variables);
+ CURRENT_PROGRAM_SIZE += 1;
+ }
+ else
+ {
+ add_f_code(F_PUSH_IDENTIFIER_LVALUE);
+ add_byte(i + num_virtual_variables);
+ }
+
+ /* Ok, assign */
+ add_f_code(F_VOID_ASSIGN);
+ CURRENT_PROGRAM_SIZE += 4;
+ add_new_init_jump();
+ } /* PREPARE_INSERT() block */
+ } /* if (float variable) */
+
+ return i;
+} /* define_global_variable() */
+
+/*-------------------------------------------------------------------------*/
static void
+init_global_variable (int i, ident_t* name, fulltype_t actual_type, typeflags_t opt_star, int assign_op, fulltype_t exprtype)
+/* This is called directly from a parser rule: <type> [*] <name> = <expr>
+ * It will be called after the call to define_global_variable().
+ * It assigns the result of <expr> to the variable.
+ */
+{
+ PREPARE_INSERT(4)
+
+ if (!(actual_type.typeflags & (TYPE_MOD_PRIVATE | TYPE_MOD_PUBLIC
+ | TYPE_MOD_PROTECTED)))
+ {
+ actual_type.typeflags |= default_varmod;
+ }
+
+ actual_type.typeflags |= opt_star;
+
+#ifdef DEBUG
+ if (i & VIRTUAL_VAR_TAG)
+ {
+ /* When we want to allow 'late' initializers for
+ * inherited variables, it must have a distinct syntax,
+ * lest name clashs remain undetected, making LPC code
+ * hard to debug.
+ */
+ fatal("Newly declared variable is virtual\n");
+ }
+#endif
+ variables_initialized = MY_TRUE; /* We have __INIT code */
+
+ /* Push the variable reference and create the assignment */
+
+ if (i + num_virtual_variables > 0xff)
+ {
+ add_f_code(F_PUSH_IDENTIFIER16_LVALUE);
+ add_short(i + num_virtual_variables);
+ CURRENT_PROGRAM_SIZE += 1;
+ }
+ else
+ {
+ add_f_code(F_PUSH_IDENTIFIER_LVALUE);
+ add_byte(i + num_virtual_variables);
+ }
+
+ /* Only simple assigns are allowed */
+ if (assign_op != F_ASSIGN)
+ yyerror("Illegal initialization");
+
+ /* Do the types match? */
+ actual_type.typeflags &= TYPE_MOD_MASK;
+ if (!compatible_types(actual_type, exprtype, MY_TRUE))
+ {
+ yyerrorf("Type mismatch %s when initializing %s"
+ , get_two_types(actual_type, exprtype)
+ , get_txt(name->name));
+ }
+
+ /* Ok, assign */
+ add_f_code(F_VOID_ASSIGN);
+ CURRENT_PROGRAM_SIZE += 3;
+ add_new_init_jump();
+} /* init_global_variable() */
+
+/*-------------------------------------------------------------------------*/
+static void
store_function_header ( p_int start
, string_t * name, fulltype_t returntype
, int num_args, int num_vars
@@ -5450,6 +5616,7 @@
%type <fulltype> type
%type <fulltype> opt_basic_type basic_type
%type <fulltype> non_void_type opt_basic_non_void_type basic_non_void_type
+%type <fulltype> name_list member_name_list local_name_list
%type <inh_flags> inheritance_qualifier inheritance_qualifiers
%type <typeflags> inheritance_modifier_list inheritance_modifier
%ifdef USE_NEW_INLINES
@@ -5470,7 +5637,6 @@
%type <lrvalue> parse_command
%endif
%type <lvalue> lvalue name_lvalue local_name_lvalue foreach_var_lvalue
-%type <lvalue> new_local_name
%type <index> index_range index_expr
%type <case_label> case_label
%type <address> optional_else
@@ -5617,10 +5783,8 @@
#endif /* USE_NEW_INLINES */
}
- | type name_list ';' /* Variable definition */
+ | name_list ';' /* Variable definition */
{
- if ($1.typeflags == 0)
- yyerror("Missing type");
#ifndef USE_NEW_INLINES
if (first_inline_fun)
insert_inline_fun_now = MY_TRUE;
@@ -5817,7 +5981,7 @@
context_decl:
- basic_type local_name_list
+ local_name_list
{ /* Empty action to void value from local_name_list */ }
; /* context_decl */
@@ -5933,32 +6097,43 @@
; /* member_list */
member:
- basic_non_void_type member_name_list ';'
+ member_name_list ';'
{
- /* The member_name_list adds the struct members, using
- * the value of current_type set by basic_non_void_type.
- */
+ /* The member_name_list adds the struct members. */
}
; /* member */
member_name_list:
- member_name
- | member_name_list ',' member_name
-; /* member_name_list */
-
-member_name:
- optional_star L_IDENTIFIER
+ basic_non_void_type optional_star L_IDENTIFIER
{
+ fulltype_t actual_type = $1;
vartype_t type;
- current_type.typeflags |= $1;
- assign_full_to_vartype(&type, current_type);
- add_struct_member($2->name, type, NULL);
- if ($2->type == I_TYPE_UNKNOWN)
- free_shared_identifier($2);
+
+ actual_type.typeflags |= $2;
+
+ assign_full_to_vartype(&type, actual_type);
+ add_struct_member($3->name, type, NULL);
+ if ($3->type == I_TYPE_UNKNOWN)
+ free_shared_identifier($3);
+
+ $$ = $1;
}
-; /* member_name */
+ | member_name_list ',' optional_star L_IDENTIFIER
+ {
+ fulltype_t actual_type = $1;
+ vartype_t type;
+
+ actual_type.typeflags |= $3;
+
+ assign_full_to_vartype(&type, actual_type);
+ add_struct_member($4->name, type, NULL);
+ if ($4->type == I_TYPE_UNKNOWN)
+ free_shared_identifier($4);
+
+ $$ = $1;
+ }
+; /* member_name_list */
-
%endif /* USE_STRUCTS */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
@@ -6373,14 +6548,12 @@
type: type_modifier_list opt_basic_type
{
set_fulltype($$, $1 | $2.typeflags, $2.t_struct);
- current_type = $$;
} ;
non_void_type: type_modifier_list opt_basic_non_void_type
{
set_fulltype($$, $1 | $2.typeflags, $2.t_struct);
- current_type = $$;
} ;
@@ -6411,15 +6584,15 @@
basic_non_void_type:
- L_STATUS { $$ = Type_Number; current_type = $$; }
- | L_INT { $$ = Type_Number; current_type = $$; }
- | L_STRING_DECL { $$ = Type_String; current_type = $$; }
- | L_OBJECT { $$ = Type_Object; current_type = $$; }
- | L_CLOSURE_DECL { $$ = Type_Closure; current_type = $$; }
- | L_SYMBOL_DECL { $$ = Type_Symbol; current_type = $$; }
- | L_FLOAT_DECL { $$ = Type_Float; current_type = $$; }
- | L_MAPPING { $$ = Type_Mapping; current_type = $$; }
- | L_MIXED { $$ = Type_Any; current_type = $$; }
+ L_STATUS { $$ = Type_Number; }
+ | L_INT { $$ = Type_Number; }
+ | L_STRING_DECL { $$ = Type_String; }
+ | L_OBJECT { $$ = Type_Object; }
+ | L_CLOSURE_DECL { $$ = Type_Closure; }
+ | L_SYMBOL_DECL { $$ = Type_Symbol; }
+ | L_FLOAT_DECL { $$ = Type_Float; }
+ | L_MAPPING { $$ = Type_Mapping; }
+ | L_MIXED { $$ = Type_Any; }
%ifdef USE_STRUCTS
| L_STRUCT identifier
{
@@ -6438,7 +6611,6 @@
}
free_mstring($2);
- current_type = $$;
}
%endif /* USE_STRUCTS */
; /* basic_non_void_type */
@@ -6446,7 +6618,7 @@
basic_type:
basic_non_void_type
- | L_VOID { $$ = Type_Void; current_type = $$; }
+ | L_VOID { $$ = Type_Void; }
; /* basic_type */
@@ -6561,209 +6733,55 @@
; /* new_arg_name */
+
name_list:
- new_name
- | name_list ',' new_name;
-
-
-new_name:
/* Simple variable definition */
- optional_star L_IDENTIFIER
+ type optional_star L_IDENTIFIER
{
%line
- fulltype_t actual_type = current_type;
+ if ($1.typeflags == 0)
+ yyerror("Missing type");
- variables_defined = MY_TRUE;
+ define_global_variable($3, $1, $2, MY_FALSE);
+ $$ = $1;
+ }
- if (!(actual_type.typeflags & (TYPE_MOD_PRIVATE | TYPE_MOD_PUBLIC
- | TYPE_MOD_PROTECTED)))
- {
- actual_type.typeflags |= default_varmod;
- }
+ /* Variable definition with initialization */
- if (actual_type.typeflags & TYPE_MOD_VARARGS)
- {
- yyerror("can't declare a variable as varargs");
- actual_type.typeflags &= ~TYPE_MOD_VARARGS;
- }
+ | type optional_star L_IDENTIFIER
+ {
+ if ($1.typeflags == 0)
+ yyerror("Missing type");
- actual_type.typeflags |= $1;
+ $<number>$ = define_global_variable($3, $1, $2, MY_TRUE);
+ }
- if (!pragma_share_variables)
- actual_type.typeflags |= VAR_INITIALIZED;
+ L_ASSIGN expr0
+ {
+ init_global_variable($<number>4, $3, $1, $2, $5, $6.type);
+ $$ = $1;
+ }
- define_variable($2, actual_type);
-
- if (!(actual_type.typeflags & TYPE_MOD_POINTER)
- && (actual_type.typeflags & PRIMARY_TYPE_MASK) == TYPE_FLOAT
- )
- {
- int i = verify_declared($2); /* Is the var declared? */
-
- /* Prepare the init code */
- transfer_init_control();
-
- /* If this is the first variable initialization and
- * pragma_share_variables is in effect, insert
- * the check for blueprint/clone initialisation:
- * if (clonep(this_object())) return 1;
- */
- if (!variables_initialized && pragma_share_variables)
- {
- ins_f_code(F_THIS_OBJECT);
- ins_f_code(F_CLONEP);
- ins_f_code(F_BRANCH_WHEN_ZERO);
- ins_byte(2);
- ins_f_code(F_CONST1);
- ins_f_code(F_RETURN);
- }
-
- {
- PREPARE_INSERT(5)
- /* Must come after the non-local program code inserts! */
-
- add_f_code(F_FCONST0);
-
-#ifdef DEBUG
- if (i & VIRTUAL_VAR_TAG)
- {
- /* When we want to allow 'late' initializers for
- * inherited variables, it must have a distinct syntax,
- * lest name clashs remain undetected, making LPC code
- * hard to debug.
- */
- fatal("Newly declared variable is virtual\n");
- }
-#endif
- variables_initialized = MY_TRUE; /* We have __INIT code */
- if (!pragma_share_variables)
- VARIABLE(i)->type.typeflags |= VAR_INITIALIZED;
-
- /* Push the variable reference and create the assignment */
-
- if (i + num_virtual_variables > 0xff)
- {
- add_f_code(F_PUSH_IDENTIFIER16_LVALUE);
- add_short(i + num_virtual_variables);
- CURRENT_PROGRAM_SIZE += 1;
- }
- else
- {
- add_f_code(F_PUSH_IDENTIFIER_LVALUE);
- add_byte(i + num_virtual_variables);
- }
-
- /* Ok, assign */
- add_f_code(F_VOID_ASSIGN);
- CURRENT_PROGRAM_SIZE += 4;
- add_new_init_jump();
- } /* PREPARE_INSERT() block */
- } /* if (float variable) */
+ | name_list ',' optional_star L_IDENTIFIER
+ {
+ define_global_variable($4, $1, $3, MY_FALSE);
+ $$ = $1;
}
/* Variable definition with initialization */
- | optional_star L_IDENTIFIER
+ | name_list ',' optional_star L_IDENTIFIER
{
- fulltype_t actual_type = current_type;
-
- variables_defined = MY_TRUE;
-
- if (!(actual_type.typeflags & (TYPE_MOD_PRIVATE | TYPE_MOD_PUBLIC
- | TYPE_MOD_PROTECTED)))
- {
- actual_type.typeflags |= default_varmod;
- }
-
- actual_type.typeflags |= $1;
-
- define_variable($2, actual_type);
- $<number>$ = verify_declared($2); /* Is the var declared? */
-
- /* Prepare the init code */
- transfer_init_control();
-
- /* If this is the first variable initialization and
- * pragma_share_variables is in effect, insert
- * the check for blueprint/clone initialisation:
- * if (clonep(this_object())) return 1;
- */
- if (!variables_initialized && pragma_share_variables)
- {
- ins_f_code(F_THIS_OBJECT);
- ins_f_code(F_CLONEP);
- ins_f_code(F_BRANCH_WHEN_ZERO);
- ins_byte(2);
- ins_f_code(F_CONST1);
- ins_f_code(F_RETURN);
- }
+ $<number>$ = define_global_variable($4, $1, $3, MY_TRUE);
}
L_ASSIGN expr0
-
{
- fulltype_t actual_type = current_type;
- fulltype_t exprtype = $5.type;
- int i = $<number>3;
- PREPARE_INSERT(4)
-
- if (!(actual_type.typeflags & (TYPE_MOD_PRIVATE | TYPE_MOD_PUBLIC
- | TYPE_MOD_PROTECTED)))
- {
- actual_type.typeflags |= default_varmod;
- }
-
- actual_type.typeflags |= $1;
-
-#ifdef DEBUG
- if (i & VIRTUAL_VAR_TAG)
- {
- /* When we want to allow 'late' initializers for
- * inherited variables, it must have a distinct syntax,
- * lest name clashs remain undetected, making LPC code
- * hard to debug.
- */
- fatal("Newly declared variable is virtual\n");
- }
-#endif
- variables_initialized = MY_TRUE; /* We have __INIT code */
- if (!pragma_share_variables)
- VARIABLE(i)->type.typeflags |= VAR_INITIALIZED;
-
- /* Push the variable reference and create the assignment */
-
- if (i + num_virtual_variables > 0xff)
- {
- add_f_code(F_PUSH_IDENTIFIER16_LVALUE);
- add_short(i + num_virtual_variables);
- CURRENT_PROGRAM_SIZE += 1;
- }
- else
- {
- add_f_code(F_PUSH_IDENTIFIER_LVALUE);
- add_byte(i + num_virtual_variables);
- }
-
- /* Only simple assigns are allowed */
- if ($4 != F_ASSIGN)
- yyerror("Illegal initialization");
-
- /* Do the types match? */
- actual_type.typeflags &= TYPE_MOD_MASK;
- if (!compatible_types(actual_type, exprtype, MY_TRUE))
- {
- yyerrorf("Type mismatch %s when initializing %s"
- , get_two_types(actual_type, exprtype)
- , get_txt($2->name));
- }
-
- /* Ok, assign */
- add_f_code(F_VOID_ASSIGN);
- CURRENT_PROGRAM_SIZE += 3;
- add_new_init_jump();
+ init_global_variable($<number>5, $4, $1, $3, $6, $7.type);
+ $$ = $1;
}
-; /* new_name */
+; /* name_list */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
@@ -6803,224 +6821,81 @@
statements:
/* empty */
- | statements basic_type local_name_list ';'
+ | statements local_name_list ';'
| statements statement
;
local_name_list:
- new_local
- | local_name_list ',' new_local
-;
-
-
-new_local:
- new_local_name
+ basic_type optional_star L_IDENTIFIER
{
- /* If this is a float variable, we need to insert an appropriate
- * initializer, as the default svalue-0 is not a valid float value.
- */
-
- Bool need_value = MY_FALSE;
-%line
-
-#ifdef USE_NEW_INLINES
- /* When parsing context variables, the context_closure instruction
- * expects a value on the stack. If we do a float initialization,
- * we leave the 0.0 on the stack, otherwise we'll push a 0.
- * For normal float locals, we'll create the bytecode to assign
- * the float 0.
- */
- need_value = current_inline && current_inline->parse_context;
-#endif /* USE_NEW_INLINES */
-
- if (!($1.type.typeflags & TYPE_MOD_POINTER)
- && ($1.type.typeflags & PRIMARY_TYPE_MASK) == TYPE_FLOAT
- )
- {
- ins_f_code(F_FCONST0);
-
- if (!need_value)
- {
- if (!add_lvalue_code(&$1, F_VOID_ASSIGN))
- YYACCEPT;
- }
-
- need_value = MY_FALSE;
- } /* if (float variable) */
-
- if (need_value) /* If we still need a value... */
- {
- ins_number(0);
- }
+ struct lvalue_s lv;
+ define_local_variable($3, $1, $2, &lv, MY_FALSE, MY_FALSE);
+
+ $$ = $1;
}
-
- | new_local_name L_ASSIGN expr0
+ | basic_type optional_star L_LOCAL
{
- /* We got a "<name> = <expr>" type declaration. */
-
- fulltype_t type2 = $3.type;
-
-%line
-#ifdef USE_NEW_INLINES
-#ifdef DEBUG_INLINES
-if (current_inline && current_inline->parse_context) printf("DEBUG: inline context decl: name = expr, program_size %d\n", CURRENT_PROGRAM_SIZE);
-#endif /* DEBUG_INLINES */
-#endif /* USE_NEW_INLINES */
- type2.typeflags &= TYPEID_MASK;
-
- /* Check the assignment for validity */
- if (exact_types.typeflags && !compatible_types($1.type, type2, MY_TRUE))
- {
- yyerrorf("Bad assignment %s", get_two_types($1.type, type2));
- }
-
- if ($2 != F_ASSIGN)
- {
- yyerror("Only plain assignments allowed here");
- }
-
- if (type2.typeflags & TYPE_MOD_REFERENCE)
- yyerror("Can't trace reference assignments");
-
- /* If we're parsing a context variable, just leave the
- * value on the stack for the context_closure instruction.
- * For normal locals, add the bytecode to create the lvalue
- * and do the assignment.
- */
-#ifdef USE_NEW_INLINES
- if (!current_inline || !current_inline->parse_context)
-#endif /* USE_NEW_INLINES */
- {
- if (!add_lvalue_code(&$1, F_VOID_ASSIGN))
- YYACCEPT;
- } /* parsed context var */
+ struct lvalue_s lv;
+ define_local_variable($3, $1, $2, &lv, MY_TRUE, MY_FALSE);
+
+ $$ = $1;
}
-; /* new_local */
-
-new_local_name:
- optional_star L_IDENTIFIER
+ | basic_type optional_star L_IDENTIFIER
{
- /* A new local variable */
-
- block_scope_t *scope = block_scope + block_depth - 1;
- ident_t *q;
- fulltype_t actual_type = current_type;
-
- actual_type.typeflags |= $1;
-
-#ifdef USE_NEW_INLINES
- if (current_inline && current_inline->parse_context)
- {
-#ifdef DEBUG_INLINES
-printf("DEBUG: context name '%s'\n", get_txt($2->name));
-#endif /* DEBUG_INLINES */
- q = add_context_name($2, actual_type, -1);
- $$.u.simple[0] = F_PUSH_CONTEXT_LVALUE;
- $$.u.simple[1] = q->u.local.context;
- }
- else
- {
- q = add_local_name($2, actual_type, block_depth);
- if (use_local_scopes && scope->num_locals == 1)
- {
- /* First definition of a local, so insert the
- * clear_locals bytecode and remember its position
- */
- scope->addr = mem_block[A_PROGRAM].current_size;
- ins_f_code(F_CLEAR_LOCALS);
- ins_byte(scope->first_local);
- ins_byte(0);
- }
-
- $$.u.simple[0] = F_PUSH_LOCAL_VARIABLE_LVALUE;
- $$.u.simple[1] = q->u.local.num;
- }
-#else /* USE_NEW_INLINES */
- q = add_local_name($2, actual_type, block_depth, MY_FALSE);
-
- if (use_local_scopes && scope->num_locals == 1)
- {
- /* First definition of a local, so insert the
- * clear_locals bytecode and remember its position
- */
- scope->addr = mem_block[A_PROGRAM].current_size;
- ins_f_code(F_CLEAR_LOCALS);
- ins_byte(scope->first_local);
- ins_byte(0);
- }
-
- $$.u.simple[0] = F_PUSH_LOCAL_VARIABLE_LVALUE;
- $$.u.simple[1] = q->u.local.num;
-#endif /* USE_NEW_INLINES */
- $$.length = 0;
- $$.type = actual_type;
+ define_local_variable($3, $1, $2, &$<lvalue>$, MY_FALSE, MY_TRUE);
}
-
- | optional_star L_LOCAL
+ L_ASSIGN expr0
{
- /* A local name is redeclared. If this happens on a deeper
- * level, it is even legal.
- */
-
- ident_t *q;
- block_scope_t *scope = block_scope + block_depth - 1;
- fulltype_t actual_type = current_type;
-
- actual_type.typeflags |= $1;
-
-#ifdef USE_NEW_INLINES
- if (current_inline && current_inline->parse_context)
- {
-#ifdef DEBUG_INLINES
-printf("DEBUG: context name '%s'\n", get_txt($2->name));
-#endif /* DEBUG_INLINES */
- if (current_inline->block_depth+1 <= $2->u.local.depth)
- yyerrorf("Illegal to redeclare local name '%s'"
- , get_txt($2->name));
-
- q = add_context_name($2, actual_type, -1);
- $$.u.simple[0] = F_PUSH_CONTEXT_LVALUE;
- $$.u.simple[1] = q->u.local.context;
- }
- else
- {
- q = redeclare_local($2, actual_type, block_depth);
- if (use_local_scopes && scope->num_locals == 1)
- {
- /* First definition of a local, so insert the
- * clear_locals bytecode and remember its position
- */
- scope->addr = mem_block[A_PROGRAM].current_size;
- ins_f_code(F_CLEAR_LOCALS);
- ins_byte(scope->first_local);
- ins_byte(0);
- }
-
- $$.u.simple[0] = F_PUSH_LOCAL_VARIABLE_LVALUE;
- $$.u.simple[1] = q->u.local.num;
- }
-#else /* USE_NEW_INLINES */
- q = redeclare_local($2, actual_type, block_depth);
-
- if (use_local_scopes && scope->num_locals == 1)
- {
- /* First definition of a local, so insert the
- * clear_locals bytecode and remember its position
- */
- scope->addr = mem_block[A_PROGRAM].current_size;
- ins_f_code(F_CLEAR_LOCALS);
- ins_byte(scope->first_local);
- ins_byte(0);
- }
-
- $$.u.simple[0] = F_PUSH_LOCAL_VARIABLE_LVALUE;
- $$.u.simple[1] = q->u.local.num;
-#endif /* USE_NEW_INLINES */
- $$.length = 0;
- $$.type = actual_type;
+ init_local_variable($3, &$<lvalue>4, $5, $6.type);
+
+ $$ = $1;
}
-; /* new_local_name */
+ | basic_type optional_star L_LOCAL
+ {
+ define_local_variable($3, $1, $2, &$<lvalue>$, MY_TRUE, MY_TRUE);
+ }
+ L_ASSIGN expr0
+ {
+ init_local_variable($3, &$<lvalue>4, $5, $6.type);
+
+ $$ = $1;
+ }
+ | local_name_list ',' optional_star L_IDENTIFIER
+ {
+ struct lvalue_s lv;
+ define_local_variable($4, $1, $3, &lv, MY_FALSE, MY_FALSE);
+
+ $$ = $1;
+ }
+ | local_name_list ',' optional_star L_LOCAL
+ {
+ struct lvalue_s lv;
+ define_local_variable($4, $1, $3, &lv, MY_TRUE, MY_FALSE);
+
+ $$ = $1;
+ }
+ | local_name_list ',' optional_star L_IDENTIFIER
+ {
+ define_local_variable($4, $1, $3, &$<lvalue>$, MY_FALSE, MY_TRUE);
+ }
+ L_ASSIGN expr0
+ {
+ init_local_variable($4, &$<lvalue>5, $6, $7.type);
+
+ $$ = $1;
+ }
+ | local_name_list ',' optional_star L_LOCAL
+ {
+ define_local_variable($4, $1, $3, &$<lvalue>$, MY_TRUE, MY_TRUE);
+ }
+ L_ASSIGN expr0
+ {
+ init_local_variable($4, &$<lvalue>5, $6, $7.type);
+
+ $$ = $1;
+ }
+; /* local_name_list */
statement:
@@ -11516,8 +11391,14 @@
local_name_lvalue:
- basic_type new_local_name
- { $$ = $2; }
+ basic_type optional_star L_IDENTIFIER
+ {
+ define_local_variable($3, $1, $2, &$$, MY_FALSE, MY_TRUE);
+ }
+ | basic_type optional_star L_LOCAL
+ {
+ define_local_variable($3, $1, $2, &$$, MY_TRUE, MY_TRUE);
+ }
; /* local_name_lvalue */
@@ -13820,6 +13701,173 @@
/*=========================================================================*/
/*-------------------------------------------------------------------------*/
+static void
+define_local_variable (ident_t* name, fulltype_t actual_type, typeflags_t opt_star, struct lvalue_s *lv, Bool redeclare, Bool with_init)
+/* This is called directly from a parser rule: <type> [*] <name>
+ * if with_init is true, then an initialization of this variable will follow.
+ * if redeclare is true, then a local name is redeclared.
+ * It creates the local variable and returns the corresponding lvalue
+ * in lv.
+ */
+{
+ /* redeclare:
+ * MY_FALSE: A new local variable
+ * MY_TRUE: A local name is redeclared. If this happens
+ * on a deeper level, it is even legal.
+ */
+
+ block_scope_t *scope = block_scope + block_depth - 1;
+ ident_t *q;
+
+ actual_type.typeflags |= opt_star;
+
+#ifdef USE_NEW_INLINES
+ if (current_inline && current_inline->parse_context)
+ {
+#ifdef DEBUG_INLINES
+printf("DEBUG: context name '%s'\n", get_txt(name->name));
+#endif /* DEBUG_INLINES */
+
+ if (redeclare && current_inline->block_depth+1 <= name->u.local.depth)
+ yyerrorf("Illegal to redeclare local name '%s'"
+ , get_txt(name->name));
+
+ q = add_context_name(name, actual_type, -1);
+ lv->u.simple[0] = F_PUSH_CONTEXT_LVALUE;
+ lv->u.simple[1] = q->u.local.context;
+ }
+ else
+ {
+ if(redeclare)
+ q = redeclare_local(name, actual_type, block_depth);
+ else
+ q = add_local_name(name, actual_type, block_depth);
+ if (use_local_scopes && scope->num_locals == 1)
+ {
+ /* First definition of a local, so insert the
+ * clear_locals bytecode and remember its position
+ */
+ scope->addr = mem_block[A_PROGRAM].current_size;
+ ins_f_code(F_CLEAR_LOCALS);
+ ins_byte(scope->first_local);
+ ins_byte(0);
+ }
+
+ lv->u.simple[0] = F_PUSH_LOCAL_VARIABLE_LVALUE;
+ lv->u.simple[1] = q->u.local.num;
+ }
+#else /* USE_NEW_INLINES */
+ if (redeclare)
+ q = redeclare_local(name, actual_type, block_depth);
+ else
+ q = add_local_name(name, actual_type, block_depth, MY_FALSE);
+
+ if (use_local_scopes && scope->num_locals == 1)
+ {
+ /* First definition of a local, so insert the
+ * clear_locals bytecode and remember its position
+ */
+ scope->addr = mem_block[A_PROGRAM].current_size;
+ ins_f_code(F_CLEAR_LOCALS);
+ ins_byte(scope->first_local);
+ ins_byte(0);
+ }
+
+ lv->u.simple[0] = F_PUSH_LOCAL_VARIABLE_LVALUE;
+ lv->u.simple[1] = q->u.local.num;
+#endif /* USE_NEW_INLINES */
+ lv->length = 0;
+ lv->type = actual_type;
+
+ if (!with_init)
+ {
+ /* If this is a float variable, we need to insert an appropriate
+ * initializer, as the default svalue-0 is not a valid float value.
+ */
+
+ Bool need_value = MY_FALSE;
+%line
+
+#ifdef USE_NEW_INLINES
+ /* When parsing context variables, the context_closure instruction
+ * expects a value on the stack. If we do a float initialization,
+ * we leave the 0.0 on the stack, otherwise we'll push a 0.
+ * For normal float locals, we'll create the bytecode to assign
+ * the float 0.
+ */
+ need_value = current_inline && current_inline->parse_context;
+#endif /* USE_NEW_INLINES */
+
+ if (!(actual_type.typeflags & TYPE_MOD_POINTER)
+ && (actual_type.typeflags & PRIMARY_TYPE_MASK) == TYPE_FLOAT
+ )
+ {
+ ins_f_code(F_FCONST0);
+
+ if (!need_value)
+ {
+ if (!add_lvalue_code(lv, F_VOID_ASSIGN))
+ return;
+ }
+
+ need_value = MY_FALSE;
+ } /* if (float variable) */
+
+ if (need_value) /* If we still need a value... */
+ {
+ ins_number(0);
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+static void
+init_local_variable (ident_t* name, struct lvalue_s *lv, int assign_op, fulltype_t type2)
+/* This is called directly from a parser rule: <type> [*] <name> = <expr>
+ * It will be called after the call to define_local_variable().
+ * It assigns the result of <expr> to the variable.
+ */
+{
+ /* We got a "<name> = <expr>" type declaration. */
+
+%line
+#ifdef USE_NEW_INLINES
+#ifdef DEBUG_INLINES
+if (current_inline && current_inline->parse_context) printf("DEBUG: inline context decl: name = expr, program_size %d\n", CURRENT_PROGRAM_SIZE);
+#endif /* DEBUG_INLINES */
+#endif /* USE_NEW_INLINES */
+
+ type2.typeflags &= TYPEID_MASK;
+
+ /* Check the assignment for validity */
+ if (exact_types.typeflags && !compatible_types(lv->type, type2, MY_TRUE))
+ {
+ yyerrorf("Bad assignment %s", get_two_types(lv->type, type2));
+ }
+
+ if (assign_op != F_ASSIGN)
+ {
+ yyerror("Only plain assignments allowed here");
+ }
+
+ if (type2.typeflags & TYPE_MOD_REFERENCE)
+ yyerror("Can't trace reference assignments");
+
+ /* If we're parsing a context variable, just leave the
+ * value on the stack for the context_closure instruction.
+ * For normal locals, add the bytecode to create the lvalue
+ * and do the assignment.
+ */
+#ifdef USE_NEW_INLINES
+ if (!current_inline || !current_inline->parse_context)
+#endif /* USE_NEW_INLINES */
+ {
+ if (!add_lvalue_code(lv, F_VOID_ASSIGN))
+ return;
+ } /* parsed context var */
+}
+
+/*-------------------------------------------------------------------------*/
static Bool
add_lvalue_code ( struct lvalue_s * lv, int instruction)
| ||||
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2005-06-24 07:37 | Gnomi | New Issue | |
| 2005-08-25 12:26 | Gnomi | File Added: 3.3currenttype.diff | |
| 2005-08-25 12:29 | Gnomi | Note Added: 0000384 | |
| 2006-03-14 23:08 |
|
Status | new => resolved |
| 2006-03-14 23:08 |
|
Fixed in Version | => 3.3.714 |
| 2006-03-14 23:08 |
|
Resolution | open => fixed |
| 2006-03-14 23:08 |
|
Assigned To | => lars |
| 2006-03-14 23:08 |
|
Note Added: 0000498 | |
| 2007-10-06 19:55 |
|
Status | resolved => closed |
| 2010-11-16 09:42 |
|
Source_changeset_attached | => ldmud.git master 1b6d3ffe |
| 2018-01-29 18:59 |
|
Source_changeset_attached | => ldmud.git master 1b6d3ffe |
| 2018-01-29 21:57 |
|
Source_changeset_attached | => ldmud.git master 1b6d3ffe |