pike.git/src/program.c:25:
#include "constants.h"
#include "operators.h"
#include "builtin_functions.h"
#include "stuff.h"
#include "mapping.h"
#include "cyclic.h"
#include "pike_security.h"
#include "pike_types.h"
#include "opcodes.h"
#include "version.h"
+ #include "block_allocator.h"
#include "block_alloc.h"
#include "pikecode.h"
#include "pike_compiler.h"
#include "module_support.h"
#include <errno.h>
#include <fcntl.h>
#define sp Pike_sp
#undef ATTRIBUTE
#define ATTRIBUTE(X)
static void low_enter_compiler(struct object *ce, int inherit);
static void exit_program_struct(struct program *);
static size_t add_xstorage(size_t size,
size_t alignment,
ptrdiff_t modulo_orig);
- #undef EXIT_BLOCK
- #define EXIT_BLOCK(P) exit_program_struct( (P) )
+ static struct block_allocator program_allocator = BA_INIT_PAGES(sizeof(struct program), 4);
- #undef COUNT_OTHER
- #define COUNT_OTHER() do{ \
- struct program *p; \
- for(p=first_program;p;p=p->next) \
- { \
- size+=p->total_size - sizeof (struct program); \
- } \
- }while(0)
+ ATTRIBUTE((malloc))
+ struct program * alloc_program() {
+ return ba_alloc(&program_allocator);
+ }
- BLOCK_ALLOC_FILL_PAGES(program, 4)
+ void really_free_program(struct program * p) {
+ exit_program_struct(p);
+ ba_free(&program_allocator, p);
+ }
-
+ void count_memory_in_programs(size_t *num, size_t *_size) {
+ size_t size;
+ struct program *p;
+ ba_count_all(&program_allocator, num, &size);
+ for(p=first_program;p;p=p->next) {
+ size+=p->total_size - sizeof (struct program);
+ }
+ }
-
+ void free_all_program_blocks() {
+ ba_destroy(&program_allocator);
+ }
+
/* #define COMPILER_DEBUG */
/* #define PROGRAM_BUILD_DEBUG */
#ifdef COMPILER_DEBUG
#define CDFPRINTF(X) fprintf X
#else /* !COMPILER_DEBUG */
#define CDFPRINTF(X)
#endif /* COMPILER_DEBUG */
/*
pike.git/src/program.c:89:
* For normal applications, the hitrate is most likely well over 90%,
* but that should be verified.
* - Holistiska Centralbyrån (Hubbe)
*/
/* Define the size of the cache that is used for method lookup. */
/* A value of zero disables this cache */
#define FIND_FUNCTION_HASHSIZE 16384
/* Programs with less methods will not use the cache for method lookups.. */
- #define FIND_FUNCTION_HASH_TRESHOLD 9
+ #define FIND_FUNCTION_HASH_TRESHOLD 0
#define DECLARE
#include "compilation.h"
struct pike_string *this_program_string;
static struct pike_string *this_string, *this_function_string;
static struct pike_string *UNDEFINED_string;
/* Common compiler subsystems */
pike.git/src/program.c:1843:
if(!IS_UNDEFINED (Pike_sp-1))
{
ret=mkconstantsvaluenode(Pike_sp-1);
}
}
pop_stack();
return ret;
}
+ /* This function is intended to simplify resolving of
+ * program symbols during compile-time for C-modules.
+ *
+ * A typical use-case is for a C-module inheriting
+ * code written in Pike.
+ */
+ PMOD_EXPORT struct program *resolve_program(struct pike_string *ident)
+ {
+ struct program *ret = NULL;
+ struct node_s *n = resolve_identifier(ident);
+ if (n) {
+ if ((n->token == F_CONSTANT) && (TYPEOF(n->u.sval) == T_PROGRAM) &&
+ (ret = n->u.sval.u.program)) {
+ add_ref(ret);
+ } else {
+ my_yyerror("Invalid program identifier '%S'.", ident);
+ }
+ free_node(n);
+ } else {
+ my_yyerror("Unknown program identifier '%S'.", ident);
+ }
+ return ret;
+ }
+
/*! @decl constant this
*!
*! Builtin read only variable that evaluates to the current object.
*!
*! @seealso
*! @[this_program], @[this_object()]
*/
/*! @decl constant this_program
*!
pike.git/src/program.c:1898:
}
if ((inherit_num == -1) || (!TEST_COMPAT(7,6) && (inherit_num >= 0))) {
if (ident == this_string) {
/* Handle this. */
return mkthisnode(state->new_program, inherit_num);
}
/* Handle this_program */
if (ident == this_program_string) {
- node *n = mkefuncallnode("object_program",
+ node *n;
+ if (!state_depth && (inherit_num == -1) && colon_colon_ref &&
+ !TEST_COMPAT(7,8) &&
+ state->previous && state->previous->new_program) {
+ /* ::this_program
+ *
+ * This refers to the previous definition of the current class
+ * in its parent, and is typically used with inherit like:
+ *
+ * inherit Foo;
+ *
+ * // Override the Bar inherited from Foo.
+ * class Bar {
+ * // Bar is based on the implementation from Foo.
+ * inherit ::this_program;
+ *
+ * // ...
+ * }
+ */
+ struct program *parent;
+ struct pike_string *name = NULL;
+ int e;
+ int i;
+
+ /* Find the name of the current class. */
+ parent = state->previous->new_program;
+ for (e = parent->num_identifier_references; e--;) {
+ struct identifier *id = ID_FROM_INT(parent, e);
+ struct svalue *s;
+ if (!IDENTIFIER_IS_CONSTANT(id->identifier_flags) ||
+ (id->func.const_info.offset < 0)) {
+ continue;
+ }
+ s = &PROG_FROM_INT(parent, e)->
+ constants[id->func.const_info.offset].sval;
+ if ((TYPEOF(*s) != T_PROGRAM) ||
+ (s->u.program != state->new_program)) {
+ continue;
+ }
+ /* Found! */
+ name = id->name;
+ break;
+ }
+ if (!name) {
+ yyerror("Failed to find current class in its parent.");
+ return NULL;
+ }
+
+ /* Find ::name in the parent. */
+ i = reference_inherited_identifier(state->previous, NULL, name);
+ if (i == -1) {
+ my_yyerror("Failed to find previous inherited definition of %S "
+ "in parent.", name);
+ return NULL;
+ }
+ n = mkexternalnode(parent, i);
+ } else {
+ n = mkefuncallnode("object_program",
mkthisnode(state->new_program, inherit_num));
-
+ }
/* We know this expression is constant. */
n->node_info &= ~OPT_NOT_CONST;
n->tree_info &= ~OPT_NOT_CONST;
return n;
}
/* Handle this_function */
if (ident == this_function_string) {
int i;
if ((i = Pike_compiler->compiler_frame->current_function_number) >= 0) {
pike.git/src/program.c:2241:
struct reference *ref =
Pike_compiler->new_program->identifier_references + cur_id;
struct identifier *i;
/* No need to do anything for ourselves. */
if (ref == new_ref) continue;
/* Do not zapp hidden identifiers */
if(ref->id_flags & ID_HIDDEN) continue;
+ if(ref->id_flags & ID_VARIANT) continue;
+
/* Do not zapp functions with the wrong name... */
if((i = ID_FROM_PTR(Pike_compiler->new_program, ref))->name != name)
continue;
/* Do not zapp inherited inline ('local') identifiers,
* or inherited externals with new externals,
* since this makes it hard to identify in encode_value().
*/
if((ref->id_flags & (ID_INLINE|ID_INHERITED)) == (ID_INLINE|ID_INHERITED)
|| (ref->id_flags & new_ref->id_flags & ID_EXTERN)) {
pike.git/src/program.c:2278:
continue;
}
if ((ref->id_flags & (ID_INHERITED|ID_USED)) == (ID_INHERITED|ID_USED)) {
struct inherit *inh = INHERIT_FROM_PTR(Pike_compiler->new_program, ref);
struct reference *sub_ref;
/* Find the inherit one level away. */
while (inh->inherit_level > 1) inh--;
+ #if 0
#ifdef PIKE_DEBUG
if (!inh->inherit_level) {
-
+ /* FIXME: This is valid for references that are about to be
+ * overridden by the variant dispatcher.
+ */
Pike_fatal("Inherit without intermediate levels.\n");
}
#endif
-
+ #endif
sub_ref = PTR_FROM_INT(inh->prog, cur_id - inh->identifier_level);
/* Check if the symbol was used before it was inherited. */
if ((c->lex.pragmas & ID_STRICT_TYPES) &&
(sub_ref->id_flags & ID_USED)) {
struct identifier *sub_id = ID_FROM_PTR(inh->prog, sub_ref);
if (IDENTIFIER_IS_FUNCTION(sub_id->identifier_flags)) {
if ((Pike_compiler->compiler_pass == 2) &&
!pike_types_le(ID_FROM_PTR(Pike_compiler->new_program,
pike.git/src/program.c:2364:
* Consider this a fatal?
*/
p->identifiers[i].run_time_type = T_FUNCTION;
}
}
/* Fixup identifier overrides. */
for (i = 0; i < p->num_identifier_references; i++) {
struct reference *ref = p->identifier_references + i;
if (ref->id_flags & ID_HIDDEN) continue;
+ if (ref->id_flags & ID_VARIANT) continue;
if (ref->inherit_offset != 0) continue;
override_identifier (ref, ID_FROM_PTR (p, ref)->name);
}
/* Ok, sort for binsearch */
for(e=i=0;i<(int)p->num_identifier_references;i++)
{
struct reference *funp;
struct identifier *fun;
funp=p->identifier_references+i;
if(funp->id_flags & ID_HIDDEN) continue;
-
+ if(funp->id_flags & ID_VARIANT) continue;
fun=ID_FROM_PTR(p, funp);
if(funp->id_flags & ID_INHERITED)
{
int found_better=-1;
int funa_is_prototype;
/* NOTE: Mixin is currently not supported for PRIVATE symbols. */
if(funp->id_flags & ID_PRIVATE) continue;
funa_is_prototype = fun->func.offset == -1;
/* if(fun->func.offset == -1) continue; * prototype */
/* check for multiple definitions */
for(t=i+1;t<(int)p->num_identifier_references;t++)
{
struct reference *funpb;
struct identifier *funb;
funpb=p->identifier_references+t;
if (funpb->id_flags & ID_HIDDEN) continue;
-
+ if (funpb->id_flags & ID_VARIANT) continue;
funb=ID_FROM_PTR(p,funpb);
/* if(funb->func.offset == -1) continue; * prototype */
if(fun->name==funb->name)
{
if (!(funpb->id_flags & ID_PROTECTED)) {
/* Only regard this symbol as better if it
* will end up in the index further below.
*/
found_better=t;
pike.git/src/program.c:2494:
if (id >= 0) {
// LFUNs are used.
p->identifier_references[id].id_flags |= ID_USED;
}
}
/* Complain about unused private symbols. */
for (i = 0; i < p->num_identifier_references; i++) {
struct reference *ref = p->identifier_references + i;
if (ref->id_flags & ID_HIDDEN) continue;
+ if (ref->id_flags & ID_VARIANT) continue;
if (ref->inherit_offset != 0) continue;
if ((ref->id_flags & (ID_HIDDEN|ID_PRIVATE|ID_USED)) == ID_PRIVATE) {
yywarning("%S is private but not used anywhere.",
ID_FROM_PTR(p, ref)->name);
}
}
/* Set the PROGRAM_LIVE_OBJ flag by looking for destroy() and
* inherited PROGRAM_LIVE_OBJ flags. This is done at fixation time
pike.git/src/program.c:2648:
struct pike_string *name,
int flags,
int *idp)
{
struct compilation *c = THIS_COMPILATION;
int id=0;
struct svalue tmp;
CHECK_COMPILER();
- #ifdef WITH_FACETS
- if(Pike_compiler->compiler_pass == 1 && p) {
- p->facet_index = -1;
- p->facet_group = NULL;
- }
- #endif
-
+
/* We don't want to change thread, but we don't want to
* wait for the other threads to complete either.
*/
low_init_threads_disable();
c->compilation_depth++;
if (!Pike_compiler->compiler_frame) {
new_node_s_context();
}
pike.git/src/program.c:3024:
{
if(p->inherits[e].prog)
free_program(p->inherits[e].prog);
}
if(p->inherits[e].parent)
free_object(p->inherits[e].parent);
}
DOUBLEUNLINK(first_program, p);
- #ifdef WITH_FACETS
- if(p->facet_group)
- {
- free_object(p->facet_group);
- }
- #endif
-
+
if(p->flags & PROGRAM_OPTIMIZED)
{
#ifdef PIKE_USE_MACHINE_CODE
do {
/* NOTE: Assumes all BAR's are before any FOO. */
#define BAR(NUMTYPE,TYPE,ARGTYPE,NAME) \
if (p->NAME) mexec_free(p->NAME);
#define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \
if (p->NAME) { \
dmfree(p->NAME); \
pike.git/src/program.c:3239:
case T_FLOAT: return ALIGNOF(FLOAT_TYPE);
case T_INT: return ALIGNOF(INT_TYPE);
case PIKE_T_FREE:
case PIKE_T_GET_SET: return 1;
default: return ALIGNOF(void *);
}
}
#ifdef PIKE_DEBUG
- void dump_program_tables (const struct program *p, int indent)
+ PMOD_EXPORT void dump_program_tables (const struct program *p, int indent)
{
int d;
if (!p) {
fprintf(stderr, "%*sProgram: NULL\n\n", indent, "");
return;
}
fprintf(stderr,
"%*sProgram flags: 0x%04x\n\n",
pike.git/src/program.c:3694:
p) > 0)) {
Pike_fatal("Program->identifier_index[%ld] > "
"Program->identifier_index[%ld]\n",
(long)(e-1), (long)e);
}
}
}
#endif
+ static void f_dispatch_variant(INT32 args);
+
+ int is_variant_dispatcher(struct program *prog, int fun)
+ {
+ struct reference *ref;
+ struct identifier *id;
+ if (fun < 0) return 0;
+ ref = PTR_FROM_INT(prog, fun);
+ id = ID_FROM_PTR(prog, ref);
+ return (IDENTIFIER_IS_C_FUNCTION(id->identifier_flags) &&
+ (id->func.c_fun == f_dispatch_variant));
+ }
+
+ static int add_variant_dispatcher(struct pike_string *name,
+ struct pike_type *type,
+ int id_flags)
+ {
+ union idptr dispatch_fun;
+ dispatch_fun.c_fun = f_dispatch_variant;
+ return define_function(name, type, id_flags & ~(ID_VARIANT|ID_LOCAL),
+ IDENTIFIER_C_FUNCTION, &dispatch_fun, 0);
+ }
+
/* Note: This function is misnamed, since it's run after both passes. /mast */
/* finish-states:
*
* 0: First pass.
* 1: Last pass.
* 2: Called from decode_value().
*/
struct program *end_first_pass(int finish)
{
struct compilation *c = THIS_COMPILATION;
int e;
- struct program *prog;
+ struct program *prog = Pike_compiler->new_program;
struct pike_string *s;
-
+ int num_refs = prog->num_identifier_references;
+ union idptr dispatch_fun;
-
+ dispatch_fun.c_fun = f_dispatch_variant;
+
+ /* Collect variant functions that have been defined in this program,
+ * and add the corresponding dispatchers.
+ */
+ for (e = 0; e < num_refs; e++) {
+ struct identifier *id;
+ struct pike_string *name;
+ struct pike_type *type;
+ int id_flags;
+ int j;
+ if (prog->identifier_references[e].inherit_offset) continue;
+ if (!is_variant_dispatcher(prog, e)) continue;
+ /* Found a dispatcher. */
+
+ id = ID_FROM_INT(prog, e);
+ name = id->name;
+ type = NULL;
+ id_flags = 0;
+
+ CDFPRINTF((stderr, "Collecting variants of \"%s\"...\n", name->str));
+
+ /* Collect the variants of the function. */
+ j = prog->num_identifier_references;
+ while ((j = really_low_find_variant_identifier(name, prog, NULL, j,
+ SEE_PROTECTED|SEE_PRIVATE)) >= 0) {
+ struct reference *ref = prog->identifier_references + j;
+ id = ID_FROM_INT(prog, j);
+ id_flags |= ref->id_flags;
+ /* NB: The dispatcher needs the variant references to
+ * not get overloaded for the ::-operator to work.
+ */
+ prog->identifier_references[j].id_flags |= ID_LOCAL;
+ {
+ struct pike_type * temp = type;
+ type = or_pike_types(type, id->type, 1);
+ if (temp) free_type(temp);
+ }
+ #ifdef COMPILER_DEBUG
+ fprintf(stderr, "type: ");
+ simple_describe_type(id->type);
+ fprintf(stderr, "\n");
+ #endif
+ }
+ #ifdef COMPILER_DEBUG
+ fprintf(stderr, "Dispatcher type: ");
+ simple_describe_type(type);
+ fprintf(stderr, "\n");
+ #endif
+ /* Update the type of the dispatcher. */
+ id = ID_FROM_INT(prog, e);
+ free_type(id->type);
+ id->type = type;
+ prog->identifier_references->id_flags |= id_flags & ~(ID_VARIANT|ID_LOCAL);
+ next_ref:
+ ;
+ }
+
debug_malloc_touch(Pike_compiler->fake_object);
debug_malloc_touch(Pike_compiler->fake_object->storage);
MAKE_CONST_STRING(s,"__INIT");
/* Collect references to inherited __INIT functions */
if (!(Pike_compiler->new_program->flags & PROGRAM_AVOID_CHECK)) {
for(e=Pike_compiler->new_program->num_inherits-1;e;e--)
{
pike.git/src/program.c:4239: Inside #if 0
fprintf(stderr, " %04d: %04d %s\n",
e, p->inherits[e].inherit_level,
p->inherits[e].name?p->inherits[e].name->str:"NULL");
#endif /* 0 */
if (p->inherits[e].inherit_level > 1) continue;
if (name == p->inherits[e].name) return e;
}
return 0;
}
- /* Reference the symbol super_name::function_name */
- node *reference_inherited_identifier(struct pike_string *super_name,
- struct pike_string *function_name)
+ /* Reference the symbol inherit::name in the lexical context
+ * specified by state.
+ *
+ * Returns the reference in state->new_program if found.
+ */
+ PMOD_EXPORT int reference_inherited_identifier(struct program_state *state,
+ struct pike_string *inherit,
+ struct pike_string *name)
{
- int n,e,id;
- struct compilation *c = THIS_COMPILATION;
- struct program_state *state=Pike_compiler->previous;
-
+ int e, id;
struct program *p;
-
+
#ifdef PIKE_DEBUG
- if(function_name!=debug_findstring(function_name))
- Pike_fatal("reference_inherited_function on nonshared string.\n");
+ if (name != debug_findstring(name))
+ Pike_fatal("reference_inherited_identifier on nonshared string.\n");
#endif
- p=Pike_compiler->new_program;
+ if (!state) state = Pike_compiler;
- /* FIXME: This loop could be optimized by advancing by the number
- * of inherits in the inherit. But in that case the loop
- * would have to go the other way.
- */
- for(e=p->num_inherits-1;e>0;e--)
- {
- if(p->inherits[e].inherit_level!=1) continue;
- if(!p->inherits[e].name) continue;
+ p = state->new_program;
- if(super_name)
- if(super_name != p->inherits[e].name)
- continue;
-
- id=low_reference_inherited_identifier(0,
- e,
- function_name,
- SEE_PROTECTED);
-
- if(id!=-1)
- return mkidentifiernode(id);
-
- if(ISCONSTSTR(function_name,"`->") ||
- ISCONSTSTR(function_name,"`[]"))
- {
- return mknode(F_MAGIC_INDEX,mknewintnode(e),mknewintnode(0));
- }
-
- if(ISCONSTSTR(function_name,"`->=") ||
- ISCONSTSTR(function_name,"`[]="))
- {
- return mknode(F_MAGIC_SET_INDEX,mknewintnode(e),mknewintnode(0));
- }
-
- if(ISCONSTSTR(function_name,"_indices"))
- {
- return mknode(F_MAGIC_INDICES,mknewintnode(e),mknewintnode(0));
- }
-
- if(ISCONSTSTR(function_name,"_values"))
- {
- return mknode(F_MAGIC_VALUES,mknewintnode(e),mknewintnode(0));
- }
- }
-
-
- for(n=0;n<c->compilation_depth;n++,state=state->previous)
- {
- struct program *p=state->new_program;
-
+
/* FIXME: This loop could be optimized by advancing by the number
* of inherits in the inherit. But in that case the loop
* would have to go the other way.
*/
- for(e=p->num_inherits-1;e>0;e--)
- {
- if(p->inherits[e].inherit_level!=1) continue;
- if(!p->inherits[e].name) continue;
+ for (e = p->num_inherits; e--;) {
+ if (p->inherits[e].inherit_level != 1) continue;
+ if (inherit && (inherit != p->inherits[e].name)) continue;
- if(super_name)
- if(super_name != p->inherits[e].name)
- continue;
+ id = low_reference_inherited_identifier(state, e, name, SEE_PROTECTED);
- id=low_reference_inherited_identifier(state,e,function_name,SEE_PROTECTED);
-
- if(id!=-1)
- return mkexternalnode(p, id);
-
- if(ISCONSTSTR(function_name,"`->") ||
- ISCONSTSTR(function_name,"`[]"))
- {
- return mknode(F_MAGIC_INDEX,
- mknewintnode(e),mknewintnode(n+1));
+ if (id != -1) return id;
}
- if(ISCONSTSTR(function_name,"`->=") ||
- ISCONSTSTR(function_name,"`[]="))
- {
- return mknode(F_MAGIC_SET_INDEX,
- mknewintnode(e),mknewintnode(n+1));
+ return -1;
}
- if(ISCONSTSTR(function_name,"_indices"))
- {
- return mknode(F_MAGIC_INDICES,
- mknewintnode(e),mknewintnode(n+1));
- }
-
- if(ISCONSTSTR(function_name,"_values"))
- {
- return mknode(F_MAGIC_VALUES,
- mknewintnode(e),mknewintnode(n+1));
- }
- }
- }
-
- return 0;
- }
-
+
/* FIXME: This function probably doesn't do what it is intended to do
* if the last inherit had inherits of its own. Consider removal.
*/
void rename_last_inherit(struct pike_string *n)
{
if(Pike_compiler->new_program->inherits[Pike_compiler->new_program->num_inherits].name)
free_string(Pike_compiler->new_program->inherits[Pike_compiler->new_program->num_inherits].name);
copy_shared_string(Pike_compiler->new_program->inherits[Pike_compiler->new_program->num_inherits].name,
n);
}
pike.git/src/program.c:4436: Inside #if 0
parent_offset+=i->parent_offset;
#endif
return locate_parent_state(&state,
&i,
&parent_identifier,
depth);
}
#endif
- #ifdef WITH_FACETS
- void check_for_facet_inherit(struct program *p)
- {
- /* If the inherit statement comes before the facet keyword in the
- * class declaration the class will be temporarily marked as a
- * product-class, but this will be taken care of when the facet
- * keyword is found. */
- if (!p) return;
- if (Pike_compiler->new_program->facet_group &&
- p->facet_group != Pike_compiler->new_program->facet_group)
- yyerror("A class can not belong to two facet-groups.");
- if (p->flags & PROGRAM_IS_FACET) {
- if (Pike_compiler->new_program->flags & PROGRAM_IS_FACET) {
- if(Pike_compiler->new_program->facet_index != p->facet_index)
- yyerror("Facet class can't inherit from class in different facet.");
- }
- /* Otherwise this is a product class */
- else {
- if( !Pike_compiler->new_program->facet_group ) {
- Pike_compiler->new_program->flags |= PROGRAM_IS_PRODUCT;
- add_ref(p->facet_group);
- Pike_compiler->new_program->facet_group = p->facet_group;
- }
- push_int(Pike_compiler->new_program->id);
- push_int(p->facet_index);
- push_int(p->id);
- safe_apply(p->facet_group, "add_product_class", 3);
- pop_stack();
- }
- }
- /* The inherited class is not a facet class */
- else if (p->flags & PROGRAM_IS_PRODUCT) {
- if (Pike_compiler->new_program->flags & PROGRAM_IS_FACET) {
- yyerror("Facet class can't inherit from product class.");
- }
- else if(Pike_compiler->new_program->flags & PROGRAM_IS_PRODUCT){
- yyerror("Product class can't inherit from other product class.");
- }
- /* A class that inherits from a product class is also a product class */
- else {
- Pike_compiler->new_program->flags |= PROGRAM_IS_PRODUCT;
- add_ref(p->facet_group);
- Pike_compiler->new_program->facet_group = p->facet_group;
- }
- }
- }
- #endif
-
-
- /*
- * make this program inherit another program
- */
- PMOD_EXPORT void low_inherit(struct program *p,
+ void lower_inherit(struct program *p,
struct object *parent,
int parent_identifier,
int parent_offset,
INT32 flags,
struct pike_string *name)
{
int e;
ptrdiff_t inherit_offset, storage_offset;
struct inherit inherit;
pike.git/src/program.c:4575:
}
if (!(p->flags & (PROGRAM_FINISHED | PROGRAM_PASS_1_DONE))) {
yyerror ("Cannot inherit program in pass 1 "
"which is only a placeholder.");
yyerror ("(You probably have a cyclic symbol dependency that the "
"compiler cannot handle.)");
return;
}
- #ifdef WITH_FACETS
- /* Check if inherit is a facet inherit. */
- check_for_facet_inherit(p);
- #endif
-
+
if (p == placeholder_program) {
yyerror("Trying to inherit placeholder program (resolver problem).");
return;
}
/* parent offset was increased by 42 for above test.. */
if(parent_offset)
parent_offset-=42;
inherit_offset = Pike_compiler->new_program->num_inherits;
pike.git/src/program.c:4764:
if (fun.id_flags & ID_PUBLIC)
fun.id_flags |= flags & ~ID_PRIVATE;
else
fun.id_flags |= flags;
fun.id_flags |= ID_INHERITED;
add_to_identifier_references(fun);
}
}
+ /*
+ * make this program inherit another program
+ */
+ PMOD_EXPORT void low_inherit(struct program *p,
+ struct object *parent,
+ int parent_identifier,
+ int parent_offset,
+ INT32 flags,
+ struct pike_string *name)
+ {
+ lower_inherit(p, parent, parent_identifier, parent_offset, flags, name);
+
+ /* Don't do this for OBJECT_PARENT or INHERIT_PARENT inherits.
+ * They may show up here from decode_value().
+ */
+ if (parent_offset >= 42) {
+ if (p->flags & (PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT)) {
+ /* We'll need the parent pointer as well... */
+ struct program_state *state = Pike_compiler;
+
+ /* parent offset was increased by 42 by the caller... */
+ parent_offset -= 42;
+
+ while (state && state->new_program && parent_offset--) {
+ state->new_program->flags |= PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT;
+ state = state->previous;
+ }
+ }
+ }
+ }
+
PMOD_EXPORT void do_inherit(struct svalue *s,
INT32 flags,
struct pike_string *name)
{
struct object *parent_obj = NULL;
int parent_id = -1;
struct program *p = low_program_from_svalue(s, &parent_obj, &parent_id);
low_inherit(p, parent_obj, parent_id, 0, flags, name);
}
pike.git/src/program.c:4835:
do_inherit(s,flags,name);
return;
}else{
low_inherit(s->u.program,
0,
numid,
offset+42,
flags,
name);
}
- if (n->token == F_EXTERNAL) {
- struct program *p=program_from_svalue(s);
- if (p->flags & (PROGRAM_NEEDS_PARENT|PROGRAM_NEEDS_PARENT)) {
- /* We'll need the parent pointer as well... */
- struct program_state *state = Pike_compiler;
-
- while (state && (state->new_program->id != n->u.integer.a)) {
- state->new_program->flags |= PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT;
- state = state->previous;
- }
- }
- }
+
}else{
yyerror("Inherit identifier is not a constant program");
return;
}
break;
default:
resolv_class(n);
do_inherit(Pike_sp-1, flags, name);
pop_stack();
pike.git/src/program.c:5126: Inside #if defined(PROFILING)
dummy.opt_flags = 0;
#ifdef PROFILING
dummy.self_time=0;
dummy.num_calls=0;
dummy.recur_depth=0;
dummy.total_time=0;
#endif
if (run_time_type == PIKE_T_FREE) dummy.func.offset = -1;
- if (flags & ID_PRIVATE) flags |= ID_INLINE;
+ if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;
ref.id_flags=flags;
ref.identifier_offset=Pike_compiler->new_program->num_identifiers;
ref.inherit_offset=0;
ref.run_time_type = PIKE_T_UNKNOWN;
add_to_variable_index(ref.identifier_offset);
debug_add_to_identifiers(dummy);
pike.git/src/program.c:5174:
free_string(n);
free_type(t);
return ret;
}
/* type is a serialized tokenized type. */
PMOD_EXPORT int quick_map_variable(const char *name,
int name_length,
size_t offset,
const char *type,
- int type_length,
+ int UNUSED(type_length),
INT32 run_time_type,
INT32 flags)
{
int ret;
struct pike_string *n;
struct pike_type *t;
n = make_shared_binary_string(name, name_length);
t = make_pike_type(type);
pike.git/src/program.c:5339:
}
}
if (flags & ID_EXTERN) {
run_time_type = PIKE_T_FREE;
} else {
run_time_type=compile_type_to_runtime_type(type);
switch(run_time_type)
{
- #ifdef AUTO_BIGNUM
+
case T_INT:
- #endif
+
case T_OBJECT:
/* Make place for the object subtype. */
case T_FUNCTION:
case T_PROGRAM:
run_time_type = T_MIXED;
}
}
n=low_define_variable(name,type,flags,
low_add_storage(sizeof_variable(run_time_type),
pike.git/src/program.c:5502:
id=ID_FROM_INT(Pike_compiler->new_program,n);
if(id->func.const_info.offset>=0) {
/* Update the stored constant. */
assign_svalue (&PROG_FROM_INT(Pike_compiler->new_program,n)->
constants[id->func.const_info.offset].sval, c);
} else {
id->run_time_type = (unsigned char) TYPEOF(*c);
id->func.const_info.offset = store_constant(c, 0, 0);
}
free_type(id->type);
- if ((TYPEOF(*c) == T_INT) && !(flags & ID_INLINE)) {
- if (c->u.integer) {
- copy_pike_type(id->type, int_type_string);
- } else {
- copy_pike_type(id->type, zero_type_string);
- }
- } else {
- id->type = get_type_of_svalue(c);
- }
+ if( !(flags & ID_INLINE) )
+ id->type = get_lax_type_of_svalue( c );
+ else
+ id->type = get_type_of_svalue( c );
#ifdef PROGRAM_BUILD_DEBUG
fprintf (stderr, "%.*sstored constant #%d at %d\n",
cc->compilation_depth, "",
n, id->func.const_info.offset);
#endif
}
return n;
}
#ifdef PIKE_DEBUG
pike.git/src/program.c:5540:
#endif
copy_shared_string(dummy.name, name);
dummy.identifier_flags = IDENTIFIER_CONSTANT;
dummy.filename_strno = store_prog_string(cc->lex.current_file);
dummy.linenumber = cc->lex.current_line;
#if 1
if (c) {
#endif
- if ((TYPEOF(*c) == T_INT) && !(flags & ID_INLINE)) {
- if (c->u.integer) {
- copy_pike_type(dummy.type, int_type_string);
- } else {
- copy_pike_type(dummy.type, zero_type_string);
- }
- } else {
- dummy.type = get_type_of_svalue(c);
- }
+ if( !(flags & ID_INLINE) )
+ dummy.type = get_lax_type_of_svalue( c );
+ else
+ dummy.type = get_type_of_svalue( c );
dummy.run_time_type = (unsigned char) TYPEOF(*c);
dummy.func.const_info.offset = store_constant(c, 0, 0);
dummy.opt_flags=OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND;
if(TYPEOF(*c) == PIKE_T_PROGRAM && (c->u.program->flags & PROGRAM_CONSTANT))
dummy.opt_flags=0;
#if 1
}
else {
copy_pike_type(dummy.type, mixed_type_string);
dummy.run_time_type=T_MIXED;
dummy.func.const_info.offset = -1;
dummy.opt_flags=0;
}
#endif
- if (flags & ID_PRIVATE) flags |= ID_INLINE;
+ if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;
ref.id_flags=flags;
ref.identifier_offset=Pike_compiler->new_program->num_identifiers;
ref.inherit_offset=0;
ref.run_time_type = PIKE_T_UNKNOWN;
#ifdef PROFILING
dummy.self_time=0;
dummy.num_calls=0;
dummy.recur_depth=0;
pike.git/src/program.c:5774:
* if func isn't given, it is supposed to be a prototype.
*/
INT32 define_function(struct pike_string *name,
struct pike_type *type,
unsigned flags,
unsigned function_flags,
union idptr *func,
unsigned opt_flags)
{
struct compilation *c = THIS_COMPILATION;
+ struct program *prog = Pike_compiler->new_program;
struct identifier *funp,fun;
struct reference ref;
struct svalue *lfun_type;
int run_time_type = T_FUNCTION;
INT32 i;
int getter_setter = -1;
int is_setter = 0;
CHECK_COMPILER();
pike.git/src/program.c:5867:
int level = REPORT_NOTICE;
if (!match_types(type, gs_type)) {
level = REPORT_ERROR;
} else if (c->lex.pragmas & ID_STRICT_TYPES) {
level = REPORT_WARNING;
}
yytype_report(level, NULL, 0, gs_type,
NULL, 0, type, 0,
"Type mismatch for callback function %S:", name);
}
+ if (flags & ID_VARIANT) {
+ my_yyerror("Variants not supported for getter/setters: %S", name);
+ flags &= ~ID_VARIANT;
+ }
i = isidentifier(symbol);
if ((i >= 0) &&
- !((ref = PTR_FROM_INT(Pike_compiler->new_program, i))->
- id_flags & ID_INHERITED)) {
+ !((ref = PTR_FROM_INT(prog, i))->id_flags & ID_INHERITED)) {
/* Not an inherited symbol. */
- struct identifier *id = ID_FROM_INT(Pike_compiler->new_program, i);
+ struct identifier *id = ID_FROM_INT(prog, i);
if (!IDENTIFIER_IS_VARIABLE(id->identifier_flags)) {
my_yyerror("Illegal to redefine function %S with variable.", symbol);
} else if (id->run_time_type != PIKE_T_GET_SET) {
my_yyerror("Illegal to redefine a current variable with a getter/setter: %S.", symbol);
} else {
if ((ref->id_flags | ID_USED) != (flags | ID_USED)) {
if (Pike_compiler->compiler_pass == 1) {
yywarning("Modifier mismatch for variable %S.", symbol);
}
ref->id_flags &= flags | ID_USED;
}
getter_setter = i;
}
/* FIXME: Update id->type here. */
} else {
struct identifier *id;
i = low_define_variable(symbol, symbol_type, flags,
~0, PIKE_T_GET_SET);
- id = ID_FROM_INT(Pike_compiler->new_program, i);
+ id = ID_FROM_INT(prog, i);
/* Paranoia. */
id->func.gs_info.getter = -1;
id->func.gs_info.setter = -1;
getter_setter = i;
}
/* NOTE: The function needs to have the same PRIVATE/INLINE
* behaviour as the variable for overloading to behave
* as expected.
*
* FIXME: Force PRIVATE?
*/
flags |= ID_PROTECTED /* | ID_PRIVATE | ID_INLINE | ID_USED */;
free_type(symbol_type);
free_string(symbol);
}
}
if(IDENTIFIER_IS_C_FUNCTION(function_flags))
- Pike_compiler->new_program->flags |= PROGRAM_HAS_C_METHODS;
+ prog->flags |= PROGRAM_HAS_C_METHODS;
if (Pike_compiler->compiler_pass == 1) {
/* Mark the type as tentative by setting the runtime-type
* to T_MIXED.
*
* NOTE: This should be reset to T_FUNCTION in pass 2.
*/
run_time_type = T_MIXED;
}
- i=isidentifier(name);
+ i = isidentifier(name);
+ if (Pike_compiler->compiler_pass == 1) {
+ if (flags & ID_VARIANT) {
+ if (i >= 0) {
+ if (!is_variant_dispatcher(prog, i)) {
+ /* This function will be the termination function for
+ * our variant dispatcher.
+ */
+ struct reference ref = prog->identifier_references[i];
+ /* Make sure to not get complaints about multiple
+ * definitions when adding the variant dispatcher.
+ */
+ prog->identifier_references[i].id_flags |= ID_INHERITED;
+ add_variant_dispatcher(name, type, flags);
+ /* Restore the termination function as a variant. */
+ ref.id_flags |= ID_VARIANT;
+ if (is_variant_dispatcher(prog, i)) {
+ /* The termination function got replaced with
+ * the variant dispatcher.
+ */
+ add_to_identifier_references(ref);
+ } else {
+ /* The termination function is still in the same place. */
+ prog->identifier_references[i].id_flags = ref.id_flags;
+ }
+ } else if (prog->identifier_references[i].inherit_offset) {
+ /* NB: If we are overriding an inherited dispatcher, there's
+ * no need to go via it, since our new dispatcher can
+ * just continue on with the old ones variant functions.
+ */
+ add_variant_dispatcher(name, type, flags);
+ }
+ } else {
+ add_variant_dispatcher(name, type, flags);
+ }
+ i = really_low_find_variant_identifier(name, prog, type,
+ prog->num_identifier_references,
+ SEE_PROTECTED|SEE_PRIVATE);
+ } else if (is_variant_dispatcher(prog, i) &&
+ !prog->identifier_references[i].inherit_offset) {
+ if (!func || (func->c_fun != f_dispatch_variant) ||
+ !IDENTIFIER_IS_C_FUNCTION(function_flags)) {
+ /* FIXME: What about the case
+ *
+ * non-variant prototype;
+ *
+ * variant;
+ *
+ * non-variant definition.
+ */
+ my_yyerror("Overriding variant function %S() with "
+ "non-variant in the same class.",
+ name);
+ }
+ }
+ } else if (i >= 0) {
+ /* Pass 2 */
+ if (is_variant_dispatcher(prog, i)) {
+ if (!func || (func->c_fun != f_dispatch_variant) ||
+ !IDENTIFIER_IS_C_FUNCTION(function_flags)) {
+ /* Variant or variant termination function in second pass. */
+ flags |= ID_VARIANT;
+ i = really_low_find_variant_identifier(name, prog, type,
+ prog->num_identifier_references,
+ SEE_PROTECTED|SEE_PRIVATE);
+ }
+ }
+ }
if(i >= 0)
{
int overridden;
/* already defined */
#ifdef PROGRAM_BUILD_DEBUG
fprintf(stderr, "%.*sexisted as identifier #%d\n",
c->compilation_depth, "", i);
#endif
- funp=ID_FROM_INT(Pike_compiler->new_program, i);
- ref=Pike_compiler->new_program->identifier_references[i];
+ funp = ID_FROM_INT(prog, i);
+ ref = prog->identifier_references[i];
if (funp->identifier_flags & IDENTIFIER_HAS_BODY)
/* Keep this flag. */
function_flags |= IDENTIFIER_HAS_BODY;
if(!(ref.id_flags & ID_INHERITED)) /* not inherited */
{
if( !( IDENTIFIER_IS_FUNCTION(funp->identifier_flags) &&
( (!func || func->offset == -1) || (funp->func.offset == -1))))
{
my_yyerror("Identifier %S defined twice.", name);
if (getter_setter != -1) {
- struct identifier *id = ID_FROM_INT(Pike_compiler->new_program,
- getter_setter);
+ struct identifier *id = ID_FROM_INT(prog, getter_setter);
(&id->func.gs_info.getter)[is_setter] = i;
}
return i;
}
/* Note: The type from pass 1 may be incompatible with the one from
* pass 2. Only do this in pass 2, and only if the previous
* type isn't from pass 1.
*/
if ((Pike_compiler->compiler_pass == 2) &&
(funp->run_time_type == T_FUNCTION)) {
/* match types against earlier prototype or vice versa */
if(!match_types(type, funp->type))
{
- if (!(flags & ID_VARIANT)) {
+
yytype_report(REPORT_ERROR, NULL, 0,
funp->type,
NULL, 0, type, 0,
"Prototype doesn't match for function %S.", name);
}
}
- }
+
if(func)
funp->func = *func;
#if 0 /* prototypes does not override non-prototypes, ok? */
else
funp->func.offset = -1;
#endif
funp->identifier_flags=function_flags;
funp->run_time_type = run_time_type;
pike.git/src/program.c:6006:
if((ref.id_flags & ID_FINAL)
#if 0
&& !(funp->func.offset == -1)
#endif
)
{
my_yyerror("Illegal to redefine 'final' function %S.", name);
}
+ if (!(flags & ID_VARIANT) && (Pike_compiler->compiler_pass == 1) &&
+ (funp->func.c_fun == f_dispatch_variant) &&
+ (!func || (func->c_fun != f_dispatch_variant) ||
+ !IDENTIFIER_IS_C_FUNCTION(function_flags)) &&
+ IDENTIFIER_IS_C_FUNCTION(funp->identifier_flags)) {
+ /* Overriding a variant function dispatcher with
+ * a non-variant function in pass 1.
+ *
+ * Hide the corresponding variant functions.
+ */
+ int j = prog->num_identifier_references;
+ while ((j = really_low_find_variant_identifier(name, prog, NULL, j,
+ SEE_PROTECTED|SEE_PRIVATE)) != -1) {
+ if (!prog->identifier_references[j].inherit_offset) {
+ /* FIXME: This doesn't catch all cases, and should probably
+ * be moved to a place where it does.
+ */
+ my_yyerror("Overloading variant function %S with non-variant in same class.",
+ name);
+ }
+ prog->identifier_references[j].id_flags |= ID_HIDDEN;
+ }
+ }
if(ref.id_flags & ID_INLINE)
{
#ifdef PROGRAM_BUILD_DEBUG
fprintf(stderr, "%.*sidentifier is local\n",
c->compilation_depth, "");
#endif
/* Hide the previous definition, and make a new definition. */
- Pike_compiler->new_program->identifier_references[i].id_flags |=
- ID_PROTECTED;
+ prog->identifier_references[i].id_flags |= ID_PROTECTED;
goto make_a_new_def;
}
/* Otherwise we alter the existing definition */
#ifdef PROGRAM_BUILD_DEBUG
fprintf(stderr, "%.*saltering the existing definition\n",
c->compilation_depth, "");
#endif
copy_shared_string(fun.name, name);
pike.git/src/program.c:6041:
fun.identifier_flags=function_flags;
if(func)
fun.func = *func;
else
fun.func.offset = -1;
fun.opt_flags = opt_flags;
- ref.identifier_offset=Pike_compiler->new_program->num_identifiers;
+ ref.identifier_offset = prog->num_identifiers;
debug_add_to_identifiers(fun);
}
- if (flags & ID_PRIVATE) flags |= ID_INLINE;
+ if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;
ref.inherit_offset = 0;
ref.id_flags = flags;
- if ((overridden = override_identifier (&ref, name)) >= 0) {
+ if (flags & ID_VARIANT) {
+ ref.id_flags |= ID_USED;
+ prog->identifier_references[i] = ref;
+ overridden = i;
+ } else {
+ overridden = override_identifier(&ref, name);
+ }
+ if (overridden >= 0) {
#ifdef PIKE_DEBUG
- struct reference *oref =
- Pike_compiler->new_program->identifier_references+overridden;
+ struct reference *oref = prog->identifier_references+overridden;
if((oref->inherit_offset != ref.inherit_offset) ||
(oref->identifier_offset != ref.identifier_offset) ||
((oref->id_flags | ID_USED) != (ref.id_flags | ID_USED))) {
fprintf(stderr,
"ref: %d:%d 0x%04x\n"
"got: %d:%d 0x%04x (%d)\n",
ref.inherit_offset, ref.identifier_offset,
ref.id_flags,
oref->inherit_offset,
oref->identifier_offset,
oref->id_flags,
overridden);
Pike_fatal("New function overloading algorithm failed!\n");
}
#endif
if (getter_setter != -1) {
- struct identifier *id = ID_FROM_INT(Pike_compiler->new_program,
- getter_setter);
+ struct identifier *id = ID_FROM_INT(prog, getter_setter);
INT32 old_i = (&id->func.gs_info.getter)[is_setter];
if ((old_i >= 0) && (old_i != overridden)) {
my_yyerror("Multiple definitions for %S.", name);
}
(&id->func.gs_info.getter)[is_setter] = overridden;
}
return overridden;
}
/* NOTE: At this point we already have the identifier in the
* new program, and just need to add the reference.
pike.git/src/program.c:6113:
else
fun.func.offset = -1;
fun.opt_flags = opt_flags;
#ifdef PIKE_DEBUG
if (a_flag > 5) {
fprintf(stderr,
"Adding new function #%d: '%s'\n"
" identifier_flags:0x%02x opt_flags:0x%04x\n",
- Pike_compiler->new_program->num_identifiers,
+ prog->num_identifiers,
fun.name->str,
fun.identifier_flags, fun.opt_flags);
}
#endif /* PIKE_DEBUG */
- i=Pike_compiler->new_program->num_identifiers;
+ i = prog->num_identifiers;
debug_add_to_identifiers(fun);
- if (flags & ID_PRIVATE) flags |= ID_INLINE;
+ if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;
ref.id_flags = flags;
ref.identifier_offset = i;
ref.inherit_offset = 0;
}
ref.run_time_type = PIKE_T_UNKNOWN;
/* Add the reference. */
- i=Pike_compiler->new_program->num_identifier_references;
+ i = prog->num_identifier_references;
add_to_identifier_references(ref);
#ifdef PROGRAM_BUILD_DEBUG
fprintf(stderr, "%.*sadded new definition #%d\n",
c->compilation_depth, "", i);
#endif
if (getter_setter != -1) {
- struct identifier *id = ID_FROM_INT(Pike_compiler->new_program,
- getter_setter);
+ struct identifier *id = ID_FROM_INT(prog, getter_setter);
INT32 old_i = (&id->func.gs_info.getter)[is_setter];
if (old_i >= 0) {
my_yyerror("Multiple definitions for %S.", name);
}
(&id->func.gs_info.getter)[is_setter] = i;
}
return i;
}
pike.git/src/program.c:6285:
#endif /* PIKE_DEBUG */
id = -1;
depth = 0;
last_inh = prog->num_inherits;
i = (int)prog->num_identifier_references;
while(i--)
{
funp = prog->identifier_references + i;
if(funp->id_flags & ID_HIDDEN) continue;
+ if(funp->id_flags & ID_VARIANT) continue;
if(funp->id_flags & ID_PROTECTED)
if(!(flags & SEE_PROTECTED))
continue;
fun = ID_FROM_PTR(prog, funp);
/* if(fun->func.offset == -1) continue; * Prototype */
if(!is_same_string(fun->name,name)) continue;
if(funp->id_flags & ID_INHERITED)
{
struct inherit *inh = INHERIT_FROM_PTR(prog, funp);
if ((funp->id_flags & ID_PRIVATE) && !(flags & SEE_PRIVATE)) continue;
pike.git/src/program.c:6325:
depth = inh->inherit_level;
id = i;
}
} else {
return i;
}
}
return id;
}
+ int really_low_find_variant_identifier(struct pike_string *name,
+ struct program *prog,
+ struct pike_type *type,
+ int start_pos,
+ int flags)
+ {
+ struct reference *funp;
+ struct identifier *fun;
+ int id, i, depth, last_inh;
+
+ #if 1
+ #ifdef COMPILER_DEBUG
+ fprintf(stderr,"th(%ld) %p Trying to find variant \"%s\" start=%d flags=%d\n"
+ " type: ",
+ (long)th_self(), prog, name->str, start_pos, flags);
+ simple_describe_type(type);
+ fprintf(stderr, "\n");
+ #endif
+ #endif
+
+ #ifdef PIKE_DEBUG
+ if (!prog) {
+ Pike_fatal("really_low_find_variant_identifier(\"%s\", NULL, %p, %d, %d)\n"
+ "prog is NULL!\n", name->str, type, start_pos, flags);
+ }
+ #endif /* PIKE_DEBUG */
+
+ id = -1;
+ depth = 0;
+ last_inh = prog->num_inherits;
+ i = start_pos;
+ #ifdef PIKE_DEBUG
+ if (i > (int)prog->num_identifier_references) {
+ Pike_fatal("really_low_find_variant_identifier(\"%s\", %p, %p, %d, %d):\n"
+ "Start position is past max: %d\n",
+ name->str, prog, type, start_pos, flags,
+ prog->num_identifier_references);
+ }
+ #endif /* PIKE_DEBUG */
+ while(i--)
+ {
+ funp = prog->identifier_references + i;
+ if(funp->id_flags & ID_HIDDEN) continue;
+ if(!(funp->id_flags & ID_VARIANT)) continue;
+ if(funp->id_flags & ID_PROTECTED)
+ if(!(flags & SEE_PROTECTED))
+ continue;
+ fun = ID_FROM_PTR(prog, funp);
+ /* if(fun->func.offset == -1) continue; * Prototype */
+ if(!is_same_string(fun->name,name)) continue;
+ if(type && (fun->type != type)) continue;
+ if(funp->id_flags & ID_INHERITED)
+ {
+ struct inherit *inh = INHERIT_FROM_PTR(prog, funp);
+ if ((funp->id_flags & ID_PRIVATE) && !(flags & SEE_PRIVATE)) continue;
+ if (!depth || (depth > inh->inherit_level)) {
+ if (id != -1) {
+ int j;
+ int min_level = depth;
+ for (j=last_inh-1; j > funp->inherit_offset; j--) {
+ struct inherit *inh2 = prog->inherits + j;
+ if (inh2->inherit_level >= min_level) {
+ /* Got deeper in the inherit graph */
+ continue;
+ }
+ min_level = inh2->inherit_level;
+ }
+ if (!(inh->inherit_level < min_level)) {
+ continue;
+ }
+ /* Found new identifier on the path from the old identifier to
+ * the root.
+ */
+ }
+ last_inh = funp->inherit_offset;
+ depth = inh->inherit_level;
+ id = i;
+ }
+ } else {
+ CDFPRINTF((stderr, "Found %d\n", i));
+ return i;
+ }
+ }
+ CDFPRINTF((stderr, "Found %d\n", id));
+ return id;
+ }
+
+ /**
+ * This is the dispatcher function for variant functions.
+ *
+ * cf end_first_pass().
+ */
+ static void f_dispatch_variant(INT32 args)
+ {
+ struct pike_frame *fp = Pike_fp;
+ struct program *prog = fp->context->prog;
+ struct reference *funp = PTR_FROM_INT(fp->current_program, fp->fun);
+ struct identifier *id = ID_FROM_PTR(fp->current_program, funp);
+ struct pike_string *name = id->name;
+ int fun_num = prog->num_identifier_references;
+ int flags = 0;
+
+ /* NB: The following is mostly to support a potential future
+ * case where a mixed set of protections would cause
+ * multiple dispatchers with the same name to be added
+ * (but different protection (and types)).
+ */
+ if (funp->id_flags & ID_PRIVATE) {
+ flags = SEE_PRIVATE|SEE_PROTECTED;
+ } else if (funp->id_flags & ID_PROTECTED) {
+ flags = SEE_PROTECTED;
+ }
+
+ while ((fun_num = really_low_find_variant_identifier(name, prog, NULL,
+ fun_num, flags)) != -1) {
+ int i;
+ struct pike_type *t;
+ struct pike_type *ret;
+
+ id = ID_FROM_INT(prog, fun_num);
+ add_ref(t = id->type);
+
+ /* Check whether the type is compatible with our arguments. */
+ for (i = 0; i < args; i++) {
+ struct pike_type *cont = check_call_svalue(t, 0, Pike_sp+i - args);
+ free_type(t);
+ if (!(t = cont)) break;
+ }
+ if (!t) continue;
+ ret = new_get_return_type(t, 0);
+ free_type(t);
+ if (!ret) continue;
+ free_type(ret);
+
+ /* Found a function to call! */
+ apply_current(fun_num, args);
+ return;
+ }
+ Pike_error("Invalid arguments to %S()!\n", name);
+ }
+
PMOD_EXPORT int low_find_lfun(struct program *p, ptrdiff_t lfun)
{
struct pike_string *lfun_name = lfun_strings[lfun];
unsigned int flags = 0;
#if 0
struct identifier *id;
#endif
int i =
really_low_find_shared_string_identifier(lfun_name,
dmalloc_touch(struct program *,
pike.git/src/program.c:6483:
return i;
reference_shared_string(str);
add_to_strings(str);
return i;
}
/* NOTE: O(n²)! */
int store_constant(const struct svalue *foo,
int equal,
- struct pike_string *constant_name)
+ struct pike_string *UNUSED(constant_name))
{
struct program_constant tmp;
volatile unsigned int e;
JMP_BUF jmp;
if (SETJMP(jmp)) {
handle_compile_exception ("Error comparing constants.");
/* Assume that if `==() throws an error, the svalues aren't equal. */
e = Pike_compiler->new_program->num_constants;
} else {
pike.git/src/program.c:6548:
*/
struct array *program_indices(struct program *p)
{
int e;
int n = 0;
struct array *res;
for (e = p->num_identifier_references; e--; ) {
struct identifier *id;
if (p->identifier_references[e].id_flags &
- (ID_HIDDEN|ID_PROTECTED|ID_PRIVATE)) {
+ (ID_HIDDEN|ID_VARIANT|ID_PROTECTED|ID_PRIVATE)) {
continue;
}
id = ID_FROM_INT(p, e);
if (IDENTIFIER_IS_ALIAS(id->identifier_flags)) {
/* FIXME!
*/
continue;
} else if (IDENTIFIER_IS_CONSTANT(id->identifier_flags)) {
if (id->func.const_info.offset >= 0) {
struct program *p2 = PROG_FROM_INT(p, e);
pike.git/src/program.c:6587:
}
struct array *program_values(struct program *p)
{
int e;
int n = 0;
struct array *res;
for(e = p->num_identifier_references; e--; ) {
struct identifier *id;
if (p->identifier_references[e].id_flags &
- (ID_HIDDEN|ID_PROTECTED|ID_PRIVATE)) {
+ (ID_HIDDEN|ID_VARIANT|ID_PROTECTED|ID_PRIVATE)) {
continue;
}
id = ID_FROM_INT(p, e);
if (IDENTIFIER_IS_ALIAS(id->identifier_flags)) {
/* FIXME!
*/
continue;
} else if (IDENTIFIER_IS_CONSTANT(id->identifier_flags)) {
if (id->func.const_info.offset >= 0) {
struct program *p2 = PROG_FROM_INT(p, e);
pike.git/src/program.c:6626:
}
struct array *program_types(struct program *p)
{
int e;
int n = 0;
struct array *res;
for (e = p->num_identifier_references; e--; ) {
struct identifier *id;
if (p->identifier_references[e].id_flags &
- (ID_HIDDEN|ID_PROTECTED|ID_PRIVATE)) {
+ (ID_HIDDEN|ID_VARIANT|ID_PROTECTED|ID_PRIVATE)) {
continue;
}
id = ID_FROM_INT(p, e);
if (IDENTIFIER_IS_ALIAS(id->identifier_flags)) {
/* FIXME!
*/
continue;
} else if (IDENTIFIER_IS_CONSTANT(id->identifier_flags)) {
if (id->func.const_info.offset >= 0) {
struct program *p2 = PROG_FROM_INT(p, e);
pike.git/src/program.c:7669:
if (s) {
push_string(s);
yyreport(REPORT_ERROR, parser_system_string, 1, "%s");
}
}
pop_stack();
free_svalue(&thrown);
}
- extern void yyparse(void);
+ extern int yyparse(void);
#ifdef PIKE_DEBUG
#define do_yyparse() do { \
struct svalue *save_sp=Pike_sp; \
yyparse(); /* Parse da program */ \
if(save_sp != Pike_sp) { \
Pike_fatal("yyparse() left %"PRINTPTRDIFFT"d droppings on the stack!\n", \
Pike_sp - save_sp); \
} \
}while(0)
pike.git/src/program.c:7696: Inside #if defined(PIKE_DEBUG)
#ifdef PIKE_DEBUG
struct supporter_marker
{
struct supporter_marker *next;
void *data;
int level, verified;
};
- #undef EXIT_BLOCK
- #define EXIT_BLOCK(P)
- #undef COUNT_OTHER
- #define COUNT_OTHER()
-
+
#undef INIT_BLOCK
#define INIT_BLOCK(X) do { (X)->level = (X)->verified = 0; }while(0)
PTR_HASH_ALLOC(supporter_marker, 128);
static int supnum;
#define SNUM(X) (get_supporter_marker((X))->level)
static void mark_supporters(struct Supporter *s)
{
pike.git/src/program.c:9717:
/*! @class CompilerState
*!
*! Keeps the state of a single program/class during compilation.
*!
*! @note
*! Not in use yet!
*/
#define THIS_PROGRAM_STATE ((struct program_state *)(Pike_fp->current_storage))
- static void program_state_event_handler(int event)
+ static void program_state_event_handler(int UNUSED(event))
{
#if 0
struct program_state *c = THIS_PROGRAM_STATE;
switch (event) {
case PROG_EVENT_INIT:
#define INIT
#include "compilation.h"
break;
case PROG_EVENT_EXIT:
#define EXIT
pike.git/src/program.c:10145:
}
free_string(name_tmp);
free_type(type_tmp);
return ret;
}
PMOD_EXPORT int quick_add_function(const char *name,
int name_length,
void (*cfun)(INT32),
const char *type,
- int type_length,
+ int UNUSED(type_length),
unsigned flags,
unsigned opt_flags)
{
int ret;
struct pike_string *name_tmp;
struct pike_type *type_tmp;
union idptr tmp;
/* fprintf(stderr,"ADD_FUNC: %s\n",name); */
name_tmp = make_shared_binary_string(name, name_length);
type_tmp = make_pike_type(type);
pike.git/src/program.c:10211: Inside #if defined(PIKE_DEBUG)
}
#endif
}
#endif
#undef THIS
#define THIS ((struct pike_trampoline *)(CURRENT_STORAGE))
struct program *pike_trampoline_program=0;
- static void apply_trampoline(INT32 args)
+ static void apply_trampoline(INT32 UNUSED(args))
{
Pike_error("Internal error: Trampoline magic failed!\n");
}
static void not_trampoline(INT32 args)
{
pop_n_elems(args);
if (!THIS->frame || !THIS->frame->current_object ||
!THIS->frame->current_object->prog) {
push_int(1);
pike.git/src/program.c:10249:
ref_push_function (THIS->frame->current_object, THIS->func);
init_buf(&save_buf);
describe_svalue (sp - 1, 0, 0);
str = complex_free_buf(&save_buf);
pop_stack();
push_string (make_shared_binary_string (str.str, str.len));
free (str.str);
}
- static void init_trampoline(struct object *o)
+ static void init_trampoline(struct object *UNUSED(o))
{
THIS->frame=0;
}
- static void exit_trampoline(struct object *o)
+ static void exit_trampoline(struct object *UNUSED(o))
{
if(THIS->frame)
{
free_pike_scope(THIS->frame);
THIS->frame=0;
}
}
static void gc_check_frame(struct pike_frame *f)
{
pike.git/src/program.c:10277:
if(f->current_object)
debug_gc_check (f->current_object, " as current_object in trampoline frame");
if(f->current_program)
debug_gc_check (f->current_program, " as current_program in trampoline frame");
debug_gc_check_svalues (f->locals, f->num_locals, " in locals of trampoline frame");
if(f->scope && !debug_gc_check (f->scope, " as scope frame of trampoline frame"))
gc_check_frame(f->scope);
}
}
- static void gc_check_trampoline(struct object *o)
+ static void gc_check_trampoline(struct object *UNUSED(o))
{
if (THIS->frame &&
!debug_gc_check (THIS->frame, " as trampoline frame"))
gc_check_frame(THIS->frame);
}
static void gc_recurse_frame(struct pike_frame *f)
{
if(f->current_object) gc_recurse_object(f->current_object);
if(f->current_program) gc_recurse_program(f->current_program);
if(f->flags & PIKE_FRAME_MALLOCED_LOCALS)
gc_recurse_svalues(f->locals,f->num_locals);
if(f->scope) gc_recurse_frame(f->scope);
}
- static void gc_recurse_trampoline(struct object *o)
+ static void gc_recurse_trampoline(struct object *UNUSED(o))
{
if (THIS->frame) gc_recurse_frame(THIS->frame);
}
/* This placeholder should be used
* in the first compiler pass to take the place
* of unknown things
*/
struct program *placeholder_program;
pike.git/src/program.c:10333:
MAKE_CONST_STRING (s, "__placeholder_object");
ref_push_string (s);
}
void init_program(void)
{
size_t i;
struct svalue key;
struct svalue val;
struct svalue id;
- init_program_blocks();
+
MAKE_CONST_STRING(this_function_string,"this_function");
MAKE_CONST_STRING(this_program_string,"this_program");
MAKE_CONST_STRING(this_string,"this");
MAKE_CONST_STRING(UNDEFINED_string,"UNDEFINED");
MAKE_CONST_STRING(parser_system_string, "parser");
MAKE_CONST_STRING(type_check_system_string, "type_check");
lfun_ids = allocate_mapping(NUM_LFUNS);
pike.git/src/program.c:11121:
/* returns 1 if a implements b */
static int low_implements(struct program *a, struct program *b)
{
int e;
struct pike_string *s=findstring("__INIT");
for(e=0;e<b->num_identifier_references;e++)
{
struct identifier *bid;
int i;
- if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN))
+ if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))
continue; /* Skip protected & hidden */
bid = ID_FROM_INT(b,e);
if(s == bid->name) continue; /* Skip __INIT */
i = find_shared_string_identifier(bid->name,a);
if (i == -1) {
if (b->identifier_references[e].id_flags & (ID_OPTIONAL))
continue; /* It's ok... */
#if 0
fprintf(stderr, "Missing identifier \"%s\"\n", bid->name->str);
#endif /* 0 */
pike.git/src/program.c:11202:
if (a->num_identifier_references < b->num_identifier_references) {
struct program *tmp = a;
a = b;
b = tmp;
}
for(e=0;e<b->num_identifier_references;e++)
{
struct identifier *bid;
int i;
- if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN))
+ if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))
continue; /* Skip protected & hidden */
/* FIXME: What if they aren't protected & hidden in a? */
bid = ID_FROM_INT(b,e);
if(s == bid->name) continue; /* Skip __INIT */
i = find_shared_string_identifier(bid->name,a);
if (i == -1) {
continue; /* It's ok... */
}
pike.git/src/program.c:11324:
}
SET_CYCLIC_RET(1);
a_file = get_program_line(a, &a_line);
b_file = get_program_line(b, &b_line);
for(e=0;e<b->num_identifier_references;e++)
{
struct identifier *bid;
int i;
- if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN))
+ if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))
continue; /* Skip protected & hidden */
/* FIXME: What if they aren't protected & hidden in a? */
bid = ID_FROM_INT(b,e);
if(s == bid->name) continue; /* Skip __INIT */
i = find_shared_string_identifier(bid->name,a);
if (i == -1) {
continue; /* It's ok... */
}
pike.git/src/program.c:11386:
}
SET_CYCLIC_RET(1);
a_file = get_program_line(a, &a_line);
b_file = get_program_line(b, &b_line);
for(e=0;e<b->num_identifier_references;e++)
{
struct identifier *bid;
int i;
- if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN))
+ if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))
continue; /* Skip protected & hidden */
bid = ID_FROM_INT(b,e);
if(s == bid->name) continue; /* Skip __INIT */
i = find_shared_string_identifier(bid->name,a);
if (i == -1) {
INT_TYPE bid_line = b_line;
struct pike_string *bid_file;
if (b->identifier_references[e].id_flags & (ID_OPTIONAL))
continue; /* It's ok... */
bid_file = get_identifier_line(b, e, &bid_line);
pike.git/src/program.c:11433:
bid->name);
}
continue;
}
}
free_string(b_file);
free_string(a_file);
END_CYCLIC();
}
+ /* FIXME: Code duplication of yyexplain_not_compatible() above! */
+ /* Explains why a is not compatible with b */
+ void string_builder_explain_not_compatible(struct string_builder *s,
+ struct program *a,
+ struct program *b)
+ {
+ int e;
+ struct pike_string *init_string = findstring("__INIT");
+ int res = 1;
+ DECLARE_CYCLIC();
+
+ /* Optimize the loop somewhat */
+ if (a->num_identifier_references < b->num_identifier_references) {
+ struct program *tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ if (BEGIN_CYCLIC(a, b)) {
+ END_CYCLIC();
+ return;
+ }
+ SET_CYCLIC_RET(1);
+
+ for(e=0;e<b->num_identifier_references;e++)
+ {
+ struct identifier *bid;
+ int i;
+ if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))
+ continue; /* Skip protected & hidden */
+
+ /* FIXME: What if they aren't protected & hidden in a? */
+
+ bid = ID_FROM_INT(b,e);
+ if(init_string == bid->name) continue; /* Skip __INIT */
+ i = find_shared_string_identifier(bid->name,a);
+ if (i == -1) {
+ continue; /* It's ok... */
+ }
+
+ /* Note: Uses weaker check for constant integers. */
+ if(((bid->run_time_type != PIKE_T_INT) ||
+ (ID_FROM_INT(a, i)->run_time_type != PIKE_T_INT)) &&
+ !match_types(ID_FROM_INT(a,i)->type, bid->type)) {
+ ref_push_program(a);
+ ref_push_program(b);
+ ref_push_type_value(ID_FROM_INT(a, i)->type);
+ ref_push_type_value(bid->type);
+ string_builder_sprintf(s,
+ "Identifier %S in %O is incompatible with "
+ "the same in %O.\n"
+ "Expected: %O\n"
+ "Got : %O\n",
+ bid->name, Pike_sp-4,
+ Pike_sp-3,
+ Pike_sp-2,
+ Pike_sp-1);
+ pop_n_elems(4);
+ }
+ }
+ END_CYCLIC();
+ return;
+ }
+
+ /* FIXME: code duplication of yyexplain_not_implements() above! */
+ /* Explains why a does not implement b */
+ void string_builder_explain_not_implements(struct string_builder *s,
+ struct program *a,
+ struct program *b)
+ {
+ int e;
+ struct pike_string *init_string = findstring("__INIT");
+ DECLARE_CYCLIC();
+
+ if (BEGIN_CYCLIC(a, b)) {
+ END_CYCLIC();
+ return;
+ }
+ SET_CYCLIC_RET(1);
+
+ for(e=0;e<b->num_identifier_references;e++)
+ {
+ struct identifier *bid;
+ int i;
+ if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))
+ continue; /* Skip protected & hidden */
+ bid = ID_FROM_INT(b,e);
+ if(init_string == bid->name) continue; /* Skip __INIT */
+ i = find_shared_string_identifier(bid->name,a);
+ if (i == -1) {
+ if (b->identifier_references[e].id_flags & (ID_OPTIONAL))
+ continue; /* It's ok... */
+ ref_push_type_value(bid->type);
+ string_builder_sprintf(s,
+ "Missing identifier %O %S.\n",
+ Pike_sp-1, bid->name);
+ pop_stack();
+ continue;
+ }
+
+ if (!pike_types_le(bid->type, ID_FROM_INT(a, i)->type)) {
+ ref_push_type_value(bid->type);
+ ref_push_type_value(ID_FROM_INT(a, i)->type);
+ if(!match_types(ID_FROM_INT(a,i)->type, bid->type)) {
+ string_builder_sprintf(s,
+ "Type of identifier %S does not match.\n"
+ "Expected: %O.\n"
+ "Got : %O.\n",
+ bid->name,
+ Pike_sp-2,
+ Pike_sp-1);
+ } else {
+ string_builder_sprintf(s,
+ "Type of identifier %S is not strictly compatible.",
+ "Expected: %O.\n"
+ "Got : %O.\n",
+ bid->name,
+ Pike_sp-2,
+ Pike_sp-1);
+ }
+ pop_n_elems(2);
+ continue;
+ }
+ }
+ END_CYCLIC();
+ }
+
PMOD_EXPORT void *parent_storage(int depth)
{
struct external_variable_context loc;
loc.o = Pike_fp->current_object;
loc.parent_identifier = 0;
loc.inherit = Pike_fp->context;
find_external_context(&loc, depth);