e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
aedfb12002-10-09Martin Nilsson 
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h" #include <ctype.h> #include "svalue.h" #include "stralloc.h"
4d404a2013-02-19Henrik Grubbström (Grubba) #include "pike_types.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "array.h" #include "program.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "constants.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "object.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "multiset.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "mapping.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
b8cda21997-01-21Fredrik Hübinette (Hubbe) #include "las.h"
93dd411999-11-23Henrik Grubbström (Grubba) #include "lex.h"
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) #include "pike_memory.h"
6c39401999-10-28Fredrik Hübinette (Hubbe) #include "bignum.h"
fbafd01999-12-12Henrik Grubbström (Grubba) #include "main.h"
f76b4c2000-05-11Henrik Grubbström (Grubba) #include "opcodes.h"
e026a72004-03-10Henrik Grubbström (Grubba) #include "cyclic.h"
16c5692007-03-31Henrik Grubbström (Grubba) #include "gc.h"
e021fe2008-04-14Henrik Grubbström (Grubba) #include "pike_compiler.h"
d476592013-06-12Arne Goedeke #include "block_allocator.h"
8079a42014-01-11Tobias S. Josefowitz #include "bitvector.h"
c1835b2017-11-11Tobias S. Josefowitz #include "gc_header.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) 
5528582000-12-01Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG
f37a212002-08-14Henrik Grubbström (Grubba) #define PIKE_TYPE_DEBUG
5528582000-12-01Henrik Grubbström (Grubba) #endif /* PIKE_DEBUG */
02f0631999-11-24Fredrik Hübinette (Hubbe) 
7926bf2007-03-26Henrik Grubbström (Grubba) 
71a9672001-03-03Henrik Grubbström (Grubba) /* Number of entries in the struct pike_type hash-table. */
830d982015-12-10Per Hedbor /* 256Kb */ #define PIKE_TYPE_HASH_SIZE 32767
71a9672001-03-03Henrik Grubbström (Grubba)  #ifdef PIKE_TYPE_DEBUG static int indent=0; #endif
1d53281996-11-25Fredrik Hübinette (Hubbe) int max_correct_args;
daea6d2007-03-20Henrik Grubbström (Grubba) PMOD_EXPORT struct pike_type *string0_type_string;
71a9672001-03-03Henrik Grubbström (Grubba) PMOD_EXPORT struct pike_type *string_type_string; PMOD_EXPORT struct pike_type *int_type_string;
218dba2020-01-08Henrik Grubbström (Grubba) PMOD_EXPORT struct pike_type *int_pos_type_string;
71a9672001-03-03Henrik Grubbström (Grubba) PMOD_EXPORT struct pike_type *float_type_string; PMOD_EXPORT struct pike_type *function_type_string;
6901f22020-09-25Henrik Grubbström (Grubba) PMOD_EXPORT struct pike_type *void_function_type_string;
71a9672001-03-03Henrik Grubbström (Grubba) PMOD_EXPORT struct pike_type *object_type_string; PMOD_EXPORT struct pike_type *program_type_string; PMOD_EXPORT struct pike_type *array_type_string; PMOD_EXPORT struct pike_type *multiset_type_string; PMOD_EXPORT struct pike_type *mapping_type_string; PMOD_EXPORT struct pike_type *type_type_string; PMOD_EXPORT struct pike_type *mixed_type_string; PMOD_EXPORT struct pike_type *void_type_string; PMOD_EXPORT struct pike_type *zero_type_string;
38f9312014-05-03Henrik Grubbström (Grubba) PMOD_EXPORT struct pike_type *inheritable_type_string; PMOD_EXPORT struct pike_type *typeable_type_string;
d6f6d62013-11-08Henrik Grubbström (Grubba) PMOD_EXPORT struct pike_type *enumerable_type_string;
71a9672001-03-03Henrik Grubbström (Grubba) PMOD_EXPORT struct pike_type *any_type_string; PMOD_EXPORT struct pike_type *weak_type_string; /* array|mapping|multiset|function */
6f16cb2008-05-18Henrik Grubbström (Grubba) struct pike_type *sscanf_type_string;
1874052018-04-21Henrik Grubbström (Grubba) PMOD_EXPORT struct pike_type *utf8_type_string;
71a9672001-03-03Henrik Grubbström (Grubba) 
68ec3f2014-08-18Martin Nilsson PMOD_EXPORT struct pike_string *literal_string_string; PMOD_EXPORT struct pike_string *literal_int_string; PMOD_EXPORT struct pike_string *literal_float_string; PMOD_EXPORT struct pike_string *literal_function_string; PMOD_EXPORT struct pike_string *literal_object_string; PMOD_EXPORT struct pike_string *literal_program_string; PMOD_EXPORT struct pike_string *literal_array_string; PMOD_EXPORT struct pike_string *literal_multiset_string; PMOD_EXPORT struct pike_string *literal_mapping_string; PMOD_EXPORT struct pike_string *literal_type_string; PMOD_EXPORT struct pike_string *literal_mixed_string;
da62282020-12-23Henrik Grubbström (Grubba) /* Special case for converting T_ZERO into int(0) during processing. * Note that int(0) is usually automatically converted into T_ZERO, * so we need to define the type by hand explicitly here. */ static struct pike_type int0_type_string_storage = { GC_HEADER_INIT(1), 0, NULL, 0, T_INT, NULL, NULL, }; #define int0_type_string (&int0_type_string_storage)
68ec3f2014-08-18Martin Nilsson 
9405012007-04-26Martin Stjernholm #ifdef DO_PIKE_CLEANUP
94b2fb2001-03-28Henrik Grubbström (Grubba) struct pike_type_location *all_pike_type_locations = NULL;
9405012007-04-26Martin Stjernholm #endif /* DO_PIKE_CLEANUP */
94b2fb2001-03-28Henrik Grubbström (Grubba) 
71a9672001-03-03Henrik Grubbström (Grubba) static struct pike_type *a_markers[10], *b_markers[10]; static struct program *implements_a; static struct program *implements_b;
da371d2003-11-18Henrik Grubbström (Grubba) static int implements_mode;
71a9672001-03-03Henrik Grubbström (Grubba)  #ifdef PIKE_DEBUG
d4d96c2020-09-09Henrik Grubbström (Grubba) void TYPE_STACK_DEBUG(const char *fun)
71a9672001-03-03Henrik Grubbström (Grubba) {
d4d96c2020-09-09Henrik Grubbström (Grubba)  if (l_flag > 2) { fprintf(stderr, "%25s(): stack_depth:%-3ld mark_stack_depth:%ld\n", fun, (long)(Pike_compiler->type_stackp - type_stack), (long)(Pike_compiler->pike_type_mark_stackp - pike_type_mark_stack)); if (Pike_compiler->type_stackp != type_stack) { fprintf(stderr, "%25s : top: ", ""); simple_describe_type(peek_type_stack()); fprintf(stderr, "\n"); } }
71a9672001-03-03Henrik Grubbström (Grubba) } #endif /* PIKE_DEBUG */ static void clear_markers(void) { unsigned int e; for(e=0;e<NELEM(a_markers);e++) { if(a_markers[e]) { free_type(a_markers[e]); a_markers[e]=0; } if(b_markers[e]) { free_type(b_markers[e]); b_markers[e]=0; } } }
38a96a2020-01-04Henrik Grubbström (Grubba) void compiler_discard_top_type(void) { TYPE_STACK_DEBUG("discard_top_type"); #ifdef PIKE_DEBUG
1d54a12020-05-19Henrik Grubbström (Grubba)  if (pike_type_mark_stack == Pike_compiler->pike_type_mark_stackp) { /* Type mark stack empty. */ if (type_stack == Pike_compiler->type_stackp) Pike_fatal("Type stack underflow.\n"); } else if (!peek_stack_mark())
38a96a2020-01-04Henrik Grubbström (Grubba)  Pike_fatal("Type stack underflow.\n"); #endif free_type(*(Pike_compiler->type_stackp--)); }
884b6f2008-06-17Martin Stjernholm void compiler_discard_type (void) { ptrdiff_t len = pop_stack_mark();
38a96a2020-01-04Henrik Grubbström (Grubba)  TYPE_STACK_DEBUG("discard_type");
884b6f2008-06-17Martin Stjernholm  for (;len > 0; len--) { /* Get rid of excess junk. */
38a96a2020-01-04Henrik Grubbström (Grubba)  compiler_discard_top_type();
884b6f2008-06-17Martin Stjernholm  } }
64133e2021-09-27Henrik Grubbström (Grubba) static struct pike_type *low_pop_type(void) { TYPE_STACK_DEBUG("low_pop_type"); return *(Pike_compiler->type_stackp--); } #define low_pop_type() ((struct pike_type *)debug_malloc_pass(low_pop_type()))
71a9672001-03-03Henrik Grubbström (Grubba) struct pike_type *debug_pop_type(void) { struct pike_type *t = pop_unfinished_type(); TYPE_STACK_DEBUG("pop_type"); type_stack_mark(); return t; } struct pike_type *debug_compiler_pop_type(void) { TYPE_STACK_DEBUG("compiler_pop_type"); if(Pike_compiler->num_parse_error) {
5261002004-03-12Henrik Grubbström (Grubba)  struct pike_type *res;
884b6f2008-06-17Martin Stjernholm  compiler_discard_type(); add_ref(res = mixed_type_string);
71a9672001-03-03Henrik Grubbström (Grubba)  type_stack_mark();
5261002004-03-12Henrik Grubbström (Grubba)  return res;
71a9672001-03-03Henrik Grubbström (Grubba)  }else{ return debug_pop_type(); } }
e68c782006-07-05Martin Stjernholm PMOD_EXPORT char *get_name_of_type(TYPE_T t)
71a9672001-03-03Henrik Grubbström (Grubba) {
9e5e9b2020-09-16Henrik Grubbström (Grubba)  switch(t & PIKE_T_MASK)
71a9672001-03-03Henrik Grubbström (Grubba)  {
97a7332008-03-30Martin Stjernholm  case T_ARRAY: return "array"; case T_MAPPING: return "mapping"; case T_MULTISET: return "multiset"; case T_OBJECT: return "object"; case T_FUNCTION: return "function"; case T_PROGRAM: return "program"; case T_STRING: return "string"; case T_TYPE: return "type"; case T_INT: return "int"; case T_FLOAT: return "float"; case T_ZERO: return "zero"; case T_VOID: return "void"; case T_MIXED: return "mixed"; default: return "unknown"; #ifdef PIKE_DEBUG /* Let's make it able to describe any type constant in debug mode. */ case T_UNFINISHED: return "T_UNFINISHED"; case T_MANY: return "T_MANY"; case PIKE_T_INT_UNTYPED: return "PIKE_T_INT_UNTYPED"; case PIKE_T_GET_SET: return "PIKE_T_GET_SET"; case PIKE_T_FREE: return "PIKE_T_FREE";
0bd03e2020-07-13Henrik Grubbström (Grubba)  case PIKE_T_FUNCTION_ARG: return "PIKE_T_FUNCTION_ARG";
0a3d9f2020-07-18Henrik Grubbström (Grubba)  case PIKE_T_FIND_LFUN: return "PIKE_T_FIND_LFUN";
5745e22021-07-04Henrik Grubbström (Grubba)  case PIKE_T_SET_CAR: return "PIKE_T_SET_CAR"; case PIKE_T_SET_CDR: return "PIKE_T_SET_CDR";
0a3d9f2020-07-18Henrik Grubbström (Grubba) 
97a7332008-03-30Martin Stjernholm  case PIKE_T_ATTRIBUTE: return "PIKE_T_ATTRIBUTE"; case PIKE_T_NSTRING: return "PIKE_T_NSTRING";
d785932020-01-14Henrik Grubbström (Grubba)  case PIKE_T_LSTRING: return "PIKE_T_LSTRING"; case PIKE_T_LARRAY: return "PIKE_T_LARRAY";
97a7332008-03-30Martin Stjernholm  case PIKE_T_RING: return "PIKE_T_RING"; case PIKE_T_NAME: return "PIKE_T_NAME"; case PIKE_T_SCOPE: return "PIKE_T_SCOPE"; case PIKE_T_TUPLE: return "PIKE_T_TUPLE"; case T_ASSIGN: return "T_ASSIGN"; case T_DELETED: return "T_DELETED"; case PIKE_T_UNKNOWN: return "PIKE_T_UNKNOWN"; case T_OBJ_INDEX: return "T_OBJ_INDEX"; case T_SVALUE_PTR: return "T_SVALUE_PTR"; case T_ARRAY_LVALUE: return "T_ARRAY_LVALUE"; case T_NOT: return "T_NOT"; case T_AND: return "T_AND"; case T_OR: return "T_OR"; case T_STORAGE: return "object storage"; case T_MAPPING_DATA: return "mapping_data"; case T_PIKE_FRAME: return "pike_frame"; case T_MULTISET_DATA: return "multiset_data"; case T_STRUCT_CALLABLE: return "callable"; #endif
71a9672001-03-03Henrik Grubbström (Grubba)  } } #define TWOT(X,Y) (((X) << 8)+(Y)) static int low_pike_types_le(struct pike_type *a, struct pike_type *b, int array_cnt, unsigned int flags); static int low_check_indexing(struct pike_type *type, struct pike_type *index_type, node *n);
0929a02002-09-12Marcus Comstedt static void internal_parse_type(const char **s);
71a9672001-03-03Henrik Grubbström (Grubba)  /* * New and improved type representation system. * * This representation is new in Pike 7.3. * * Node: Car: Cdr: * --------------------------------------------- * SCOPE num vars (int) type * ASSIGN variable (int) type
ce88d62001-03-19Henrik Grubbström (Grubba)  * NAME name (string) type
64ac752007-11-03Henrik Grubbström (Grubba)  * ATTRIBUTE name (string) type Added in 7.7.
71a9672001-03-03Henrik Grubbström (Grubba)  * FUNCTION type FUNCTION|MANY * MANY many type return type
64ac752007-11-03Henrik Grubbström (Grubba)  * RING type type Reserved. * TUPLE type type Reserved.
71a9672001-03-03Henrik Grubbström (Grubba)  * MAPPING index type value type
1a82092007-04-17Henrik Grubbström (Grubba)  * OR type (not OR) type
71a9672001-03-03Henrik Grubbström (Grubba)  * AND type type
16edb92020-01-03Henrik Grubbström (Grubba)  * ARRAY len type type len added in 8.1
71a9672001-03-03Henrik Grubbström (Grubba)  * MULTISET type - * NOT type -
0aa8592021-11-11Henrik Grubbström (Grubba)  * '0'-'9' - - Marker $0-$9.
71a9672001-03-03Henrik Grubbström (Grubba)  * FLOAT - -
16edb92020-01-03Henrik Grubbström (Grubba)  * STRING len type ZERO, INT or OR len:8.1, Range:7.7
9b5a822001-03-29Henrik Grubbström (Grubba)  * TYPE type -
a62da42021-12-22Henrik Grubbström (Grubba)  * AUTO type - Added in 8.1
6d33d82001-03-28Henrik Grubbström (Grubba)  * PROGRAM type -
71a9672001-03-03Henrik Grubbström (Grubba)  * MIXED - - * VOID - - * ZERO - -
a62da42021-12-22Henrik Grubbström (Grubba)  * UNKNOWN - - Represented as NULL
71a9672001-03-03Henrik Grubbström (Grubba)  * INT min (int) max (int) * OBJECT implements/is object id(int)
d79bff2020-07-17Henrik Grubbström (Grubba)  * OPERATOR type Depends on bit #15. Added in 8.1
a62da42021-12-22Henrik Grubbström (Grubba)  * TRANSITIVE fun_type fun_type Added in 8.1 * * Operator types:
0a3d9f2020-07-18Henrik Grubbström (Grubba)  * FIND_LFUN object type lfun (int) Added in 8.1
92a3912021-11-27Henrik Grubbström (Grubba)  * GET_RETURN fun type - Added in 8.1
5745e22021-07-04Henrik Grubbström (Grubba)  * SET_CAR type type Added in 8.1 * SET_CDR type type Added in 8.1
71a9672001-03-03Henrik Grubbström (Grubba)  * * Note that the cdr of a FUNCTION is a valid FUNCTION for the rest of * the arguments. * * Note also that functions that don't take any arguments, or just * a many argument just have a MANY node, and no FUNCTION node. *
5fc9642020-08-17Henrik Grubbström (Grubba)  * TRANSITIVE has a car with the current state, and a cdr with the * function type to apply. *
71a9672001-03-03Henrik Grubbström (Grubba)  */
d476592013-06-12Arne Goedeke static struct block_allocator type_allocator = BA_INIT(sizeof(struct pike_type), 128); PMOD_EXPORT void really_free_pike_type(struct pike_type * t) {
dd80342020-12-19Henrik Grubbström (Grubba)  dmalloc_unregister(t, 0);
d476592013-06-12Arne Goedeke  ba_free(&type_allocator, t); } ATTRIBUTE((malloc))
3b54e52014-08-21Martin Nilsson PMOD_EXPORT struct pike_type * alloc_pike_type(void) {
c1835b2017-11-11Tobias S. Josefowitz  struct pike_type *t = ba_alloc(&type_allocator);
dd80342020-12-19Henrik Grubbström (Grubba)  dmalloc_register(t, sizeof(struct pike_type), DMALLOC_LOCATION());
abe64b2018-05-19Tobias S. Josefowitz  gc_init_marker(t);
c1835b2017-11-11Tobias S. Josefowitz  return t;
d476592013-06-12Arne Goedeke } PMOD_EXPORT void count_memory_in_pike_types(size_t *n, size_t *s) { ba_count_all(&type_allocator, n, s); }
71a9672001-03-03Henrik Grubbström (Grubba) 
23db452003-08-20Martin Stjernholm struct pike_type **pike_type_hash = NULL; size_t pike_type_hash_size = 0;
71a9672001-03-03Henrik Grubbström (Grubba) 
9b5a822001-03-29Henrik Grubbström (Grubba) void debug_free_type(struct pike_type *t)
71a9672001-03-03Henrik Grubbström (Grubba) {
f8db7f2021-02-05Henrik Grubbström (Grubba)  loop:
6c633b2019-12-15Henrik Grubbström (Grubba)  if (!t) return;
f588b42003-03-15Henrik Grubbström (Grubba) #ifdef DEBUG_MALLOC if (t == (struct pike_type *)(size_t)0x55555555) { Pike_fatal("Freeing dead type.\n"); } #endif /* DEBUG_MALLOC */
50ea682003-03-14Henrik Grubbström (Grubba)  if (!sub_ref(t)) {
64017e2013-05-31Per Hedbor  unsigned INT32 hash = t->hash & pike_type_hash_size;
71a9672001-03-03Henrik Grubbström (Grubba)  struct pike_type **t2 = pike_type_hash + hash; struct pike_type *car, *cdr; unsigned INT32 type;
64017e2013-05-31Per Hedbor #ifdef PIKE_DEBUG
878cad2005-02-02Henrik Grubbström (Grubba)  /* PIKE_DEBUG code */
64017e2013-05-31Per Hedbor  if (hash > pike_type_hash_size) {
878cad2005-02-02Henrik Grubbström (Grubba)  Pike_fatal("Modulo operation failed for hash:%u, index:%u, size:%u.\n", t->hash, hash, pike_type_hash_size); } /* End PIKE_DEBUG code */
64017e2013-05-31Per Hedbor #endif
9b5a822001-03-29Henrik Grubbström (Grubba)  while (*t2) { if (*t2 == t) { *t2 = t->next; break; }
71a9672001-03-03Henrik Grubbström (Grubba)  t2 = &((*t2)->next); } car = t->car; cdr = t->cdr; type = t->type;
d476592013-06-12Arne Goedeke  really_free_pike_type((struct pike_type*)debug_malloc_pass(t));
71a9672001-03-03Henrik Grubbström (Grubba)  /* FIXME: Recursion: Should we use a stack? */
9e5e9b2020-09-16Henrik Grubbström (Grubba)  switch(type & PIKE_T_MASK) {
71a9672001-03-03Henrik Grubbström (Grubba)  case T_FUNCTION: case T_MANY: case T_TUPLE: case T_MAPPING: case T_OR: case T_AND:
ce88d62001-03-19Henrik Grubbström (Grubba)  case PIKE_T_RING:
16edb92020-01-03Henrik Grubbström (Grubba)  case T_ARRAY: case T_STRING:
5fc9642020-08-17Henrik Grubbström (Grubba)  case PIKE_T_TRANSITIVE:
71a9672001-03-03Henrik Grubbström (Grubba)  /* Free car & cdr */ free_type(car);
97a7332008-03-30Martin Stjernholm  t = (struct pike_type *) cdr;
3992b92021-05-07Henrik Grubbström (Grubba)  if (t) debug_free_type_preamble (t);
71a9672001-03-03Henrik Grubbström (Grubba)  goto loop;
5e06a82016-03-19Henrik Grubbström (Grubba)  case PIKE_T_AUTO: if (!car) break;
5f50842018-02-12Marcus Comstedt  /* FALLTHRU */
71a9672001-03-03Henrik Grubbström (Grubba)  case T_MULTISET: case T_NOT:
9b5a822001-03-29Henrik Grubbström (Grubba)  case T_TYPE: case T_PROGRAM:
71a9672001-03-03Henrik Grubbström (Grubba)  /* Free car */
97a7332008-03-30Martin Stjernholm  t = (struct pike_type *) car;
3992b92021-05-07Henrik Grubbström (Grubba)  if (t) debug_free_type_preamble (t);
71a9672001-03-03Henrik Grubbström (Grubba)  goto loop;
13670c2015-05-25Martin Nilsson 
71a9672001-03-03Henrik Grubbström (Grubba)  case T_SCOPE: case T_ASSIGN: /* Free cdr */
97a7332008-03-30Martin Stjernholm  t = (struct pike_type *) cdr;
3992b92021-05-07Henrik Grubbström (Grubba)  if (t) debug_free_type_preamble (t);
71a9672001-03-03Henrik Grubbström (Grubba)  goto loop;
f62c412001-03-05Henrik Grubbström (Grubba) 
9129122007-04-21Henrik Grubbström (Grubba)  case PIKE_T_ATTRIBUTE:
f62c412001-03-05Henrik Grubbström (Grubba)  case PIKE_T_NAME: free_string((struct pike_string *)car);
97a7332008-03-30Martin Stjernholm  t = (struct pike_type *) cdr;
3992b92021-05-07Henrik Grubbström (Grubba)  if (t) debug_free_type_preamble (t);
f62c412001-03-05Henrik Grubbström (Grubba)  goto loop;
9b5a822001-03-29Henrik Grubbström (Grubba) 
d79bff2020-07-17Henrik Grubbström (Grubba)  case PIKE_T_OPERATOR: /* Free car and maybe cdr. */ if (type & 0x8000) { /* Free cdr. */ free_type(cdr); } t = car;
3992b92021-05-07Henrik Grubbström (Grubba)  if (t) debug_free_type_preamble(t);
d79bff2020-07-17Henrik Grubbström (Grubba)  goto loop;
9b5a822001-03-29Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case T_FLOAT: case T_MIXED: case T_VOID: case T_ZERO: case PIKE_T_UNKNOWN: case T_INT: case T_OBJECT: break; default:
5aad932002-08-15Marcus Comstedt  Pike_fatal("free_type(): Unhandled type-node: %d\n", type);
9b5a822001-03-29Henrik Grubbström (Grubba)  break; #endif /* PIKE_DEBUG */
71a9672001-03-03Henrik Grubbström (Grubba)  } } }
5ec6eb2021-03-18Henrik Grubbström (Grubba) /* NB: Steals the references to car and cdr. */
0613212022-05-02Henrik Grubbström (Grubba) static struct pike_type *debug_mk_type(unsigned INT32 type, struct pike_type *car, struct pike_type *cdr, unsigned int flag_method)
71a9672001-03-03Henrik Grubbström (Grubba) {
7926bf2007-03-26Henrik Grubbström (Grubba)  /* FIXME: The hash ought to be based on the tree contents, regardless * of what the adresses of the type nodes are. */
71a9672001-03-03Henrik Grubbström (Grubba)  struct pike_type *t;
13670c2015-05-25Martin Nilsson  unsigned INT32 index,
bd67392015-10-14Martin Nilsson  hash = (unsigned INT32) ((ptrdiff_t)type*0x10204081)^ (0x8003*PTR_TO_INT(car))^ ~(0x10001*PTR_TO_INT(cdr));
64017e2013-05-31Per Hedbor  hash ^= (hash >> 20) ^ (hash >> 12); hash ^= (hash >> 7) ^ (hash >> 4); index = hash & pike_type_hash_size;
a071042005-06-03Henrik Grubbström (Grubba) #ifdef PIKE_EXTRA_DEBUG static unsigned INT32 extra_debug_index = (unsigned INT32)~0; #endif /* PIKE_EXTRA_DEBUG */
64017e2013-05-31Per Hedbor #ifdef PIKE_DEBUG
e87c522004-03-11Henrik Grubbström (Grubba)  /* PIKE_DEBUG code */
9e5e9b2020-09-16Henrik Grubbström (Grubba)  if ((type & ~PIKE_T_MASK) && ((type & PIKE_T_MASK) != PIKE_T_OPERATOR)) {
2148b02005-02-05Henrik Grubbström (Grubba)  /* The bad type node on OSF/1 seems to be: * * type: 0xffff * car: valid pointer. * cdr: 0x400000000 * next: 0x100000000 */ Pike_fatal("Attempt to create an invalid type node: %d(%s)\n" " car: %p\n" " cdr: %p\n", type, get_name_of_type(type), car, cdr); }
64017e2013-05-31Per Hedbor  if (index > pike_type_hash_size) {
2d76f22005-05-20Martin Stjernholm  Pike_fatal("Modulo operation failed for hash:%u, index:%u, " "size:%"PRINTSIZET"d.\n",
e87c522004-03-11Henrik Grubbström (Grubba)  hash, index, pike_type_hash_size); } /* End PIKE_DEBUG code */
64017e2013-05-31Per Hedbor #endif
a071042005-06-03Henrik Grubbström (Grubba) #ifdef PIKE_EXTRA_DEBUG if ((!~extra_debug_index) && (type == T_FUNCTION) && (car->type == T_STRING) && (cdr->type == T_FUNCTION) && (cdr->car->type == T_STRING) && (cdr->cdr->type == T_MANY) && (cdr->cdr->car->type == T_VOID) && (cdr->cdr->cdr->type == T_STRING)) { /* Attempt to detect why we get a core-dump on OSF/1 * when loading Unicode.so from test_resolv. * * The problem triggs when the type for normalize() is created. * function(string,string:string) * /grubba 2005-02-04 * * Load order: * Module Hashtable status Note * Nettle.so OK * ___Oracle.so - load_module() fails. * Image.so - loads ok. * Unicode.so FAIL * * pike_type node: * Field Before After * t 1404b5020 1404b5020 * t->type 4 (function) 65535 (unknown) * t->car 1404863f8 (1404863f8) 140557560 (1404863f8) * t->cdr 1404b43d8 (1404b43d8) 400000000 (1404b43d8) * t->next 0 100000000 * /grubba 2005-06-03 */ extra_debug_index = index; } #endif /* PIKE_EXTRA_DEBUG */
dcf5082021-01-26Henrik Grubbström (Grubba)  if (type == PIKE_T_UNKNOWN) return NULL;
71a9672001-03-03Henrik Grubbström (Grubba)  for(t = pike_type_hash[index]; t; t = t->next) {
3841f32005-02-04Henrik Grubbström (Grubba) #ifdef PIKE_EXTRA_DEBUG
a071042005-06-03Henrik Grubbström (Grubba)  if (index == extra_debug_index) {
2148b02005-02-05Henrik Grubbström (Grubba)  fprintf(stderr, " %s:%d:PIKE_EXTRA_DEBUG:\n" " t: %p\n",
3841f32005-02-04Henrik Grubbström (Grubba)  __FILE__, __LINE__, t);
2148b02005-02-05Henrik Grubbström (Grubba)  fprintf(stderr, " t->type:%d (%s)\n" " t->car: %p (%p)\n" " t->cdr: %p (%p)\n" " t->next:%p\n",
3841f32005-02-04Henrik Grubbström (Grubba)  t->type, get_name_of_type(t->type), t->car, car,
2148b02005-02-05Henrik Grubbström (Grubba)  t->cdr, cdr, t->next);
3841f32005-02-04Henrik Grubbström (Grubba)  } #endif /* PIKE_EXTRA_DEBUG */
71a9672001-03-03Henrik Grubbström (Grubba)  if ((t->hash == hash) && (t->type == type) && (t->car == car) && (t->cdr == cdr)) {
9b5a822001-03-29Henrik Grubbström (Grubba)  /* Free car & cdr as appropriate. */
9e5e9b2020-09-16Henrik Grubbström (Grubba)  switch(type & PIKE_T_MASK) {
f62c412001-03-05Henrik Grubbström (Grubba)  case T_FUNCTION: case T_MANY: case T_TUPLE: case T_MAPPING: case T_OR: case T_AND:
ce88d62001-03-19Henrik Grubbström (Grubba)  case PIKE_T_RING:
16edb92020-01-03Henrik Grubbström (Grubba)  case T_ARRAY: case T_STRING:
5fc9642020-08-17Henrik Grubbström (Grubba)  case PIKE_T_TRANSITIVE:
f62c412001-03-05Henrik Grubbström (Grubba)  /* Free car & cdr */
9b5a822001-03-29Henrik Grubbström (Grubba)  free_type((struct pike_type *)debug_malloc_pass(car)); free_type((struct pike_type *)debug_malloc_pass(cdr));
f62c412001-03-05Henrik Grubbström (Grubba)  break; case T_MULTISET: case T_NOT:
6d33d82001-03-28Henrik Grubbström (Grubba)  case T_TYPE: case T_PROGRAM:
f62c412001-03-05Henrik Grubbström (Grubba)  /* Free car */
9b5a822001-03-29Henrik Grubbström (Grubba)  free_type((struct pike_type *)debug_malloc_pass(car));
f62c412001-03-05Henrik Grubbström (Grubba)  break;
6e0fce2013-05-28Per Hedbor  case PIKE_T_AUTO: if( car ) free_type((struct pike_type *)debug_malloc_pass(car)); break;
13670c2015-05-25Martin Nilsson 
f62c412001-03-05Henrik Grubbström (Grubba)  case T_SCOPE: case T_ASSIGN: /* Free cdr */
9b5a822001-03-29Henrik Grubbström (Grubba)  free_type((struct pike_type *)debug_malloc_pass(cdr));
f62c412001-03-05Henrik Grubbström (Grubba)  break;
9129122007-04-21Henrik Grubbström (Grubba)  case PIKE_T_ATTRIBUTE:
f62c412001-03-05Henrik Grubbström (Grubba)  case PIKE_T_NAME:
9b5a822001-03-29Henrik Grubbström (Grubba)  free_string((struct pike_string *)debug_malloc_pass(car)); free_type((struct pike_type *)debug_malloc_pass(cdr)); break;
d79bff2020-07-17Henrik Grubbström (Grubba)  case PIKE_T_OPERATOR: if (type & 0x8000) { free_type((struct pike_type *)debug_malloc_pass(cdr)); } free_type((struct pike_type *)debug_malloc_pass(car)); break;
9b5a822001-03-29Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case T_FLOAT: case T_MIXED: case T_VOID: case T_ZERO: case PIKE_T_UNKNOWN: case T_INT: case T_OBJECT: break; default:
5aad932002-08-15Marcus Comstedt  Pike_fatal("mk_type(): Unhandled type-node: %d\n", type);
f62c412001-03-05Henrik Grubbström (Grubba)  break;
9b5a822001-03-29Henrik Grubbström (Grubba) #endif /* PIKE_DEBUG */
f62c412001-03-05Henrik Grubbström (Grubba)  }
9b5a822001-03-29Henrik Grubbström (Grubba)  add_ref((struct pike_type *)debug_malloc_pass(t));
71a9672001-03-03Henrik Grubbström (Grubba)  return t; } }
641a3f2007-04-16Henrik Grubbström (Grubba)  #ifdef PIKE_DEBUG if ((type == T_OR) && (car->type == T_OR)) { Pike_fatal("Invalid CAR to OR node.\n"); } #endif
13670c2015-05-25Martin Nilsson 
c16db22020-12-18Henrik Grubbström (Grubba)  debug_malloc_pass(t = alloc_pike_type());
71a9672001-03-03Henrik Grubbström (Grubba) 
50ea682003-03-14Henrik Grubbström (Grubba)  t->refs = 0; add_ref(t); /* For DMALLOC... */
71a9672001-03-03Henrik Grubbström (Grubba)  t->type = type;
eb66fa2022-02-16Henrik Grubbström (Grubba)  t->flags = flag_method & ~PT_FLAG_MARK_ASSIGN;
71a9672001-03-03Henrik Grubbström (Grubba)  t->car = car; t->cdr = cdr; t->hash = hash; t->next = pike_type_hash[index]; pike_type_hash[index] = t; if (flag_method) {
7926bf2007-03-26Henrik Grubbström (Grubba)  if (flag_method == PT_IS_MARKER) { t->flags = PT_FLAG_MARKER_0 << (type-'0');
790d032007-05-09Henrik Grubbström (Grubba)  } else if (type == PIKE_T_SCOPE) { /* The scope blocks propagation of markers. */ t->flags = cdr->flags & ~(PT_FLAG_MARKER|PT_FLAG_ASSIGN);
04404a2022-02-18Henrik Grubbström (Grubba)  } else if (type == T_NOT) {
eb66fa2022-02-16Henrik Grubbström (Grubba)  if (car) {
dc02db2022-02-23Henrik Grubbström (Grubba)  /* NB: We cannot set the PT_FLAG_MIXED flag, * as inverting a non-mixed type does not * give mixed. */ t->flags |= (car->flags ^ ~PT_FLAG_MARK_ASSIGN) & ~PT_FLAG_MIXED;
04404a2022-02-18Henrik Grubbström (Grubba)  } } else if (flag_method & PT_COPY_MORE) { if (car && (flag_method & PT_COPY_CAR)) {
eb66fa2022-02-16Henrik Grubbström (Grubba)  t->flags |= car->flags; }
04404a2022-02-18Henrik Grubbström (Grubba)  if (cdr && (flag_method & PT_COPY_CDR)) {
eb66fa2022-02-16Henrik Grubbström (Grubba)  t->flags |= cdr->flags; }
71a9672001-03-03Henrik Grubbström (Grubba)  } else { if (car && (flag_method & PT_COPY_CAR)) {
eb66fa2022-02-16Henrik Grubbström (Grubba)  t->flags |= car->flags & PT_FLAG_MARK_ASSIGN;
71a9672001-03-03Henrik Grubbström (Grubba)  } if (cdr && (flag_method & PT_COPY_CDR)) {
eb66fa2022-02-16Henrik Grubbström (Grubba)  t->flags |= cdr->flags & PT_FLAG_MARK_ASSIGN;;
71a9672001-03-03Henrik Grubbström (Grubba)  } } }
9b5a822001-03-29Henrik Grubbström (Grubba) #ifdef DEBUG_MALLOC
9e5e9b2020-09-16Henrik Grubbström (Grubba)  switch(type & PIKE_T_MASK) {
9b5a822001-03-29Henrik Grubbström (Grubba)  case T_FUNCTION: case T_MANY: case T_TUPLE: case T_MAPPING: case T_OR: case T_AND: case PIKE_T_RING:
16edb92020-01-03Henrik Grubbström (Grubba)  case T_ARRAY: case T_STRING:
5fc9642020-08-17Henrik Grubbström (Grubba)  case PIKE_T_TRANSITIVE:
9b5a822001-03-29Henrik Grubbström (Grubba)  debug_malloc_pass(car); debug_malloc_pass(cdr); break;
13670c2015-05-25Martin Nilsson 
9b5a822001-03-29Henrik Grubbström (Grubba)  case T_MULTISET: case T_NOT: case T_TYPE: case T_PROGRAM:
5e06a82016-03-19Henrik Grubbström (Grubba)  case PIKE_T_AUTO:
9b5a822001-03-29Henrik Grubbström (Grubba)  debug_malloc_pass(car); break;
13670c2015-05-25Martin Nilsson 
9b5a822001-03-29Henrik Grubbström (Grubba)  case T_ASSIGN:
7926bf2007-03-26Henrik Grubbström (Grubba)  t->flags |= PT_FLAG_ASSIGN_0 << PTR_TO_INT(car);
5f50842018-02-12Marcus Comstedt  /* FALLTHRU */
7926bf2007-03-26Henrik Grubbström (Grubba)  case T_SCOPE:
9b5a822001-03-29Henrik Grubbström (Grubba)  debug_malloc_pass(cdr); break;
9129122007-04-21Henrik Grubbström (Grubba)  case PIKE_T_ATTRIBUTE:
9b5a822001-03-29Henrik Grubbström (Grubba)  case PIKE_T_NAME: debug_malloc_pass(car); debug_malloc_pass(cdr); break;
d79bff2020-07-17Henrik Grubbström (Grubba)  case PIKE_T_OPERATOR: if (type & 0x8000) { debug_malloc_pass(cdr); } debug_malloc_pass(car); break;
9b5a822001-03-29Henrik Grubbström (Grubba)  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
4e6c082007-05-02Henrik Grubbström (Grubba)  case T_FLOAT:
9b5a822001-03-29Henrik Grubbström (Grubba)  case T_MIXED: case T_VOID: case T_ZERO: case PIKE_T_UNKNOWN: case T_INT: case T_OBJECT: break; default:
5aad932002-08-15Marcus Comstedt  Pike_fatal("mk_type(): Unhandled type-node: %d\n", type);
9b5a822001-03-29Henrik Grubbström (Grubba)  break; }
7926bf2007-03-26Henrik Grubbström (Grubba) #else /* !DEBUG_MALLOC */ if (type == T_ASSIGN) { t->flags |= PT_FLAG_ASSIGN_0 << PTR_TO_INT(car); }
9b5a822001-03-29Henrik Grubbström (Grubba) #endif /* DEBUG_MALLOC */
71a9672001-03-03Henrik Grubbström (Grubba)  return t; }
9b5a822001-03-29Henrik Grubbström (Grubba) #ifdef DEBUG_MALLOC #define mk_type(T,CAR,CDR,FLAG) ((struct pike_type *)debug_malloc_pass(debug_mk_type(T,CAR,CDR,FLAG))) #else /* !DEBUG_MALLOC */ #define mk_type debug_mk_type #endif /* DEBUG_MALLOC */
18cec02014-05-22Per Hedbor struct pike_type **type_stack; struct pike_type ***pike_type_mark_stack;
71a9672001-03-03Henrik Grubbström (Grubba) 
b084942019-10-17Henrik Grubbström (Grubba) ptrdiff_t peek_stack_mark(void) { if(Pike_compiler->pike_type_mark_stackp-1 < pike_type_mark_stack) Pike_fatal("Type mark stack underflow\n"); TYPE_STACK_DEBUG("peek_stack_mark"); return Pike_compiler->type_stackp - Pike_compiler->pike_type_mark_stackp[-1]; }
71a9672001-03-03Henrik Grubbström (Grubba) ptrdiff_t pop_stack_mark(void)
13670c2015-05-25Martin Nilsson {
71a9672001-03-03Henrik Grubbström (Grubba)  Pike_compiler->pike_type_mark_stackp--; if(Pike_compiler->pike_type_mark_stackp<pike_type_mark_stack)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Type mark stack underflow\n");
71a9672001-03-03Henrik Grubbström (Grubba)  TYPE_STACK_DEBUG("pop_stack_mark"); return Pike_compiler->type_stackp - *Pike_compiler->pike_type_mark_stackp; } void type_stack_pop_to_mark(void) { pop_stack_mark();
5b368e2001-03-31Henrik Grubbström (Grubba)  while(Pike_compiler->type_stackp > *Pike_compiler->pike_type_mark_stackp) { free_type(*(Pike_compiler->type_stackp--)); }
71a9672001-03-03Henrik Grubbström (Grubba)  TYPE_STACK_DEBUG("type_stack_pop_to_mark"); }
9b5a822001-03-29Henrik Grubbström (Grubba) struct pike_type *debug_peek_type_stack(void) { return *(Pike_compiler->type_stackp); }
69aa4b2003-01-26Mirar (Pontus Hagland) void debug_push_int_type(INT_TYPE min, INT_TYPE max)
71a9672001-03-03Henrik Grubbström (Grubba) {
2710802003-01-26Mirar (Pontus Hagland) #if SIZEOF_INT_TYPE > 4 /* a bit kludgy: should maybe really allow 64 bit INT_TYPE */ /* see also extract_type_int */ if (min<MIN_INT32) min=MIN_INT32; else if (min>MAX_INT32) min=MAX_INT32; if (max<MIN_INT32) max=MIN_INT32; else if (max>MAX_INT32) max=MAX_INT32; #endif
483c2f2003-11-24Henrik Grubbström (Grubba) 
12efe22014-09-04Stephen R. van den Berg #ifdef PIKE_DEBUG /* FIXME: Kludge to support 2^32-1 */
ce3d2f2014-10-01Martin Nilsson  if (((min>0 && max>0) || (min<0 && max<0)) && min > max)
483c2f2003-11-24Henrik Grubbström (Grubba)  Pike_fatal("push_int_type(): Bad integer range:" " min:%"PRINTPIKEINT"d, max:%"PRINTPIKEINT"d.\n", min, max); #endif /* PIKE_DEBUG */
ed0e4d2007-04-17Henrik Grubbström (Grubba) 
48f1db2007-11-03Henrik Grubbström (Grubba)  if (!min && !max) { /* Special case... */ push_type(T_ZERO); } else {
0926472022-02-23Henrik Grubbström (Grubba)  unsigned int flag_method = 0; if ((min <= 0) && (max >= 0)) { flag_method = PT_FLAG_NULLABLE; }
48f1db2007-11-03Henrik Grubbström (Grubba)  *(++Pike_compiler->type_stackp) = mk_type(T_INT, (void *)(ptrdiff_t)min,
0926472022-02-23Henrik Grubbström (Grubba)  (void *)(ptrdiff_t)max, flag_method);
48f1db2007-11-03Henrik Grubbström (Grubba)  }
71a9672001-03-03Henrik Grubbström (Grubba)  TYPE_STACK_DEBUG("push_int_type"); }
04017d2020-01-02Henrik Grubbström (Grubba) /** * Used with arrays and strings. * * On entry the type stack contains the value type. * * Generates an array or string type with no length limits. */ void debug_push_unlimited_array_type(enum PIKE_TYPE t) { struct compilation * c = MAYBE_THIS_COMPILATION; #ifdef PIKE_DEBUG if ((t != PIKE_T_ARRAY) && (t != PIKE_T_STRING)) {
908a342020-01-12Henrik Grubbström (Grubba)  Pike_fatal("Invalid type for push_unlimited_array_type(): %s (%d)\n",
04017d2020-01-02Henrik Grubbström (Grubba)  get_name_of_type(t), t); } #endif
164f282021-12-18Henrik Grubbström (Grubba)  if (!peek_type_stack()) { push_type(PIKE_T_ZERO);
ff76fd2020-01-21Henrik Grubbström (Grubba)  } else { push_int_type(0, MAX_INT32); }
04017d2020-01-02Henrik Grubbström (Grubba)  push_type(t);
087e502020-08-28Henrik Grubbström (Grubba)  TYPE_STACK_DEBUG("push_array_type");
04017d2020-01-02Henrik Grubbström (Grubba) }
0079612014-09-30Per Hedbor static int (*program_id_to_id)(int) = NULL; PMOD_EXPORT void set_program_id_to_id( int (*to)(int) ) { program_id_to_id = to; }
9b5a822001-03-29Henrik Grubbström (Grubba) void debug_push_object_type(int flag, INT32 id)
71a9672001-03-03Henrik Grubbström (Grubba) {
0079612014-09-30Per Hedbor  if( program_id_to_id ) id = program_id_to_id(id);
71a9672001-03-03Henrik Grubbström (Grubba)  *(++Pike_compiler->type_stackp) = mk_type(T_OBJECT, (void *)(ptrdiff_t)flag, (void *)(ptrdiff_t)id, 0); TYPE_STACK_DEBUG("push_object_type"); }
9b5a822001-03-29Henrik Grubbström (Grubba) void debug_push_object_type_backwards(int flag, INT32 id)
71a9672001-03-03Henrik Grubbström (Grubba) { push_object_type(flag, id); }
9b5a822001-03-29Henrik Grubbström (Grubba) void debug_push_scope_type(int level)
71a9672001-03-03Henrik Grubbström (Grubba) { *Pike_compiler->type_stackp = mk_type(T_SCOPE, (void *)(ptrdiff_t)level, *Pike_compiler->type_stackp,
04404a2022-02-18Henrik Grubbström (Grubba)  PT_COPY_MORE|PT_COPY_CDR);
71a9672001-03-03Henrik Grubbström (Grubba)  TYPE_STACK_DEBUG("push_scope_type"); }
9b5a822001-03-29Henrik Grubbström (Grubba) void debug_push_assign_type(int marker)
71a9672001-03-03Henrik Grubbström (Grubba) {
9e6f6f2001-03-18Henrik Grubbström (Grubba)  marker -= '0';
13670c2015-05-25Martin Nilsson #ifdef PIKE_DEBUG
9e6f6f2001-03-18Henrik Grubbström (Grubba)  if ((marker < 0) || (marker > 9)) {
ecdbac2003-01-17Johan Sundström  Pike_fatal("Bad assign marker: %d\n", marker);
54f8ac2001-03-17Henrik Grubbström (Grubba)  } #endif /* PIKE_DEBUG */
9e6f6f2001-03-18Henrik Grubbström (Grubba) 
71a9672001-03-03Henrik Grubbström (Grubba)  *Pike_compiler->type_stackp = mk_type(T_ASSIGN, (void *)(ptrdiff_t)marker, *Pike_compiler->type_stackp, PT_COPY_CDR); TYPE_STACK_DEBUG("push_assign_type"); }
9129122007-04-21Henrik Grubbström (Grubba) void debug_push_type_attribute(struct pike_string *attr) { /* fprintf(stderr, "push_type_attribute(\"%s\")\n", attr->str); */ add_ref(attr); *Pike_compiler->type_stackp = mk_type(PIKE_T_ATTRIBUTE, (void *)attr, *Pike_compiler->type_stackp,
04404a2022-02-18Henrik Grubbström (Grubba)  PT_COPY_MORE|PT_COPY_CDR);
087e502020-08-28Henrik Grubbström (Grubba)  TYPE_STACK_DEBUG("push_type_attribute");
9129122007-04-21Henrik Grubbström (Grubba) }
9b5a822001-03-29Henrik Grubbström (Grubba) void debug_push_type_name(struct pike_string *name)
f62c412001-03-05Henrik Grubbström (Grubba) { /* fprintf(stderr, "push_type_name(\"%s\")\n", name->str); */
7a9b312022-03-08Henrik Grubbström (Grubba)  if ((peek_type_stack() == zero_type_string) && (name->len == 4) && !name->size_shift && !strcmp(name->str, "zero")) { /* Do not generate a name node for zero = zero. * This simplifies detecting zero. */ return; }
f62c412001-03-05Henrik Grubbström (Grubba)  add_ref(name); *Pike_compiler->type_stackp = mk_type(PIKE_T_NAME, (void *)name, *Pike_compiler->type_stackp,
04404a2022-02-18Henrik Grubbström (Grubba)  PT_COPY_MORE|PT_COPY_CDR);
f62c412001-03-05Henrik Grubbström (Grubba)  TYPE_STACK_DEBUG("push_type_name"); }
d79bff2020-07-17Henrik Grubbström (Grubba) static struct pike_type *apply_type_operator(enum PIKE_TYPE op, struct pike_type *arg1, struct pike_type *arg2); void debug_push_type_operator(enum PIKE_TYPE op, struct pike_type *arg) { struct pike_type *t = *Pike_compiler->type_stackp;
9e5e9b2020-09-16Henrik Grubbström (Grubba)  struct pike_type *tmp;
d79bff2020-07-17Henrik Grubbström (Grubba)  int free_arg = 0; #ifdef PIKE_DEBUG
9e5e9b2020-09-16Henrik Grubbström (Grubba)  if ((op & PIKE_T_MASK) != 0x80) {
d79bff2020-07-17Henrik Grubbström (Grubba)  Pike_fatal("Invalid operator for push_operator: 0x%04x\n", op); } #endif /* Attempt to propagate the operator towards the leaf nodes. */
d6fc022021-03-31Henrik Grubbström (Grubba)  switch(t?(t->type & PIKE_T_MASK):PIKE_T_UNKNOWN) {
d79bff2020-07-17Henrik Grubbström (Grubba)  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case T_ASSIGN: case PIKE_T_OPERATOR: case PIKE_T_SCOPE: /* Deferred evaluation. */ if (op & 0x8000) {
744ee72021-07-11Henrik Grubbström (Grubba)  add_ref(arg);
d79bff2020-07-17Henrik Grubbström (Grubba)  *Pike_compiler->type_stackp = mk_type(op, *Pike_compiler->type_stackp, arg, PT_COPY_BOTH); } else { *Pike_compiler->type_stackp = mk_type(op, *Pike_compiler->type_stackp, arg, PT_COPY_CAR); } break; case PIKE_T_NAME: case PIKE_T_ATTRIBUTE: { Pike_compiler->type_stackp--; push_finished_type(t->cdr); push_type_operator(op, arg); if (t->type == PIKE_T_NAME) { push_type_name((struct pike_string *)t->car); } else { push_type_attribute((struct pike_string *)t->car); } free_type(t); break; } case T_NOT: { /* Unary propagate. */ int unop = t->type; pop_type_stack(t->type); push_type_operator(op, arg); push_type(unop); break; } case T_AND: case T_OR: { struct pike_type *tmp; int binop = t->type; /* Propagate. */ pop_type_stack(t->type); tmp = *Pike_compiler->type_stackp; Pike_compiler->type_stackp--; push_type_operator(op, arg); Pike_compiler->type_stackp++; *Pike_compiler->type_stackp = tmp; push_type_operator(op, arg); push_type(binop); break; }
b7976f2022-03-23Henrik Grubbström (Grubba) 
d79bff2020-07-17Henrik Grubbström (Grubba)  default:
b7976f2022-03-23Henrik Grubbström (Grubba)  /* Check the second argument. */ switch(((op & 0x8000) && arg)?(arg->type & PIKE_T_MASK):PIKE_T_UNKNOWN) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case T_ASSIGN: case PIKE_T_OPERATOR: case PIKE_T_SCOPE: /* Deferred evaluation. */ add_ref(arg); *Pike_compiler->type_stackp = mk_type(op, *Pike_compiler->type_stackp, arg, PT_COPY_BOTH); break; default: *Pike_compiler->type_stackp = apply_type_operator(op, t, arg); free_type(t); break; }
d79bff2020-07-17Henrik Grubbström (Grubba)  break; }
b7976f2022-03-23Henrik Grubbström (Grubba) 
087e502020-08-28Henrik Grubbström (Grubba)  TYPE_STACK_DEBUG("push_type_operator");
d79bff2020-07-17Henrik Grubbström (Grubba) }
9b5a822001-03-29Henrik Grubbström (Grubba) void debug_push_finished_type(struct pike_type *t)
71a9672001-03-03Henrik Grubbström (Grubba) {
be6fec2001-04-01Henrik Grubbström (Grubba)  copy_pike_type(*(++Pike_compiler->type_stackp), t);
71a9672001-03-03Henrik Grubbström (Grubba)  TYPE_STACK_DEBUG("push_finished_type"); }
641a3f2007-04-16Henrik Grubbström (Grubba) static void push_reverse_joiner_type(unsigned int type) { /* fprintf(stderr, "push_reverse_joiner_type(%d)\n", type); */
9e5e9b2020-09-16Henrik Grubbström (Grubba)  switch(type & PIKE_T_MASK) {
641a3f2007-04-16Henrik Grubbström (Grubba)  case T_OR: case T_AND: /* Special case: Check if the two top elements are equal. */ if (Pike_compiler->type_stackp[-1] == Pike_compiler->type_stackp[0]) { free_type(*(Pike_compiler->type_stackp--)); return; } /* Make a new type of the top two types. */ --Pike_compiler->type_stackp; #ifdef PIKE_DEBUG if ((*Pike_compiler->type_stackp)->type == type) { Pike_fatal("Invalid CAR to push_reverse_joiner_type().\n"); } #endif /* PIKE_DEBUG */ *Pike_compiler->type_stackp = mk_type(type, *Pike_compiler->type_stackp, *(Pike_compiler->type_stackp+1),
04404a2022-02-18Henrik Grubbström (Grubba)  ((type == T_OR)? PT_COPY_MORE : 0) |
641a3f2007-04-16Henrik Grubbström (Grubba)  PT_COPY_BOTH); break; default: Pike_fatal("Illegal reverse joiner type: %d\n", type); } }
64133e2021-09-27Henrik Grubbström (Grubba) #define push_reverse_joiner_type(T) do { \ push_reverse_joiner_type(T); \ debug_malloc_touch(debug_peek_type_stack()); \ } while (0)
641a3f2007-04-16Henrik Grubbström (Grubba)  static void low_or_pike_types(struct pike_type *t1, struct pike_type *t2, int zero_implied);
7e877a2003-04-02Martin Stjernholm void debug_push_type(unsigned int type)
71a9672001-03-03Henrik Grubbström (Grubba) { /* fprintf(stderr, "push_type(%d)\n", type); */
9e5e9b2020-09-16Henrik Grubbström (Grubba)  switch(type & PIKE_T_MASK) {
5a3fd82005-03-21Henrik Grubbström (Grubba)  case T_OR: case T_AND: /* Special case: Check if the two top elements are equal. */ if (Pike_compiler->type_stackp[-1] == Pike_compiler->type_stackp[0]) { free_type(*(Pike_compiler->type_stackp--)); return; }
4f6e752021-03-30Henrik Grubbström (Grubba)  if (!Pike_compiler->type_stackp[0]) { Pike_compiler->type_stackp--; if ((type & PIKE_T_MASK) == T_AND) { free_type(Pike_compiler->type_stackp[0]); Pike_compiler->type_stackp[0] = NULL; } return; } if (!Pike_compiler->type_stackp[-1]) { if ((type & PIKE_T_MASK) == T_AND) { free_type(Pike_compiler->type_stackp[0]); } else { Pike_compiler->type_stackp[-1] = Pike_compiler->type_stackp[0]; } Pike_compiler->type_stackp--; return; }
7926bf2007-03-26Henrik Grubbström (Grubba)  if (Pike_compiler->type_stackp[0]->type == type) { /* The top type is the same as our type. * Split it and join the parts with the other type. */
64133e2021-09-27Henrik Grubbström (Grubba)  struct pike_type *top = low_pop_type();
7926bf2007-03-26Henrik Grubbström (Grubba)  push_finished_type(top->cdr); push_type(type); push_finished_type(top->car); push_type(type); free_type(top); return; }
641a3f2007-04-16Henrik Grubbström (Grubba)  if (type == T_OR) {
64133e2021-09-27Henrik Grubbström (Grubba)  struct pike_type *t1 = low_pop_type(); struct pike_type *t2 = low_pop_type();
641a3f2007-04-16Henrik Grubbström (Grubba)  low_or_pike_types(t1, t2, 0); free_type(t2); free_type(t1);
7926bf2007-03-26Henrik Grubbström (Grubba)  return; }
5f50842018-02-12Marcus Comstedt  /* FALLTHRU */
71a9672001-03-03Henrik Grubbström (Grubba)  case T_FUNCTION: case T_MANY: case T_TUPLE: case T_MAPPING:
ce88d62001-03-19Henrik Grubbström (Grubba)  case PIKE_T_RING:
d2edc32020-01-07Henrik Grubbström (Grubba)  case T_ARRAY: case T_STRING:
5fc9642020-08-17Henrik Grubbström (Grubba)  case PIKE_T_TRANSITIVE:
71a9672001-03-03Henrik Grubbström (Grubba)  /* Make a new type of the top two types. */ --Pike_compiler->type_stackp; *Pike_compiler->type_stackp = mk_type(type, *(Pike_compiler->type_stackp+1), *Pike_compiler->type_stackp, PT_COPY_BOTH); break;
6513262014-02-16Henrik Grubbström (Grubba)  case T_PROGRAM:
be352e2022-03-30Henrik Grubbström (Grubba)  if (!*Pike_compiler->type_stackp || (*Pike_compiler->type_stackp)->type != T_OBJECT) {
90582b2014-02-16Henrik Grubbström (Grubba)  struct pike_type *t = (*Pike_compiler->type_stackp);
be352e2022-03-30Henrik Grubbström (Grubba)  while (t && ((t->type == PIKE_T_NAME) || (t->type == PIKE_T_ATTRIBUTE))) {
90582b2014-02-16Henrik Grubbström (Grubba)  t = t->cdr; }
be352e2022-03-30Henrik Grubbström (Grubba)  if (!t || (t->type != T_OBJECT)) {
90582b2014-02-16Henrik Grubbström (Grubba)  /* Not a program type, convert it to a type type. */ type = T_TYPE; }
6513262014-02-16Henrik Grubbström (Grubba)  }
5f50842018-02-12Marcus Comstedt  /* FALLTHRU */
71a9672001-03-03Henrik Grubbström (Grubba)  case T_MULTISET:
54f8ac2001-03-17Henrik Grubbström (Grubba)  case T_TYPE:
ec9bc12016-05-01Henrik Grubbström (Grubba)  case PIKE_T_AUTO:
71a9672001-03-03Henrik Grubbström (Grubba)  /* Make a new type of the top type, and put it in car. */ *Pike_compiler->type_stackp = mk_type(type, *Pike_compiler->type_stackp, NULL, PT_COPY_CAR); break;
f8b1042020-10-02Henrik Grubbström (Grubba)  case T_NOT: /* Make a new type of the top type, and put it in car. * * Special case: Remove double inversions. */ { struct pike_type *t = *Pike_compiler->type_stackp;
4f6e752021-03-30Henrik Grubbström (Grubba)  if (!t) { Pike_compiler->type_stackp--; push_type(T_MIXED); push_type(T_VOID); push_type(T_OR); break; }
f8b1042020-10-02Henrik Grubbström (Grubba)  if (t->type == T_NOT) { *Pike_compiler->type_stackp = t->car; add_ref(t->car); free_type(t); break; } *Pike_compiler->type_stackp = mk_type(type, t, NULL, PT_COPY_CAR); } break;
71a9672001-03-03Henrik Grubbström (Grubba)  case T_SCOPE: case T_ASSIGN: case T_INT: case T_OBJECT:
9129122007-04-21Henrik Grubbström (Grubba)  case PIKE_T_ATTRIBUTE:
f62c412001-03-05Henrik Grubbström (Grubba)  case PIKE_T_NAME:
71a9672001-03-03Henrik Grubbström (Grubba)  default:
408a1e2004-10-30Martin Stjernholm  /* Should not occur. */
157fc62007-03-03Henrik Grubbström (Grubba)  Pike_fatal("Unsupported argument to push_type(): %d\n", type);
71a9672001-03-03Henrik Grubbström (Grubba)  break; case T_VOID:
eb66fa2022-02-16Henrik Grubbström (Grubba)  /* Leaf type. */ *(++Pike_compiler->type_stackp) = mk_type(type, NULL, NULL, PT_FLAG_VOIDABLE); break;
71a9672001-03-03Henrik Grubbström (Grubba)  case T_ZERO:
0926472022-02-23Henrik Grubbström (Grubba)  /* Leaf type. */ *(++Pike_compiler->type_stackp) = mk_type(type, NULL, NULL, PT_FLAG_NULLABLE); break; case T_MIXED: /* Leaf type. */ *(++Pike_compiler->type_stackp) = mk_type(type, NULL, NULL, PT_FLAG_MIXED|PT_FLAG_NULLABLE); break;
eb66fa2022-02-16Henrik Grubbström (Grubba)  case T_FLOAT:
71a9672001-03-03Henrik Grubbström (Grubba)  case PIKE_T_UNKNOWN: /* Leaf type. */ *(++Pike_compiler->type_stackp) = mk_type(type, NULL, NULL, 0); break;
d79bff2020-07-17Henrik Grubbström (Grubba)  case PIKE_T_OPERATOR:
744ee72021-07-11Henrik Grubbström (Grubba)  if (type & 0x8000) { struct pike_type *t = *(--Pike_compiler->type_stackp); *Pike_compiler->type_stackp = Pike_compiler->type_stackp[1]; push_type_operator(type, t); free_type(t); } else { push_type_operator(type, NULL); }
d79bff2020-07-17Henrik Grubbström (Grubba)  break;
71a9672001-03-03Henrik Grubbström (Grubba)  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* Marker. */
7926bf2007-03-26Henrik Grubbström (Grubba)  *(++Pike_compiler->type_stackp) = mk_type(type, NULL, NULL, PT_IS_MARKER);
71a9672001-03-03Henrik Grubbström (Grubba)  break; } TYPE_STACK_DEBUG("push_type"); } /* Pop one level of types. This is the inverse of push_type() */
7e877a2003-04-02Martin Stjernholm void debug_pop_type_stack(unsigned int expected)
13670c2015-05-25Martin Nilsson {
71a9672001-03-03Henrik Grubbström (Grubba)  struct pike_type *top; if(Pike_compiler->type_stackp<type_stack)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Type stack underflow\n");
71a9672001-03-03Henrik Grubbström (Grubba) 
2be1db2001-04-18Henrik Grubbström (Grubba)  top = *(Pike_compiler->type_stackp); /* Special case... */
928bb12021-01-27Henrik Grubbström (Grubba)  if (!top || top->type == T_MIXED) return; /* Probably due to an earlier error */
2be1db2001-04-18Henrik Grubbström (Grubba)  Pike_compiler->type_stackp--;
5b368e2001-03-31Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG
9129122007-04-21Henrik Grubbström (Grubba)  if ((top->type != expected) && (top->type != PIKE_T_NAME) && (top->type != PIKE_T_ATTRIBUTE)) {
5aad932002-08-15Marcus Comstedt  Pike_fatal("Unexpected type on stack: %d (expected %d)\n", top->type, expected);
5b368e2001-03-31Henrik Grubbström (Grubba)  } #endif /* PIKE_DEBUG */ /* OPTIMIZE: It looks like this function is always called with * expected == T_ARRAY. */
9e5e9b2020-09-16Henrik Grubbström (Grubba)  switch(top->type & PIKE_T_MASK) {
71a9672001-03-03Henrik Grubbström (Grubba)  case T_FUNCTION: case T_MANY: case T_TUPLE: case T_MAPPING: case T_OR: case T_AND:
ce88d62001-03-19Henrik Grubbström (Grubba)  case PIKE_T_RING:
fe1b262021-12-25Henrik Grubbström (Grubba)  case T_ARRAY: case T_STRING:
5fc9642020-08-17Henrik Grubbström (Grubba)  case PIKE_T_TRANSITIVE:
71a9672001-03-03Henrik Grubbström (Grubba)  /* Both car & cdr. */ push_finished_type(top->cdr); push_finished_type(top->car); break; case T_MULTISET: case T_NOT:
54f8ac2001-03-17Henrik Grubbström (Grubba)  case T_TYPE:
6d33d82001-03-28Henrik Grubbström (Grubba)  case T_PROGRAM:
ec9bc12016-05-01Henrik Grubbström (Grubba)  case PIKE_T_AUTO:
71a9672001-03-03Henrik Grubbström (Grubba)  /* car */ push_finished_type(top->car); break; case T_SCOPE: case T_ASSIGN: /* cdr */ push_finished_type(top->cdr); break; case T_INT: case T_OBJECT: case T_FLOAT: case T_MIXED: case T_VOID: case T_ZERO: case PIKE_T_UNKNOWN: case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* Leaf */ break;
9129122007-04-21Henrik Grubbström (Grubba)  case PIKE_T_ATTRIBUTE:
f62c412001-03-05Henrik Grubbström (Grubba)  case PIKE_T_NAME: /* Pop the name and recurse. */ push_finished_type(top->cdr);
5b368e2001-03-31Henrik Grubbström (Grubba)  pop_type_stack(expected);
f62c412001-03-05Henrik Grubbström (Grubba)  break;
d79bff2020-07-17Henrik Grubbström (Grubba)  case PIKE_T_OPERATOR: if (top->type & 0x8000) { push_finished_type(top->cdr); } push_finished_type(top->car); break;
71a9672001-03-03Henrik Grubbström (Grubba)  default: Pike_error("pop_type_stack(): Unhandled node type: %d\n", top->type); } free_type(top); TYPE_STACK_DEBUG("pop_type_stack"); }
7e877a2003-04-02Martin Stjernholm void debug_push_reverse_type(unsigned int type)
71a9672001-03-03Henrik Grubbström (Grubba) { /* fprintf(stderr, "push_reverse_type(%d)\n", type); */
d79bff2020-07-17Henrik Grubbström (Grubba)  switch(type & 0x80ff) {
71a9672001-03-03Henrik Grubbström (Grubba)  case T_FUNCTION: case T_MANY: case T_TUPLE: case T_MAPPING: case T_OR: case T_AND:
ce88d62001-03-19Henrik Grubbström (Grubba)  case PIKE_T_RING:
d2edc32020-01-07Henrik Grubbström (Grubba)  case PIKE_T_ARRAY: case PIKE_T_STRING:
d79bff2020-07-17Henrik Grubbström (Grubba)  case PIKE_T_OPERATOR | 0x8000:
5fc9642020-08-17Henrik Grubbström (Grubba)  case PIKE_T_TRANSITIVE:
71a9672001-03-03Henrik Grubbström (Grubba)  { /* Binary type-node. -- swap the types. */ struct pike_type *tmp = Pike_compiler->type_stackp[0]; Pike_compiler->type_stackp[0] = Pike_compiler->type_stackp[-1]; Pike_compiler->type_stackp[-1] = tmp; break; } } push_type(type); TYPE_STACK_DEBUG("push_reverse_type"); }
77f0d62013-12-12Henrik Grubbström (Grubba) static int is_int_type(struct pike_type *t) { loop:
9e5e9b2020-09-16Henrik Grubbström (Grubba)  switch(t->type & PIKE_T_MASK) {
77f0d62013-12-12Henrik Grubbström (Grubba)  case T_INT: case T_ZERO: case T_VOID: case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
d79bff2020-07-17Henrik Grubbström (Grubba)  case PIKE_T_OPERATOR:
77f0d62013-12-12Henrik Grubbström (Grubba)  return 1; case T_OR: case T_AND: return is_int_type(t->car) && is_int_type(t->cdr); case PIKE_T_NAME: case PIKE_T_ATTRIBUTE: case PIKE_T_SCOPE: case T_ASSIGN: t = t->cdr; goto loop; default: return 0; } }
7926bf2007-03-26Henrik Grubbström (Grubba) /* The marker_set is used as follows: *
838c212007-04-27Henrik Grubbström (Grubba)  * PT_FLAG_MARKER_n Indicates that marker #n should be kept after * expansion.
7926bf2007-03-26Henrik Grubbström (Grubba)  *
838c212007-04-27Henrik Grubbström (Grubba)  * PT_FLAG_ASSIGN_n Indicates that the assign to marker #n should * NOT be removed.
7926bf2007-03-26Henrik Grubbström (Grubba)  */ static void debug_push_finished_type_with_markers(struct pike_type *type, struct pike_type **markers, INT32 marker_set)
71a9672001-03-03Henrik Grubbström (Grubba) {
838c212007-04-27Henrik Grubbström (Grubba)  INT32 car_set, cdr_set;
71a9672001-03-03Henrik Grubbström (Grubba)  recurse:
c585d52007-04-26Henrik Grubbström (Grubba) #ifdef PIKE_TYPE_DEBUG if (l_flag > 2) {
838c212007-04-27Henrik Grubbström (Grubba)  fprintf(stderr, "push_finished_type_with_markers(("); simple_describe_type(type); fprintf(stderr, "),..., 0x%08x)...\n", marker_set);
c585d52007-04-26Henrik Grubbström (Grubba)  } #endif /* PIKE_TYPE_DEBUG */
f5b86a2021-06-03Henrik Grubbström (Grubba)  if (!type) { push_type(PIKE_T_UNKNOWN); return; }
838c212007-04-27Henrik Grubbström (Grubba)  /* We need to replace if there are any markers, or if there's a * non-masked assign. */ if (!(type->flags & (~marker_set | PT_FLAG_MARKER) & PT_FLAG_MARK_ASSIGN)) { /* Nothing to replace in this subtree. */
c585d52007-04-26Henrik Grubbström (Grubba) #ifdef PIKE_TYPE_DEBUG if (l_flag > 2) {
838c212007-04-27Henrik Grubbström (Grubba)  fprintf(stderr, "Nothing to replace in this subtree.\n");
c585d52007-04-26Henrik Grubbström (Grubba)  simple_describe_type(type); fprintf(stderr, "\n"); } #endif /* PIKE_TYPE_DEBUG */
77f0d62013-12-12Henrik Grubbström (Grubba)  if ((marker_set & PT_FLAG_INT_ONLY) && !is_int_type(type)) { push_finished_type(int_type_string); } else { push_finished_type(type); }
71a9672001-03-03Henrik Grubbström (Grubba)  return; } if ((type->type >= '0') && (type->type <= '9')) {
838c212007-04-27Henrik Grubbström (Grubba)  /* Marker. */
71a9672001-03-03Henrik Grubbström (Grubba)  unsigned int m = type->type - '0';
c585d52007-04-26Henrik Grubbström (Grubba) #ifdef PIKE_TYPE_DEBUG if ((l_flag > 2) && m) {
0aa8592021-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "Marker $%d: %p.\n", m, markers[m]);
7926bf2007-03-26Henrik Grubbström (Grubba)  }
c585d52007-04-26Henrik Grubbström (Grubba) #endif /* PIKE_TYPE_DEBUG */
838c212007-04-27Henrik Grubbström (Grubba)  if (markers[m]) { /* The marker has a value. */ struct pike_type *type = dmalloc_touch(struct pike_type *, markers[m]);
c585d52007-04-26Henrik Grubbström (Grubba) #ifdef PIKE_TYPE_DEBUG
838c212007-04-27Henrik Grubbström (Grubba)  if (l_flag > 2) { fprintf(stderr, "Marker value.\n");
7926bf2007-03-26Henrik Grubbström (Grubba)  }
838c212007-04-27Henrik Grubbström (Grubba) #endif /* FIXME: We probably ought to switch to the other marker set here. */ markers[m] = NULL;
77f0d62013-12-12Henrik Grubbström (Grubba)  push_finished_type_with_markers(type, markers, marker_set & PT_FLAG_INT_ONLY);
790d032007-05-09Henrik Grubbström (Grubba)  if (type->flags & (PT_FLAG_MARKER|PT_FLAG_ASSIGN)) { push_scope_type(0); }
838c212007-04-27Henrik Grubbström (Grubba)  if (markers[m]) free_type(markers[m]); markers[m] = dmalloc_touch(struct pike_type *, type); } else { /* The marker has not been set. */
c585d52007-04-26Henrik Grubbström (Grubba) #ifdef PIKE_TYPE_DEBUG if (l_flag > 2) {
838c212007-04-27Henrik Grubbström (Grubba)  fprintf(stderr, "No marker value.\n");
c585d52007-04-26Henrik Grubbström (Grubba)  } #endif
838c212007-04-27Henrik Grubbström (Grubba)  } if (marker_set & (PT_FLAG_MARKER_0 << m)) { /* The marker should be kept. */
c585d52007-04-26Henrik Grubbström (Grubba) #ifdef PIKE_TYPE_DEBUG if (l_flag > 2) {
838c212007-04-27Henrik Grubbström (Grubba)  fprintf(stderr, "Keep marker.\n");
c585d52007-04-26Henrik Grubbström (Grubba)  } #endif
838c212007-04-27Henrik Grubbström (Grubba)  push_type(type->type); if (markers[m]) push_type(T_OR); } else if (!markers[m]) {
4491fd2021-03-27Henrik Grubbström (Grubba)  push_type(PIKE_T_UNKNOWN);
71a9672001-03-03Henrik Grubbström (Grubba)  } TYPE_STACK_DEBUG("push_finished_type_with_markers"); return;
7926bf2007-03-26Henrik Grubbström (Grubba)  } else if (type->type == T_ASSIGN) {
838c212007-04-27Henrik Grubbström (Grubba)  /* Assign. */
7926bf2007-03-26Henrik Grubbström (Grubba)  int marker = PTR_TO_INT(type->car);
c585d52007-04-26Henrik Grubbström (Grubba) #ifdef PIKE_TYPE_DEBUG if (l_flag > 2) {
0aa8592021-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "Assign to marker $%"PRINTPTRDIFFT"d.\n",
c585d52007-04-26Henrik Grubbström (Grubba)  CAR_TO_INT(type)); } #endif /* PIKE_TYPE_DEBUG */
838c212007-04-27Henrik Grubbström (Grubba)  if (marker_set & (PT_FLAG_ASSIGN_0 << marker)) { /* The assignment should be kept as-is. */ #ifdef PIKE_TYPE_DEBUG if (l_flag > 2) { fprintf(stderr, "Keep assignment.\n"); } #endif /* PIKE_TYPE_DEBUG */ /* Clear the flag. */ push_finished_type_with_markers(type->cdr, markers, marker_set & ~(PT_FLAG_ASSIGN_0 << marker)); push_assign_type('0' + marker); TYPE_STACK_DEBUG("push_finished_type_with_markers"); return; } else { #ifdef PIKE_TYPE_DEBUG if (l_flag > 2) { fprintf(stderr, "Strip assignment.\n"); } #endif /* PIKE_TYPE_DEBUG */
7926bf2007-03-26Henrik Grubbström (Grubba)  type = type->cdr; goto recurse; } } else if (type->type == PIKE_T_NAME) {
f62c412001-03-05Henrik Grubbström (Grubba)  /* Strip the name, since it won't be correct anymore. */ type = type->cdr; goto recurse;
838c212007-04-27Henrik Grubbström (Grubba)  } else if (type->type == PIKE_T_ATTRIBUTE) { /* Keep the attribute. */ push_finished_type_with_markers(type->cdr, markers, marker_set); push_type_attribute((struct pike_string *)type->car);
65367f2013-12-10Henrik Grubbström (Grubba)  goto done;
9e5e9b2020-09-16Henrik Grubbström (Grubba)  } else if ((type->type & PIKE_T_MASK) == PIKE_T_OPERATOR) {
d79bff2020-07-17Henrik Grubbström (Grubba)  push_finished_type_with_markers(type->car, markers, marker_set);
34b5bf2022-03-24Henrik Grubbström (Grubba)  if (type->type & 0x8000) { struct pike_type *t; type_stack_mark(); push_finished_type_with_markers(type->cdr, markers, marker_set); t = pop_unfinished_type(); push_type_operator(type->type, t); free_type(t); } else { push_type_operator(type->type, type->cdr); }
d79bff2020-07-17Henrik Grubbström (Grubba)  goto done;
5fc9642020-08-17Henrik Grubbström (Grubba)  } else if (type->type == PIKE_T_TRANSITIVE) { push_finished_type(type->cdr); push_finished_type_with_markers(type->car, markers, marker_set); push_type(PIKE_T_TRANSITIVE); goto done;
f62c412001-03-05Henrik Grubbström (Grubba)  }
71a9672001-03-03Henrik Grubbström (Grubba)  /* FIXME: T_SCOPE */
838c212007-04-27Henrik Grubbström (Grubba)  if (type->car) { /* Keep markers for assigns in the car. */ cdr_set = marker_set | ((type->car->flags & PT_FLAG_ASSIGN)>>PT_ASSIGN_SHIFT); } else { cdr_set = marker_set; } if (type->cdr) { /* Keep assigns for markers in the cdr. */ car_set = marker_set | ((type->cdr->flags & PT_FLAG_MARKER)<<PT_ASSIGN_SHIFT); } else { car_set = marker_set; }
7926bf2007-03-26Henrik Grubbström (Grubba)  if ((type->type == T_OR) || (type->type == T_AND)) { /* Special case handling for implicit zero. */ /* FIXME: Probably ought to use {or,and}_pike_types() here. * Problem is that they may mess with the markers... */
9f194c2007-04-01Henrik Grubbström (Grubba) 
7926bf2007-03-26Henrik Grubbström (Grubba)  type_stack_mark();
838c212007-04-27Henrik Grubbström (Grubba)  /* We want to keep markers that have assigns in the car. */ push_finished_type_with_markers(type->cdr, markers, cdr_set);
7926bf2007-03-26Henrik Grubbström (Grubba)  if (type->type == T_OR) {
9f194c2007-04-01Henrik Grubbström (Grubba)  struct pike_type *first = pop_type(); struct pike_type *second; struct pike_type *res;
838c212007-04-27Henrik Grubbström (Grubba)  push_finished_type_with_markers(type->car, markers, car_set);
9f194c2007-04-01Henrik Grubbström (Grubba)  second = pop_unfinished_type(); push_finished_type(res = or_pike_types(first, second, 1)); free_type(second); free_type(first); free_type(res);
7926bf2007-03-26Henrik Grubbström (Grubba)  } else if (peek_type_stack() == zero_type_string) { pop_stack_mark(); } else { type_stack_mark();
838c212007-04-27Henrik Grubbström (Grubba)  push_finished_type_with_markers(type->car, markers, car_set);
7926bf2007-03-26Henrik Grubbström (Grubba)  if (peek_type_stack() == zero_type_string) { free_type(pop_unfinished_type()); free_type(pop_unfinished_type()); push_finished_type(zero_type_string); } else { pop_stack_mark(); pop_stack_mark(); push_type(T_AND); } } } else {
d5a7dc2019-12-16Henrik Grubbström (Grubba)  /* Make sure to filter invalid nodes from the marker in case * it is a string type. */ if (type->type == PIKE_T_STRING) cdr_set |= PT_FLAG_INT_ONLY;
7926bf2007-03-26Henrik Grubbström (Grubba)  if (type->cdr) {
838c212007-04-27Henrik Grubbström (Grubba)  /* In all other cases type->cdr will be a valid node if is not NULL. */ push_finished_type_with_markers(type->cdr, markers, cdr_set);
e139592021-02-25Henrik Grubbström (Grubba)  } else { switch(type->type) { case T_OR: case T_AND: case T_FUNCTION: case T_MANY: case T_TUPLE: case T_MAPPING: case PIKE_T_RING: case T_ARRAY: case T_STRING: case PIKE_T_TRANSITIVE: push_type(PIKE_T_UNKNOWN); break; }
7926bf2007-03-26Henrik Grubbström (Grubba)  }
d5a7dc2019-12-16Henrik Grubbström (Grubba)  if (type->car) { /* In all other cases type->car will be a valid node if it is not NULL. */ push_finished_type_with_markers(type->car, markers, car_set);
e139592021-02-25Henrik Grubbström (Grubba)  } else { switch(type->type) { case T_OR: case T_AND: case T_FUNCTION: case T_MANY: case T_TUPLE: case T_MAPPING: case PIKE_T_RING: case T_ARRAY: case T_STRING: case PIKE_T_TRANSITIVE: case T_PROGRAM: case T_MULTISET: case T_TYPE: case PIKE_T_AUTO: case T_NOT: push_type(PIKE_T_UNKNOWN); break; }
d5a7dc2019-12-16Henrik Grubbström (Grubba)  }
7926bf2007-03-26Henrik Grubbström (Grubba)  /* push_type has sufficient magic to recreate the type. */ push_type(type->type);
71a9672001-03-03Henrik Grubbström (Grubba)  }
65367f2013-12-10Henrik Grubbström (Grubba)  done:
71a9672001-03-03Henrik Grubbström (Grubba)  TYPE_STACK_DEBUG("push_finished_type_with_markers"); }
2adac42003-03-07Henrik Grubbström (Grubba) static void push_type_field(TYPE_FIELD field) { field &= (BIT_BASIC|BIT_COMPLEX); if (!field) { /* No values. */
bdd4f42021-05-10Henrik Grubbström (Grubba)  push_type(PIKE_T_UNKNOWN);
2adac42003-03-07Henrik Grubbström (Grubba)  } else if (field == (BIT_BASIC|BIT_COMPLEX)) { /* All values. */ push_type(T_MIXED); } else { /* Check the bits... */
ce7b1a2021-11-20Henrik Grubbström (Grubba)  push_type(PIKE_T_UNKNOWN);
2adac42003-03-07Henrik Grubbström (Grubba)  if (field & BIT_COMPLEX) { if (field & BIT_ARRAY) { push_type(T_MIXED);
04017d2020-01-02Henrik Grubbström (Grubba)  push_unlimited_array_type(T_ARRAY);
2adac42003-03-07Henrik Grubbström (Grubba)  push_type(T_OR); } if (field & BIT_MAPPING) { push_type(T_MIXED); push_type(T_MIXED); push_type(T_MAPPING); push_type(T_OR); } if (field & BIT_MULTISET) { push_type(T_MIXED); push_type(T_MULTISET); push_type(T_OR); } if (field & BIT_OBJECT) { push_object_type(0, 0); push_type(T_OR); } if (field & BIT_FUNCTION) { push_type(T_ZERO); push_type(T_ZERO); push_type(T_MIXED); push_type(T_OR); push_type(T_MANY); push_type(T_OR); } if (field & BIT_PROGRAM) { push_object_type(0, 0); push_type(T_PROGRAM); push_type(T_OR); } } if (field & BIT_BASIC) { if (field & BIT_STRING) {
4e6c082007-05-02Henrik Grubbström (Grubba)  push_int_type(MIN_INT32, MAX_INT32);
04017d2020-01-02Henrik Grubbström (Grubba)  push_unlimited_array_type(T_STRING);
2adac42003-03-07Henrik Grubbström (Grubba)  push_type(T_OR); } if (field & BIT_TYPE) { push_type(T_MIXED); push_type(T_TYPE); push_type(T_OR); } if (field & BIT_INT) { push_int_type(MIN_INT32, MAX_INT32); push_type(T_OR); } if (field & BIT_FLOAT) { push_type(T_FLOAT); push_type(T_OR); } } }
087e502020-08-28Henrik Grubbström (Grubba)  TYPE_STACK_DEBUG("push_type_field");
2adac42003-03-07Henrik Grubbström (Grubba) }
71a9672001-03-03Henrik Grubbström (Grubba) INT32 extract_type_int(char *p) {
8079a42014-01-11Tobias S. Josefowitz  return get_unaligned_be32(p);
71a9672001-03-03Henrik Grubbström (Grubba) } struct pike_type *debug_pop_unfinished_type(void) { ptrdiff_t len; len = pop_stack_mark(); if (len != 1) {
2d76f22005-05-20Martin Stjernholm  Pike_fatal("pop_unfinished_type(): Unexpected len: %"PRINTPTRDIFFT"d\n", len);
71a9672001-03-03Henrik Grubbström (Grubba)  } TYPE_STACK_DEBUG("pop_unfinished_type");
64133e2021-09-27Henrik Grubbström (Grubba)  return low_pop_type();
71a9672001-03-03Henrik Grubbström (Grubba) } /******/
d265982011-01-15Henrik Grubbström (Grubba) static struct pike_string *internal_parse_type_string(const char **_s) { const unsigned char **s = (const unsigned char **)_s; const unsigned char *p; struct string_builder tmp;
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
d265982011-01-15Henrik Grubbström (Grubba)  if(**s != '\"') yyerror("Expected '\"'."); else ++*s; init_string_builder(&tmp, 0); p = *s; while(1) { int c; do { c = *p++; } while ((c > '\\') || ((c != '\"') && (c != '\\') && (c != '\n'))); string_builder_binary_strcat(&tmp, *_s, p - (1 + *s)); if (c == '"') { *s = ++p; break; } else if (c == '\\') { p_wchar2 buf; ptrdiff_t len = 0; if (!parse_esc_seq0((p_wchar0 *)p, &buf, &len)) { string_builder_putchar(&tmp, buf); p += len; } else { yyerror("Invalid \\-escape."); } } else { yyerror("Expected '\"'."); break; } *s = p; } return finish_string_builder(&tmp); }
0929a02002-09-12Marcus Comstedt static void internal_parse_typeA(const char **_s)
71a9672001-03-03Henrik Grubbström (Grubba) { char buf[80]; unsigned int len;
0929a02002-09-12Marcus Comstedt  const unsigned char **s = (const unsigned char **)_s;
13670c2015-05-25Martin Nilsson 
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
71a9672001-03-03Henrik Grubbström (Grubba) 
5e6dc22017-01-10Martin Nilsson  for(len=0;isidchar(EXTRACT_UCHAR(s[0]+len));len++)
71a9672001-03-03Henrik Grubbström (Grubba)  {
6e878a2007-01-10Henrik Grubbström (Grubba)  if(len>=sizeof(buf)-1) {
2d76f22005-05-20Martin Stjernholm  my_yyerror("Buffer overflow in parse_type(\"%s\") (limit %"PRINTSIZET"d).",
be9b022003-06-06Henrik Grubbström (Grubba)  *s, sizeof(buf)); push_type(T_MIXED); return; }
71a9672001-03-03Henrik Grubbström (Grubba)  buf[len] = s[0][len]; } buf[len]=0; *s += len;
13670c2015-05-25Martin Nilsson 
71a9672001-03-03Henrik Grubbström (Grubba)  switch(buf[0]) { case 'z': if(!strcmp(buf,"zero")) { push_type(T_ZERO); break; } goto bad_type; case 'i': if(!strcmp(buf,"int")) {
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  if(**s=='(') { INT32 min,max; ++*s;
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
1f1c672003-11-24Henrik Grubbström (Grubba)  if (**s != '.') {
2ae97e2014-09-03Martin Nilsson  min=strtol((const char *)*s,(char **)s,0);
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
1f1c672003-11-24Henrik Grubbström (Grubba)  } else {
1abbfb2006-07-05Martin Stjernholm  min = MIN_INT32;
1f1c672003-11-24Henrik Grubbström (Grubba)  }
71a9672001-03-03Henrik Grubbström (Grubba)  if(s[0][0]=='.' && s[0][1]=='.') s[0]+=2;
be9b022003-06-06Henrik Grubbström (Grubba)  else { yyerror("Missing .. in integer type."); }
13670c2015-05-25Martin Nilsson 
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
1f1c672003-11-24Henrik Grubbström (Grubba)  if (**s != ')') {
2ae97e2014-09-03Martin Nilsson  max=strtol((const char *)*s,(char **)s,0);
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
1f1c672003-11-24Henrik Grubbström (Grubba)  } else {
1abbfb2006-07-05Martin Stjernholm  max = MAX_INT32;
1f1c672003-11-24Henrik Grubbström (Grubba)  }
71a9672001-03-03Henrik Grubbström (Grubba) 
be9b022003-06-06Henrik Grubbström (Grubba)  if(**s != ')') yyerror("Missing ')' in integer range."); else ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  push_int_type(min, max); }else{ push_int_type(MIN_INT32, MAX_INT32); } break; } goto bad_type; case 'f': if(!strcmp(buf,"function")) {
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  if(**s == '(') { int nargs = 0; ++*s;
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  while(1) { if(**s == ':') { push_type(T_VOID); break; } internal_parse_type(_s); if(**s==',') { nargs++; ++*s;
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  } else if(s[0][0]=='.' && s[0][1]=='.' && s[0][2]=='.') { *s+=3;
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
be9b022003-06-06Henrik Grubbström (Grubba)  if(**s != ':') { yyerror("Missing ':' after ... in function type.");
adb7ea2008-01-13Henrik Grubbström (Grubba)  --*s;
be9b022003-06-06Henrik Grubbström (Grubba)  }
71a9672001-03-03Henrik Grubbström (Grubba)  break; } else { nargs++; } }
be9b022003-06-06Henrik Grubbström (Grubba)  /* Skip the colon. */
71a9672001-03-03Henrik Grubbström (Grubba)  ++*s; internal_parse_type(_s); /* return type */ push_reverse_type(T_MANY); while (nargs-- > 0) { push_reverse_type(T_FUNCTION); }
be9b022003-06-06Henrik Grubbström (Grubba)  if(**s != ')') yyerror("Missing ')' in function type."); else ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  }else{ push_type(T_VOID); push_type(T_MIXED); push_type(T_OR); push_type(T_VOID); push_type(T_ZERO); push_type(T_OR); push_type(T_MANY); } break; } if(!strcmp(buf,"float")) { push_type(T_FLOAT); break; } goto bad_type; case 'o': if(!strcmp(buf,"object")) {
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
f37a212002-08-14Henrik Grubbström (Grubba)  if(**s == '(') /* object({,is,implements} {id,this_program}) */
c02ce62001-03-18Per Hedbor  {
f37a212002-08-14Henrik Grubbström (Grubba)  int is = 0, id;
c02ce62001-03-18Per Hedbor  ++*s;
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
c02ce62001-03-18Per Hedbor  if( **s != 'i' )
f37a212002-08-14Henrik Grubbström (Grubba)  goto no_is_implements;
c02ce62001-03-18Per Hedbor  ++*s;
f37a212002-08-14Henrik Grubbström (Grubba)  if( **s == 's' ) { ++*s; if (**s != ' ') { goto bad_type; } is = 1; ++*s; } else {
d416062006-07-06Marcus Comstedt  if (strncmp((const char *)*s, "mplements ", 10)) {
f37a212002-08-14Henrik Grubbström (Grubba)  goto bad_type; } *s += 10; }
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
f37a212002-08-14Henrik Grubbström (Grubba)  no_is_implements:
c02ce62001-03-18Per Hedbor  if( !**s ) goto bad_type;
d416062006-07-06Marcus Comstedt  if (!strncmp((const char *)*s, "this_program", 12)) {
f37a212002-08-14Henrik Grubbström (Grubba)  id = Pike_compiler->new_program->id; *s += 12; } else {
13670c2015-05-25Martin Nilsson  id = atoi( (const char *)*s );
f37a212002-08-14Henrik Grubbström (Grubba)  while( **s >= '0' && **s <= '9' ) ++*s; }
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
c02ce62001-03-18Per Hedbor  if( !**s || **s != ')' ) goto bad_type; ++*s; push_object_type(is, id); } else push_object_type(0, 0);
71a9672001-03-03Henrik Grubbström (Grubba)  break; } goto bad_type; case 'p':
6d33d82001-03-28Henrik Grubbström (Grubba)  if(!strcmp(buf,"program")) { push_object_type(0, 0); push_type(T_PROGRAM); break; }
71a9672001-03-03Henrik Grubbström (Grubba)  goto bad_type; case 's':
157fc62007-03-03Henrik Grubbström (Grubba)  if(!strcmp(buf,"string")) {
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
157fc62007-03-03Henrik Grubbström (Grubba)  if(**s == '(') {
4e6c082007-05-02Henrik Grubbström (Grubba)  INT32 min,max;
157fc62007-03-03Henrik Grubbström (Grubba)  ++*s;
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
4e6c082007-05-02Henrik Grubbström (Grubba)  if (**s != '.') {
2ae97e2014-09-03Martin Nilsson  min=strtol((const char *)*s,(char **)s,0);
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
4e6c082007-05-02Henrik Grubbström (Grubba)  } else { min = MIN_INT32; } if(s[0][0]=='.' && s[0][1]=='.') s[0]+=2; else { yyerror("Missing .. in integer type."); }
13670c2015-05-25Martin Nilsson 
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
4e6c082007-05-02Henrik Grubbström (Grubba)  if (**s != ')') {
2ae97e2014-09-03Martin Nilsson  max=strtol((const char *)*s,(char **)s,0);
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
4e6c082007-05-02Henrik Grubbström (Grubba)  } else { max = MAX_INT32; }
157fc62007-03-03Henrik Grubbström (Grubba)  if(**s != ')') yyerror("Missing ')' in string width."); else ++*s;
4e6c082007-05-02Henrik Grubbström (Grubba)  push_int_type(min, max);
157fc62007-03-03Henrik Grubbström (Grubba)  } else {
4e6c082007-05-02Henrik Grubbström (Grubba)  push_finished_type(int_type_string);
157fc62007-03-03Henrik Grubbström (Grubba)  }
04017d2020-01-02Henrik Grubbström (Grubba)  push_unlimited_array_type(T_STRING);
157fc62007-03-03Henrik Grubbström (Grubba)  break; }
71a9672001-03-03Henrik Grubbström (Grubba)  goto bad_type; case 'v': if(!strcmp(buf,"void")) { push_type(T_VOID); break; } goto bad_type; case 't': if (!strcmp(buf,"tuple")) {
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  if(**s == '(') { ++*s; internal_parse_type(_s);
be9b022003-06-06Henrik Grubbström (Grubba)  if(**s != ',') yyerror("Expected ','."); else ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  internal_parse_type(_s);
be9b022003-06-06Henrik Grubbström (Grubba)  if(**s != ')') yyerror("Expected ')'."); else ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  }else{ push_type(T_MIXED); push_type(T_MIXED); } push_reverse_type(T_TUPLE); break; }
54f8ac2001-03-17Henrik Grubbström (Grubba)  /* FIXME: Handle type(T) */ if(!strcmp(buf,"type")) { push_type(T_MIXED); push_type(T_TYPE); break; }
71a9672001-03-03Henrik Grubbström (Grubba)  goto bad_type; case 'm': if(!strcmp(buf,"mixed")) { push_type(T_MIXED); break; } if(!strcmp(buf,"mapping")) {
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  if(**s == '(') { ++*s; internal_parse_type(_s);
be9b022003-06-06Henrik Grubbström (Grubba)  if(**s != ':') yyerror("Expected ':'."); else ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  internal_parse_type(_s);
be9b022003-06-06Henrik Grubbström (Grubba)  if(**s != ')') yyerror("Expected ')'."); else ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  }else{ push_type(T_MIXED); push_type(T_MIXED); } push_reverse_type(T_MAPPING); break; } if(!strcmp(buf,"multiset")) {
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  if(**s == '(') { ++*s; internal_parse_type(_s);
be9b022003-06-06Henrik Grubbström (Grubba)  if(**s != ')') yyerror("Expected ')'."); else ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  }else{ push_type(T_MIXED); } push_type(T_MULTISET); break; } goto bad_type; case 'u': if(!strcmp(buf,"unknown")) { push_type(PIKE_T_UNKNOWN); break; } goto bad_type; case 'a': if(!strcmp(buf,"array")) {
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  if(**s == '(') { ++*s; internal_parse_type(_s);
be9b022003-06-06Henrik Grubbström (Grubba)  if(**s != ')') yyerror("Expected ')'."); else ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  }else{ push_type(T_MIXED); }
04017d2020-01-02Henrik Grubbström (Grubba)  push_unlimited_array_type(T_ARRAY);
71a9672001-03-03Henrik Grubbström (Grubba)  break; } goto bad_type;
d265982011-01-15Henrik Grubbström (Grubba)  case '_': if (!strcmp(buf, "__attribute__")) {
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
d265982011-01-15Henrik Grubbström (Grubba)  if(**s == '(') { struct pike_string *attr; ++*s; attr = internal_parse_type_string(_s);
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
d265982011-01-15Henrik Grubbström (Grubba)  if(**s != ',') yyerror("Expected ','."); else ++*s; internal_parse_type(_s); if(**s != ')') yyerror("Expected ')'."); else ++*s; push_type_attribute(attr); free_string(attr); }else{ push_type(T_MIXED); } break; } else if (!strcmp(buf, "__deprecated__")) { struct pike_string *deprecated_string; MAKE_CONST_STRING(deprecated_string, "deprecated");
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
d265982011-01-15Henrik Grubbström (Grubba)  if(**s == '(') { ++*s; internal_parse_type(_s); if(**s != ')') yyerror("Expected ')'."); else ++*s; }else{ push_type(T_MIXED); } push_type_attribute(deprecated_string); break; } goto bad_type;
71a9672001-03-03Henrik Grubbström (Grubba)  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if(atoi(buf)<10) {
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  if(**s=='=') { ++*s; internal_parse_type(_s); push_assign_type(buf[0]); }else{ push_type(buf[0]); } break; }
3595ea2018-02-12Marcus Comstedt  /* FALLTHRU */
71a9672001-03-03Henrik Grubbström (Grubba)  default: bad_type:
be9b022003-06-06Henrik Grubbström (Grubba)  push_type(T_MIXED); my_yyerror("Couldn't parse type. (%s).", buf);
71a9672001-03-03Henrik Grubbström (Grubba)  }
e045b22014-09-03Martin Nilsson  while(isspace(**s)) ++*s;
71a9672001-03-03Henrik Grubbström (Grubba) }
0929a02002-09-12Marcus Comstedt static void internal_parse_typeB(const char **s)
71a9672001-03-03Henrik Grubbström (Grubba) {
e045b22014-09-03Martin Nilsson  while(isspace(EXTRACT_UCHAR(*s))) ++*s;
71a9672001-03-03Henrik Grubbström (Grubba)  switch(**s) {
c404c02022-04-28Henrik Grubbström (Grubba)  case '!': case '~':
71a9672001-03-03Henrik Grubbström (Grubba)  ++*s; internal_parse_typeB(s); push_type(T_NOT); break; case '(': ++*s; internal_parse_type(s);
e045b22014-09-03Martin Nilsson  while(isspace(EXTRACT_UCHAR(*s))) ++*s;
be9b022003-06-06Henrik Grubbström (Grubba)  if(**s != ')') { yyerror("Expected ')' in type."); }
71a9672001-03-03Henrik Grubbström (Grubba)  ++*s; break;
13670c2015-05-25Martin Nilsson 
71a9672001-03-03Henrik Grubbström (Grubba)  default: internal_parse_typeA(s); } }
0929a02002-09-12Marcus Comstedt static void internal_parse_typeCC(const char **s)
71a9672001-03-03Henrik Grubbström (Grubba) { internal_parse_typeB(s);
e045b22014-09-03Martin Nilsson  while(isspace(EXTRACT_UCHAR(*s))) ++*s;
13670c2015-05-25Martin Nilsson 
71a9672001-03-03Henrik Grubbström (Grubba)  while(**s == '*') { ++*s;
e045b22014-09-03Martin Nilsson  while(isspace(EXTRACT_UCHAR(*s))) ++*s;
04017d2020-01-02Henrik Grubbström (Grubba)  push_unlimited_array_type(T_ARRAY);
71a9672001-03-03Henrik Grubbström (Grubba)  } }
0929a02002-09-12Marcus Comstedt static void internal_parse_typeC(const char **s)
71a9672001-03-03Henrik Grubbström (Grubba) { internal_parse_typeCC(s); if(**s == '&') { ++*s; internal_parse_typeC(s); push_reverse_type(T_AND); } }
0929a02002-09-12Marcus Comstedt static void internal_parse_type(const char **s)
71a9672001-03-03Henrik Grubbström (Grubba) { internal_parse_typeC(s); while(**s == '|') { ++*s; internal_parse_typeC(s); push_type(T_OR); } } /* This function is used when adding simul efuns so that * the types for the functions can be easily stored in strings. * It takes a string on the exact same format as Pike and returns a type * struct. */
0929a02002-09-12Marcus Comstedt struct pike_type *parse_type(const char *s)
71a9672001-03-03Henrik Grubbström (Grubba) { struct pike_type *ret; #ifdef PIKE_DEBUG struct pike_type **ts=Pike_compiler->type_stackp; struct pike_type ***ptms=Pike_compiler->pike_type_mark_stackp; #endif /* fprintf(stderr, "parse_type(\"%s\")...\n", s); */ TYPE_STACK_DEBUG("parse_type"); type_stack_mark();
be9b022003-06-06Henrik Grubbström (Grubba) 
71a9672001-03-03Henrik Grubbström (Grubba)  internal_parse_type(&s); if( *s )
be9b022003-06-06Henrik Grubbström (Grubba)  yyerror("Extra junk at end of type definition.");
71a9672001-03-03Henrik Grubbström (Grubba)  ret=pop_unfinished_type(); #ifdef PIKE_DEBUG if(ts!=Pike_compiler->type_stackp || ptms!=Pike_compiler->pike_type_mark_stackp)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Type stack whacked in parse_type.\n");
71a9672001-03-03Henrik Grubbström (Grubba) #endif return ret; } void simple_describe_type(struct pike_type *s) {
36e8ba2021-07-10Henrik Grubbström (Grubba)  DECLARE_CYCLIC(); if (BEGIN_CYCLIC(s, NULL)) { Pike_fatal("Circular type!\n"); } SET_CYCLIC_RET(1);
71a9672001-03-03Henrik Grubbström (Grubba)  if (s) {
491ab02007-03-31Henrik Grubbström (Grubba)  /* fprintf(stderr, "[[[%p]]]", s); */
9e5e9b2020-09-16Henrik Grubbström (Grubba)  switch(s->type & PIKE_T_MASK) {
71a9672001-03-03Henrik Grubbström (Grubba)  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
0aa8592021-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "$%d", s->type-'0');
71a9672001-03-03Henrik Grubbström (Grubba)  break;
f62c412001-03-05Henrik Grubbström (Grubba)  case PIKE_T_NAME:
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, "{ %s = ", ((struct pike_string *)s->car)->str);
f62c412001-03-05Henrik Grubbström (Grubba)  simple_describe_type(s->cdr);
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, " }");
f62c412001-03-05Henrik Grubbström (Grubba)  break;
9129122007-04-21Henrik Grubbström (Grubba)  case PIKE_T_ATTRIBUTE:
e021fe2008-04-14Henrik Grubbström (Grubba)  { struct pike_string *deprecated; MAKE_CONST_STRING(deprecated, "deprecated"); if (((struct pike_string *)s->car) == deprecated) { fprintf(stderr, "__deprecated__("); } else { fprintf(stderr, "__attribute__(\"%s\", ", ((struct pike_string *)s->car)->str); } simple_describe_type(s->cdr); fprintf(stderr, ")"); }
9129122007-04-21Henrik Grubbström (Grubba)  break;
71a9672001-03-03Henrik Grubbström (Grubba)  case T_SCOPE:
6fd0692003-07-01Martin Stjernholm  fprintf(stderr, "scope(%"PRINTPTRDIFFT"d, ", CAR_TO_INT(s));
71a9672001-03-03Henrik Grubbström (Grubba)  simple_describe_type(s->cdr);
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, ")");
71a9672001-03-03Henrik Grubbström (Grubba)  break; case T_TUPLE:
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, "tuple(");
71a9672001-03-03Henrik Grubbström (Grubba)  simple_describe_type(s->car);
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, ", ");
71a9672001-03-03Henrik Grubbström (Grubba)  simple_describe_type(s->cdr);
13670c2015-05-25Martin Nilsson  fprintf(stderr, ")");
71a9672001-03-03Henrik Grubbström (Grubba)  break; case T_ASSIGN:
0aa8592021-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "($%"PRINTPTRDIFFT"d = ", CAR_TO_INT(s));
71a9672001-03-03Henrik Grubbström (Grubba)  simple_describe_type(s->cdr);
13670c2015-05-25Martin Nilsson  fprintf(stderr, ")");
71a9672001-03-03Henrik Grubbström (Grubba)  break; case T_INT: {
d2361e2003-06-30Martin Stjernholm  INT32 min = CAR_TO_INT(s); INT32 max = CDR_TO_INT(s);
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, "int");
2bda502013-12-16Henrik Grubbström (Grubba)  if(min!=MIN_INT32 || max!=MAX_INT32) { if (!min && max && !(max & (max+1))) { int j = 0; while (max) { max >>= 1; j++; } fprintf(stderr, "(%dbit)", j);
6f65902019-12-22Henrik Grubbström (Grubba)  } else if (min == max) { fprintf(stderr, "(%ld)", (long)min);
2bda502013-12-16Henrik Grubbström (Grubba)  } else { fprintf(stderr, "(%ld..%ld)",(long)min,(long)max); } }
71a9672001-03-03Henrik Grubbström (Grubba)  break; }
35ce412001-03-27Henrik Grubbström (Grubba)  case T_FLOAT: fprintf(stderr, "float"); break;
157fc62007-03-03Henrik Grubbström (Grubba)  case T_STRING: {
4e6c082007-05-02Henrik Grubbström (Grubba)  INT32 min; INT32 max; fprintf(stderr, "string");
ce56eb2020-01-11Henrik Grubbström (Grubba)  if ((s->car == int_pos_type_string) && (s->cdr == int_type_string)) { break; } fprintf(stderr, "("); if (s->car != int_pos_type_string) { simple_describe_type(s->car); fprintf(stderr, ": "); } s = s->cdr;
e8699e2021-04-03Henrik Grubbström (Grubba)  if (s && (s != int_type_string)) {
4e6c082007-05-02Henrik Grubbström (Grubba)  while (s->type == T_OR) {
8151ac2008-06-18Henrik Grubbström (Grubba)  struct pike_type *char_type = s->car; while(char_type->type == T_ASSIGN) { char_type = char_type->cdr; }
b908572008-09-08Henrik Grubbström (Grubba)  if (char_type->type == T_ZERO) { fprintf(stderr, "zero | "); s = s->cdr; continue; }
0548c52021-09-16Henrik Grubbström (Grubba)  if (char_type->type == T_MIXED) { fprintf(stderr, "mixed | "); s = s->cdr; continue; }
0551da2013-12-13Henrik Grubbström (Grubba)  if ((char_type->type >= '0') && (char_type->type <= '9')) { fprintf(stderr, "$%c | ", char_type->type); s = s->cdr; continue; }
4e6c082007-05-02Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG
8151ac2008-06-18Henrik Grubbström (Grubba)  if (char_type->type != T_INT) {
4e6c082007-05-02Henrik Grubbström (Grubba)  Pike_fatal("Invalid node type (%d:%s) in string type.\n",
8151ac2008-06-18Henrik Grubbström (Grubba)  char_type->type, get_name_of_type(char_type->type));
4e6c082007-05-02Henrik Grubbström (Grubba)  } #endif /* PIKE_DEBUG */
8151ac2008-06-18Henrik Grubbström (Grubba)  min = CAR_TO_INT(char_type); max = CDR_TO_INT(char_type);
a776c92014-01-11Arne Goedeke  if (!min && max && max != MAX_INT32 && !(max & (max+1))) {
2bda502013-12-16Henrik Grubbström (Grubba)  int j = 0; while (max) { max >>= 1; j++; } fprintf(stderr, "%dbit", j); } else {
6f65902019-12-22Henrik Grubbström (Grubba)  if ((min != MIN_INT32) || (max == min)) {
2bda502013-12-16Henrik Grubbström (Grubba)  fprintf(stderr, "%d", min); }
6f65902019-12-22Henrik Grubbström (Grubba)  if (max != min) { fprintf(stderr, ".."); if (max != MAX_INT32) { fprintf(stderr, "%d", max); }
2bda502013-12-16Henrik Grubbström (Grubba)  }
4e6c082007-05-02Henrik Grubbström (Grubba)  } fprintf(stderr, " | "); s = s->cdr; }
8151ac2008-06-18Henrik Grubbström (Grubba)  while(s->type == T_ASSIGN) { s = s->cdr; }
9b12ee2021-11-06Henrik Grubbström (Grubba)  if (!s) { fprintf(stderr, "__unknown__"); } else if (s->type == T_ZERO) {
b908572008-09-08Henrik Grubbström (Grubba)  fprintf(stderr, "zero");
e8699e2021-04-03Henrik Grubbström (Grubba)  } else if (s->type == T_MIXED) { fprintf(stderr, "mixed");
0551da2013-12-13Henrik Grubbström (Grubba)  } else if ((s->type >= '0') && (s->type <= '9')) { fprintf(stderr, "$%c", s->type);
b908572008-09-08Henrik Grubbström (Grubba)  } else {
4e6c082007-05-02Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG
b908572008-09-08Henrik Grubbström (Grubba)  if (s->type != T_INT) { Pike_fatal("Invalid node type (%d:%s) in string type.\n", s->type, get_name_of_type(s->type)); }
4e6c082007-05-02Henrik Grubbström (Grubba) #endif /* PIKE_DEBUG */
b908572008-09-08Henrik Grubbström (Grubba)  min = CAR_TO_INT(s); max = CDR_TO_INT(s);
a776c92014-01-11Arne Goedeke  if (!min && max && max != MAX_INT32 && !(max & (max+1))) {
2bda502013-12-16Henrik Grubbström (Grubba)  int j = 0; while (max) { max >>= 1; j++; } fprintf(stderr, "%dbit", j); } else {
6f65902019-12-22Henrik Grubbström (Grubba)  if ((min != MIN_INT32) || (min == max)) {
2bda502013-12-16Henrik Grubbström (Grubba)  fprintf(stderr, "%d", min); }
6f65902019-12-22Henrik Grubbström (Grubba)  if (min != max) { fprintf(stderr, ".."); if (max != MAX_INT32) { fprintf(stderr, "%d", max); }
2bda502013-12-16Henrik Grubbström (Grubba)  }
b908572008-09-08Henrik Grubbström (Grubba)  }
4e6c082007-05-02Henrik Grubbström (Grubba)  }
157fc62007-03-03Henrik Grubbström (Grubba)  }
ce56eb2020-01-11Henrik Grubbström (Grubba)  fprintf(stderr, ")");
157fc62007-03-03Henrik Grubbström (Grubba)  break; }
54f8ac2001-03-17Henrik Grubbström (Grubba)  case T_TYPE:
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, "type(");
54f8ac2001-03-17Henrik Grubbström (Grubba)  simple_describe_type(s->car);
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, ")");
54f8ac2001-03-17Henrik Grubbström (Grubba)  break;
6d33d82001-03-28Henrik Grubbström (Grubba)  case T_PROGRAM: fprintf(stderr, "program("); simple_describe_type(s->car); fprintf(stderr, ")"); break;
71a9672001-03-03Henrik Grubbström (Grubba)  case T_OBJECT:
6fd0692003-07-01Martin Stjernholm  fprintf(stderr, "object(%s %"PRINTPTRDIFFT"d)",
71a9672001-03-03Henrik Grubbström (Grubba)  s->car?"is":"implements",
d2361e2003-06-30Martin Stjernholm  CDR_TO_INT(s));
71a9672001-03-03Henrik Grubbström (Grubba)  break; case T_FUNCTION: case T_MANY:
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, "function(");
71a9672001-03-03Henrik Grubbström (Grubba)  while(s->type == T_FUNCTION) { simple_describe_type(s->car); s = s->cdr; if ((s->type == T_FUNCTION) ||
fb013e2020-08-19Henrik Grubbström (Grubba)  ((s->type == T_MANY) && (s->car->type != T_VOID))) {
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, ", ");
71a9672001-03-03Henrik Grubbström (Grubba)  } }
0bd03e2020-07-13Henrik Grubbström (Grubba)  if (s->type != T_MANY) { fprintf(stderr, ", @"); simple_describe_type(s); fprintf(stderr, ")"); } else {
f94e432021-01-30Henrik Grubbström (Grubba)  if (!s->car || (s->car->type != T_VOID)) {
0bd03e2020-07-13Henrik Grubbström (Grubba)  simple_describe_type(s->car); fprintf(stderr, "..."); } fprintf(stderr, ":"); simple_describe_type(s->cdr); fprintf(stderr, ")");
71a9672001-03-03Henrik Grubbström (Grubba)  } break;
5026702020-05-18Henrik Grubbström (Grubba)  case T_ARRAY: /* FIXME: cdr */
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, "array(");
ce56eb2020-01-11Henrik Grubbström (Grubba)  if (s->car != int_pos_type_string) { simple_describe_type(s->car); fprintf(stderr, ":"); }
d5a7dc2019-12-16Henrik Grubbström (Grubba)  simple_describe_type(s->cdr);
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, ")");
71a9672001-03-03Henrik Grubbström (Grubba)  break; case T_MAPPING:
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, "mapping(");
71a9672001-03-03Henrik Grubbström (Grubba)  simple_describe_type(s->car);
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, ":");
71a9672001-03-03Henrik Grubbström (Grubba)  simple_describe_type(s->cdr);
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, ")");
71a9672001-03-03Henrik Grubbström (Grubba)  break; case T_MULTISET:
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, "multiset(");
71a9672001-03-03Henrik Grubbström (Grubba)  simple_describe_type(s->car);
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, ")");
71a9672001-03-03Henrik Grubbström (Grubba)  break;
13670c2015-05-25Martin Nilsson 
35ce412001-03-27Henrik Grubbström (Grubba)  case PIKE_T_UNKNOWN: fprintf(stderr, "unknown"); break;
ce88d62001-03-19Henrik Grubbström (Grubba)  case PIKE_T_RING:
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, "ring(");
ce88d62001-03-19Henrik Grubbström (Grubba)  simple_describe_type(s->car);
1588532012-12-29Jonas Walldén  fprintf(stderr, "\260");
ce88d62001-03-19Henrik Grubbström (Grubba)  simple_describe_type(s->cdr);
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, ")");
ce88d62001-03-19Henrik Grubbström (Grubba)  break;
71a9672001-03-03Henrik Grubbström (Grubba)  case T_OR:
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, "or(");
71a9672001-03-03Henrik Grubbström (Grubba)  simple_describe_type(s->car);
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, "|");
71a9672001-03-03Henrik Grubbström (Grubba)  simple_describe_type(s->cdr);
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, ")");
71a9672001-03-03Henrik Grubbström (Grubba)  break; case T_AND:
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, "and(");
71a9672001-03-03Henrik Grubbström (Grubba)  simple_describe_type(s->car);
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, "&");
71a9672001-03-03Henrik Grubbström (Grubba)  simple_describe_type(s->cdr);
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, ")");
71a9672001-03-03Henrik Grubbström (Grubba)  break; case T_NOT:
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, "not(");
71a9672001-03-03Henrik Grubbström (Grubba)  simple_describe_type(s->car);
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, ")");
71a9672001-03-03Henrik Grubbström (Grubba)  break;
35ce412001-03-27Henrik Grubbström (Grubba)  case T_VOID: fprintf(stderr, "void"); break; case T_ZERO: fprintf(stderr, "zero"); break; case T_MIXED: fprintf(stderr, "mixed"); break;
ec9bc12016-05-01Henrik Grubbström (Grubba)  case PIKE_T_AUTO: fprintf(stderr, "auto"); if (s->car && (s->car->type != T_ZERO)) { fprintf(stderr, "("); simple_describe_type(s->car); fprintf(stderr, ")"); } break;
d79bff2020-07-17Henrik Grubbström (Grubba)  case PIKE_T_OPERATOR: fprintf(stderr, "operator<0x%04x>(", s->type); simple_describe_type(s->car); if (s->type & 0x8000) { fprintf(stderr, ","); simple_describe_type(s->cdr);
0548c52021-09-16Henrik Grubbström (Grubba)  fprintf(stderr, ")");
d79bff2020-07-17Henrik Grubbström (Grubba)  } else { switch(s->type) {
0a3d9f2020-07-18Henrik Grubbström (Grubba)  case PIKE_T_FIND_LFUN: fprintf(stderr, ",\"%s\")", STR0(lfun_strings[CDR_TO_INT(s)])); break;
d79bff2020-07-17Henrik Grubbström (Grubba)  default: if (s->cdr) { fprintf(stderr, ",0x%08lx)", CDR_TO_INT(s)); } else { fprintf(stderr, ")"); } break; } } break;
5fc9642020-08-17Henrik Grubbström (Grubba)  case PIKE_T_TRANSITIVE: fprintf(stderr, "transitive("); simple_describe_type(s->car); fprintf(stderr, ", "); simple_describe_type(s->cdr); fprintf(stderr, ")"); break;
71a9672001-03-03Henrik Grubbström (Grubba)  default:
35ce412001-03-27Henrik Grubbström (Grubba)  fprintf(stderr, "Unknown type node: %d, %p:%p",
71a9672001-03-03Henrik Grubbström (Grubba)  s->type, s->car, s->cdr);
491ab02007-03-31Henrik Grubbström (Grubba) #ifdef DEBUG_MALLOC debug_malloc_dump_references(s, 0, 2, 0); #endif
71a9672001-03-03Henrik Grubbström (Grubba)  break; }
0e875c2022-05-07Henrik Grubbström (Grubba)  if (s->flags && (l_flag > 10)) {
7926bf2007-03-26Henrik Grubbström (Grubba)  fprintf(stderr, "[%06x]", s->flags); }
71a9672001-03-03Henrik Grubbström (Grubba)  } else {
bb96d52021-03-09Henrik Grubbström (Grubba)  fprintf(stderr, "__unknown__");
71a9672001-03-03Henrik Grubbström (Grubba)  }
36e8ba2021-07-10Henrik Grubbström (Grubba)  END_CYCLIC();
71a9672001-03-03Henrik Grubbström (Grubba) }
9b5a822001-03-29Henrik Grubbström (Grubba) 
5ee03f2020-01-10Henrik Grubbström (Grubba) static void low_describe_int_range(struct string_builder *s, struct pike_type *t) { if (!t || (t == int_type_string)) return; loop: switch(t->type) { case T_ZERO: string_builder_strcat(s, "zero"); break; case T_INT: { INT32 min=CAR_TO_INT(t); INT32 max=CDR_TO_INT(t); if (min == max) { string_builder_sprintf(s, "%ld", (long) min); } else if (!min && (max != MAX_INT32) && !(max & (max + 1))) { int j = 0; while (max) { max >>= 1; j++; } string_builder_sprintf(s, "%dbit", j); } else { if (min != MIN_INT32) { string_builder_sprintf(s, "%ld..", (long)min); } else { string_builder_strcat(s, ".."); } if (max != MAX_INT32) { string_builder_sprintf(s, "%ld", (long)max); } } } break; case T_ASSIGN:
0aa8592021-11-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "$%ld = (", CAR_TO_INT(t));
a131292020-09-30Henrik Grubbström (Grubba)  low_describe_int_range(s, t->cdr); string_builder_strcat(s, ")"); break;
5ee03f2020-01-10Henrik Grubbström (Grubba)  case T_OR: low_describe_int_range(s, t->car); string_builder_strcat(s, " | "); t = t->cdr; goto loop; default: low_describe_type(s, t); break; } }
b10e412015-10-11Henrik Grubbström (Grubba) void low_describe_type(struct string_builder *s, struct pike_type *t)
71a9672001-03-03Henrik Grubbström (Grubba) {
a6dfba2005-09-09Henrik Grubbström (Grubba)  check_c_stack(1024);
bf70292021-03-09Henrik Grubbström (Grubba)  if (!t) { string_builder_strcat(s, "__unknown__"); return; }
d79bff2020-07-17Henrik Grubbström (Grubba)  switch(t->type) /* NB: No masking here! */
71a9672001-03-03Henrik Grubbström (Grubba)  { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
0aa8592021-11-11Henrik Grubbström (Grubba)  string_builder_putchar(s, '$');
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_putchar(s, t->type);
71a9672001-03-03Henrik Grubbström (Grubba)  break;
13670c2015-05-25Martin Nilsson 
71a9672001-03-03Henrik Grubbström (Grubba)  case T_ASSIGN:
0aa8592021-11-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "($%c=%T)", '0' + CAR_TO_INT(t), t->cdr);
71a9672001-03-03Henrik Grubbström (Grubba)  break; case T_SCOPE:
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "scope(%c,%T)", '0' + CAR_TO_INT(t), t->cdr);
71a9672001-03-03Henrik Grubbström (Grubba)  break; case T_TUPLE:
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "[%T,%T]", t->car, t->cdr);
71a9672001-03-03Henrik Grubbström (Grubba)  break;
b10e412015-10-11Henrik Grubbström (Grubba)  case T_VOID: string_builder_strcat(s, "void"); break; case T_ZERO: string_builder_strcat(s, "zero"); break; case T_MIXED: string_builder_strcat(s, "mixed"); break; case PIKE_T_UNKNOWN: string_builder_strcat(s, "unknown"); break;
5ee03f2020-01-10Henrik Grubbström (Grubba) 
71a9672001-03-03Henrik Grubbström (Grubba)  case T_INT:
5ee03f2020-01-10Henrik Grubbström (Grubba)  string_builder_strcat(s, "int");
13670c2015-05-25Martin Nilsson 
5ee03f2020-01-10Henrik Grubbström (Grubba)  if (t == int_type_string) break; string_builder_putchar(s, '('); low_describe_int_range(s, t); string_builder_putchar(s, ')');
71a9672001-03-03Henrik Grubbström (Grubba)  break;
5ee03f2020-01-10Henrik Grubbström (Grubba) 
b10e412015-10-11Henrik Grubbström (Grubba)  case T_FLOAT: string_builder_strcat(s, "float"); break;
6d33d82001-03-28Henrik Grubbström (Grubba)  case T_PROGRAM:
a9b2da2002-07-03Henrik Grubbström (Grubba)  if ((t->car->type == T_OBJECT) && (!t->car->cdr)) {
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_strcat(s, "program");
a9b2da2002-07-03Henrik Grubbström (Grubba)  } else {
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "program(%T)", t->car);
a9b2da2002-07-03Henrik Grubbström (Grubba)  }
6d33d82001-03-28Henrik Grubbström (Grubba)  break;
71a9672001-03-03Henrik Grubbström (Grubba)  case T_OBJECT: if (t->cdr) {
b10e412015-10-11Henrik Grubbström (Grubba)  struct svalue sval;
71868e2007-03-30Henrik Grubbström (Grubba)  if (t->car) {
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_strcat(s, "object(is ");
71868e2007-03-30Henrik Grubbström (Grubba)  } else {
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_strcat(s, "object(implements ");
71868e2007-03-30Henrik Grubbström (Grubba)  }
1cba5d2011-02-05Henrik Grubbström (Grubba)  /* We need to save the global buffer, in case id_to_program() * starts running Pike code. */
b10e412015-10-11Henrik Grubbström (Grubba)  sval.u.program = id_to_program(CDR_TO_INT(t)); if (sval.u.program) { SET_SVAL_TYPE(sval, T_PROGRAM); SET_SVAL_SUBTYPE(sval, 0); string_builder_sprintf(s, "%O)", &sval);
71868e2007-03-30Henrik Grubbström (Grubba)  } else {
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "%"PRINTPTRDIFFT"d)", CDR_TO_INT(t));
71868e2007-03-30Henrik Grubbström (Grubba)  }
71a9672001-03-03Henrik Grubbström (Grubba)  }else{
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_strcat(s, "object");
71a9672001-03-03Henrik Grubbström (Grubba)  } break;
157fc62007-03-03Henrik Grubbström (Grubba)  case T_STRING: {
5ee03f2020-01-10Henrik Grubbström (Grubba)  string_builder_strcat(s, "string");
ce56eb2020-01-11Henrik Grubbström (Grubba)  if ((t->cdr == int_type_string) && (t->car == int_pos_type_string)) {
5ee03f2020-01-10Henrik Grubbström (Grubba)  break;
157fc62007-03-03Henrik Grubbström (Grubba)  }
5ee03f2020-01-10Henrik Grubbström (Grubba)  string_builder_putchar(s, '(');
53257b2020-01-16Henrik Grubbström (Grubba)  if (t->car == zero_type_string) { /* Zero-length string. */
d4db472021-11-10Tobias S. Josefowitz  string_builder_strcat(s, "zero:");
53257b2020-01-16Henrik Grubbström (Grubba)  } else { if (t->car != int_pos_type_string) { low_describe_int_range(s, t->car);
50fbc52020-12-03Henrik Grubbström (Grubba)  string_builder_strcat(s, ": ");
53257b2020-01-16Henrik Grubbström (Grubba)  } low_describe_int_range(s, t->cdr);
ce56eb2020-01-11Henrik Grubbström (Grubba)  }
5ee03f2020-01-10Henrik Grubbström (Grubba)  string_builder_putchar(s, ')');
157fc62007-03-03Henrik Grubbström (Grubba)  break; }
54f8ac2001-03-17Henrik Grubbström (Grubba)  case T_TYPE:
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "type(%T)", t->car);
54f8ac2001-03-17Henrik Grubbström (Grubba)  break;
f62c412001-03-05Henrik Grubbström (Grubba)  case PIKE_T_NAME:
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "{ %S = %T }", (struct pike_string *)t->car, t->cdr);
f62c412001-03-05Henrik Grubbström (Grubba)  break;
13670c2015-05-25Martin Nilsson 
9129122007-04-21Henrik Grubbström (Grubba)  case PIKE_T_ATTRIBUTE:
b10e412015-10-11Henrik Grubbström (Grubba)  {
e021fe2008-04-14Henrik Grubbström (Grubba)  struct pike_string *deprecated; MAKE_CONST_STRING(deprecated, "deprecated"); if (((struct pike_string *)t->car) == deprecated) {
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "__deprecated__(%T)", t->cdr);
1874052018-04-21Henrik Grubbström (Grubba)  } else if (t == utf8_type_string) { string_builder_sprintf(s, "utf8_string");
e021fe2008-04-14Henrik Grubbström (Grubba)  } else {
b10e412015-10-11Henrik Grubbström (Grubba)  struct svalue sval; SET_SVAL(sval, PIKE_T_STRING, 0, string, (struct pike_string *)t->car); string_builder_sprintf(s, "__attribute__(%O, %T)", &sval, t->cdr);
e021fe2008-04-14Henrik Grubbström (Grubba)  }
9129122007-04-21Henrik Grubbström (Grubba)  } break;
13670c2015-05-25Martin Nilsson 
71a9672001-03-03Henrik Grubbström (Grubba)  case T_FUNCTION: case T_MANY: { if(t->type == T_MANY &&
8b7a892021-04-05Henrik Grubbström (Grubba)  ((!t->cdr && !t->car) || (t->cdr && t->cdr->type == T_OR && ((t->cdr->car->type == T_MIXED && t->cdr->cdr->type == T_VOID) || (t->cdr->cdr->type == T_MIXED && t->cdr->car->type == T_VOID)) && (!t->car || t->car->type == T_ZERO || (t->car->type == T_OR && ((t->car->car->type == T_ZERO && t->car->cdr->type == T_VOID) || (t->car->cdr->type == T_ZERO && t->car->car->type == T_VOID)))))))
71a9672001-03-03Henrik Grubbström (Grubba)  { /* function == function(zero...:mixed|void) or * function(zero|void...:mixed|void) */
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_strcat(s, "function");
71a9672001-03-03Henrik Grubbström (Grubba)  /* done */
b10e412015-10-11Henrik Grubbström (Grubba)  break;
71a9672001-03-03Henrik Grubbström (Grubba)  } else {
b10e412015-10-11Henrik Grubbström (Grubba)  int arg = 0; string_builder_strcat(s, "function(");
3172012022-04-29Henrik Grubbström (Grubba)  while(t && (t->type == T_FUNCTION))
71a9672001-03-03Henrik Grubbström (Grubba)  {
b10e412015-10-11Henrik Grubbström (Grubba)  if(arg++) string_builder_strcat(s, ", "); low_describe_type(s, t->car);
71a9672001-03-03Henrik Grubbström (Grubba)  t = t->cdr; }
3172012022-04-29Henrik Grubbström (Grubba)  if (!t || (t->type != T_MANY)) {
1b0a062020-08-27Henrik Grubbström (Grubba)  string_builder_sprintf(s, ", @%T)", t);
0bd03e2020-07-13Henrik Grubbström (Grubba)  } else {
928bb12021-01-27Henrik Grubbström (Grubba)  if(!t->car || (t->car->type != T_VOID))
0bd03e2020-07-13Henrik Grubbström (Grubba)  { if(arg++) string_builder_strcat(s, ", ");
928bb12021-01-27Henrik Grubbström (Grubba)  if (t->car) low_describe_type(s, t->car);
0bd03e2020-07-13Henrik Grubbström (Grubba)  string_builder_strcat(s, " ..."); } t = t->cdr; string_builder_sprintf(s, " : %T)", t);
71a9672001-03-03Henrik Grubbström (Grubba)  } } break; }
13670c2015-05-25Martin Nilsson 
71a9672001-03-03Henrik Grubbström (Grubba)  case T_ARRAY:
5ee03f2020-01-10Henrik Grubbström (Grubba)  string_builder_strcat(s, "array");
3086e02022-03-03Henrik Grubbström (Grubba)  if ((t->cdr == mixed_type_string) && (t->car == int_pos_type_string)) {
5ee03f2020-01-10Henrik Grubbström (Grubba)  break;
71a9672001-03-03Henrik Grubbström (Grubba)  }
5ee03f2020-01-10Henrik Grubbström (Grubba)  string_builder_putchar(s, '(');
3086e02022-03-03Henrik Grubbström (Grubba)  if (t->car == zero_type_string) { /* Zero-length array. */ string_builder_strcat(s, "zero:"); } else { if (t->car != int_pos_type_string) {
53257b2020-01-16Henrik Grubbström (Grubba)  low_describe_int_range(s, t->car);
3086e02022-03-03Henrik Grubbström (Grubba)  string_builder_putchar(s, ':'); if (t->cdr != mixed_type_string) { string_builder_putchar(s, ' '); }
ae6b1d2021-02-14Henrik Grubbström (Grubba)  }
3086e02022-03-03Henrik Grubbström (Grubba)  if (t->cdr != mixed_type_string) { string_builder_sprintf(s, "%T", t->cdr);
ce56eb2020-01-11Henrik Grubbström (Grubba)  } }
5ee03f2020-01-10Henrik Grubbström (Grubba)  string_builder_putchar(s, ')');
71a9672001-03-03Henrik Grubbström (Grubba)  break;
13670c2015-05-25Martin Nilsson 
71a9672001-03-03Henrik Grubbström (Grubba)  case T_MULTISET:
3086e02022-03-03Henrik Grubbström (Grubba)  if(t->car != mixed_type_string) {
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "multiset(%T)", t->car); } else { string_builder_strcat(s, "multiset");
71a9672001-03-03Henrik Grubbström (Grubba)  } break;
13670c2015-05-25Martin Nilsson 
71a9672001-03-03Henrik Grubbström (Grubba)  case T_NOT:
3db3f42021-04-06Henrik Grubbström (Grubba)  if (t->car && (t->car->type > T_NOT)) {
c404c02022-04-28Henrik Grubbström (Grubba)  string_builder_sprintf(s, "~(%T)", t->car);
71a9672001-03-03Henrik Grubbström (Grubba)  } else {
c404c02022-04-28Henrik Grubbström (Grubba)  string_builder_sprintf(s, "~%T", t->car);
71a9672001-03-03Henrik Grubbström (Grubba)  } break;
ce88d62001-03-19Henrik Grubbström (Grubba)  case PIKE_T_RING: /* FIXME: Should be renumbered for correct parenthesing. */
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "(%T)\260(%T)", t->car, t->cdr);
ce88d62001-03-19Henrik Grubbström (Grubba)  break;
13670c2015-05-25Martin Nilsson 
71a9672001-03-03Henrik Grubbström (Grubba)  case T_OR:
3db3f42021-04-06Henrik Grubbström (Grubba)  if (t->car && (t->car->type > T_OR)) {
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "(%T)", t->car);
71a9672001-03-03Henrik Grubbström (Grubba)  } else {
b10e412015-10-11Henrik Grubbström (Grubba)  low_describe_type(s, t->car);
71a9672001-03-03Henrik Grubbström (Grubba)  }
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_strcat(s, " | ");
3db3f42021-04-06Henrik Grubbström (Grubba)  if (t->cdr && (t->cdr->type > T_OR)) {
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "(%T)", t->cdr);
71a9672001-03-03Henrik Grubbström (Grubba)  } else {
b10e412015-10-11Henrik Grubbström (Grubba)  low_describe_type(s, t->cdr);
71a9672001-03-03Henrik Grubbström (Grubba)  } break;
13670c2015-05-25Martin Nilsson 
71a9672001-03-03Henrik Grubbström (Grubba)  case T_AND:
3db3f42021-04-06Henrik Grubbström (Grubba)  if (t->car && (t->car->type > T_AND)) {
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "(%T)", t->car);
71a9672001-03-03Henrik Grubbström (Grubba)  } else {
b10e412015-10-11Henrik Grubbström (Grubba)  low_describe_type(s, t->car);
71a9672001-03-03Henrik Grubbström (Grubba)  }
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_strcat(s, " & ");
3db3f42021-04-06Henrik Grubbström (Grubba)  if (t->cdr && (t->cdr->type > T_AND)) {
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "(%T)", t->cdr);
71a9672001-03-03Henrik Grubbström (Grubba)  } else {
b10e412015-10-11Henrik Grubbström (Grubba)  low_describe_type(s, t->cdr);
71a9672001-03-03Henrik Grubbström (Grubba)  } break;
13670c2015-05-25Martin Nilsson 
71a9672001-03-03Henrik Grubbström (Grubba)  case T_MAPPING:
3086e02022-03-03Henrik Grubbström (Grubba)  if ((t->car != mixed_type_string) || (t->cdr != mixed_type_string)) {
b10e412015-10-11Henrik Grubbström (Grubba)  string_builder_sprintf(s, "mapping(%T:%T)", t->car, t->cdr); } else { string_builder_strcat(s, "mapping");
71a9672001-03-03Henrik Grubbström (Grubba)  } break;
3db3f42021-04-06Henrik Grubbström (Grubba) 
ec9bc12016-05-01Henrik Grubbström (Grubba)  case PIKE_T_AUTO:
3db3f42021-04-06Henrik Grubbström (Grubba)  if (t->car && (t->car->type != T_ZERO)) {
ec9bc12016-05-01Henrik Grubbström (Grubba)  string_builder_sprintf(s, "auto(%T)", t->car); } else { string_builder_strcat(s, "auto"); } break;
0a3d9f2020-07-18Henrik Grubbström (Grubba)  case PIKE_T_FIND_LFUN: string_builder_sprintf(s, "find_lfun(%T, \"%S\")", t->car, lfun_strings[CDR_TO_INT(t)]); break;
5fc9642020-08-17Henrik Grubbström (Grubba)  case PIKE_T_TRANSITIVE: string_builder_sprintf(s, "transitive(%T, %T)", t->car, t->cdr); break;
71a9672001-03-03Henrik Grubbström (Grubba)  default: {
9e5e9b2020-09-16Henrik Grubbström (Grubba)  if ((t->type & PIKE_T_MASK) == PIKE_T_OPERATOR) {
5745e22021-07-04Henrik Grubbström (Grubba)  switch(t->type) {
92a3912021-11-27Henrik Grubbström (Grubba)  case PIKE_T_GET_RETURN: string_builder_strcat(s, "get_return"); break;
5745e22021-07-04Henrik Grubbström (Grubba)  case PIKE_T_SET_CAR: string_builder_strcat(s, "set_car"); break; case PIKE_T_SET_CDR: string_builder_strcat(s, "set_cdr"); break; default: string_builder_sprintf(s, "operator(0x%04x)", t->type); break; } string_builder_sprintf(s, "(%T", t->car);
d79bff2020-07-17Henrik Grubbström (Grubba)  if (t->type & 0x8000) { string_builder_sprintf(s, ",%T)", t->cdr); } else if (t->cdr) { string_builder_sprintf(s, ",0x%08lx)", CDR_TO_INT(t)); } else { string_builder_strcat(s, ")"); } } else { string_builder_sprintf(s, "unknown code(%d)", t->type); }
71a9672001-03-03Henrik Grubbström (Grubba)  break; } } } struct pike_string *describe_type(struct pike_type *type) {
b10e412015-10-11Henrik Grubbström (Grubba)  struct string_builder s; ONERROR err;
71a9672001-03-03Henrik Grubbström (Grubba)  if(!type) return make_shared_string("mixed");
b10e412015-10-11Henrik Grubbström (Grubba)  init_string_builder(&s, 0); SET_ONERROR(err, free_string_builder, &s); low_describe_type(&s, type); UNSET_ONERROR(err); return finish_string_builder(&s);
71a9672001-03-03Henrik Grubbström (Grubba) } /******/
1a85d12021-06-10Henrik Grubbström (Grubba) static TYPE_T low_compile_type_to_runtime_type(struct pike_type *t)
71a9672001-03-03Henrik Grubbström (Grubba) {
1a85d12021-06-10Henrik Grubbström (Grubba)  switch(t?t->type:PIKE_T_UNKNOWN) /* Note: No masking here. */
71a9672001-03-03Henrik Grubbström (Grubba)  {
ce88d62001-03-19Henrik Grubbström (Grubba)  case PIKE_T_RING:
5745e22021-07-04Henrik Grubbström (Grubba)  case PIKE_T_SET_CAR: case PIKE_T_SET_CDR:
1a85d12021-06-10Henrik Grubbström (Grubba)  return low_compile_type_to_runtime_type(t->car);
ce88d62001-03-19Henrik Grubbström (Grubba) 
71a9672001-03-03Henrik Grubbström (Grubba)  case T_OR: {
1a85d12021-06-10Henrik Grubbström (Grubba)  TYPE_T car_t = low_compile_type_to_runtime_type(t->car); TYPE_T cdr_t = low_compile_type_to_runtime_type(t->cdr);
8daadf2021-06-10Henrik Grubbström (Grubba)  if (car_t == cdr_t)
1a85d12021-06-10Henrik Grubbström (Grubba)  return car_t; if (car_t == PIKE_T_VOID) { car_t = PIKE_T_ZERO; } if (cdr_t == PIKE_T_VOID) { cdr_t = PIKE_T_ZERO; } if ((car_t == PIKE_T_ZERO) && (cdr_t != PIKE_T_FLOAT)) { return cdr_t; } if ((cdr_t == PIKE_T_ZERO) && (car_t != PIKE_T_FLOAT)) { return car_t; }
71a9672001-03-03Henrik Grubbström (Grubba)  }
5f50842018-02-12Marcus Comstedt  /* FALLTHRU */
71a9672001-03-03Henrik Grubbström (Grubba)  case T_TUPLE: /* FIXME: Shouldn't occur/should be converted to array? */
5f50842018-02-12Marcus Comstedt  /* FALLTHRU */
71a9672001-03-03Henrik Grubbström (Grubba)  default: return T_MIXED; case T_SCOPE:
f62c412001-03-05Henrik Grubbström (Grubba)  case PIKE_T_NAME:
9129122007-04-21Henrik Grubbström (Grubba)  case PIKE_T_ATTRIBUTE:
1a85d12021-06-10Henrik Grubbström (Grubba)  return low_compile_type_to_runtime_type(t->cdr);
71a9672001-03-03Henrik Grubbström (Grubba)  case T_MANY:
0a3d9f2020-07-18Henrik Grubbström (Grubba)  case PIKE_T_FIND_LFUN:
71a9672001-03-03Henrik Grubbström (Grubba)  return T_FUNCTION; case T_ARRAY: case T_MAPPING: case T_MULTISET: case T_OBJECT: case T_PROGRAM: case T_FUNCTION:
13670c2015-05-25Martin Nilsson 
71a9672001-03-03Henrik Grubbström (Grubba)  case T_STRING: case T_TYPE: case T_INT: case T_FLOAT:
1a85d12021-06-10Henrik Grubbström (Grubba)  case T_ZERO: case T_VOID:
71a9672001-03-03Henrik Grubbström (Grubba)  return t->type; } }
1a85d12021-06-10Henrik Grubbström (Grubba) TYPE_T compile_type_to_runtime_type(struct pike_type *t) { TYPE_T ret = low_compile_type_to_runtime_type(t); if ((ret == PIKE_T_ZERO) || (ret == PIKE_T_VOID)) { return PIKE_T_INT; } return ret; }
fe607e2019-04-09Henrik Grubbström (Grubba) /** * Check whether a type is for a __deprecated__ value. * * @param t * Type to check. */ int deprecated_typep(struct pike_type *t) { struct pike_string *deprecated_string; MAKE_CONST_STRING(deprecated_string, "deprecated"); while (t) {
9e5e9b2020-09-16Henrik Grubbström (Grubba)  switch(t->type & PIKE_T_MASK) {
fe607e2019-04-09Henrik Grubbström (Grubba)  case PIKE_T_ATTRIBUTE: if (((struct pike_string*)t->car) == deprecated_string) { return 1; } /* FALLTHRU */ case PIKE_T_SCOPE: case T_ASSIGN: case PIKE_T_NAME: t = t->cdr; continue;
d79bff2020-07-17Henrik Grubbström (Grubba)  case PIKE_T_OPERATOR:
5fc9642020-08-17Henrik Grubbström (Grubba)  case PIKE_T_TRANSITIVE:
d79bff2020-07-17Henrik Grubbström (Grubba)  t = t->car; continue;
fe607e2019-04-09Henrik Grubbström (Grubba)  } break; } return 0; }
8ea4b12022-03-20Henrik Grubbström (Grubba) /** * Get the range for an integer type. * * @param t * Integer type to check. * * @param range * Array of two elements (min, max) before calling the * function, the array should be initialized to (max, min). * * Returns 1 if t contained an integer type. This also implies * that range has been updated accordingly. * * Returns 0 if t did not contain any integer type. The range * array will be left unmodified in this case. */
a570c52016-06-13Henrik Grubbström (Grubba) int get_int_type_range(struct pike_type *t, INT_TYPE *range) { int ret = 0; loop:
8ea4b12022-03-20Henrik Grubbström (Grubba)  switch(t?t->type:PIKE_T_UNKNOWN) {
a570c52016-06-13Henrik Grubbström (Grubba)  case T_INT: { INT_TYPE min = CAR_TO_INT(t); INT_TYPE max = CDR_TO_INT(t); if (range[0] > min) range[0] = min; if (range[1] < max) range[1] = max; return 1; } break; case T_ZERO: case T_VOID: if (range[0] > 0) range[0] = 0; if (range[1] < 0) range[1] = 0; return 1; case T_SCOPE: case T_ASSIGN: case PIKE_T_NAME: case PIKE_T_ATTRIBUTE: t = t->cdr; goto loop; case T_OR: case T_AND:
503d5e2021-12-14Henrik Grubbström (Grubba)  ret = ret | get_int_type_range(t->car, range);
a570c52016-06-13Henrik Grubbström (Grubba)  t = t->cdr; goto loop;
76b6e02022-02-20Henrik Grubbström (Grubba)  case T_MIXED:
8ea4b12022-03-20Henrik Grubbström (Grubba)  t = int_type_string; goto loop;
a570c52016-06-13Henrik Grubbström (Grubba)  default: break; } return ret; }
641a3f2007-04-16Henrik Grubbström (Grubba) static void low_or_pike_types(struct pike_type *t1, struct pike_type *t2, int zero_implied); /* Push either t1, t2 or the OR of t1 and t2. * Returns -1 if t1 was pushed. * 0 if the OR was pushed. (Successful join) * 1 if t2 was pushed.
2a61e82011-03-24Henrik Grubbström (Grubba)  * * zero_implied: One of: * 0 the zero type (if any) must be explicit in the result. * 1 the zero type is implicit. * 3 zero is implicit and integers are regarded as masks (cf enums).
641a3f2007-04-16Henrik Grubbström (Grubba)  */ static int lower_or_pike_types(struct pike_type *t1, struct pike_type *t2,
1a82092007-04-17Henrik Grubbström (Grubba)  int zero_implied, int elem_on_stack)
641a3f2007-04-16Henrik Grubbström (Grubba) {
1a82092007-04-17Henrik Grubbström (Grubba)  int ret = 0; struct pike_type *t = NULL; struct pike_type *top = NULL;
641a3f2007-04-16Henrik Grubbström (Grubba) #if 0 fprintf(stderr, " lower_or_pike_types("); simple_describe_type(t1); fprintf(stderr, ", "); simple_describe_type(t2); fprintf(stderr, ")\n"); #endif if (t1 == t2) {
1a82092007-04-17Henrik Grubbström (Grubba)  t = t1;
790d032007-05-09Henrik Grubbström (Grubba)  } else if (!t1) { t = t2; ret = 1; } else if (!t2) { t = t1; ret = -1;
2631f82007-05-07Henrik Grubbström (Grubba)  } else if (zero_implied && (t1->type == T_ZERO)) { t = t2; } else if (zero_implied && (t2->type == T_ZERO)) { t = t1;
ff85722021-03-22Henrik Grubbström (Grubba)  } else if ((t1->type == T_NOT) && pike_types_le(t1->car, t2, 0, 0)) {
739c8b2020-07-15Henrik Grubbström (Grubba)  t = mixed_type_string;
ff85722021-03-22Henrik Grubbström (Grubba)  } else if ((t2->type == T_NOT) && pike_types_le(t2->car, t1, 0, 0)) {
739c8b2020-07-15Henrik Grubbström (Grubba)  t = mixed_type_string;
790d032007-05-09Henrik Grubbström (Grubba)  } else if ((t1->type ^ '0') < (t2->type ^ '0')) { /* Note: Adjusted order to get markers first. */
1a82092007-04-17Henrik Grubbström (Grubba)  t = t1; ret = -1;
790d032007-05-09Henrik Grubbström (Grubba)  } else if ((t1->type ^ '0') > (t2->type ^ '0')) { /* Note: Adjusted order to get markers first. */
1a82092007-04-17Henrik Grubbström (Grubba)  t = t2; ret = 1;
641a3f2007-04-16Henrik Grubbström (Grubba)  } else { #ifdef PIKE_DEBUG if (t1->type != t2->type) { Pike_fatal("Lost track of types t1->type: %d, t2->type: %d\n", t1->type, t2->type); } #endif /* PIKE_DEBUG */ switch(t1->type) { case T_INT:
1a82092007-04-17Henrik Grubbström (Grubba)  if (CAR_TO_INT(t1) < CAR_TO_INT(t2)) { t = t1; ret = -1; } else { t = t2; ret = 1; } break; case T_STRING:
641a3f2007-04-16Henrik Grubbström (Grubba)  {
d5a7dc2019-12-16Henrik Grubbström (Grubba)  low_or_pike_types(t1->cdr, t2->cdr, 1);
04017d2020-01-02Henrik Grubbström (Grubba)  push_unlimited_array_type(T_STRING);
4e6c082007-05-02Henrik Grubbström (Grubba)  return 0;
1a82092007-04-17Henrik Grubbström (Grubba)  } break; case T_OBJECT: if (!CDR_TO_INT(t1)) { t = t1; } else if (!CDR_TO_INT(t2)) { t = t2; } else if (CDR_TO_INT(t1) < CDR_TO_INT(t2)) { t = t1; ret = -1; } else { t = t2; ret = 1; } break; case T_MAPPING:
3be0112021-02-20Henrik Grubbström (Grubba)  if (!t1->car) { t = t1; ret = -1; break; } if (!t2->car) { t = t2; ret = 1; break; }
1a82092007-04-17Henrik Grubbström (Grubba)  if (t1->car->type < t2->car->type) { t = t1; ret = -1; break; } if (t1->car->type > t2->car->type) { t = t2; ret = 1; break; }
3be0112021-02-20Henrik Grubbström (Grubba)  if (!t1->cdr) { t = t1; ret = -1; break; } if (!t2->cdr) { t = t2; ret = 1; break; }
1a82092007-04-17Henrik Grubbström (Grubba)  if (t1->cdr->type < t2->cdr->type) { t = t1; ret = -1; break; } if (t1->cdr->type > t2->cdr->type) { t = t2; ret = 1; break; } t = t1; ret = -1; break; case T_ARRAY:
3be0112021-02-20Henrik Grubbström (Grubba)  if (!t1->cdr) { if (!t2->cdr) { /* Probably not reached as t1 and t2 ought to be equal. */ t = t1; ret = 0; break; } t = t1; ret = -1; break; } if (!t2->cdr) { t = t2; ret = 1; break; }
d5a7dc2019-12-16Henrik Grubbström (Grubba)  if (t1->cdr->type < t2->cdr->type) { t = t1; ret = -1; break; } else if (t1->cdr->type > t2->cdr->type) { t = t2; ret = 1; break; } if (t1 < t2) { t = t1; ret = -1; } else { t = t2; ret = 1; } break;
1a82092007-04-17Henrik Grubbström (Grubba)  case T_MULTISET:
3be0112021-02-20Henrik Grubbström (Grubba)  if (!t1->car) { if (!t2->car) { t = t1; ret = 0; break; } t = t1; ret = -1; break; } if (!t2->car) { t = t2; ret = 1; break; }
1a82092007-04-17Henrik Grubbström (Grubba)  if (t1->car->type < t2->car->type) { t = t1; ret = -1; break; } else if (t1->car->type > t2->car->type) { t = t2; ret = 1; break; }
5f50842018-02-12Marcus Comstedt  /* FALLTHRU */
1a82092007-04-17Henrik Grubbström (Grubba)  default:
790d032007-05-09Henrik Grubbström (Grubba) #if 0
ff85722021-03-22Henrik Grubbström (Grubba)  if (pike_types_le(t1, t2, 0, 0)) {
790d032007-05-09Henrik Grubbström (Grubba)  t = t2;
ff85722021-03-22Henrik Grubbström (Grubba)  } else if (pike_types_le(t2, t1, 0, 0)) {
790d032007-05-09Henrik Grubbström (Grubba)  t = t1; } else #endif /* 0 */ if (t1 < t2) { t = t1; ret = -1; } else { t = t2; ret = 1; }
1a82092007-04-17Henrik Grubbström (Grubba)  break; } }
2631f82007-05-07Henrik Grubbström (Grubba)  if (!elem_on_stack) {
efd38b2016-02-24Henrik Grubbström (Grubba)  if (t) { push_finished_type(t); } else {
57a5b22021-06-09Henrik Grubbström (Grubba)  push_type(PIKE_T_UNKNOWN);
efd38b2016-02-24Henrik Grubbström (Grubba)  } } else if (!t) { /* No need to do anything. */
2631f82007-05-07Henrik Grubbström (Grubba)  } else if ((top = peek_type_stack())->type != t->type) { if (zero_implied && (top->type == T_ZERO)) { Pike_compiler->type_stackp--; free_type(top); push_finished_type(t); } else if (zero_implied && (t->type == T_ZERO)) { /* The zero is implied. */ } else { push_finished_type(t); }
790d032007-05-09Henrik Grubbström (Grubba)  } else if (t == top) { /* No need to do anything. */
1a82092007-04-17Henrik Grubbström (Grubba)  } else {
57a5b22021-06-09Henrik Grubbström (Grubba)  switch(t?t->type:PIKE_T_UNKNOWN) {
1a82092007-04-17Henrik Grubbström (Grubba)  case T_FLOAT:
9e66382007-04-18Henrik Grubbström (Grubba)  case T_MIXED: case T_VOID: case T_ZERO:
1a82092007-04-17Henrik Grubbström (Grubba)  /* There can only be one. */ break; case T_INT: { INT32 min1 = CAR_TO_INT(t); INT32 max1 = CDR_TO_INT(t); INT32 min2 = CAR_TO_INT(top); INT32 max2 = CDR_TO_INT(top);
641a3f2007-04-16Henrik Grubbström (Grubba)  if (zero_implied) { if (min1 == 1) min1 = 0; if (min2 == 1) min2 = 0; if (max1 == -1) max1 = 0; if (max2 == -1) max2 = 0;
2a61e82011-03-24Henrik Grubbström (Grubba)  if (zero_implied == 3) { /* Or between integer masks. * This is a bit more lenient than the default further below, * and is used for generating the type for enums. */
1609542011-03-25Henrik Grubbström (Grubba)  /* Ensure that zero is always in the range. * This also ensures that there'll be an overlap. */ if (max1 < 0) max1 = 0;
2a61e82011-03-24Henrik Grubbström (Grubba)  if (max2 < 0) max2 = 0;
1609542011-03-25Henrik Grubbström (Grubba)  if (min1 > 0) min1 = 0;
2a61e82011-03-24Henrik Grubbström (Grubba)  if (min2 > 0) min2 = 0;
1609542011-03-25Henrik Grubbström (Grubba)  /* Both max values are now >= 0, so this or is safe. */ max1 |= max2; if ((min1 < 0) && (min2 < 0)) { min1 &= min2; }
2a61e82011-03-24Henrik Grubbström (Grubba)  }
641a3f2007-04-16Henrik Grubbström (Grubba)  }
2a61e82011-03-24Henrik Grubbström (Grubba) 
2a5cf02021-09-15Marcus Comstedt  if ((max2 < MAX_INT32) && (min1 > max2 + 1)) {
641a3f2007-04-16Henrik Grubbström (Grubba)  /* No overlap. */
1a82092007-04-17Henrik Grubbström (Grubba)  push_finished_type(t); #ifdef PIKE_DEBUG
2a5cf02021-09-15Marcus Comstedt  } else if ((max1 < MAX_INT32) && (min2 > max1 + 1)) {
1a82092007-04-17Henrik Grubbström (Grubba)  /* No overlap and wrong order! */ Pike_fatal("Bad integer ordering in lower_or_pike_types().\n"); #endif
641a3f2007-04-16Henrik Grubbström (Grubba)  } else {
1a82092007-04-17Henrik Grubbström (Grubba)  Pike_compiler->type_stackp--; free_type(top);
641a3f2007-04-16Henrik Grubbström (Grubba)  /* Overlap */ min1 = MINIMUM(min1, min2); max1 = MAXIMUM(max1, max2); push_int_type(min1, max1); } } break; case T_STRING: {
4e6c082007-05-02Henrik Grubbström (Grubba)  Pike_compiler->type_stackp--;
d5a7dc2019-12-16Henrik Grubbström (Grubba)  low_or_pike_types(t->cdr, top->cdr, 1);
04017d2020-01-02Henrik Grubbström (Grubba)  push_unlimited_array_type(T_STRING);
4e6c082007-05-02Henrik Grubbström (Grubba)  free_type(top);
641a3f2007-04-16Henrik Grubbström (Grubba)  }
1a82092007-04-17Henrik Grubbström (Grubba)  break; case T_OBJECT: if (CDR_TO_INT(top)) { push_finished_type(t); } break;
641a3f2007-04-16Henrik Grubbström (Grubba)  case T_ARRAY:
d5a7dc2019-12-16Henrik Grubbström (Grubba)  Pike_compiler->type_stackp--; low_or_pike_types(t->cdr, top->cdr, zero_implied);
04017d2020-01-02Henrik Grubbström (Grubba)  push_unlimited_array_type(t->type);
d5a7dc2019-12-16Henrik Grubbström (Grubba)  free_type(top); break;
641a3f2007-04-16Henrik Grubbström (Grubba)  case T_MULTISET:
1a82092007-04-17Henrik Grubbström (Grubba)  Pike_compiler->type_stackp--; low_or_pike_types(t->car, top->car, zero_implied); push_type(t->type); free_type(top); break;
641a3f2007-04-16Henrik Grubbström (Grubba)  case T_MAPPING:
1a82092007-04-17Henrik Grubbström (Grubba)  if (t->car == top->car) { Pike_compiler->type_stackp--; push_finished_type(t->car); low_or_pike_types(t->cdr, top->cdr, zero_implied);
641a3f2007-04-16Henrik Grubbström (Grubba)  push_reverse_type(T_MAPPING);
1a82092007-04-17Henrik Grubbström (Grubba)  free_type(top); break; } else if (t->cdr == top->cdr) { Pike_compiler->type_stackp--; push_finished_type(t->cdr); low_or_pike_types(t->car, top->car, zero_implied);
641a3f2007-04-16Henrik Grubbström (Grubba)  push_type(T_MAPPING);
1a82092007-04-17Henrik Grubbström (Grubba)  free_type(top); break;
641a3f2007-04-16Henrik Grubbström (Grubba)  }
5f50842018-02-12Marcus Comstedt  /* FALLTHRU */
641a3f2007-04-16Henrik Grubbström (Grubba)  default:
790d032007-05-09Henrik Grubbström (Grubba)  if (t < top) { Pike_compiler->type_stackp--; push_finished_type(t); push_finished_type(top); free_type(top); } else { push_finished_type(t); }
1a82092007-04-17Henrik Grubbström (Grubba)  break;
641a3f2007-04-16Henrik Grubbström (Grubba)  } }
1a82092007-04-17Henrik Grubbström (Grubba)  return ret;
641a3f2007-04-16Henrik Grubbström (Grubba) }
71a9672001-03-03Henrik Grubbström (Grubba) static void low_or_pike_types(struct pike_type *t1, struct pike_type *t2, int zero_implied) {
641a3f2007-04-16Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG struct pike_type *arg1 = t1; struct pike_type *arg2 = t2; #endif
57a5b22021-06-09Henrik Grubbström (Grubba)  check_c_stack(1024);
641a3f2007-04-16Henrik Grubbström (Grubba) #if 0 fprintf(stderr, " low_or_pike_types("); simple_describe_type(t1); fprintf(stderr, ", "); simple_describe_type(t2); fprintf(stderr, ")\n"); #endif
71a9672001-03-03Henrik Grubbström (Grubba)  if(!t1) {
dc150a2022-02-19Henrik Grubbström (Grubba)  push_finished_type(t2);
71a9672001-03-03Henrik Grubbström (Grubba)  }
0926472022-02-23Henrik Grubbström (Grubba)  else if((!t2) || ((t2->type == T_ZERO) && (zero_implied || (t1->flags & PT_FLAG_NULLABLE)))) {
71a9672001-03-03Henrik Grubbström (Grubba)  push_finished_type(t1); }
0926472022-02-23Henrik Grubbström (Grubba)  else if ((t1->type == T_ZERO) && (zero_implied || (t2->flags & PT_FLAG_NULLABLE))) {
71a9672001-03-03Henrik Grubbström (Grubba)  push_finished_type(t2); }
9f194c2007-04-01Henrik Grubbström (Grubba)  else if (t1 == t2) { push_finished_type(t1); }
0926472022-02-23Henrik Grubbström (Grubba)  else if ((t1->flags & (PT_FLAG_MIXED|PT_FLAG_VOIDABLE)) == (PT_FLAG_MIXED|PT_FLAG_VOIDABLE)) { push_finished_type(t1); } else if ((t2->flags & (PT_FLAG_MIXED|PT_FLAG_VOIDABLE)) == (PT_FLAG_MIXED|PT_FLAG_VOIDABLE)) { push_finished_type(t2); }
dc150a2022-02-19Henrik Grubbström (Grubba)  else if ((t1->type == T_MIXED) && (t2->type != T_VOID)) { push_finished_type(t1); if (t2->flags & PT_FLAG_VOIDABLE) { push_type(T_VOID); push_type(T_OR); } } else if ((t2->type == T_MIXED) && (t1->type != T_VOID)) { push_finished_type(t2); if (t1->flags & PT_FLAG_VOIDABLE) { push_type(T_VOID); push_type(T_OR); } }
790d032007-05-09Henrik Grubbström (Grubba)  else if ((t1->type == T_OR) || (t2->type == T_OR)) {
1a82092007-04-17Henrik Grubbström (Grubba)  int on_stack = 0; type_stack_mark();
641a3f2007-04-16Henrik Grubbström (Grubba)  while (t1 || t2) {
790d032007-05-09Henrik Grubbström (Grubba)  struct pike_type *a = t1; struct pike_type *b = t2; struct pike_type *n1 = NULL; struct pike_type *n2 = NULL; int val; if (t1 && t1->type == T_OR) { a = t1->car; n1 = t1->cdr; } if (t2 && t2->type == T_OR) { b = t2->car; n2 = t2->cdr; }
641a3f2007-04-16Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG
790d032007-05-09Henrik Grubbström (Grubba)  if (a && b && ((a->type == T_OR) || (b->type == T_OR))) { fprintf(stderr, " low_or_pike_types("); simple_describe_type(arg1); fprintf(stderr, ", "); simple_describe_type(arg2); fprintf(stderr, ")\n a:"); simple_describe_type(a); fprintf(stderr, "\n b:"); simple_describe_type(b); fprintf(stderr, ")\n"); Pike_fatal("Invalid type to lower_or_pike_types!\n");
641a3f2007-04-16Henrik Grubbström (Grubba)  }
790d032007-05-09Henrik Grubbström (Grubba) #endif val = lower_or_pike_types(a, b, zero_implied, on_stack); if (val <= 0) t1 = n1; if (val >= 0) t2 = n2;
1a82092007-04-17Henrik Grubbström (Grubba)  on_stack = 1;
641a3f2007-04-16Henrik Grubbström (Grubba)  }
1a82092007-04-17Henrik Grubbström (Grubba)  on_stack = pop_stack_mark(); while (on_stack > 1) {
641a3f2007-04-16Henrik Grubbström (Grubba)  push_reverse_joiner_type(T_OR);
1a82092007-04-17Henrik Grubbström (Grubba)  on_stack--;
641a3f2007-04-16Henrik Grubbström (Grubba)  }
9f194c2007-04-01Henrik Grubbström (Grubba)  }
641a3f2007-04-16Henrik Grubbström (Grubba)  else {
64ac752007-11-03Henrik Grubbström (Grubba)  int val; type_stack_mark(); val = lower_or_pike_types(t1, t2, zero_implied, 0);
641a3f2007-04-16Henrik Grubbström (Grubba)  if (val < 0) {
64ac752007-11-03Henrik Grubbström (Grubba)  lower_or_pike_types(NULL, t2, zero_implied, 1);
641a3f2007-04-16Henrik Grubbström (Grubba)  } else if (val > 0) {
64ac752007-11-03Henrik Grubbström (Grubba)  lower_or_pike_types(t1, NULL, zero_implied, 1); } else { pop_stack_mark(); return; } for (val = pop_stack_mark(); val > 1; val--) {
641a3f2007-04-16Henrik Grubbström (Grubba)  push_reverse_joiner_type(T_OR);
71a9672001-03-03Henrik Grubbström (Grubba)  } } } struct pike_type *or_pike_types(struct pike_type *a, struct pike_type *b, int zero_implied) {
641a3f2007-04-16Henrik Grubbström (Grubba)  struct pike_type *res;
71a9672001-03-03Henrik Grubbström (Grubba)  type_stack_mark();
a609412011-03-24Henrik Grubbström (Grubba)  low_or_pike_types(a,b,1|zero_implied);
641a3f2007-04-16Henrik Grubbström (Grubba)  res = pop_unfinished_type(); #if 0 fprintf(stderr, " ==> "); simple_describe_type(res); fprintf(stderr, "\n"); #endif return res;
71a9672001-03-03Henrik Grubbström (Grubba) } struct pike_type *and_pike_types(struct pike_type *a, struct pike_type *b) {
0679682022-04-12Henrik Grubbström (Grubba)  return type_binop(PT_BINOP_AND, a, b, 0, 0, 0);
71a9672001-03-03Henrik Grubbström (Grubba) } static struct pike_type *low_object_lfun_type(struct pike_type *t, short lfun) { struct program *p; int i;
ff72752007-11-15Henrik Grubbström (Grubba)  while ((t->type == PIKE_T_NAME) || (t->type == PIKE_T_ATTRIBUTE)) { t = t->cdr; } #ifdef PIKE_DEBUG if (t->type != T_OBJECT) { fprintf(stderr, "Invalid type to low_object_lfun_type("); simple_describe_type(t); fprintf(stderr, ", \"%s\")\n", lfun_names[lfun]); Pike_fatal("Invalid type to low_object_lfun_type: %d (expected OBJECT).\n", t->type); } #endif /* PIKE_DEBUG */
d2361e2003-06-30Martin Stjernholm  p = id_to_program(CDR_TO_INT(t));
71a9672001-03-03Henrik Grubbström (Grubba)  if(!p) return 0; i=FIND_LFUN(p, lfun); if(i==-1) return 0; return ID_FROM_INT(p, i)->type; }
0a3d9f2020-07-18Henrik Grubbström (Grubba) /** * This function differs from low_object_lfun_type() above in * that it handles more cases, falls back to the default lfun * type (with a warning), and adds a reference to the returned * type. */ static struct pike_type *find_lfun_type(struct pike_type *t, int lfun) { struct pike_type *ret = NULL;
4df34c2021-12-03Henrik Grubbström (Grubba)  struct pike_type *tmp;
0a3d9f2020-07-18Henrik Grubbström (Grubba)  struct svalue *s;
7a67cf2022-03-07Henrik Grubbström (Grubba)  loop:
0a3d9f2020-07-18Henrik Grubbström (Grubba)  if (!t) return NULL; switch(t->type) { case PIKE_T_NAME: case PIKE_T_ATTRIBUTE: t = t->cdr; goto loop; case T_OBJECT: { struct program *p = NULL; if (t->cdr) { p = id_to_program(CDR_TO_INT(t)); } if (p) { int f = FIND_LFUN(p, lfun); if (f != -1) { struct identifier *id = ID_FROM_INT(p, f); ret = id->type; add_ref(ret); return ret; }
03fc172021-12-01Henrik Grubbström (Grubba) #if 0
6674e42021-12-02Henrik Grubbström (Grubba)  ref_push_string(lfun_strings[lfun]);
0a3d9f2020-07-18Henrik Grubbström (Grubba)  yytype_report(REPORT_WARNING, NULL, 0, NULL, NULL, 0, t,
1247b72020-08-15Henrik Grubbström (Grubba)  1, "Expected object implementing lfun::%s().");
03fc172021-12-01Henrik Grubbström (Grubba) #endif
6674e42021-12-02Henrik Grubbström (Grubba)  return NULL;
0a3d9f2020-07-18Henrik Grubbström (Grubba)  } break; } case T_PROGRAM: t = t->car; goto loop; case T_FUNCTION: case T_MANY: t = t->cdr; goto loop; case T_OR: case T_AND:
4df34c2021-12-03Henrik Grubbström (Grubba)  ret = find_lfun_type(t->car, lfun); tmp = find_lfun_type(t->cdr, lfun); if (!ret) { if (!tmp) return NULL; if (t->type == T_AND) { free_type(tmp); } else { ret = tmp; } } else if (tmp) { type_stack_mark(); push_finished_type(ret); free_type(ret); push_finished_type(tmp); free_type(tmp); push_type(t->type); return pop_unfinished_type(); } return ret;
0a3d9f2020-07-18Henrik Grubbström (Grubba)  case T_MIXED: break;
5e69d02022-03-31Henrik Grubbström (Grubba)  case T_ZERO: case T_VOID:
0a3d9f2020-07-18Henrik Grubbström (Grubba)  default:
5e69d02022-03-31Henrik Grubbström (Grubba)  return NULL;
0a3d9f2020-07-18Henrik Grubbström (Grubba)  } #if 0 /* FIXME: This does not work, as lfun_types contains narrow types * (zero for arguments, etc), while we here want the wide type * (mixed for arguments, etc). */ s = low_mapping_string_lookup(lfun_types, lfun_strings[lfun]); #ifdef PIKE_DEBUG if (!s) { Pike_fatal("Unknown lfun: %s\n", STR0(lfun_strings[lfun])); } #endif if (TYPEOF(*s) == PIKE_T_TYPE) { ret = s->u.type; add_ref(ret); return ret; } return NULL; #else add_ref(function_type_string); return function_type_string; #endif }
71a9672001-03-03Henrik Grubbström (Grubba)  /******/
bdaf7f2020-09-18Henrik Grubbström (Grubba) struct remap_state { unsigned char map[0x20]; unsigned INT32 allocated;
fda6742022-04-08Henrik Grubbström (Grubba)  struct mapping *markers[2];
bdaf7f2020-09-18Henrik Grubbström (Grubba) };
c97a452021-12-17Henrik Grubbström (Grubba) #ifdef PIKE_NULL_IS_SPECIAL #define INIT_REMAP_STATE(REMAP) do { \ memset(&REMAP, 0, sizeof(struct remap_state)); \
fda6742022-04-08Henrik Grubbström (Grubba)  REMAP.markers[0] = NULL; \ REMAP.markers[1] = NULL; \
c97a452021-12-17Henrik Grubbström (Grubba)  } while(0) #else #define INIT_REMAP_STATE(REMAP) do { \ memset(&REMAP, 0, sizeof(struct remap_state)); \ } while(0) #endif static inline void exit_remap_state(struct remap_state *remap) {
fda6742022-04-08Henrik Grubbström (Grubba)  if (remap && remap->markers[0]) { free_mapping(remap->markers[0]); remap->markers[0] = NULL; } if (remap && remap->markers[1]) { free_mapping(remap->markers[1]); remap->markers[1] = NULL;
c97a452021-12-17Henrik Grubbström (Grubba)  } } #define EXIT_REMAP_STATE(REMAP) exit_remap_state(&REMAP)
eaf18d2020-09-26Henrik Grubbström (Grubba) static int alloc_remap_marker(struct remap_state *remap, int marker, enum pt_remap_flags flags)
bdaf7f2020-09-18Henrik Grubbström (Grubba) { int ret;
0240eb2020-09-29Henrik Grubbström (Grubba)  marker = marker & 0x0f;
bdaf7f2020-09-18Henrik Grubbström (Grubba) 
b383342021-11-14Henrik Grubbström (Grubba)  if (!remap || (flags & PT_FLAG_REMAP_INHIBIT)) return '0' | marker;
3eb8912020-09-21Henrik Grubbström (Grubba) 
0240eb2020-09-29Henrik Grubbström (Grubba)  if (flags & PT_FLAG_REMAP_SWAP_MARKERS) marker |= 0x10; if ((ret = remap->map[marker])) return ret;
bdaf7f2020-09-18Henrik Grubbström (Grubba) 
3eb8912020-09-21Henrik Grubbström (Grubba)  for (ret = 0; ret < 10; ret++) { if (!(remap->allocated & (1 << ret))) { remap->allocated |= (1 << ret); ret |= '0';
0240eb2020-09-29Henrik Grubbström (Grubba)  remap->map[marker] = ret;
3eb8912020-09-21Henrik Grubbström (Grubba)  return ret; } } return 0; }
eaf18d2020-09-26Henrik Grubbström (Grubba) static int remap_marker(struct remap_state *remap, int marker, enum pt_remap_flags flags)
3eb8912020-09-21Henrik Grubbström (Grubba) { int ret;
0240eb2020-09-29Henrik Grubbström (Grubba)  marker = marker & 0x0f;
b383342021-11-14Henrik Grubbström (Grubba)  if (!remap || (flags & PT_FLAG_REMAP_INHIBIT)) return '0' | marker;
3eb8912020-09-21Henrik Grubbström (Grubba) 
0240eb2020-09-29Henrik Grubbström (Grubba)  if (flags & PT_FLAG_REMAP_SWAP_MARKERS) marker |= 0x10;
3eb8912020-09-21Henrik Grubbström (Grubba) 
0240eb2020-09-29Henrik Grubbström (Grubba)  if ((ret = remap->map[marker])) return ret;
bdaf7f2020-09-18Henrik Grubbström (Grubba)  for (ret = 0; ret < 10; ret++) { if (!(remap->allocated & (1 << ret))) { remap->allocated |= (1 << ret); ret |= '0';
0240eb2020-09-29Henrik Grubbström (Grubba)  remap->map[marker] = ret;
bdaf7f2020-09-18Henrik Grubbström (Grubba)  return ret; } } return 0; }
eaf18d2020-09-26Henrik Grubbström (Grubba) static void free_marker(struct remap_state *remap, int marker, enum pt_remap_flags flags)
bdaf7f2020-09-18Henrik Grubbström (Grubba) { int m;
b383342021-11-14Henrik Grubbström (Grubba)  if (!remap || (flags & PT_FLAG_REMAP_INHIBIT)) return;
bdaf7f2020-09-18Henrik Grubbström (Grubba) 
0240eb2020-09-29Henrik Grubbström (Grubba)  marker &= 0x0f; if (flags & PT_FLAG_REMAP_SWAP_MARKERS) marker |= 0x10;
eaf18d2020-09-26Henrik Grubbström (Grubba) 
0240eb2020-09-29Henrik Grubbström (Grubba)  if (!(m = remap->map[marker])) return;
bdaf7f2020-09-18Henrik Grubbström (Grubba) 
0240eb2020-09-29Henrik Grubbström (Grubba)  remap->map[marker] = 0;
bdaf7f2020-09-18Henrik Grubbström (Grubba)  remap->allocated &= ~(1 << (m & 0x0f)); }
fda6742022-04-08Henrik Grubbström (Grubba) static int lookup_marker(struct remap_state *remap, int marker, enum pt_remap_flags flags, struct pike_type **result_type)
003e122020-10-05Henrik Grubbström (Grubba) {
fda6742022-04-08Henrik Grubbström (Grubba)  struct svalue key, *val = NULL; int marker_set = !!(flags & PT_FLAG_REMAP_SWAP_MARKERS);
003e122020-10-05Henrik Grubbström (Grubba) 
fda6742022-04-08Henrik Grubbström (Grubba)  if (!remap || !remap->markers[marker_set] || !marker) { return 0; }
003e122020-10-05Henrik Grubbström (Grubba)  SET_SVAL(key, T_INT, NUMBER_NUMBER, integer, marker);
fda6742022-04-08Henrik Grubbström (Grubba)  val = low_mapping_lookup(remap->markers[marker_set], &key); if (!val) return 0;
003e122020-10-05Henrik Grubbström (Grubba) 
8507642021-12-21Henrik Grubbström (Grubba)  if ((TYPEOF(*val) == PIKE_T_TYPE) && val->u.type) { add_ref(val->u.type);
fda6742022-04-08Henrik Grubbström (Grubba)  *result_type = val->u.type; } else { *result_type = NULL;
003e122020-10-05Henrik Grubbström (Grubba)  }
fda6742022-04-08Henrik Grubbström (Grubba)  return 1;
003e122020-10-05Henrik Grubbström (Grubba) }
fda6742022-04-08Henrik Grubbström (Grubba) #define lookup_marker(REMAP, M, F, RES) (lookup_marker(REMAP, M, F, RES)?(debug_malloc_pass(*(RES)),1):0)
003e122020-10-05Henrik Grubbström (Grubba) 
c97a452021-12-17Henrik Grubbström (Grubba) static void store_marker(struct remap_state *remap, int marker,
fda6742022-04-08Henrik Grubbström (Grubba)  struct pike_type *value, enum pt_remap_flags flags)
003e122020-10-05Henrik Grubbström (Grubba) { struct svalue key, val;
fda6742022-04-08Henrik Grubbström (Grubba)  int marker_set = !!(flags & PT_FLAG_REMAP_SWAP_MARKERS);
003e122020-10-05Henrik Grubbström (Grubba) 
c97a452021-12-17Henrik Grubbström (Grubba)  if (!remap || !marker) return;
fda6742022-04-08Henrik Grubbström (Grubba)  if (!remap->markers[marker_set]) { remap->markers[marker_set] = allocate_mapping(10);
c97a452021-12-17Henrik Grubbström (Grubba)  }
003e122020-10-05Henrik Grubbström (Grubba)  SET_SVAL(key, T_INT, NUMBER_NUMBER, integer, marker);
8507642021-12-21Henrik Grubbström (Grubba)  if (value) { SET_SVAL(val, T_TYPE, 0, type, value); } else { SET_SVAL(val, T_INT, NUMBER_NUMBER, integer, 0); }
fda6742022-04-08Henrik Grubbström (Grubba)  mapping_insert(remap->markers[marker_set], &key, &val);
003e122020-10-05Henrik Grubbström (Grubba) }
fda6742022-04-08Henrik Grubbström (Grubba) #define store_marker(REMAP, M, T, F) store_marker(REMAP, M, debug_malloc_pass(T), F)
003e122020-10-05Henrik Grubbström (Grubba) 
3fb8742021-12-23Henrik Grubbström (Grubba) /** * Copy marker assignments from remap->markers to
78d2442022-01-02Henrik Grubbström (Grubba)  * their corresponding T_ASSIGN nodes (aka backpatch).
3fb8742021-12-23Henrik Grubbström (Grubba)  * * Leave the result on the type stack. */ static void push_and_fixup_markers(struct pike_type *t,
fda6742022-04-08Henrik Grubbström (Grubba)  struct remap_state *remap, enum pt_remap_flags flags)
3fb8742021-12-23Henrik Grubbström (Grubba) { if (!t || !(t->flags & PT_FLAG_ASSIGN) || !remap || !remap->markers) { /* Type t does not contain any marker assignments, * or the remap state has no markers set. */ push_finished_type(t); return; } /* NB: Many of the cases in the switch below are unreached * as they never contain a T_ASSIGN and thus are * handled by the PT_FLAG_ASSIGN test above. */ switch(t->type & (0x8000 | PIKE_T_MASK)) { case T_ASSIGN: { int marker = '0' + CAR_TO_INT(t);
fda6742022-04-08Henrik Grubbström (Grubba)  struct pike_type *t2 = NULL; if (lookup_marker(remap, marker | 0x100, flags, &t2)) { push_finished_type(t2); free_type(t2); } else { push_finished_type(t->cdr); }
3fb8742021-12-23Henrik Grubbström (Grubba)  push_assign_type(marker); } break; case PIKE_T_NAME:
fda6742022-04-08Henrik Grubbström (Grubba)  push_and_fixup_markers(t->cdr, remap, flags);
3fb8742021-12-23Henrik Grubbström (Grubba)  push_type_name((struct pike_string *)(t->car)); break; case PIKE_T_ATTRIBUTE:
fda6742022-04-08Henrik Grubbström (Grubba)  push_and_fixup_markers(t->cdr, remap, flags);
3fb8742021-12-23Henrik Grubbström (Grubba)  push_type_attribute((struct pike_string *)(t->car)); break; case T_SCOPE:
fda6742022-04-08Henrik Grubbström (Grubba)  push_and_fixup_markers(t->cdr, remap, flags);
3fb8742021-12-23Henrik Grubbström (Grubba)  push_scope_type(CAR_TO_INT(t)); break; case T_MULTISET: case T_NOT: case T_TYPE: case PIKE_T_AUTO: case T_PROGRAM: /* t->car is node. */
fda6742022-04-08Henrik Grubbström (Grubba)  push_and_fixup_markers(t->car, remap, flags);
3fb8742021-12-23Henrik Grubbström (Grubba)  push_type(t->type); break; case PIKE_T_OPERATOR: push_finished_type(t->car); push_type_operator(t->type, t->cdr); break; case T_FUNCTION: case T_MANY: case PIKE_T_RING: case T_TUPLE: case T_MAPPING: case T_OR: case T_AND: case T_ARRAY: case T_STRING: case PIKE_T_OPERATOR | 0x8000: /* t->car and t->cdr are nodes. */
fda6742022-04-08Henrik Grubbström (Grubba)  push_and_fixup_markers(t->cdr, remap, flags); push_and_fixup_markers(t->car, remap, flags);
3fb8742021-12-23Henrik Grubbström (Grubba)  push_type(t->type); break;
203aec2022-05-03Henrik Grubbström (Grubba)  case PIKE_T_TRANSITIVE: push_finished_type(t->cdr); push_and_fixup_markers(t->car, remap, flags); push_type(t->type); break;
3fb8742021-12-23Henrik Grubbström (Grubba)  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case T_MIXED: case T_VOID: case T_ZERO: case T_FLOAT: case T_INT: case T_OBJECT: /* Leaf type. */ push_finished_type(t); break; default: Pike_fatal("Unsupported type in push_and_fixup_markers().\n"); } }
6494d12020-09-20Henrik Grubbström (Grubba) static void push_remap_markers(struct pike_type *t, struct remap_state *remap,
eaf18d2020-09-26Henrik Grubbström (Grubba)  enum pt_remap_flags flags)
6494d12020-09-20Henrik Grubbström (Grubba) {
b383342021-11-14Henrik Grubbström (Grubba)  if (!t || (flags & PT_FLAG_REMAP_INHIBIT) ||
c97a452021-12-17Henrik Grubbström (Grubba)  (!remap && !(flags & PT_FLAG_REMAP_EVAL_MARKERS))) {
6494d12020-09-20Henrik Grubbström (Grubba)  push_finished_type(t); return; } /* FIXME: Use the type flags to detect whether we can just push * the type verbatim. */ switch(t->type & PIKE_T_MASK) { case T_ASSIGN: {
957a002020-09-22Henrik Grubbström (Grubba)  int marker = alloc_remap_marker(remap, CAR_TO_INT(t), flags);
003e122020-10-05Henrik Grubbström (Grubba) 
c97a452021-12-17Henrik Grubbström (Grubba)  if (!(flags & PT_FLAG_REMAP_EVAL_MARKERS)) { push_remap_markers(t->cdr, remap, flags);
003e122020-10-05Henrik Grubbström (Grubba)  push_assign_type(marker); } else {
fda6742022-04-08Henrik Grubbström (Grubba)  struct pike_type *old = NULL;
003e122020-10-05Henrik Grubbström (Grubba)  struct pike_type *new = t->cdr;
fda6742022-04-08Henrik Grubbström (Grubba)  lookup_marker(remap, marker, flags, &old);
8c23612021-06-04Henrik Grubbström (Grubba)  if (new) { if (old) { new = or_pike_types(old, new, 0); } else { add_ref(new); }
fda6742022-04-08Henrik Grubbström (Grubba)  store_marker(remap, marker, new, flags);
8507642021-12-21Henrik Grubbström (Grubba)  free_type(new);
003e122020-10-05Henrik Grubbström (Grubba)  }
8507642021-12-21Henrik Grubbström (Grubba)  free_type(old);
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(t->cdr, remap, flags);
003e122020-10-05Henrik Grubbström (Grubba)  } if (flags & PT_FLAG_REMAP_BOTH_MARKERS) { marker = alloc_remap_marker(remap, CAR_TO_INT(t), flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
c97a452021-12-17Henrik Grubbström (Grubba)  if (!(flags & PT_FLAG_REMAP_EVAL_MARKERS)) {
003e122020-10-05Henrik Grubbström (Grubba)  push_assign_type(marker); } else {
fda6742022-04-08Henrik Grubbström (Grubba)  struct pike_type *old = NULL;
003e122020-10-05Henrik Grubbström (Grubba)  struct pike_type *new = t->cdr;
fda6742022-04-08Henrik Grubbström (Grubba)  lookup_marker(remap, marker, flags ^ PT_FLAG_REMAP_SWAP_MARKERS, &old);
003e122020-10-05Henrik Grubbström (Grubba)  if (old) { new = or_pike_types(old, new, 0); } else { add_ref(new); }
fda6742022-04-08Henrik Grubbström (Grubba)  store_marker(remap, marker, new, flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
8507642021-12-21Henrik Grubbström (Grubba)  free_type(new); free_type(old);
fda6742022-04-08Henrik Grubbström (Grubba)  push_remap_markers(t->cdr, remap, flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
003e122020-10-05Henrik Grubbström (Grubba)  switch(flags & PT_FLAG_REMAP_BOTH_MARKERS_MASK) { case PT_FLAG_REMAP_BOTH_MARKERS_AND: push_type(T_AND); break; case PT_FLAG_REMAP_BOTH_MARKERS_OR: push_type(T_OR); break; default: Pike_fatal("Unsupported marker joining method.\n"); break; } } }
6494d12020-09-20Henrik Grubbström (Grubba)  break; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': {
957a002020-09-22Henrik Grubbström (Grubba)  int marker = remap_marker(remap, t->type, flags);
fda6742022-04-08Henrik Grubbström (Grubba)  struct pike_type *value = NULL;
003e122020-10-05Henrik Grubbström (Grubba) 
fda6742022-04-08Henrik Grubbström (Grubba)  if (lookup_marker(remap, marker, flags, &value)) {
b9ab462022-05-07Marcus Comstedt  push_finished_type(value);
8507642021-12-21Henrik Grubbström (Grubba)  free_type(value);
45627b2022-04-06Henrik Grubbström (Grubba)  if (marker && (flags & PT_FLAG_REMAP_KEEP_MARKERS)) { push_type(marker); push_type(T_OR); }
c97a452021-12-17Henrik Grubbström (Grubba)  } else if (flags & PT_FLAG_REMAP_EVAL_MARKERS) {
45627b2022-04-06Henrik Grubbström (Grubba)  /* Marker without matching assign. * NB: Not an error. Consider * * function($0 = mixed...: $0|float) * * when evaluating the $0|float to get the * return value, $0 will not be bound. */ push_type(PIKE_T_UNKNOWN);
6494d12020-09-20Henrik Grubbström (Grubba)  } else {
003e122020-10-05Henrik Grubbström (Grubba)  /* Remap the marker. */ if (!marker) { /* FIXME: Improve error handling here. */ push_type(T_MIXED); } else { push_type(marker); }
6494d12020-09-20Henrik Grubbström (Grubba)  }
003e122020-10-05Henrik Grubbström (Grubba) 
eaf18d2020-09-26Henrik Grubbström (Grubba)  if (flags & PT_FLAG_REMAP_BOTH_MARKERS) { marker = remap_marker(remap, t->type, flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
fda6742022-04-08Henrik Grubbström (Grubba)  value = NULL; if (lookup_marker(remap, marker, flags ^ PT_FLAG_REMAP_SWAP_MARKERS, &value)) {
b9ab462022-05-07Marcus Comstedt  push_finished_type(value);
8507642021-12-21Henrik Grubbström (Grubba)  free_type(value);
c97a452021-12-17Henrik Grubbström (Grubba)  } else if (flags & PT_FLAG_REMAP_EVAL_MARKERS) {
003e122020-10-05Henrik Grubbström (Grubba)  /* Marker without matching assign. */ /* FIXME: Report error? */
a01d932020-09-24Henrik Grubbström (Grubba)  push_type(T_MIXED); } else {
003e122020-10-05Henrik Grubbström (Grubba)  /* Remap the marker. */ if (!marker) { /* FIXME: Improve error handling here. */ push_type(T_MIXED); } else { push_type(marker); }
a01d932020-09-24Henrik Grubbström (Grubba)  }
003e122020-10-05Henrik Grubbström (Grubba) 
eaf18d2020-09-26Henrik Grubbström (Grubba)  switch(flags & PT_FLAG_REMAP_BOTH_MARKERS_MASK) { case PT_FLAG_REMAP_BOTH_MARKERS_AND:
a01d932020-09-24Henrik Grubbström (Grubba)  push_type(T_AND); break;
eaf18d2020-09-26Henrik Grubbström (Grubba)  case PT_FLAG_REMAP_BOTH_MARKERS_OR:
a01d932020-09-24Henrik Grubbström (Grubba)  push_type(T_OR); break; default: Pike_fatal("Unsupported marker joining method.\n"); break; } }
6494d12020-09-20Henrik Grubbström (Grubba)  break; }
674bb62020-09-22Henrik Grubbström (Grubba)  case PIKE_T_NAME:
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(t->cdr, remap, flags);
90dca52020-09-23Henrik Grubbström (Grubba)  push_type_name((struct pike_string *)(t->car));
6494d12020-09-20Henrik Grubbström (Grubba)  break;
674bb62020-09-22Henrik Grubbström (Grubba)  case PIKE_T_ATTRIBUTE:
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(t->cdr, remap, flags);
90dca52020-09-23Henrik Grubbström (Grubba)  push_type_attribute((struct pike_string *)(t->car));
6494d12020-09-20Henrik Grubbström (Grubba)  break; case T_SCOPE:
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(t->cdr, remap, flags);
6494d12020-09-20Henrik Grubbström (Grubba)  push_scope_type(CAR_TO_INT(t)); break; case PIKE_T_OPERATOR:
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(t->car, remap, flags);
6494d12020-09-20Henrik Grubbström (Grubba)  if (t->type & 0x8000) {
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(t->cdr, remap, flags);
6494d12020-09-20Henrik Grubbström (Grubba)  push_reverse_type(t->type); } else { switch(t->type) {
92a3912021-11-27Henrik Grubbström (Grubba)  case PIKE_T_GET_RETURN: push_type_operator(t->type, NULL); break;
6494d12020-09-20Henrik Grubbström (Grubba)  case PIKE_T_FIND_LFUN: push_type_operator(t->type, t->cdr); break; default: Pike_fatal("Unsupported operator %d in push_remap_markers().\n", t->type); break; } } break; /* Verbatim */ case T_OBJECT: case T_VOID: case T_ZERO: case T_INT: case T_FLOAT: case PIKE_T_MIXED: push_finished_type(t); break; /* Unary */ case T_PROGRAM: case T_MULTISET: case T_NOT: case T_TYPE: case PIKE_T_AUTO:
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(t->car, remap, flags);
6494d12020-09-20Henrik Grubbström (Grubba)  push_type(t->type); break; /* Binary */ case T_OR: case T_AND: case T_FUNCTION: case T_MANY: case T_TUPLE: case T_MAPPING: case PIKE_T_RING: case T_ARRAY: case T_STRING:
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(t->car, remap, flags); push_remap_markers(t->cdr, remap, flags);
6494d12020-09-20Henrik Grubbström (Grubba)  push_reverse_type(t->type); break;
203aec2022-05-03Henrik Grubbström (Grubba)  /* Special */ case PIKE_T_TRANSITIVE: push_remap_markers(t->car, remap, flags); push_finished_type(t->cdr); push_reverse_type(t->type); break;
6494d12020-09-20Henrik Grubbström (Grubba)  } } /** * Remap markers (if any) in the type. */ static struct pike_type *remap_markers(struct pike_type *t, struct remap_state *remap,
eaf18d2020-09-26Henrik Grubbström (Grubba)  enum pt_remap_flags flags)
6494d12020-09-20Henrik Grubbström (Grubba) {
0a71852020-10-23Henrik Grubbström (Grubba)  if (!t) return NULL;
70cdaa2020-12-06Henrik Grubbström (Grubba)  if (flags & PT_FLAG_REMAP_TRACE) { fprintf(stderr, "remap_markers("); simple_describe_type(t);
fda6742022-04-08Henrik Grubbström (Grubba)  fprintf(stderr, ", {"); simple_describe_mapping(remap?remap->markers[0]:NULL); simple_describe_mapping(remap?remap->markers[1]:NULL); fprintf(stderr, "}, %p, 0x%02x)\n", remap, flags);
70cdaa2020-12-06Henrik Grubbström (Grubba)  }
6494d12020-09-20Henrik Grubbström (Grubba)  type_stack_mark();
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(t, remap, flags);
70cdaa2020-12-06Henrik Grubbström (Grubba)  if (flags & PT_FLAG_REMAP_TRACE) { fprintf(stderr, "remap ==> "); simple_describe_type(peek_type_stack()); fprintf(stderr, "\n"); }
6494d12020-09-20Henrik Grubbström (Grubba)  return pop_unfinished_type(); }
4f759e2022-04-11Henrik Grubbström (Grubba) static void push_expand_transitive_remap(struct pike_type *cont, struct pike_type *trans, struct remap_state *remap, enum pt_remap_flags flags, int num_args) { struct pike_type *tmp; TYPE_STACK_DEBUG("expand_transitive_remap"); switch(cont?(cont->type & PIKE_T_MASK):PIKE_T_UNKNOWN) { case PIKE_T_UNKNOWN: if (!trans) { push_type(PIKE_T_UNKNOWN); } else { /* A car of __unknown__ is short-hand for having it identical * to the cdr. */ push_expand_transitive_remap(trans, trans, remap, flags, num_args); } break; case T_OR: case T_AND: push_expand_transitive_remap(cont->cdr, trans, remap, flags, num_args); push_expand_transitive_remap(cont->car, trans, remap, flags, num_args); push_type(cont->type); break; case PIKE_T_FUNCTION: /* * transitive(function(a, b, ...:c), X) * * ==> * * function(a, @transitive(function(b, ...:c), X) */ push_expand_transitive_remap(cont->cdr, trans, remap, flags, num_args + 1); push_remap_markers(cont->car, remap, flags); push_type(cont->type); break; case T_MANY: if (num_args) { /* No need to expand further for now. */ push_finished_type(trans); push_remap_markers(cont, remap, flags); push_type(PIKE_T_TRANSITIVE); } else { /* Two cases: * * transitive(function(:x), function(x, a, b, ...: c)) * * ==> * * function(:x) | expand(transitive(function(a, b, ...: c), * function(x, a, b, ...:c))) * * And * * transitive(function(t...:x), function(x, a, b, ...: c)) * * ==> * * function(t...:x) | * function(t, @transitive(function(t...:x), * function(x, a, b, c, ...:c)))) | * expand(transitive(function(a, b, ...: c), * function(x, a, b, ...:c))) */ DECLARE_CYCLIC(); push_remap_markers(cont, remap, flags); if (!BEGIN_CYCLIC(cont, trans)) { SET_CYCLIC_RET(1); /* Check many arg. */ push_remap_markers(cont->car, remap, flags); if (peek_type_stack() != void_type_string) { push_finished_type(trans); push_remap_markers(cont, remap, flags); push_type(PIKE_T_TRANSITIVE); push_reverse_type(PIKE_T_FUNCTION); push_type(T_OR); } else { compiler_discard_top_type(); } push_remap_markers(cont->cdr, remap, flags); tmp = low_new_check_call(trans, peek_type_stack(), 0, NULL); compiler_discard_top_type(); if (tmp) { /* Valid recursion. */ push_expand_transitive_remap(tmp, trans, remap, flags, 0); free_type(tmp); push_type(T_OR); } } END_CYCLIC(); } break; case PIKE_T_OPERATOR: if (num_args) { /* No need to expand futher for now. */ push_finished_type(trans); push_finished_type(cont); push_type(PIKE_T_TRANSITIVE); } else { /* We have no idea. */ push_type(PIKE_T_MIXED); } break; case PIKE_T_MIXED: push_type(PIKE_T_MIXED); break; case T_VOID: push_type(T_VOID); break; default: /* Unsupported. */ fprintf(stderr, "Attempting to expand unsupported type: "); simple_describe_type(cont); fprintf(stderr, "\n"); push_finished_type(function_type_string); Pike_fatal("Attempt to expand unsupported type: %d\n", cont->type); break; } } /* Partially expand transitive types, so that eg matching * against function types works as expected. */ static struct pike_type *expand_transitive_remap(struct pike_type *fun, struct remap_state *remap, enum pt_remap_flags flags) { struct pike_type *ret_type; struct pike_type *cont_type; assert(fun->type == PIKE_T_TRANSITIVE); type_stack_mark(); push_expand_transitive_remap(fun->car, fun->cdr, remap, flags, 0); #if 0 fprintf(stderr, "expand_transitive_remap("); simple_describe_type(fun); fprintf(stderr, ") ==> "); simple_describe_type(peek_type_stack()); fprintf(stderr, "\n"); #endif return pop_unfinished_type(); }
d41c192020-09-27Henrik Grubbström (Grubba) static struct pike_type *low_intersect_types(struct pike_type *a, struct pike_type *b, struct remap_state *remap, enum pt_cmp_flags aflags, enum pt_cmp_flags bflags, enum pt_remap_flags remap_flags);
b98ea32020-10-10Henrik Grubbström (Grubba) 
4565782020-10-11Henrik Grubbström (Grubba) static void push_binop(enum pt_binop op) { struct pike_type *a, *b; switch(op) { case PT_BINOP_AND: push_type(T_AND); break; case PT_BINOP_OR: push_type(T_OR); break; case PT_BINOP_B: a = low_pop_type(); b = low_pop_type(); push_finished_type(b); free_type(a); free_type(b); break; case PT_BINOP_A: a = low_pop_type(); b = low_pop_type(); push_finished_type(a); free_type(a); free_type(b); break; case PT_BINOP_ALL: a = low_pop_type(); b = low_pop_type(); push_type(T_MIXED); free_type(a); free_type(b); break; case PT_BINOP_NONE:
9d46f22021-02-02Henrik Grubbström (Grubba)  a = low_pop_type(); b = low_pop_type(); push_type(PIKE_T_UNKNOWN); free_type(a); free_type(b); break;
4565782020-10-11Henrik Grubbström (Grubba)  case PT_BINOP_MINUS: case PT_BINOP_INVERSE_MINUS: /* One of the minterms. */ if (op & PT_BINOP_NOT_B) { a = low_pop_type(); push_type(T_NOT); push_finished_type(a); free_type(a); } if (op & PT_BINOP_NOT_A) { push_type(T_NOT); } push_type(T_AND); break; case PT_BINOP_NOR: push_type(T_OR); push_type(T_NOT); break; default: { enum pt_binop inv_op = (~op) & PT_BINOP_ALL; if (!(inv_op & (inv_op - 1))) { /* An inverted minterm. */ if (inv_op & PT_BINOP_NOT_B) { a = low_pop_type(); push_type(T_NOT); push_finished_type(a); push_type(T_NOT); free_type(a); } if (inv_op & PT_BINOP_NOT_A) { push_type(T_NOT); } push_type(T_OR); break; } /* FIXME: XOR, NXOR */ Pike_fatal("Unsupported binary type operation: 0x%02x\n", op); } } }
5716772022-03-28Martin Nilsson #if 0 /* unused */
4565782020-10-11Henrik Grubbström (Grubba) static void push_reverse_binop(enum pt_binop op) { /* Swap bits 1 & 2 in op to reverse the meanings of the arguments. */ push_binop((op & PT_BINOP_XNOR) | ((op & PT_BINOP_MINUS) ? PT_BINOP_INVERSE_MINUS : 0) | ((op & PT_BINOP_INVERSE_MINUS) ? PT_BINOP_MINUS : 0)); }
5716772022-03-28Martin Nilsson #endif
4565782020-10-11Henrik Grubbström (Grubba) 
b98ea32020-10-10Henrik Grubbström (Grubba) /**
4ba44c2020-12-05Henrik Grubbström (Grubba)  * Low-level set operation (AND, MINUS, OR, etc) on two types.
b98ea32020-10-10Henrik Grubbström (Grubba)  * * Note: * There are two major operating modes; the external, where * the two types have unrelated markers, which then need to * be remapped in the result, and the internal, where the * two types have related markers (this mode is used mainly * when evaluating a type). * * The internal mode is indicated via the remap state being NULL. */
3136e52021-01-04Henrik Grubbström (Grubba) static struct pike_type *lower_type_binop(enum pt_binop op, struct pike_type *a, struct pike_type *b, struct remap_state *remap, enum pt_cmp_flags aflags, enum pt_cmp_flags bflags, enum pt_remap_flags remap_flags);
b98ea32020-10-10Henrik Grubbström (Grubba) static struct pike_type *low_type_binop(enum pt_binop op, struct pike_type *a, struct pike_type *b, struct remap_state *remap, enum pt_cmp_flags aflags, enum pt_cmp_flags bflags, enum pt_remap_flags remap_flags) {
3136e52021-01-04Henrik Grubbström (Grubba) #ifdef DEBUG_MALLOC #define low_type_binop(OP, A, B, REMAP, AFLAGS, BFLAGS, REMAP_FLAGS) \ ((struct pike_type *) \ debug_malloc_pass(low_type_binop(OP, debug_malloc_pass(A), \ debug_malloc_pass(B), \ debug_malloc_pass(REMAP), \ AFLAGS, BFLAGS, REMAP_FLAGS))) #endif /* DEBUG_MALLOC */ #ifdef PIKE_DEBUG struct pike_type **save_type_stackp = Pike_compiler->type_stackp; struct pike_type ***save_mark_stackp = Pike_compiler->pike_type_mark_stackp; #endif struct pike_type *ret;
b98ea32020-10-10Henrik Grubbström (Grubba) 
70cdaa2020-12-06Henrik Grubbström (Grubba)  if (remap_flags & PT_FLAG_REMAP_TRACE) { fprintf(stderr, "low_type_binop(0x%04x, ", op); simple_describe_type(a); fprintf(stderr, ", "); simple_describe_type(b); fprintf(stderr, ", %p, 0x%04x, 0x%04x, 0x%02x)\n", remap, aflags, bflags, remap_flags); }
64133e2021-09-27Henrik Grubbström (Grubba)  ret = debug_malloc_pass(lower_type_binop(op, a, b, remap, aflags, bflags, remap_flags));
3136e52021-01-04Henrik Grubbström (Grubba)  if (remap_flags & PT_FLAG_REMAP_TRACE) { fprintf(stderr, "ret: "); simple_describe_type(ret); fprintf(stderr, "\n"); } #ifdef PIKE_DEBUG if ((save_type_stackp != Pike_compiler->type_stackp) || (save_mark_stackp != Pike_compiler->pike_type_mark_stackp)) { fprintf(stderr, "low_type_binop stack level corruption!\n" "op : 0x%x\na: ", op); simple_describe_type(a); fprintf(stderr, "\nb: "); simple_describe_type(b); fprintf(stderr, "\nret: "); simple_describe_type(ret); fprintf(stderr, "\n\n"); Pike_fatal("Stack level corruption!\n" "type stack: %p (expected: %p)\n" "mark stack: %p (expected: %p)\n", Pike_compiler->type_stackp, save_type_stackp, Pike_compiler->pike_type_mark_stackp, save_mark_stackp); } #endif return ret; } static struct pike_type *lower_type_binop(enum pt_binop op, struct pike_type *a, struct pike_type *b, struct remap_state *remap, enum pt_cmp_flags aflags, enum pt_cmp_flags bflags, enum pt_remap_flags remap_flags) { struct pike_type *tmp, *tmp2, *ret; struct pike_type *aret = NULL, *bret = NULL; enum pt_cmp_flags avoidable; enum pt_cmp_flags bvoidable; recur:
b98ea32020-10-10Henrik Grubbström (Grubba)  switch(op) { case PT_BINOP_AND: case PT_BINOP_MINUS: break; case PT_BINOP_INVERSE_MINUS: tmp = a; a = b; b = tmp; avoidable = aflags; aflags = bflags; bflags = avoidable; remap_flags ^= PT_FLAG_REMAP_SWAP_MARKERS; op = PT_BINOP_MINUS; break; case PT_BINOP_NOR: type_stack_mark();
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(a, remap, remap_flags); push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
b98ea32020-10-10Henrik Grubbström (Grubba)  push_type(T_OR); push_type(T_NOT); return pop_unfinished_type(); case PT_BINOP_OR: type_stack_mark();
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(a, remap, remap_flags); push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
b98ea32020-10-10Henrik Grubbström (Grubba)  push_type(T_OR); return pop_unfinished_type();
0c2a762021-01-01Henrik Grubbström (Grubba)  case PT_BINOP_XOR: /* A XOR B == (A OR B) - (A AND B) */ tmp = low_type_binop(PT_BINOP_OR, a, b, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; tmp2 = low_type_binop(PT_BINOP_AND, a, b, remap, aflags, bflags, remap_flags); if (!tmp2) return tmp;
323bb42021-12-30Henrik Grubbström (Grubba)  ret = low_type_binop(PT_BINOP_MINUS, tmp, tmp2, NULL, 0, 0, remap_flags & PT_FLAG_REMAP_INEXACT);
0c2a762021-01-01Henrik Grubbström (Grubba)  free_type(tmp); free_type(tmp2); return ret; case PT_BINOP_XNOR: /* A XNOR B == (A NAND B) - (A NOR B) */ tmp = low_type_binop(PT_BINOP_NAND, a, b, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; tmp2 = low_type_binop(PT_BINOP_NOR, a, b, remap, aflags, bflags, remap_flags); if (!tmp2) return tmp;
323bb42021-12-30Henrik Grubbström (Grubba)  ret = low_type_binop(PT_BINOP_MINUS, tmp, tmp2, NULL, 0, 0, remap_flags & PT_FLAG_REMAP_INEXACT);
0c2a762021-01-01Henrik Grubbström (Grubba)  free_type(tmp); free_type(tmp2); return ret;
b98ea32020-10-10Henrik Grubbström (Grubba)  default:
3774602021-03-06Henrik Grubbström (Grubba)  /* Make the C-compiler happy. */ #ifdef PIKE_DEBUG
b98ea32020-10-10Henrik Grubbström (Grubba)  Pike_fatal("Unsupported binary type operation: 0x%02x\n", op); #endif
3774602021-03-06Henrik Grubbström (Grubba)  break;
b98ea32020-10-10Henrik Grubbström (Grubba)  }
44a5bc2021-04-10Henrik Grubbström (Grubba)  full_loop:
b98ea32020-10-10Henrik Grubbström (Grubba)  if (a == b) { if (op & PT_BINOP_AND) { /* FIXME: Perform masking of remap_flags here. */
c97a452021-12-17Henrik Grubbström (Grubba)  return remap_markers(a, remap,
b98ea32020-10-10Henrik Grubbström (Grubba)  remap_flags | PT_FLAG_REMAP_BOTH_MARKERS_AND); } else { return NULL; } } /* First check for markers. */
9c6b942021-05-20Henrik Grubbström (Grubba)  switch(a?a->type:PIKE_T_UNKNOWN) {
b98ea32020-10-10Henrik Grubbström (Grubba)  case T_ASSIGN: {
42e9be2021-12-24Henrik Grubbström (Grubba)  int marker;
78d2442022-01-02Henrik Grubbström (Grubba)  tmp = low_type_binop(PT_BINOP_AND, a->cdr, b, remap, aflags, bflags, remap_flags);
42e9be2021-12-24Henrik Grubbström (Grubba)  marker = alloc_remap_marker(remap, CAR_TO_INT(a), remap_flags);
a3cd6c2022-04-07Henrik Grubbström (Grubba)  /* Marker value */
fda6742022-04-08Henrik Grubbström (Grubba)  store_marker(remap, marker, tmp, remap_flags);
78d2442022-01-02Henrik Grubbström (Grubba)  if (op != PT_BINOP_AND) { if ((op == PT_BINOP_MINUS) && !tmp) { tmp = a->cdr; if (tmp) add_ref(tmp); } else if ((op == PT_BINOP_MINUS) && (tmp == a->cdr)) { free_type(tmp); tmp = NULL; } else { free_type(tmp); tmp = low_type_binop(op, a->cdr, b, remap, aflags, bflags, remap_flags); } }
a3cd6c2022-04-07Henrik Grubbström (Grubba)  /* Value to backpatch. */
fda6742022-04-08Henrik Grubbström (Grubba)  store_marker(remap, marker | 0x100, tmp, remap_flags);
78d2442022-01-02Henrik Grubbström (Grubba)  if (!tmp) return NULL;
42e9be2021-12-24Henrik Grubbström (Grubba)  type_stack_mark(); push_finished_type(tmp); push_assign_type(marker); free_type(tmp); return pop_unfinished_type();
b98ea32020-10-10Henrik Grubbström (Grubba)  } }
9c6b942021-05-20Henrik Grubbström (Grubba)  switch(b?b->type:PIKE_T_UNKNOWN) {
b98ea32020-10-10Henrik Grubbström (Grubba)  case T_ASSIGN: {
42e9be2021-12-24Henrik Grubbström (Grubba)  int marker;
78d2442022-01-02Henrik Grubbström (Grubba)  tmp = low_type_binop(PT_BINOP_AND, a, b->cdr, remap, aflags, bflags, remap_flags);
42e9be2021-12-24Henrik Grubbström (Grubba)  marker = alloc_remap_marker(remap, CAR_TO_INT(b), remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
a3cd6c2022-04-07Henrik Grubbström (Grubba)  /* Marker value */
fda6742022-04-08Henrik Grubbström (Grubba)  store_marker(remap, marker, tmp, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
78d2442022-01-02Henrik Grubbström (Grubba)  if (op != PT_BINOP_AND) { if ((op == PT_BINOP_MINUS) && !tmp) { tmp = a; if (tmp) add_ref(tmp); } else if ((op == PT_BINOP_MINUS) && (tmp == a)) { free_type(tmp); tmp = NULL; } else { free_type(tmp); tmp = low_type_binop(op, a, b->cdr, remap, aflags, bflags, remap_flags); } }
a3cd6c2022-04-07Henrik Grubbström (Grubba)  /* Value to backpatch. */
fda6742022-04-08Henrik Grubbström (Grubba)  store_marker(remap, marker | 0x100, tmp, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
78d2442022-01-02Henrik Grubbström (Grubba) 
a3cd6c2022-04-07Henrik Grubbström (Grubba)  /* NB: We can only keep the marker assignment in the PT_BINOP_AND * case. * * See also the b->type == '0'..'9' case further below. */ if ((op == PT_BINOP_AND) && tmp) { type_stack_mark(); push_finished_type(tmp); push_assign_type(marker); free_type(tmp); tmp = pop_unfinished_type(); }
78d2442022-01-02Henrik Grubbström (Grubba) 
a3cd6c2022-04-07Henrik Grubbström (Grubba)  return tmp;
b98ea32020-10-10Henrik Grubbström (Grubba)  } } /* Attributes and names. */
9c6b942021-05-20Henrik Grubbström (Grubba)  switch(a?a->type:PIKE_T_UNKNOWN) {
b98ea32020-10-10Henrik Grubbström (Grubba)  case PIKE_T_NAME: tmp = low_type_binop(op, a->cdr, b, remap, aflags, bflags, remap_flags); if (!tmp) return NULL;
90785c2021-11-06Henrik Grubbström (Grubba)  if (tmp != a->cdr) return tmp;
b98ea32020-10-10Henrik Grubbström (Grubba)  type_stack_mark(); push_finished_type(tmp); push_type_name((struct pike_string *)(a->car)); free_type(tmp); return pop_unfinished_type(); case PIKE_T_ATTRIBUTE: tmp = low_type_binop(op, a->cdr, b, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_type_attribute((struct pike_string *)(a->car)); free_type(tmp); return pop_unfinished_type(); case T_SCOPE:
0b7cb52021-03-19Henrik Grubbström (Grubba)  tmp = low_type_binop(op, a->cdr, b, remap, aflags | PT_FLAG_CMP_INSEPARABLE, bflags, remap_flags);
b98ea32020-10-10Henrik Grubbström (Grubba)  if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_scope_type(CAR_TO_INT(a)); free_type(tmp); return pop_unfinished_type(); }
9c6b942021-05-20Henrik Grubbström (Grubba)  switch(b?b->type:PIKE_T_UNKNOWN) {
b98ea32020-10-10Henrik Grubbström (Grubba)  case PIKE_T_NAME: tmp = low_type_binop(op, a, b->cdr, remap, aflags, bflags, remap_flags); if (!tmp) return NULL;
90785c2021-11-06Henrik Grubbström (Grubba)  if (tmp != b->cdr) return tmp;
b98ea32020-10-10Henrik Grubbström (Grubba)  type_stack_mark(); push_finished_type(tmp); push_type_name((struct pike_string *)(b->car)); free_type(tmp); return pop_unfinished_type(); case PIKE_T_ATTRIBUTE: tmp = low_type_binop(op, a, b->cdr, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_type_attribute((struct pike_string *)(b->car)); free_type(tmp); return pop_unfinished_type(); case T_SCOPE:
0b7cb52021-03-19Henrik Grubbström (Grubba)  tmp = low_type_binop(op, a, b->cdr, remap, aflags, bflags | PT_FLAG_CMP_INSEPARABLE, remap_flags);
b98ea32020-10-10Henrik Grubbström (Grubba)  if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_scope_type(CAR_TO_INT(b)); free_type(tmp); return pop_unfinished_type(); } /* Check consolidated types. */
9c6b942021-05-20Henrik Grubbström (Grubba)  switch(a?a->type:PIKE_T_UNKNOWN) {
b98ea32020-10-10Henrik Grubbström (Grubba)  case T_OR: /* (a1 | a2) op b <==> (a1 op b) | (a2 op b) */
2f74582021-12-19Henrik Grubbström (Grubba)  { struct mapping *orig_markers = NULL;
fda6742022-04-08Henrik Grubbström (Grubba)  int marker_set = !!(remap_flags & PT_FLAG_REMAP_SWAP_MARKERS);
2f74582021-12-19Henrik Grubbström (Grubba)  if (remap) { /* Do not propagate marker changes between the branches * of the T_OR node. * * FIXME: It is theoretically possible to propagate marker * changes up if they are compatible in both branches. */
fda6742022-04-08Henrik Grubbström (Grubba)  orig_markers = remap->markers[marker_set]; remap->markers[marker_set] = copy_mapping(orig_markers);
2f74582021-12-19Henrik Grubbström (Grubba)  } tmp = low_type_binop(op, a->car, b, remap, aflags, bflags, remap_flags);
323bb42021-12-30Henrik Grubbström (Grubba)  if ((remap_flags & PT_FLAG_REMAP_INEXACT) && tmp) { if ((op == PT_BINOP_AND) || (op == PT_BINOP_MINUS)) {
fda6742022-04-08Henrik Grubbström (Grubba)  if (orig_markers) { do_free_mapping(remap->markers[marker_set]); remap->markers[marker_set] = orig_markers;
4645cd2022-01-01Henrik Grubbström (Grubba)  }
323bb42021-12-30Henrik Grubbström (Grubba)  free_type(tmp); add_ref(a); return a; } }
fda6742022-04-08Henrik Grubbström (Grubba)  if (orig_markers) { do_free_mapping(remap->markers[marker_set]); remap->markers[marker_set] = copy_mapping(orig_markers);
2f74582021-12-19Henrik Grubbström (Grubba)  } tmp2 = low_type_binop(op, a->cdr, b, remap, aflags, bflags, remap_flags);
fda6742022-04-08Henrik Grubbström (Grubba)  if (orig_markers) { do_free_mapping(remap->markers[marker_set]); remap->markers[marker_set] = orig_markers;
2f74582021-12-19Henrik Grubbström (Grubba)  } }
bedd4d2021-12-27Henrik Grubbström (Grubba) #if 0
0b7cb52021-03-19Henrik Grubbström (Grubba)  if ((op & PT_BINOP_NOT_A) || (aflags & PT_FLAG_CMP_INSEPARABLE)) { if (!tmp2) { free_type(tmp); return NULL; } if (!tmp) { free_type(tmp2); return NULL; } } else { if (!tmp2) return tmp; if (!tmp) return tmp2; }
bedd4d2021-12-27Henrik Grubbström (Grubba) #else if (!tmp2) return tmp; if (!tmp) return tmp2; #endif
b98ea32020-10-10Henrik Grubbström (Grubba)  type_stack_mark(); push_finished_type(tmp); push_finished_type(tmp2); push_reverse_type(T_OR); free_type(tmp); free_type(tmp2); return pop_unfinished_type(); case T_AND: tmp = low_type_binop(op, a->car, b, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; tmp2 = low_type_binop(op, a->cdr, b, remap, aflags, bflags, remap_flags); if (!tmp2) { free_type(tmp); return NULL; } switch(op) { case PT_BINOP_AND: /* NB: Attempt to avoid keeping the result from inverted types, * in order to reduce type expansion. */ if (a->car->type == T_NOT) { /* (!a1 & a2) & b <==> (a2 & b) & !a1 */ free_type(tmp);
c97a452021-12-17Henrik Grubbström (Grubba)  tmp = remap_markers(a->car, remap, remap_flags);
b98ea32020-10-10Henrik Grubbström (Grubba)  } else if (a->cdr->type == T_NOT) { /* (a1 & !a2) & b <==> (a1 & b) & !a2 */ free_type(tmp2);
c97a452021-12-17Henrik Grubbström (Grubba)  tmp2 = remap_markers(a->cdr, remap, remap_flags);
b98ea32020-10-10Henrik Grubbström (Grubba)  } break;
da52982020-11-01Henrik Grubbström (Grubba)  default: /* Make the C-compiler happy. */ break;
b98ea32020-10-10Henrik Grubbström (Grubba)  } type_stack_mark(); push_finished_type(tmp); push_finished_type(tmp2); push_reverse_type(T_AND); free_type(tmp); free_type(tmp2); return pop_unfinished_type(); }
9c6b942021-05-20Henrik Grubbström (Grubba)  switch(b?b->type:PIKE_T_UNKNOWN) {
b98ea32020-10-10Henrik Grubbström (Grubba)  case T_OR:
aff26a2021-12-20Henrik Grubbström (Grubba)  { struct mapping *orig_markers = NULL;
fda6742022-04-08Henrik Grubbström (Grubba)  int marker_set = !(remap_flags & PT_FLAG_REMAP_SWAP_MARKERS);
aff26a2021-12-20Henrik Grubbström (Grubba)  if (remap) { /* Do not propagate marker changes between the branches * of the T_OR node. * * FIXME: It is theoretically possible to propagate marker * changes up if they are compatible in both branches. */
fda6742022-04-08Henrik Grubbström (Grubba)  orig_markers = remap->markers[marker_set]; remap->markers[marker_set] = copy_mapping(orig_markers);
aff26a2021-12-20Henrik Grubbström (Grubba)  } tmp = low_type_binop(op, a, b->car, remap, aflags, bflags, remap_flags);
757ed72022-01-08Henrik Grubbström (Grubba)  if (remap_flags & PT_FLAG_REMAP_INEXACT) { if (tmp && (op == PT_BINOP_AND)) {
fda6742022-04-08Henrik Grubbström (Grubba)  if (orig_markers) { do_free_mapping(remap->markers[marker_set]); remap->markers[marker_set] = orig_markers;
4645cd2022-01-01Henrik Grubbström (Grubba)  }
323bb42021-12-30Henrik Grubbström (Grubba)  free_type(tmp); add_ref(a); return a;
757ed72022-01-08Henrik Grubbström (Grubba)  } else if (!tmp && (op == PT_BINOP_MINUS)) {
fda6742022-04-08Henrik Grubbström (Grubba)  if (orig_markers) { do_free_mapping(remap->markers[marker_set]); remap->markers[marker_set] = orig_markers;
757ed72022-01-08Henrik Grubbström (Grubba)  } return NULL;
323bb42021-12-30Henrik Grubbström (Grubba)  } }
fda6742022-04-08Henrik Grubbström (Grubba)  if (orig_markers) { do_free_mapping(remap->markers[marker_set]); remap->markers[marker_set] = copy_mapping(orig_markers);
aff26a2021-12-20Henrik Grubbström (Grubba)  } if ((op == PT_BINOP_MINUS) || (op == PT_BINOP_OR)) { /* Special case to avoid excessively complicated expressions * in the result. * * A - (B | C) == (A - B) - C * rather than * A - (B | C) == (A - B) & (A - C) * * A | (B | C) == (A | B) | C * rather than * A | (B | C) == (A | B) | (A | C) */ tmp2 = remap_markers(b->cdr, remap,
e191a12022-04-04Henrik Grubbström (Grubba)  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
aff26a2021-12-20Henrik Grubbström (Grubba)  ret = low_type_binop(op, tmp, tmp2, NULL, aflags, bflags, 0);
fda6742022-04-08Henrik Grubbström (Grubba)  if (orig_markers) { do_free_mapping(remap->markers[marker_set]); remap->markers[marker_set] = orig_markers;
aff26a2021-12-20Henrik Grubbström (Grubba)  } free_type(tmp); free_type(tmp2); return ret; } /* op secondary * 0 0000 0 0000 * 1 0001 7 0111 * 2 0010 1 0001 * 3 0011 1, 3, 5, 7 0011 * 4 0100 7 0111 * 5 0101 7 0111 * 6 0110 - * 7 0111 7 0111 * 8 1000 1 0001 * 9 1001 - * 10 1010 1 0001 * 11 1011 1 0001 * 12 1100 1, 3, 5, 7 0011 * 13 1101 7 0111 * 14 1110 1 0001 * 15 1111 15 1111
c205b22021-04-09Henrik Grubbström (Grubba)  *
aff26a2021-12-20Henrik Grubbström (Grubba)  * Note that secondary ops 1 and 7 are swapped for T_AND and T_OR.
c205b22021-04-09Henrik Grubbström (Grubba)  */
aff26a2021-12-20Henrik Grubbström (Grubba)  tmp2 = low_type_binop(op, a, b->cdr, remap, aflags, bflags, remap_flags);
fda6742022-04-08Henrik Grubbström (Grubba)  if (orig_markers) { do_free_mapping(remap->markers[marker_set]); remap->markers[marker_set] = orig_markers;
aff26a2021-12-20Henrik Grubbström (Grubba)  }
c205b22021-04-09Henrik Grubbström (Grubba)  }
aff26a2021-12-20Henrik Grubbström (Grubba)  /* FIXME: XOR and XNOR not supported cf above. */ if ("071377-71-11371f"[op] == '1') { /* Secondary operator is AND. */ if (!tmp2) { free_type(tmp); return NULL; } if (!tmp) { free_type(tmp2); return NULL; } type_stack_mark(); push_finished_type(tmp); push_finished_type(tmp2); push_reverse_type(T_AND); } else { /* Secondary operator is OR. */ if (!tmp2) return tmp; if (!tmp) return tmp2; type_stack_mark(); push_finished_type(tmp); push_finished_type(tmp2); push_reverse_type(T_OR); } free_type(tmp); free_type(tmp2); return pop_unfinished_type();
c205b22021-04-09Henrik Grubbström (Grubba)  case T_AND:
aff26a2021-12-20Henrik Grubbström (Grubba)  /* op secondary * 0 0000 0 0000 * 1 0001 1 0001 * 2 0010 7 0111 * 3 0011 1, 3, 5, 7 0011 * 4 0100 1 0001 * 5 0101 1 0001 * 6 0110 - * 7 0111 1 0001 * 8 1000 7 0111 * 9 1001 - * 10 1010 7 0111 * 11 1011 7 0111 * 12 1100 1, 3, 5, 7 0011 * 13 1101 1 0001 * 14 1110 7 0111 * 15 1111 15 1111
bfbb5d2021-01-08Henrik Grubbström (Grubba)  * * Note that secondary ops 1 and 7 are swapped for T_AND and T_OR.
0727652021-01-05Henrik Grubbström (Grubba)  */
b98ea32020-10-10Henrik Grubbström (Grubba)  tmp = low_type_binop(op, a, b->car, remap, aflags, bflags, remap_flags); tmp2 = low_type_binop(op, a, b->cdr, remap, aflags, bflags, remap_flags);
bfbb5d2021-01-08Henrik Grubbström (Grubba)  /* FIXME: XOR and XNOR not supported cf above. */
aff26a2021-12-20Henrik Grubbström (Grubba)  if ("017311-17-77317f"[op] == '1') {
0727652021-01-05Henrik Grubbström (Grubba)  /* Secondary operator is AND. */ if (!tmp2) { free_type(tmp); return NULL; } if (!tmp) { free_type(tmp2); return NULL; }
bfbb5d2021-01-08Henrik Grubbström (Grubba)  if ((b->type == T_AND) && (op == PT_BINOP_AND)) { /* NB: Attempt to avoid keeping the result from inverted types, * in order to reduce type expansion. */ if (b->car->type == T_NOT) { free_type(tmp);
c97a452021-12-17Henrik Grubbström (Grubba)  tmp = remap_markers(b->car, remap,
bfbb5d2021-01-08Henrik Grubbström (Grubba)  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); } else if (b->cdr->type == T_NOT) { free_type(tmp2);
c97a452021-12-17Henrik Grubbström (Grubba)  tmp2 = remap_markers(b->cdr, remap,
bfbb5d2021-01-08Henrik Grubbström (Grubba)  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); } }
0727652021-01-05Henrik Grubbström (Grubba)  type_stack_mark(); push_finished_type(tmp); push_finished_type(tmp2); push_reverse_type(T_AND); } else { /* Secondary operator is OR. */ if (!tmp2) return tmp; if (!tmp) return tmp2; type_stack_mark(); push_finished_type(tmp); push_finished_type(tmp2); push_reverse_type(T_OR); }
b98ea32020-10-10Henrik Grubbström (Grubba)  free_type(tmp); free_type(tmp2); return pop_unfinished_type(); }
9c6b942021-05-20Henrik Grubbström (Grubba)  /*
79196e2021-12-16Henrik Grubbström (Grubba)  * NB: At this point a and b are either NULL, a basic type or a marker.
9c6b942021-05-20Henrik Grubbström (Grubba)  */
79196e2021-12-16Henrik Grubbström (Grubba)  loop: switch(a ? a->type : PIKE_T_UNKNOWN) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int marker = remap_marker(remap, a->type, remap_flags);
fda6742022-04-08Henrik Grubbström (Grubba)  a = NULL;
42e9be2021-12-24Henrik Grubbström (Grubba) 
79196e2021-12-16Henrik Grubbström (Grubba)  if (!marker) { break; }
fda6742022-04-08Henrik Grubbström (Grubba)  if (!lookup_marker(remap, marker, remap_flags, &a)) { break; }
42e9be2021-12-24Henrik Grubbström (Grubba)  tmp = low_type_binop(op, a, b, remap, aflags, bflags, remap_flags); free_type(a);
fda6742022-04-08Henrik Grubbström (Grubba)  store_marker(remap, marker, tmp, remap_flags);
78d2442022-01-02Henrik Grubbström (Grubba)  if ((op == PT_BINOP_AND) || (op == PT_BINOP_MINUS)) {
fda6742022-04-08Henrik Grubbström (Grubba)  store_marker(remap, marker | 0x100, tmp, remap_flags);
79196e2021-12-16Henrik Grubbström (Grubba)  }
78d2442022-01-02Henrik Grubbström (Grubba)  if (!tmp) return NULL;
42e9be2021-12-24Henrik Grubbström (Grubba)  free_type(tmp);
79196e2021-12-16Henrik Grubbström (Grubba)  type_stack_mark(); push_type(marker); return pop_unfinished_type(); } } switch(b ? b->type : PIKE_T_UNKNOWN) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int marker = remap_marker(remap, b->type, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
fda6742022-04-08Henrik Grubbström (Grubba)  b = NULL;
79196e2021-12-16Henrik Grubbström (Grubba)  if (!marker) { break; }
fda6742022-04-08Henrik Grubbström (Grubba)  if (!lookup_marker(remap, marker, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS, &b)) { break; }
42e9be2021-12-24Henrik Grubbström (Grubba)  tmp = low_type_binop(op, a, b, remap, aflags, bflags, remap_flags); free_type(b);
78d2442022-01-02Henrik Grubbström (Grubba)  /* FIXME: Do we need to invert for PT_BINOP_MINUS here? */
fda6742022-04-08Henrik Grubbström (Grubba)  store_marker(remap, marker, tmp, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
a3cd6c2022-04-07Henrik Grubbström (Grubba)  /* NB: We can only keep the marker in the PT_BINOP_AND case, * as in the other cases we do not have the corresponding * assignment in the result. * * See also the b->type == T_ASSIGN case further above. */ if ((op == PT_BINOP_AND) && tmp) {
fda6742022-04-08Henrik Grubbström (Grubba)  store_marker(remap, marker | 0x100, tmp, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
78d2442022-01-02Henrik Grubbström (Grubba) 
a3cd6c2022-04-07Henrik Grubbström (Grubba)  free_type(tmp); type_stack_mark(); push_type(marker); return pop_unfinished_type(); }
42e9be2021-12-24Henrik Grubbström (Grubba) 
a3cd6c2022-04-07Henrik Grubbström (Grubba)  return tmp;
79196e2021-12-16Henrik Grubbström (Grubba)  } }
9c6b942021-05-20Henrik Grubbström (Grubba)  /* Handle a or b being NULL. */ /* NB: We know that a != b due to an earlier test. */ if (!a) { if (op & PT_BINOP_INVERSE_MINUS) { if (!((b == void_type_string) && (aflags & PT_FLAG_CMP_VOIDABLE)) && !((b == zero_type_string) && (aflags & PT_FLAG_CMP_NULLABLE))) { add_ref(b); return b; } } return NULL; } if (!b) { if (op & PT_BINOP_MINUS) { if (!((a == void_type_string) && (bflags & PT_FLAG_CMP_VOIDABLE)) && !((a == zero_type_string) && (bflags & PT_FLAG_CMP_NULLABLE))) { add_ref(a); return a; } } return NULL; }
79196e2021-12-16Henrik Grubbström (Grubba)  /* * NB: At this point a and b are basic types. */
b98ea32020-10-10Henrik Grubbström (Grubba)  /* Check implicit casting. */ switch(TWOT(a->type & PIKE_T_MASK, b->type & PIKE_T_MASK)) {
2e99272021-12-07Henrik Grubbström (Grubba)  case TWOT(T_PROGRAM, T_PROGRAM):
cba2e52022-05-07Henrik Grubbström (Grubba)  if (a->car == object_type_string) { if (op & PT_BINOP_AND) { return remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); } } if (b->car == object_type_string) { if (op & PT_BINOP_AND) { return remap_markers(a, remap, remap_flags); } return NULL; } /* FALLTHRU */ case TWOT(T_PROGRAM, T_TYPE):
b98ea32020-10-10Henrik Grubbström (Grubba)  case TWOT(T_PROGRAM, T_FUNCTION): case TWOT(T_PROGRAM, T_MANY):
ceaee42022-04-09Henrik Grubbström (Grubba)  case TWOT(T_PROGRAM, PIKE_T_TRANSITIVE):
b98ea32020-10-10Henrik Grubbström (Grubba)  aret = a->car; a = low_object_lfun_type(aret, LFUN_CREATE);
f88ec42022-05-05Henrik Grubbström (Grubba)  if (a) goto loop; type_stack_mark(); push_finished_type(aret); push_type(PIKE_T_UNKNOWN); push_type(T_MANY); a = pop_unfinished_type(); ret = low_type_binop(op, a, b, remap, aflags, bflags, remap_flags); free_type(a); return ret;
b98ea32020-10-10Henrik Grubbström (Grubba)  case TWOT(T_FUNCTION, T_PROGRAM): case TWOT(T_MANY, T_PROGRAM):
ceaee42022-04-09Henrik Grubbström (Grubba)  case TWOT(PIKE_T_TRANSITIVE, T_PROGRAM):
b98ea32020-10-10Henrik Grubbström (Grubba)  bret = b->car; b = low_object_lfun_type(bret, LFUN_CREATE);
f88ec42022-05-05Henrik Grubbström (Grubba)  if (b) goto loop; type_stack_mark(); push_finished_type(bret); push_type(PIKE_T_UNKNOWN); push_type(T_MANY); b = pop_unfinished_type(); ret = low_type_binop(op, a, b, remap, aflags, bflags, remap_flags); free_type(b); return ret;
b98ea32020-10-10Henrik Grubbström (Grubba)  case TWOT(T_OBJECT, T_FUNCTION): case TWOT(T_OBJECT, T_MANY): case TWOT(T_OBJECT, T_PROGRAM): case TWOT(T_OBJECT, PIKE_T_TRANSITIVE): a = low_object_lfun_type(a, LFUN_CALL); if (!a) return NULL; goto loop; case TWOT(T_FUNCTION, T_OBJECT): case TWOT(T_MANY, T_OBJECT): case TWOT(T_PROGRAM, T_OBJECT): case TWOT(PIKE_T_TRANSITIVE, T_OBJECT): b = low_object_lfun_type(b, LFUN_CALL); if (!b) return NULL; goto loop; case TWOT(PIKE_T_TRANSITIVE, T_MANY):
b999ba2022-04-01Henrik Grubbström (Grubba)  if (op == PT_BINOP_AND) { type_stack_mark(); tmp = low_type_binop(op, a->car, b, remap, aflags, bflags, remap_flags); push_finished_type(tmp);
953a102022-04-01Henrik Grubbström (Grubba)  if (tmp || !a->car) { free_type(tmp); tmp = low_type_binop(op, a->cdr, b, NULL, aflags, bflags, remap_flags); if (tmp) { push_finished_type(tmp); free_type(tmp); push_reverse_type(PIKE_T_TRANSITIVE); } }
b999ba2022-04-01Henrik Grubbström (Grubba)  return pop_unfinished_type();
f88ec42022-05-05Henrik Grubbström (Grubba)  } else if (op == PT_BINOP_MINUS) { if ((!b->car || (b->car == zero_type_string)) && ((b->cdr == mixed_type_string) || (b->cdr == any_type_string))) { return NULL; }
b999ba2022-04-01Henrik Grubbström (Grubba)  } /* FALLTHRU */ case TWOT(PIKE_T_TRANSITIVE, T_FUNCTION):
4f759e2022-04-11Henrik Grubbström (Grubba)  tmp = expand_transitive_remap(a, NULL, 0);
b98ea32020-10-10Henrik Grubbström (Grubba)  ret = low_type_binop(op, tmp, b, remap, aflags, bflags, remap_flags); free_type(tmp); return ret; case TWOT(T_MANY, PIKE_T_TRANSITIVE):
b999ba2022-04-01Henrik Grubbström (Grubba)  if (op == PT_BINOP_AND) { type_stack_mark(); tmp = low_type_binop(op, a, b->car, remap, aflags, bflags, remap_flags); push_finished_type(tmp);
953a102022-04-01Henrik Grubbström (Grubba)  if (tmp || !b->car) { free_type(tmp); tmp = low_type_binop(op, a, b->cdr, NULL, aflags, bflags, remap_flags); if (tmp) { push_finished_type(tmp); free_type(tmp); push_reverse_type(PIKE_T_TRANSITIVE); } }
b999ba2022-04-01Henrik Grubbström (Grubba)  return pop_unfinished_type(); } /* FALLTHRU */ case TWOT(T_FUNCTION, PIKE_T_TRANSITIVE):
4f759e2022-04-11Henrik Grubbström (Grubba)  tmp = expand_transitive_remap(b, NULL, 0);
b98ea32020-10-10Henrik Grubbström (Grubba)  ret = low_type_binop(op, a, tmp, remap, aflags, bflags, remap_flags); free_type(tmp); return ret;
b999ba2022-04-01Henrik Grubbström (Grubba)  case TWOT(PIKE_T_TRANSITIVE, PIKE_T_TRANSITIVE): /* FIXME: Is there a better approach? */
4f759e2022-04-11Henrik Grubbström (Grubba)  tmp = expand_transitive_remap(a, NULL, 0);
b999ba2022-04-01Henrik Grubbström (Grubba)  ret = low_type_binop(op, tmp, b, remap, aflags, bflags, remap_flags); free_type(tmp); return ret;
b98ea32020-10-10Henrik Grubbström (Grubba)  case TWOT(T_FUNCTION, PIKE_T_OPERATOR): case TWOT(PIKE_T_OPERATOR, T_FUNCTION): type_stack_mark(); push_finished_type(b);
e228172020-10-13Henrik Grubbström (Grubba)  push_finished_type(a); push_binop(op);
b98ea32020-10-10Henrik Grubbström (Grubba)  return pop_unfinished_type(); case TWOT(T_FUNCTION, T_FUNCTION): case TWOT(T_FUNCTION, T_MANY): case TWOT(T_MANY, T_FUNCTION): case TWOT(T_MANY, T_MANY): { int nargs; struct pike_type *ai = a; struct pike_type *bi = b;
1829ed2021-01-20Henrik Grubbström (Grubba)  enum pt_cmp_flags avoidable = 0; enum pt_cmp_flags bvoidable = 0;
b98ea32020-10-10Henrik Grubbström (Grubba) 
1f5b1d2022-04-13Henrik Grubbström (Grubba)  /* FIXME: What about function(__unknown__...:mixed|void)? */ if ((b->type == T_MANY) && !b->car && (b->cdr == mixed_type_string)) { /* Common case. function(__unknown__...:mixed) */ if (op == PT_BINOP_AND) { return remap_markers(a, remap, remap_flags); } return NULL; } if ((a->type == T_MANY) && !a->car && (a->cdr == mixed_type_string)) { /* Common case. function(__unknown__...:mixed) */ if (op == PT_BINOP_AND) { return remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); } add_ref(a); return a; }
b98ea32020-10-10Henrik Grubbström (Grubba)  type_stack_mark();
1829ed2021-01-20Henrik Grubbström (Grubba)  switch(op) { case PT_BINOP_AND: /* NB: For simplicity in the (common case) * many(assign(m, mixed), m), * we expand the many node (as required) to * function(assign(m, mixed), many(assign(m, mixed), m)), * and leave it to the evaluator to join the multiple * assignments with or. The alternative (and stricter) would * be to allocate a new marker for each step of the expansion * and to have explicit or nodes: * function(assign(m1, mixed), * many(assign(m2, mixed), or(m1, m2))).
b98ea32020-10-10Henrik Grubbström (Grubba)  */
1829ed2021-01-20Henrik Grubbström (Grubba)  while(1) { /* Invariant: * ai->type and bi->type are either T_FUNCTION or T_MANY. */
b98ea32020-10-10Henrik Grubbström (Grubba) 
1829ed2021-01-20Henrik Grubbström (Grubba)  /* Check the argument. */
b98ea32020-10-10Henrik Grubbström (Grubba) 
1829ed2021-01-20Henrik Grubbström (Grubba)  /* NB: The MANY argument is always voidable. */ if (ai->type == T_MANY) avoidable |= PT_FLAG_CMP_VOIDABLE; if (bi->type == T_MANY) bvoidable |= PT_FLAG_CMP_VOIDABLE;
b98ea32020-10-10Henrik Grubbström (Grubba) 
1829ed2021-01-20Henrik Grubbström (Grubba) #if 0 fprintf(stderr, "arg_check(op: 0x%x, ", op); simple_describe_type(ai); fprintf(stderr, " (%d), ", avoidable); simple_describe_type(bi); fprintf(stderr, " (%d))\n\n", bvoidable); #endif
b98ea32020-10-10Henrik Grubbström (Grubba) 
1829ed2021-01-20Henrik Grubbström (Grubba)  /* FIXME: Use implicit nullable only for legacy types. */ /* NOTE: Intentional use of PT_BINOP_OR below! * Note that for function types a larger type for * the arguments implies that the function type * is stricter. This is a DeMorgan-style effect * due to the implicit ALL and EXIST operators * for arguments in function types. Eg there are * many more functions that accept 0 as an argument * than there are functions that accept any integer. * Thus function(int:mixed) is a stricter type * than function(zero:mixed). */ tmp = low_type_binop(PT_BINOP_OR, ai->car, bi->car, remap, avoidable | PT_FLAG_CMP_NULLABLE, bvoidable | PT_FLAG_CMP_NULLABLE, remap_flags); /* Advance to the next argument. */ if (ai->type == T_FUNCTION) { ai = ai->cdr;
8e9d462020-12-28Henrik Grubbström (Grubba)  }
1829ed2021-01-20Henrik Grubbström (Grubba)  if (bi->type == T_FUNCTION) { bi = bi->cdr;
8e9d462020-12-28Henrik Grubbström (Grubba)  }
1829ed2021-01-20Henrik Grubbström (Grubba)  if ((ai->type != T_FUNCTION) && (ai->type != T_MANY)) { if (aret) { Pike_fatal("Unsupported type operation.\n");
b98ea32020-10-10Henrik Grubbström (Grubba)  }
23608c2021-09-26Henrik Grubbström (Grubba)  free_type(tmp);
1829ed2021-01-20Henrik Grubbström (Grubba)  break; } if ((bi->type != T_FUNCTION) && (bi->type != T_MANY)) { if (bret) { Pike_fatal("Unsupported type operation.\n"); }
23608c2021-09-26Henrik Grubbström (Grubba)  free_type(tmp);
1829ed2021-01-20Henrik Grubbström (Grubba)  break; } if (remap_flags & PT_FLAG_REMAP_TRACE) { fprintf(stderr, "tmp: "); simple_describe_type(tmp); fprintf(stderr, "\n");
b98ea32020-10-10Henrik Grubbström (Grubba)  }
1829ed2021-01-20Henrik Grubbström (Grubba)  push_finished_type(tmp); free_type(tmp);
b98ea32020-10-10Henrik Grubbström (Grubba)  if (avoidable && bvoidable) { /* Time to check the return types. */ if (!aret) aret = ai->cdr; if (!bret) bret = bi->cdr; tmp = low_type_binop(op, aret, bret, remap,
8aa90a2020-12-20Henrik Grubbström (Grubba)  0, 0, remap_flags);
70cdaa2020-12-06Henrik Grubbström (Grubba)  if (remap_flags & PT_FLAG_REMAP_TRACE) { fprintf(stderr, "ret_tmp: "); simple_describe_type(tmp); fprintf(stderr, "\n"); }
b98ea32020-10-10Henrik Grubbström (Grubba)  if (!tmp) goto function_fail;
9226132020-12-31Henrik Grubbström (Grubba)  nargs = peek_stack_mark();
b98ea32020-10-10Henrik Grubbström (Grubba)  push_finished_type(tmp); free_type(tmp); nargs--; push_reverse_type(T_MANY); while (nargs--) { push_reverse_type(T_FUNCTION); } return pop_unfinished_type(); }
1829ed2021-01-20Henrik Grubbström (Grubba)  } break; case PT_BINOP_MINUS: /* Subtraction (A - B)
0b7cb52021-03-19Henrik Grubbström (Grubba)  *
610e572021-05-03Henrik Grubbström (Grubba)  * T_FUNCTION(A, X) - T_FUNCTION(B, Y) ==
1829ed2021-01-20Henrik Grubbström (Grubba)  *
610e572021-05-03Henrik Grubbström (Grubba)  * B - A == Ø && X - Y == Ø * ==> Ø # Full overlap
1829ed2021-01-20Henrik Grubbström (Grubba)  *
610e572021-05-03Henrik Grubbström (Grubba)  * B - A == Ø && X - Y == Z # Argument overlap
8c0c8e2022-04-10Henrik Grubbström (Grubba)  * ==> T_FUNCTION(A, Z) # (Recurse)
1829ed2021-01-20Henrik Grubbström (Grubba)  *
610e572021-05-03Henrik Grubbström (Grubba)  * B - A == B ==> T_FUNCTION(A, X) # No overlap
8c0c8e2022-04-10Henrik Grubbström (Grubba)  * # No need to recurse
1829ed2021-01-20Henrik Grubbström (Grubba)  *
8c0c8e2022-04-10Henrik Grubbström (Grubba)  * B - A == C && X - Y == Z # Partial overlap * ==> T_FUNCTION(A - B, X) | # Keep and * T_FUNCTION(A, Z) # Recurse * * T_FUNCTION(A - B, X) | T_FUNCTION(A, X - Y)
1829ed2021-01-20Henrik Grubbström (Grubba)  *
610e572021-05-03Henrik Grubbström (Grubba)  * T_MANY analogous with T_MANY substituted for T_FUNCTION above.
1829ed2021-01-20Henrik Grubbström (Grubba)  */ /* Check the argument. */ /* NB: The MANY argument is always voidable. */ if (ai->type == T_MANY) avoidable |= PT_FLAG_CMP_VOIDABLE; if (bi->type == T_MANY) bvoidable |= PT_FLAG_CMP_VOIDABLE; #if 0 fprintf(stderr, "arg_check(op: 0x%x, ", op); simple_describe_type(ai); fprintf(stderr, " (%d), ", avoidable); simple_describe_type(bi); fprintf(stderr, " (%d))\n\n", bvoidable); #endif
610e572021-05-03Henrik Grubbström (Grubba)  if (!bi->car) { /* Common case */ tmp = NULL; } else {
8c0c8e2022-04-10Henrik Grubbström (Grubba)  /* FIXME: Use implicit nullable only for legacy types. * FIXME: What about PT_FLAG_CMP_VOID_IS_NULL? */
610e572021-05-03Henrik Grubbström (Grubba)  tmp = low_type_binop(PT_BINOP_MINUS, bi->car, ai->car, remap, bvoidable | PT_FLAG_CMP_NULLABLE | PT_FLAG_CMP_INSEPARABLE, avoidable | PT_FLAG_CMP_NULLABLE | PT_FLAG_CMP_INSEPARABLE,
25862b2021-05-21Henrik Grubbström (Grubba)  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
610e572021-05-03Henrik Grubbström (Grubba)  if (tmp) {
8c0c8e2022-04-10Henrik Grubbström (Grubba)  /* No or not full overlap. */
9851b92021-12-28Henrik Grubbström (Grubba)  if ((ai->car == void_type_string) && (tmp != bi->car) && (aflags & PT_FLAG_CMP_IGNORE_EXTRA_ARGS)) { /* End of argument list for a, and it is valid to end the * argument list here (void matched), and a implicitly * ignores any further arguments. */ free_type(tmp); tmp = NULL; } else {
8c0c8e2022-04-10Henrik Grubbström (Grubba)  if (tmp == bi->car) { /* Common case, no overlap. */ pop_stack_mark(); free_type(tmp); add_ref(ai); return ai;
9851b92021-12-28Henrik Grubbström (Grubba)  } free_type(tmp);
8c0c8e2022-04-10Henrik Grubbström (Grubba)  tmp = low_type_binop(PT_BINOP_MINUS, ai->car, bi->car, remap, avoidable | PT_FLAG_CMP_NULLABLE | PT_FLAG_CMP_INSEPARABLE, bvoidable | PT_FLAG_CMP_NULLABLE | PT_FLAG_CMP_INSEPARABLE, remap_flags); if (tmp == ai->car) { /* No overlap. * * The first overlap test likely failed due * to remapping. */ pop_stack_mark(); free_type(tmp); add_ref(ai); return ai; } push_finished_type(ai->cdr); push_finished_type(tmp); push_type(ai->type); free_type(tmp); tmp = NULL;
610e572021-05-03Henrik Grubbström (Grubba)  } } }
1829ed2021-01-20Henrik Grubbström (Grubba)  /* Advance to the next argument. */ if (ai->type == T_FUNCTION) { ai = ai->cdr; } if (bi->type == T_FUNCTION) { bi = bi->cdr; } if ((ai->type != T_FUNCTION) && (ai->type != T_MANY)) { if (aret) { Pike_fatal("Unsupported type operation.\n"); } } if ((bi->type != T_FUNCTION) && (bi->type != T_MANY)) { if (bret) { Pike_fatal("Unsupported type operation.\n"); } } if (avoidable && bvoidable) {
610e572021-05-03Henrik Grubbström (Grubba)  /* Both a & b are T_MANY. Check the return type. */
1829ed2021-01-20Henrik Grubbström (Grubba)  if (!aret) aret = ai->cdr; if (!bret) bret = bi->cdr;
8e9d462020-12-28Henrik Grubbström (Grubba) 
1829ed2021-01-20Henrik Grubbström (Grubba)  /* NB: Ignore the return type if matching against void. */
fa95442022-05-07Henrik Grubbström (Grubba)  if (bret != void_type_string) { tmp = low_type_binop(PT_BINOP_MINUS, aret, bret, remap, PT_FLAG_CMP_VOIDABLE, 0, remap_flags);
1829ed2021-01-20Henrik Grubbström (Grubba) 
fa95442022-05-07Henrik Grubbström (Grubba)  if (tmp) { /* Not full overlap for the return value. */ push_finished_type(tmp); push_finished_type(a->car); push_type(T_MANY); free_type(tmp); } else { push_type(PIKE_T_UNKNOWN); }
8c0c8e2022-04-10Henrik Grubbström (Grubba)  } else { push_type(PIKE_T_UNKNOWN);
8e9d462020-12-28Henrik Grubbström (Grubba)  }
8c0c8e2022-04-10Henrik Grubbström (Grubba)  } else { /* Recurse. */ tmp = low_type_binop(PT_BINOP_MINUS, ai, bi, remap, aflags, bflags, remap_flags);
610e572021-05-03Henrik Grubbström (Grubba) 
8c0c8e2022-04-10Henrik Grubbström (Grubba)  if (tmp) { push_finished_type(tmp); push_finished_type(a->car); push_type(PIKE_T_FUNCTION); free_type(tmp); } else { push_type(PIKE_T_UNKNOWN); } }
610e572021-05-03Henrik Grubbström (Grubba) 
8c0c8e2022-04-10Henrik Grubbström (Grubba)  while (peek_stack_mark() > 1) { push_type(T_OR);
1829ed2021-01-20Henrik Grubbström (Grubba)  }
8c0c8e2022-04-10Henrik Grubbström (Grubba)  return pop_unfinished_type();
0b7cb52021-03-19Henrik Grubbström (Grubba) 
fb51ce2021-01-25Henrik Grubbström (Grubba)  default: /* Fall back to complex_function below. */ break;
b98ea32020-10-10Henrik Grubbström (Grubba)  }
e029472020-10-16Henrik Grubbström (Grubba)  complex_function:
8c0c8e2022-04-10Henrik Grubbström (Grubba)  /* Either of ai and/or bi is a complex type. */
e029472020-10-16Henrik Grubbström (Grubba) 
e228172020-10-13Henrik Grubbström (Grubba)  if (op != PT_BINOP_AND) {
8c0c8e2022-04-10Henrik Grubbström (Grubba)  compiler_discard_type(); type_stack_mark(); push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); push_remap_markers(a, remap, remap_flags); push_binop(op); return pop_unfinished_type();
b98ea32020-10-10Henrik Grubbström (Grubba)  }
8c0c8e2022-04-10Henrik Grubbström (Grubba)  nargs = peek_stack_mark(); if ((ai && (ai->type == PIKE_T_TRANSITIVE)) || (bi && (bi->type == PIKE_T_TRANSITIVE))) { /* Expand ai and/or bi. */ tmp = low_type_binop(op, ai, bi, remap, aflags, bflags, remap_flags); push_finished_type(tmp); free_type(tmp); } else { push_remap_markers(bi, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); push_remap_markers(ai, remap, remap_flags);
b98ea32020-10-10Henrik Grubbström (Grubba) 
8c0c8e2022-04-10Henrik Grubbström (Grubba)  push_binop(op); }
b98ea32020-10-10Henrik Grubbström (Grubba)  while (nargs--) { push_reverse_type(T_FUNCTION); } return pop_unfinished_type(); function_fail:
8e9d462020-12-28Henrik Grubbström (Grubba)  compiler_discard_type();
b98ea32020-10-10Henrik Grubbström (Grubba)  return NULL; } case TWOT(T_VOID, T_ZERO):
44a5bc2021-04-10Henrik Grubbström (Grubba)  if (aflags & PT_FLAG_CMP_VOID_IS_ZERO) { a = zero_type_string; goto full_loop; }
b98ea32020-10-10Henrik Grubbström (Grubba)  if (op & PT_BINOP_AND) {
9e5b372021-01-18Henrik Grubbström (Grubba)  if (bflags & PT_FLAG_CMP_VOIDABLE) { /* Return void. */ add_ref(a); return a; }
b98ea32020-10-10Henrik Grubbström (Grubba)  /* Return zero. */ add_ref(b); return b;
0e4ccd2021-02-04Henrik Grubbström (Grubba)  } else if (op & PT_BINOP_MINUS) { if (!(bflags & PT_FLAG_CMP_VOIDABLE)) { /* Return void. */ add_ref(a); return a; }
b98ea32020-10-10Henrik Grubbström (Grubba)  } return NULL; case TWOT(T_ZERO, T_VOID):
44a5bc2021-04-10Henrik Grubbström (Grubba)  if (bflags & PT_FLAG_CMP_VOID_IS_ZERO) { b = zero_type_string; goto full_loop; }
b98ea32020-10-10Henrik Grubbström (Grubba)  if (op & PT_BINOP_AND) {
9e5b372021-01-18Henrik Grubbström (Grubba)  if (aflags & PT_FLAG_CMP_VOIDABLE) { /* Return void. */ add_ref(b); return b; }
b98ea32020-10-10Henrik Grubbström (Grubba)  /* Return zero. */ add_ref(a); return a;
0e4ccd2021-02-04Henrik Grubbström (Grubba)  } else if (op & PT_BINOP_MINUS) { if (!(aflags & PT_FLAG_CMP_VOIDABLE)) { /* Return zero. */ add_ref(a); return a; }
b98ea32020-10-10Henrik Grubbström (Grubba)  } return NULL; case TWOT(T_ZERO, T_INT):
555e922021-01-10Henrik Grubbström (Grubba)  if (!(bflags & PT_FLAG_CMP_NULLABLE)) { a = int0_type_string; }
b98ea32020-10-10Henrik Grubbström (Grubba)  break; case TWOT(T_INT, T_ZERO):
555e922021-01-10Henrik Grubbström (Grubba)  if (!(aflags & PT_FLAG_CMP_NULLABLE)) { b = int0_type_string; }
b98ea32020-10-10Henrik Grubbström (Grubba)  break; case TWOT(T_TYPE, T_TYPE): tmp = low_type_binop(op, a->car, b->car, remap,
8aa90a2020-12-20Henrik Grubbström (Grubba)  0, 0, remap_flags);
b98ea32020-10-10Henrik Grubbström (Grubba)  if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); if (a->type == b->type) { push_type(a->type); } else { push_type(T_TYPE); } free_type(tmp); return pop_unfinished_type();
2e99272021-12-07Henrik Grubbström (Grubba)  case TWOT(T_TYPE, T_PROGRAM):
b98ea32020-10-10Henrik Grubbström (Grubba)  case TWOT(T_TYPE, T_FUNCTION): case TWOT(T_TYPE, T_MANY): case TWOT(T_TYPE, PIKE_T_TRANSITIVE): type_stack_mark(); push_finished_type(a->car); push_type(T_VOID); push_type(T_MANY); push_type(T_MIXED); push_type(T_FUNCTION); tmp = pop_unfinished_type(); ret = low_type_binop(op, tmp, b, remap, aflags, bflags, remap_flags); free_type(tmp); return ret; case TWOT(T_FUNCTION, T_TYPE): case TWOT(T_MANY, T_TYPE): case TWOT(PIKE_T_TRANSITIVE, T_TYPE): type_stack_mark(); push_finished_type(b->car); push_type(T_VOID); push_type(T_MANY); push_type(T_MIXED); push_type(T_FUNCTION); tmp = pop_unfinished_type(); ret = low_type_binop(op, a, tmp, remap, aflags, bflags, remap_flags); free_type(tmp); return ret; #if 0 /* FIXME: */ case PIKE_T_RING: #endif } if (a->type != b->type) {
e755932021-02-15Henrik Grubbström (Grubba)  if (a->type == T_VOID) { if (bflags & PT_FLAG_CMP_VOIDABLE) { b = a; goto recur; }
e50f9a2021-03-21Henrik Grubbström (Grubba)  if (aflags & (PT_FLAG_CMP_NULLABLE | PT_FLAG_CMP_VOID_IS_ZERO)) {
e755932021-02-15Henrik Grubbström (Grubba)  a = zero_type_string; goto recur; }
e9d6202020-12-13Henrik Grubbström (Grubba)  }
e755932021-02-15Henrik Grubbström (Grubba)  if (b->type == T_VOID) {
213b572022-05-07Henrik Grubbström (Grubba)  if (op & PT_BINOP_AND) { if (aflags & PT_FLAG_CMP_VOIDABLE) { a = b; goto recur; }
e755932021-02-15Henrik Grubbström (Grubba)  }
e50f9a2021-03-21Henrik Grubbström (Grubba)  if (bflags & (PT_FLAG_CMP_NULLABLE | PT_FLAG_CMP_VOID_IS_ZERO)) {
e755932021-02-15Henrik Grubbström (Grubba)  b = zero_type_string; goto recur;
b5cd1e2021-01-17Henrik Grubbström (Grubba)  } }
e755932021-02-15Henrik Grubbström (Grubba)  if (a->type != T_VOID) { if (b->type == T_MIXED) { switch(op & PT_BINOP_B) { case 0: return NULL; case PT_BINOP_AND:
c97a452021-12-17Henrik Grubbström (Grubba)  return remap_markers(a, remap, remap_flags);
e755932021-02-15Henrik Grubbström (Grubba)  case PT_BINOP_INVERSE_MINUS:
0b7cb52021-03-19Henrik Grubbström (Grubba)  if (bflags & PT_FLAG_CMP_INSEPARABLE) { return NULL; }
e755932021-02-15Henrik Grubbström (Grubba)  type_stack_mark();
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(a, remap, remap_flags);
e755932021-02-15Henrik Grubbström (Grubba)  push_type(T_NOT); return pop_unfinished_type(); default: add_ref(b); return b; }
b5cd1e2021-01-17Henrik Grubbström (Grubba)  }
555e922021-01-10Henrik Grubbström (Grubba)  }
e755932021-02-15Henrik Grubbström (Grubba)  if (b->type != T_VOID) { if (a->type == T_MIXED) { switch(op & PT_BINOP_A) { case 0: return NULL; case PT_BINOP_AND:
c97a452021-12-17Henrik Grubbström (Grubba)  return remap_markers(b, remap,
e755932021-02-15Henrik Grubbström (Grubba)  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); case PT_BINOP_MINUS:
0b7cb52021-03-19Henrik Grubbström (Grubba)  if (aflags & PT_FLAG_CMP_INSEPARABLE) { return NULL; }
e755932021-02-15Henrik Grubbström (Grubba)  type_stack_mark();
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(b, remap,
b5cd1e2021-01-17Henrik Grubbström (Grubba)  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
e755932021-02-15Henrik Grubbström (Grubba)  push_type(T_NOT); return pop_unfinished_type(); default: add_ref(a); return a; }
555e922021-01-10Henrik Grubbström (Grubba)  } }
b0e7602022-01-06Henrik Grubbström (Grubba)  if (a->type == T_NOT) { /* Rotate the opcode 2 bits. * * This converts A to ~A and vice versa. */ op = ((op << 2) | (op >> 2)) & PT_BINOP_ALL; return low_type_binop(op, a->car, b, remap, aflags, bflags, remap_flags); } if (b->type == T_NOT) { /* Swap the bits of the opcode pairwise. * * This converts B to ~B and vice versa. */ op = (((op & PT_BINOP_B) << 1) | ((op >> 1) & PT_BINOP_B)) & PT_BINOP_ALL; return low_type_binop(op, a, b->car, remap, aflags, bflags, remap_flags); }
b81c0a2021-11-17Henrik Grubbström (Grubba)  /* NB: TWOT(T_INT, T_ZERO) and TWOT(T_ZERO, T_INT) have * been handled above. */ if (((a->type == T_ZERO) || (a->type == T_INT)) && (bflags & PT_FLAG_CMP_NULLABLE)) { /* FIXME: Only valid for AND and MINUS. */
3b04b02020-12-24Henrik Grubbström (Grubba)  b = zero_type_string;
b81c0a2021-11-17Henrik Grubbström (Grubba)  bflags &= ~PT_FLAG_CMP_NULLABLE;
3b04b02020-12-24Henrik Grubbström (Grubba)  goto recur; }
b81c0a2021-11-17Henrik Grubbström (Grubba)  if (((b->type == T_ZERO) || (b->type == T_INT)) && (aflags & PT_FLAG_CMP_NULLABLE)) { /* FIXME: Only valid for AND and MINUS. */ if (op == PT_BINOP_AND) { a = zero_type_string; } aflags &= ~PT_FLAG_CMP_NULLABLE;
3b04b02020-12-24Henrik Grubbström (Grubba)  goto recur; }
e9d6202020-12-13Henrik Grubbström (Grubba) 
b98ea32020-10-10Henrik Grubbström (Grubba)  if (((a->type & PIKE_T_MASK) == PIKE_T_OPERATOR) || ((b->type & PIKE_T_MASK) == PIKE_T_OPERATOR)) { type_stack_mark();
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(b, remap,
b98ea32020-10-10Henrik Grubbström (Grubba)  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(a, remap, remap_flags);
e228172020-10-13Henrik Grubbström (Grubba)  push_binop(op);
b98ea32020-10-10Henrik Grubbström (Grubba)  return pop_unfinished_type(); }
c97a452021-12-17Henrik Grubbström (Grubba) 
6ac8402020-11-03Henrik Grubbström (Grubba)  /* NB: We know that a and b do not intersect, so the operations * come in pairs and complementary pairs. */ type_stack_mark(); switch(op) { case PT_BINOP_NONE: case PT_BINOP_AND: pop_stack_mark(); return NULL; case PT_BINOP_NAND: case PT_BINOP_ALL: push_type(T_MIXED); break; case PT_BINOP_MINUS: case PT_BINOP_A:
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(a, remap, remap_flags);
6ac8402020-11-03Henrik Grubbström (Grubba)  break; case PT_BINOP_NOT_A: case PT_BINOP_NOT_A_OR_B:
0b7cb52021-03-19Henrik Grubbström (Grubba)  if (aflags & PT_FLAG_CMP_INSEPARABLE) { pop_stack_mark(); return NULL; }
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(a, remap, remap_flags);
6ac8402020-11-03Henrik Grubbström (Grubba)  push_type(T_NOT); break; case PT_BINOP_INVERSE_MINUS: case PT_BINOP_B:
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(b, remap,
6ac8402020-11-03Henrik Grubbström (Grubba)  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); break; case PT_BINOP_NOT_B: case PT_BINOP_A_OR_NOT_B:
0b7cb52021-03-19Henrik Grubbström (Grubba)  if (bflags & PT_FLAG_CMP_INSEPARABLE) { pop_stack_mark(); return NULL; }
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(b, remap,
6ac8402020-11-03Henrik Grubbström (Grubba)  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); push_type(T_NOT); break; case PT_BINOP_OR: case PT_BINOP_XOR:
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(b, remap,
6ac8402020-11-03Henrik Grubbström (Grubba)  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(a, remap, remap_flags);
6ac8402020-11-03Henrik Grubbström (Grubba)  push_type(T_OR); break; case PT_BINOP_NOR: case PT_BINOP_XNOR:
0b7cb52021-03-19Henrik Grubbström (Grubba)  if ((aflags | bflags) & PT_FLAG_CMP_INSEPARABLE) { pop_stack_mark(); return NULL; }
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(b, remap,
6ac8402020-11-03Henrik Grubbström (Grubba)  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(a, remap, remap_flags);
6ac8402020-11-03Henrik Grubbström (Grubba)  push_type(T_OR); push_type(T_NOT); break; } return pop_unfinished_type();
b98ea32020-10-10Henrik Grubbström (Grubba)  }
a0ba322020-12-27Henrik Grubbström (Grubba)  /* Invariant: a->type == b->type. */
b98ea32020-10-10Henrik Grubbström (Grubba)  switch(a->type) {
b0e7602022-01-06Henrik Grubbström (Grubba)  case T_NOT: /* Reverse the order of the bits. * * 1 <=> 8 AND <=> NOR * 2 <=> 4 MINUS <=> INVERSE_MINUS * * This inverts both A and B. */ { int i; enum pt_binop newop = 0; for (i = 0; i < 4; i++) { newop <<= 1; if (op & 1) { newop |= 1; } op >>= 1; } return low_type_binop(newop, a->car, b->car, remap, aflags, bflags, remap_flags); }
b98ea32020-10-10Henrik Grubbström (Grubba)  case T_VOID: case T_ZERO: case T_FLOAT: /* Not reached. Should be handled by the a == b test at * the beginning of the function. */ Pike_fatal("Type hashing has duplicates.\n"); return NULL; case T_INT: {
1aaf0a2020-10-15Henrik Grubbström (Grubba)  INT32 bounds[6] = { MIN_INT32, }; /* Start sentinel. */
b98ea32020-10-10Henrik Grubbström (Grubba)  int ab[6] = { 0, 0, }; int i; int nbounds = 1; INT32 bound; INT32 other;
1aaf0a2020-10-15Henrik Grubbström (Grubba)  /* * Implementation notes: * * bounds[] contains the values where the set changes in order * from smallest to largest. It always contains at least the * start sentinel value (MIN_INT32) at position 0. * * ab[] contains one bit for each of a and b indicating whether * the corresponding value in bounds[] is a member of a and/or b. * * nbounds contains the number of valid entries in bounds[] and ab[]. * * To avoid issues with overflow and similar the end sentinel * (ie MAX_INT32 + 1) is not in bounds[]. * * NB: The bits in ab are selected so that they match
b98ea32020-10-10Henrik Grubbström (Grubba)  * the shifts for the minterms in enum pt_binop.
1aaf0a2020-10-15Henrik Grubbström (Grubba)  * * bounds[] and ab[] are created with insert sort.
b98ea32020-10-10Henrik Grubbström (Grubba)  */ bound = CAR_TO_INT(a); for (i = nbounds; i-- && bounds[i] > bound;) { ab[i] |= 2; } if (bounds[i] < bound) { /* We need to insert a bound. */ memmove(bounds + i + 1, bounds + i, sizeof(bounds[i]) * (nbounds - i));
35791c2020-10-17Henrik Grubbström (Grubba)  memmove(ab + i + 1, ab + i, sizeof(ab[i]) * (nbounds - i)); i++;
b98ea32020-10-10Henrik Grubbström (Grubba)  nbounds++; bounds[i] = bound;
35791c2020-10-17Henrik Grubbström (Grubba)  ab[i] |= 2;
b98ea32020-10-10Henrik Grubbström (Grubba)  } else if (bounds[i] == bound) { ab[i] |= 2; } bound = CDR_TO_INT(a); if (bound < MAX_INT32) { bound++; for (i = nbounds; i-- && bounds[i] > bound;) { ab[i] &= ~2; } if (bounds[i] < bound) { /* We need to insert a bound. */ memmove(bounds + i + 1, bounds + i, sizeof(bounds[i]) * (nbounds - i));
35791c2020-10-17Henrik Grubbström (Grubba)  memmove(ab + i + 1, ab + i, sizeof(ab[i]) * (nbounds - i)); i++;
b98ea32020-10-10Henrik Grubbström (Grubba)  nbounds++; bounds[i] = bound;
35791c2020-10-17Henrik Grubbström (Grubba)  ab[i] &= ~2;
b98ea32020-10-10Henrik Grubbström (Grubba)  } else if (bounds[i] == bound) { ab[i] &= ~2; } } bound = CAR_TO_INT(b); for (i = nbounds; i-- && bounds[i] > bound;) { ab[i] |= 1; } if (bounds[i] < bound) { /* We need to insert a bound. */ memmove(bounds + i + 1, bounds + i, sizeof(bounds[i]) * (nbounds - i));
35791c2020-10-17Henrik Grubbström (Grubba)  memmove(ab + i + 1, ab + i, sizeof(ab[i]) * (nbounds - i)); i++;
b98ea32020-10-10Henrik Grubbström (Grubba)  nbounds++; bounds[i] = bound;
35791c2020-10-17Henrik Grubbström (Grubba)  ab[i] |= 1;
b98ea32020-10-10Henrik Grubbström (Grubba)  } else if (bounds[i] == bound) { ab[i] |= 1; } bound = CDR_TO_INT(b); if (bound < MAX_INT32) { bound++; for (i = nbounds; i-- && bounds[i] > bound;) { ab[i] &= ~1; } if (bounds[i] < bound) { /* We need to insert a bound. */ memmove(bounds + i + 1, bounds + i, sizeof(bounds[i]) * (nbounds - i));
35791c2020-10-17Henrik Grubbström (Grubba)  memmove(ab + i + 1, ab + i, sizeof(ab[i]) * (nbounds - i)); i++;
b98ea32020-10-10Henrik Grubbström (Grubba)  nbounds++; bounds[i] = bound;
35791c2020-10-17Henrik Grubbström (Grubba)  ab[i] &= ~1;
b98ea32020-10-10Henrik Grubbström (Grubba)  } else if (bounds[i] == bound) { ab[i] &= ~1; } } type_stack_mark(); for (i = 0; i < nbounds;) { bound = MAX_INT32;
35791c2020-10-17Henrik Grubbström (Grubba)  for (;i < nbounds; i++) {
b98ea32020-10-10Henrik Grubbström (Grubba)  if ((PT_BINOP_NOR >> ab[i]) & op) { /* Found start of range. */ bound = bounds[i];
35791c2020-10-17Henrik Grubbström (Grubba)  break;
b98ea32020-10-10Henrik Grubbström (Grubba)  } } if (i == nbounds) break; for (; i < nbounds; i++) { if (!((PT_BINOP_NOR >> ab[i]) & op)) { /* Found end of range. */ break; } } if (i < nbounds) { push_int_type(bound, bounds[i]-1); } else { push_int_type(bound, MAX_INT32); } } nbounds = peek_stack_mark(); if (!nbounds) { pop_stack_mark(); return NULL; }
0b7cb52021-03-19Henrik Grubbström (Grubba)  if ((op == PT_BINOP_MINUS) && (aflags & PT_FLAG_CMP_INSEPARABLE)) { if ((nbounds != 1) || (peek_type_stack() != a)) { compiler_discard_type(); return NULL; } }
b98ea32020-10-10Henrik Grubbström (Grubba)  /* NB: Loop starts at 1! */ for (i = 1; i < nbounds; i++) { push_type(T_OR); } return pop_unfinished_type(); } case T_ARRAY: case T_MAPPING: case T_STRING:
0b7cb52021-03-19Henrik Grubbström (Grubba)  /* FIXME: Handle PT_FLAG_CMP_INSEPARABLE. */
fe434c2021-11-21Henrik Grubbström (Grubba)  /* FIXME: The recursive op should probably be inverted. */
b98ea32020-10-10Henrik Grubbström (Grubba)  tmp = low_type_binop(op, a->car, b->car, remap,
8aa90a2020-12-20Henrik Grubbström (Grubba)  0, 0, remap_flags);
fe434c2021-11-21Henrik Grubbström (Grubba)  if (!tmp && (op == PT_BINOP_AND) && a->car && b->car) return NULL;
7e67622022-01-23Henrik Grubbström (Grubba)  if ((a->type == T_STRING) || (op == PT_BINOP_AND)) {
8ae7fb2020-12-26Henrik Grubbström (Grubba)  tmp2 = low_type_binop(op, a->cdr, b->cdr, remap, 0, 0, remap_flags); } else { /* Mappings may always result in UNDEFINED on indexing. * Arrays are typically initialized to all zeroes. */ tmp2 = low_type_binop(op, a->cdr, b->cdr, remap, PT_FLAG_CMP_NULLABLE, PT_FLAG_CMP_NULLABLE, remap_flags); }
fe434c2021-11-21Henrik Grubbström (Grubba)  if (!tmp2 && (op == PT_BINOP_MINUS || (a->cdr && b->cdr))) {
b98ea32020-10-10Henrik Grubbström (Grubba)  if (op == PT_BINOP_AND) { free_type(tmp); return NULL; } else if (!tmp) { return NULL; } } type_stack_mark(); if (op == PT_BINOP_MINUS) { if (tmp) { push_finished_type(a->cdr); push_finished_type(tmp);
4c07e82020-10-14Henrik Grubbström (Grubba)  push_type(a->type);
b98ea32020-10-10Henrik Grubbström (Grubba)  free_type(tmp); } if (tmp2) { push_finished_type(tmp2); push_finished_type(a->car);
4c07e82020-10-14Henrik Grubbström (Grubba)  push_type(a->type);
b98ea32020-10-10Henrik Grubbström (Grubba)  free_type(tmp2); }
000e842021-11-19Henrik Grubbström (Grubba)  switch(peek_stack_mark()) { case 0: push_type(PIKE_T_UNKNOWN); break; case 2: push_type(T_OR); break; }
b98ea32020-10-10Henrik Grubbström (Grubba)  } else { /* PT_BINOP_AND */ push_finished_type(tmp); push_finished_type(tmp2); push_reverse_type(a->type); free_type(tmp); free_type(tmp2); } return pop_unfinished_type(); case T_MULTISET: case T_PROGRAM: case T_TYPE:
0b7cb52021-03-19Henrik Grubbström (Grubba)  /* FIXME: Handle PT_FLAG_CMP_INSEPARABLE. */
b98ea32020-10-10Henrik Grubbström (Grubba)  tmp = low_type_binop(op, a->car, b->car, remap,
8aa90a2020-12-20Henrik Grubbström (Grubba)  0, 0, remap_flags);
34e19f2022-04-05Henrik Grubbström (Grubba)  if (!tmp && ((op != PT_BINOP_AND) || (a->car && b->car))) { return NULL; }
b98ea32020-10-10Henrik Grubbström (Grubba)  type_stack_mark(); push_finished_type(tmp); push_type(a->type);
b6671b2020-12-17Henrik Grubbström (Grubba)  free_type(tmp);
b98ea32020-10-10Henrik Grubbström (Grubba)  return pop_unfinished_type(); case T_OBJECT:
0b7cb52021-03-19Henrik Grubbström (Grubba)  /* FIXME: Handle PT_FLAG_CMP_INSEPARABLE. */
4c07e82020-10-14Henrik Grubbström (Grubba)  switch(op) { case PT_BINOP_AND: if (!a->cdr) {
b98ea32020-10-10Henrik Grubbström (Grubba)  add_ref(b); return b; }
4c07e82020-10-14Henrik Grubbström (Grubba)  if (!b->cdr) { add_ref(a); return a; } if (a->cdr == b->cdr) { /* We know that they differ due to the a == b test at * the befinning of the function. The only way they * can differ is that car differs. There are only two * valid values for car, so select the stricter (ie 'is-a')
b98ea32020-10-10Henrik Grubbström (Grubba)  */ type_stack_mark();
4c07e82020-10-14Henrik Grubbström (Grubba)  push_object_type(1, CDR_TO_INT(a));
b98ea32020-10-10Henrik Grubbström (Grubba)  return pop_unfinished_type(); }
4c07e82020-10-14Henrik Grubbström (Grubba)  if (a->car && b->car) { /* This is only possible if a->cdr == b->cdr, but that is * handled above. */ return NULL; } { struct program *ap = id_to_program(CDR_TO_INT(a)); struct program *bp = id_to_program(CDR_TO_INT(b)); if (!b->car && implements(ap, bp)) { add_ref(a); return a; } if (!a->car && implements(bp, ap)) { add_ref(b); return b; } if ((a->car != b->car) || !is_compatible(ap, bp)) { /* It is not possible to implement a class that * implements both of the classes. */ return NULL; } }
e029472020-10-16Henrik Grubbström (Grubba)  break;
4c07e82020-10-14Henrik Grubbström (Grubba)  case PT_BINOP_MINUS: if (!b->cdr) { return NULL; } if (a->cdr) { if (a->cdr == b->cdr) { return NULL; } if (a->car && b->car) { /* This is only possible if a->cdr == b->cdr, but that is * handled above. */ add_ref(a); return a; } { struct program *ap = id_to_program(CDR_TO_INT(a)); struct program *bp = id_to_program(CDR_TO_INT(b)); if (!b->car && implements(ap, bp)) { return NULL; } if (!is_compatible(ap, bp)) { add_ref(a); return a; } } } break; default: break;
b98ea32020-10-10Henrik Grubbström (Grubba)  }
4c07e82020-10-14Henrik Grubbström (Grubba)  type_stack_mark(); push_finished_type(b); push_finished_type(a); push_binop(op); return pop_unfinished_type();
b98ea32020-10-10Henrik Grubbström (Grubba)  }
a0ba322020-12-27Henrik Grubbström (Grubba)  /* Leaf type. Most likely not reached. */
4c07e82020-10-14Henrik Grubbström (Grubba)  if (op & PT_BINOP_AND) { add_ref(a); return a; } return NULL;
b98ea32020-10-10Henrik Grubbström (Grubba) }
529b302021-01-13Henrik Grubbström (Grubba) struct pike_type *type_binop(enum pt_binop op, struct pike_type *a, struct pike_type *b, enum pt_cmp_flags aflags, enum pt_cmp_flags bflags, enum pt_remap_flags remap_flags) { struct remap_state remap;
c97a452021-12-17Henrik Grubbström (Grubba)  struct pike_type *ret; INIT_REMAP_STATE(remap);
529b302021-01-13Henrik Grubbström (Grubba) 
c97a452021-12-17Henrik Grubbström (Grubba)  ret = low_type_binop(op, a, b, &remap, aflags, bflags, remap_flags);
529b302021-01-13Henrik Grubbström (Grubba) 
fda6742022-04-08Henrik Grubbström (Grubba)  if ((remap.markers[0] || remap.markers[1]) && ret &&
3fb8742021-12-23Henrik Grubbström (Grubba)  ((op == PT_BINOP_AND) || (op == PT_BINOP_MINUS))) { /* We may need to backpatch marker restrictions. */ #ifdef PIKE_DEBUG if (l_flag > 1) { fprintf(stderr, "Back-patching markers.\n" "Original result: "); simple_describe_type(ret);
fda6742022-04-08Henrik Grubbström (Grubba)  fprintf(stderr, "\nMarkers[0]: "); simple_describe_mapping(remap.markers[0]); fprintf(stderr, "\nMarkers[1]: "); simple_describe_mapping(remap.markers[1]);
3fb8742021-12-23Henrik Grubbström (Grubba)  fprintf(stderr, "\n"); } #endif type_stack_mark();
fda6742022-04-08Henrik Grubbström (Grubba)  push_and_fixup_markers(ret, &remap, remap_flags);
3fb8742021-12-23Henrik Grubbström (Grubba)  free_type(ret); ret = pop_unfinished_type(); #ifdef PIKE_DEBUG if (l_flag > 1) { fprintf(stderr, "Result after back-patching: "); simple_describe_type(ret); fprintf(stderr, "\n"); } #endif }
c97a452021-12-17Henrik Grubbström (Grubba)  EXIT_REMAP_STATE(remap); return ret;
529b302021-01-13Henrik Grubbström (Grubba) }
d41c192020-09-27Henrik Grubbström (Grubba) /** * Low-level subtraction (aka And-not) of two types. * * Note: * There are two major operating modes; the external, where * the two types have unrelated markers, which then need to * be remapped in the result, and the internal, where the * two types have related markers (this mode is used mainly * when evaluating a type). * * The internal mode is indicated via the remap state being NULL. */ static struct pike_type *low_subtract_types(struct pike_type *a, struct pike_type *b, struct remap_state *remap, enum pt_cmp_flags aflags, enum pt_cmp_flags bflags, enum pt_remap_flags remap_flags) { struct pike_type *tmp, *tmp2, *ret; struct pike_type *aret = NULL, *bret = NULL; enum pt_cmp_flags avoidable; enum pt_cmp_flags bvoidable; if (!a || !b) return NULL; if (a == b) { return NULL; } /* First check for markers. */ switch(a->type) { case T_ASSIGN: { int marker = alloc_remap_marker(remap, CAR_TO_INT(a), remap_flags); tmp = low_subtract_types(a->cdr, b, remap, aflags, bflags, remap_flags); if (tmp) { type_stack_mark(); push_finished_type(tmp); push_assign_type(marker); free_type(tmp); return pop_unfinished_type(); } free_marker(remap, CAR_TO_INT(a), remap_flags); return NULL; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int marker = remap_marker(remap, a->type, remap_flags); if (!marker) return NULL;
c97a452021-12-17Henrik Grubbström (Grubba)  tmp = remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
d41c192020-09-27Henrik Grubbström (Grubba)  if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_type(T_NOT); push_type(marker); push_reverse_type(T_AND); free_type(tmp); return pop_unfinished_type(); } } switch(b->type) { case T_ASSIGN: { int marker = alloc_remap_marker(remap, CAR_TO_INT(b), remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); tmp = low_subtract_types(a, b->cdr, remap, aflags, bflags, remap_flags); if (tmp) { type_stack_mark(); push_finished_type(tmp); push_assign_type(marker); free_type(tmp); return pop_unfinished_type(); } free_marker(remap, CAR_TO_INT(b), remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); return NULL; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int marker = remap_marker(remap, b->type, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); if (!marker) return NULL;
c97a452021-12-17Henrik Grubbström (Grubba)  tmp = remap_markers(a, remap, remap_flags);
d41c192020-09-27Henrik Grubbström (Grubba)  if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_type(marker); push_type(T_NOT); push_reverse_type(T_AND); free_type(tmp); return pop_unfinished_type(); } } /* Attributes and names. */ switch(a->type) { case PIKE_T_NAME: tmp = low_subtract_types(a->cdr, b, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_type_name((struct pike_string *)(a->car)); free_type(tmp); return pop_unfinished_type(); case PIKE_T_ATTRIBUTE: tmp = low_subtract_types(a->cdr, b, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_type_attribute((struct pike_string *)(a->car)); free_type(tmp); return pop_unfinished_type(); case T_SCOPE: tmp = low_subtract_types(a->cdr, b, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_scope_type(CAR_TO_INT(a)); free_type(tmp); return pop_unfinished_type(); } switch(b->type) { case PIKE_T_NAME: tmp = low_subtract_types(a, b->cdr, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp);
d10bc92020-10-08Henrik Grubbström (Grubba)  /* FIXME: Is this a good idea? */
d41c192020-09-27Henrik Grubbström (Grubba)  push_type_name((struct pike_string *)(b->car)); free_type(tmp); return pop_unfinished_type(); case PIKE_T_ATTRIBUTE: tmp = low_subtract_types(a, b->cdr, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp);
d10bc92020-10-08Henrik Grubbström (Grubba)  /* FIXME: Is this a good idea? */
d41c192020-09-27Henrik Grubbström (Grubba)  push_type_attribute((struct pike_string *)(b->car)); free_type(tmp); return pop_unfinished_type(); case T_SCOPE: tmp = low_subtract_types(a, b->cdr, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_scope_type(CAR_TO_INT(b)); free_type(tmp); return pop_unfinished_type(); } /* Check consolidated types. */ switch(a->type) { case T_OR: case T_AND: tmp = low_subtract_types(a->car, b, remap, aflags, bflags, remap_flags); if (!tmp && (a->type == T_AND)) return NULL; tmp2 = low_subtract_types(a->cdr, b, remap, aflags, bflags, remap_flags); if (!tmp2) { if (a->type == T_OR) return tmp; free_type(tmp); return NULL; }
5bafbd2020-09-28Henrik Grubbström (Grubba)  if (!tmp) { return tmp2;
d41c192020-09-27Henrik Grubbström (Grubba)  }
5bafbd2020-09-28Henrik Grubbström (Grubba)  type_stack_mark(); push_finished_type(tmp); push_finished_type(tmp2); push_reverse_type(a->type);
d41c192020-09-27Henrik Grubbström (Grubba)  free_type(tmp); free_type(tmp2);
5bafbd2020-09-28Henrik Grubbström (Grubba)  return pop_unfinished_type();
d41c192020-09-27Henrik Grubbström (Grubba)  } switch(b->type) { case T_OR: /* DeMorgan * * a & ~(b1 | b2) <==> a & ~b1 & ~b2 */ tmp = low_subtract_types(a, b->car, remap, aflags, bflags, remap_flags); if (!tmp) return NULL;
5048142020-10-01Henrik Grubbström (Grubba)  /* NB: We need to remap b->cdr separately to avoid remapping * markers in a and b->car twice. */
c97a452021-12-17Henrik Grubbström (Grubba)  tmp2 = remap_markers(b->cdr, remap,
5048142020-10-01Henrik Grubbström (Grubba)  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); ret = low_subtract_types(tmp, tmp2, NULL, aflags, bflags, 0);
d41c192020-09-27Henrik Grubbström (Grubba)  free_type(tmp);
5048142020-10-01Henrik Grubbström (Grubba)  free_type(tmp2);
d41c192020-09-27Henrik Grubbström (Grubba)  return ret; case T_AND: /* DeMorgan * * a & ~(b1 & b2) <==> a & (~b1 | ~b2) <==> (a & ~b1) | (a & ~b2) */ tmp = low_subtract_types(a, b->car, remap, aflags, bflags, remap_flags);
5048142020-10-01Henrik Grubbström (Grubba)  tmp2 = low_subtract_types(a, b->cdr, remap, aflags, bflags, remap_flags);
d41c192020-09-27Henrik Grubbström (Grubba)  if (!tmp2) return tmp; ret = or_pike_types(tmp, tmp2, 0); free_type(tmp); free_type(tmp2); return ret; } /* NB: Complex types from this point onwards are containers, * and the voidable property does not propagate into them. */ avoidable = aflags & PT_FLAG_CMP_VOIDABLE; aflags &= ~PT_FLAG_CMP_VOIDABLE; bvoidable = bflags & PT_FLAG_CMP_VOIDABLE; bflags &= ~PT_FLAG_CMP_VOIDABLE; /* Check implicit casting. */ loop: switch(TWOT(a->type & PIKE_T_MASK, b->type & PIKE_T_MASK)) { case TWOT(T_PROGRAM, T_FUNCTION): case TWOT(T_PROGRAM, T_MANY): aret = a->car; a = low_object_lfun_type(aret, LFUN_CREATE); if (!a) { a = void_function_type_string; } goto loop; case TWOT(T_FUNCTION, T_PROGRAM): case TWOT(T_MANY, T_PROGRAM): bret = b->car; b = low_object_lfun_type(bret, LFUN_CREATE); if (!b) { b = void_function_type_string; } goto loop; case TWOT(T_OBJECT, T_FUNCTION): case TWOT(T_OBJECT, T_MANY): case TWOT(T_OBJECT, T_PROGRAM): case TWOT(T_OBJECT, PIKE_T_TRANSITIVE): a = low_object_lfun_type(a, LFUN_CALL); if (!a) return NULL; goto loop; case TWOT(T_FUNCTION, T_OBJECT): case TWOT(T_MANY, T_OBJECT): case TWOT(T_PROGRAM, T_OBJECT): case TWOT(PIKE_T_TRANSITIVE, T_OBJECT): b = low_object_lfun_type(b, LFUN_CALL); if (!b) return NULL; goto loop; case TWOT(PIKE_T_TRANSITIVE, T_FUNCTION): case TWOT(PIKE_T_TRANSITIVE, T_MANY): case TWOT(PIKE_T_TRANSITIVE, T_PROGRAM): case TWOT(PIKE_T_TRANSITIVE, PIKE_T_TRANSITIVE):
4f759e2022-04-11Henrik Grubbström (Grubba)  tmp = expand_transitive_remap(a, NULL, 0);
d41c192020-09-27Henrik Grubbström (Grubba)  ret = low_subtract_types(tmp, b, remap, aflags, bflags, remap_flags); free_type(tmp); return ret; case TWOT(T_FUNCTION, PIKE_T_TRANSITIVE): case TWOT(T_MANY, PIKE_T_TRANSITIVE): case TWOT(T_PROGRAM, PIKE_T_TRANSITIVE):
4f759e2022-04-11Henrik Grubbström (Grubba)  tmp = expand_transitive_remap(b, NULL, 0);
d41c192020-09-27Henrik Grubbström (Grubba)  ret = low_subtract_types(a, tmp, remap, aflags, bflags, remap_flags); free_type(tmp); return ret; case TWOT(T_FUNCTION, PIKE_T_OPERATOR): case TWOT(PIKE_T_OPERATOR, T_FUNCTION): type_stack_mark(); push_finished_type(a); push_finished_type(b); push_type(T_NOT); push_reverse_type(T_AND); return pop_unfinished_type(); case TWOT(T_FUNCTION, T_FUNCTION): case TWOT(T_FUNCTION, T_MANY): case TWOT(T_MANY, T_FUNCTION): case TWOT(T_MANY, T_MANY): /* * function(a1, a2, a3...:aa) & ~function(b1, b2, b3...:bb) * * <==> * * If * All ai & ~bi == ai * Then * function(a1, a2, a3...:aa) * * If * All ai & ~bi == Ø * Then * Ø * * Otherwise * Keep for later evaluation. */ { int nargs; struct pike_type *ai = a; struct pike_type *bi = b; int got_empty = 0; int got_full = 0; while(1) { /* Invariant: * a->type and b->type are either T_FUNCTION or T_MANY. */ enum pt_cmp_flags avoidable = 0; enum pt_cmp_flags bvoidable = 0; /* Check the argument. */ /* NB: The MANY argument is always voidable. */ if (ai->type == T_MANY) avoidable |= PT_FLAG_CMP_VOIDABLE; if (bi->type == T_MANY) bvoidable |= PT_FLAG_CMP_VOIDABLE; tmp = low_subtract_types(ai->car, bi->car, NULL, aflags | avoidable, bflags | bvoidable, remap_flags); if (!tmp) { if (got_full) break; got_empty = 1; } else { if (tmp == ai) { got_full = 1; } else {
5048142020-10-01Henrik Grubbström (Grubba)  free_type(tmp);
d41c192020-09-27Henrik Grubbström (Grubba)  break; } free_type(tmp); if (got_empty) break; } if (avoidable && bvoidable) { /* Time to check the return types. */ if (!aret) aret = ai->cdr; if (!bret) bret = bi->cdr; tmp = low_subtract_types(aret, bret, NULL, aflags, bflags, remap_flags); if (!tmp) { if (got_full) break; got_empty = 1; } else { if (tmp == aret) { got_full = 1; } else {
5048142020-10-01Henrik Grubbström (Grubba)  free_type(tmp);
d41c192020-09-27Henrik Grubbström (Grubba)  break; } free_type(tmp); if (got_empty) break; } if (!got_full) { return NULL; } type_stack_mark();
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(a, remap, remap_flags);
d41c192020-09-27Henrik Grubbström (Grubba)  return pop_unfinished_type(); } /* Advance to the next argument. */ if (ai->type == T_FUNCTION) { ai = ai->cdr; } if (bi->type == T_FUNCTION) { bi = bi->cdr; } if ((ai->type != T_FUNCTION) && (ai->type != T_MANY)) { break; } if ((bi->type != T_FUNCTION) && (bi->type != T_MANY)) { break; } } /* Either of a and/or b is a complex type, or a partial overlap. */ type_stack_mark();
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(a, remap, remap_flags); push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
d41c192020-09-27Henrik Grubbström (Grubba)  push_type(T_NOT); push_reverse_type(T_AND); return pop_unfinished_type(); } case TWOT(T_ZERO, T_INT): if ((CAR_TO_INT(b) <= 0) && (CDR_TO_INT(b) >= 0)) { return NULL; } add_ref(a); return a; case TWOT(T_INT, T_ZERO): if ((CAR_TO_INT(a) > 0) || (CDR_TO_INT(a) < 0)) { add_ref(a); return a; } type_stack_mark(); if (CAR_TO_INT(a) < 0) { push_int_type(CAR_TO_INT(a), -1); } if (CDR_TO_INT(a) > 0) { push_int_type(1, CDR_TO_INT(a)); if (CAR_TO_INT(a) < 0) { push_reverse_type(T_OR); } } return pop_unfinished_type(); /* T_TYPE and T_PROGRAM are essentially the same thing. */ case TWOT(T_TYPE, T_TYPE): case TWOT(T_TYPE, T_PROGRAM): case TWOT(T_PROGRAM, T_TYPE): case TWOT(T_PROGRAM, T_PROGRAM): tmp = low_subtract_types(a->car, b->car, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); if (a->type == b->type) { push_type(a->type); } else { push_type(T_TYPE); } free_type(tmp); return pop_unfinished_type(); case TWOT(T_TYPE, T_FUNCTION): case TWOT(T_TYPE, T_MANY): case TWOT(T_TYPE, PIKE_T_TRANSITIVE): type_stack_mark(); push_finished_type(a->car); push_type(T_VOID); push_type(T_MANY); push_type(T_MIXED); push_type(T_FUNCTION); tmp = pop_unfinished_type(); ret = low_subtract_types(tmp, b, remap, aflags, bflags, remap_flags); free_type(tmp); return ret; case TWOT(T_FUNCTION, T_TYPE): case TWOT(T_MANY, T_TYPE): case TWOT(PIKE_T_TRANSITIVE, T_TYPE): type_stack_mark(); push_finished_type(b->car); push_type(T_VOID); push_type(T_MANY); push_type(T_MIXED); push_type(T_FUNCTION); tmp = pop_unfinished_type(); ret = low_subtract_types(a, tmp, remap, aflags, bflags, remap_flags); free_type(tmp); return ret; #if 0 /* FIXME: */ case PIKE_T_RING: #endif } if (a->type == T_VOID) { if (bvoidable) { return NULL; } add_ref(a); return a; } if (b->type == T_VOID) { add_ref(a); return a; } if (b->type == T_MIXED) { /* NB: a being void has been handled above. */ return NULL; } if (a->type == T_MIXED) { type_stack_mark();
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
d41c192020-09-27Henrik Grubbström (Grubba)  push_type(T_NOT); return pop_unfinished_type(); } if (b->type == T_NOT) { return low_intersect_types(a, b->car, remap, aflags, bflags, remap_flags); } if (a->type == T_NOT) { /* DeMorgan and(not(a), not(b)) <==> not(or(a, b)) */ type_stack_mark();
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(a->car, remap, remap_flags); push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
d41c192020-09-27Henrik Grubbström (Grubba)  push_type(T_OR); push_type(T_NOT); return pop_unfinished_type(); } if (a->type != b->type) { if (((a->type & PIKE_T_MASK) == PIKE_T_OPERATOR) || ((b->type & PIKE_T_MASK) == PIKE_T_OPERATOR)) { type_stack_mark();
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(a, remap, remap_flags); push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
d41c192020-09-27Henrik Grubbström (Grubba)  push_type(T_NOT); push_reverse_type(T_AND); return pop_unfinished_type(); } add_ref(a); return a; } switch(a->type) { case T_VOID: case T_ZERO: case T_FLOAT: /* Not reached. Should be handled by the a == b test at * the beginning of the function. */ Pike_fatal("Type hashing has duplicates.\n"); return NULL; case T_INT: { INT32 alow,blow; INT32 ahigh,bhigh; alow = CAR_TO_INT(a); blow = CAR_TO_INT(b); ahigh = CDR_TO_INT(a); bhigh = CDR_TO_INT(b); if ((blow > ahigh) || (bhigh < alow)) { /* No Overlap */ add_ref(a); return a; } type_stack_mark(); if (blow > alow) { push_int_type(alow, blow - 1); } if (bhigh < ahigh) { push_int_type(bhigh + 1, ahigh); } switch(peek_stack_mark()) { case 2: push_type(T_OR); break; case 1: break; case 0: return NULL; } return pop_unfinished_type(); } case T_ARRAY: case T_MAPPING: case T_STRING: tmp = low_subtract_types(a->car, b->car, remap, aflags, bflags, remap_flags); tmp2 = low_subtract_types(a->cdr, b->cdr, remap, aflags, bflags, remap_flags); if (!tmp && !tmp2) return NULL; type_stack_mark(); if (tmp) { push_finished_type(a->cdr); push_finished_type(tmp); push_reverse_type(a->type); free_type(tmp); } if (tmp2) { push_finished_type(tmp2); push_finished_type(a->car); push_reverse_type(a->type); free_type(tmp2); } if (peek_stack_mark() == 2) push_type(T_OR); return pop_unfinished_type(); case T_MULTISET: case T_PROGRAM: case T_TYPE: tmp = low_subtract_types(a->car, b->car, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_type(a->type); return pop_unfinished_type(); case T_OBJECT: if (!b->cdr) { return NULL; } if (a->cdr) { if (a->cdr == b->cdr) { return NULL; } if (a->car && b->car) { /* This is only possible if a->cdr == b->cdr, but that is * handled above. */ add_ref(a); return a; } { struct program *ap = id_to_program(CDR_TO_INT(a)); struct program *bp = id_to_program(CDR_TO_INT(b)); if (!b->car && implements(ap, bp)) { return NULL; } if (!is_compatible(ap, bp)) { add_ref(a); return a; } } } type_stack_mark(); push_finished_type(b); push_type(T_NOT);
4c07e82020-10-14Henrik Grubbström (Grubba)  push_finished_type(a); push_type(T_AND);
d41c192020-09-27Henrik Grubbström (Grubba)  return pop_unfinished_type(); } /* Leaf type. */ return NULL; } struct pike_type *subtract_types(struct pike_type *a, struct pike_type *b, enum pt_cmp_flags aflags, enum pt_cmp_flags bflags, enum pt_remap_flags remap_flags) { struct remap_state remap;
c97a452021-12-17Henrik Grubbström (Grubba)  struct pike_type *sub_res; INIT_REMAP_STATE(remap); sub_res = low_subtract_types(a, b, &remap, aflags, bflags, remap_flags);
d41c192020-09-27Henrik Grubbström (Grubba) 
c97a452021-12-17Henrik Grubbström (Grubba)  EXIT_REMAP_STATE(remap);
d41c192020-09-27Henrik Grubbström (Grubba) 
c97a452021-12-17Henrik Grubbström (Grubba)  return sub_res;
d41c192020-09-27Henrik Grubbström (Grubba) } /** * Low-level intersection (aka And) of two types. * * Note: * There are two major operating modes; the external, where * the two types have unrelated markers, which then need to * be remapped in the result, and the internal, where the * two types have related markers (this mode is used mainly * when evaluating a type). * * The internal mode is indicated via the remap state being NULL. */ static struct pike_type *low_intersect_types(struct pike_type *a, struct pike_type *b, struct remap_state *remap, enum pt_cmp_flags aflags, enum pt_cmp_flags bflags, enum pt_remap_flags remap_flags) { struct pike_type *tmp, *tmp2, *ret; struct pike_type *aret = NULL, *bret = NULL; enum pt_cmp_flags avoidable; enum pt_cmp_flags bvoidable; if (!a || !b) return NULL; if (a == b) { /* FIXME: Perform masking of remap_flags here. */
c97a452021-12-17Henrik Grubbström (Grubba)  return remap_markers(a, remap,
d41c192020-09-27Henrik Grubbström (Grubba)  remap_flags | PT_FLAG_REMAP_BOTH_MARKERS_AND); } /* First check for markers. */ switch(a->type) { case T_ASSIGN: { int marker = alloc_remap_marker(remap, CAR_TO_INT(a), remap_flags); tmp = low_intersect_types(a->cdr, b, remap, aflags, bflags, remap_flags); if (tmp) { type_stack_mark(); push_finished_type(tmp); push_assign_type(marker); free_type(tmp); return pop_unfinished_type(); } free_marker(remap, CAR_TO_INT(a), remap_flags); return NULL; } } switch(b->type) { case T_ASSIGN: { int marker = alloc_remap_marker(remap, CAR_TO_INT(b), remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); tmp = low_intersect_types(a, b->cdr, remap, aflags, bflags, remap_flags); if (tmp) { type_stack_mark(); push_finished_type(tmp); push_assign_type(marker); free_type(tmp); return pop_unfinished_type(); } free_marker(remap, CAR_TO_INT(b), remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); return NULL; } } /* Attributes and names. */ switch(a->type) { case PIKE_T_NAME: tmp = low_intersect_types(a->cdr, b, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_type_name((struct pike_string *)(a->car)); free_type(tmp); return pop_unfinished_type(); case PIKE_T_ATTRIBUTE: tmp = low_intersect_types(a->cdr, b, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_type_attribute((struct pike_string *)(a->car)); free_type(tmp); return pop_unfinished_type(); case T_SCOPE: tmp = low_intersect_types(a->cdr, b, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_scope_type(CAR_TO_INT(a)); free_type(tmp); return pop_unfinished_type(); } switch(b->type) { case PIKE_T_NAME: tmp = low_intersect_types(a, b->cdr, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_type_name((struct pike_string *)(b->car)); free_type(tmp); return pop_unfinished_type(); case PIKE_T_ATTRIBUTE: tmp = low_intersect_types(a, b->cdr, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_type_attribute((struct pike_string *)(b->car)); free_type(tmp); return pop_unfinished_type(); case T_SCOPE: tmp = low_intersect_types(a, b->cdr, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_scope_type(CAR_TO_INT(b)); free_type(tmp); return pop_unfinished_type(); } /* Check consolidated types. */ switch(a->type) { case T_OR: tmp = low_intersect_types(a->car, b, remap, aflags, bflags, remap_flags); tmp2 = low_intersect_types(a->cdr, b, remap, aflags, bflags, remap_flags);
1af9632020-10-03Henrik Grubbström (Grubba)  if (!tmp2) return tmp; if (!tmp) return tmp2; type_stack_mark(); push_finished_type(tmp); push_finished_type(tmp2); push_reverse_type(T_OR); free_type(tmp); free_type(tmp2); return pop_unfinished_type(); case T_AND: /* NB: Attempt to avoid keeping the result from inverted types, * in order to reduce type expansion. */ if (a->car->type == T_NOT) { tmp2 = low_intersect_types(a->cdr, b, remap, aflags, bflags, remap_flags); if (!tmp2) return NULL; tmp = low_intersect_types(a->car, b, remap, aflags, bflags, remap_flags); if (!tmp) { free_type(tmp2); return NULL; }
d41c192020-09-27Henrik Grubbström (Grubba)  free_type(tmp);
c97a452021-12-17Henrik Grubbström (Grubba)  tmp = remap_markers(a->car, remap, remap_flags);
1af9632020-10-03Henrik Grubbström (Grubba)  } else { tmp = low_intersect_types(a->car, b, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; tmp2 = low_intersect_types(a->cdr, b, remap, aflags, bflags, remap_flags); if (!tmp2) { free_type(tmp); return NULL; } if (a->cdr->type == T_NOT) { free_type(tmp2);
c97a452021-12-17Henrik Grubbström (Grubba)  tmp2 = remap_markers(a->cdr, remap, remap_flags);
1af9632020-10-03Henrik Grubbström (Grubba)  }
d41c192020-09-27Henrik Grubbström (Grubba)  }
1af9632020-10-03Henrik Grubbström (Grubba) 
5bafbd2020-09-28Henrik Grubbström (Grubba)  type_stack_mark(); push_finished_type(tmp); push_finished_type(tmp2);
1af9632020-10-03Henrik Grubbström (Grubba)  push_reverse_type(T_AND);
d41c192020-09-27Henrik Grubbström (Grubba)  free_type(tmp); free_type(tmp2);
5bafbd2020-09-28Henrik Grubbström (Grubba)  return pop_unfinished_type();
d41c192020-09-27Henrik Grubbström (Grubba)  } switch(b->type) { case T_OR: tmp = low_intersect_types(a, b->car, remap, aflags, bflags, remap_flags); tmp2 = low_intersect_types(a, b->cdr, remap, aflags, bflags, remap_flags);
1af9632020-10-03Henrik Grubbström (Grubba)  if (!tmp2) return tmp; if (!tmp) return tmp2; type_stack_mark(); push_finished_type(tmp); push_finished_type(tmp2); push_reverse_type(T_OR); free_type(tmp); free_type(tmp2); return pop_unfinished_type(); case T_AND: /* NB: Attempt to avoid keeping the result from inverted types, * in order to reduce type expansion. */ if (b->car->type == T_NOT) { tmp = low_intersect_types(a, b->cdr, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; tmp2 = low_intersect_types(a, b->car, remap, aflags, bflags, remap_flags); if (tmp2) { free_type(tmp2);
c97a452021-12-17Henrik Grubbström (Grubba)  tmp2 = remap_markers(b->car, remap,
1af9632020-10-03Henrik Grubbström (Grubba)  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); } } else { tmp = low_intersect_types(a, b->car, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; tmp2 = low_intersect_types(a, b->cdr, remap, aflags, bflags, remap_flags); if (tmp2 && (b->cdr->type == T_NOT)) { free_type(tmp2);
c97a452021-12-17Henrik Grubbström (Grubba)  tmp2 = remap_markers(b->cdr, remap,
1af9632020-10-03Henrik Grubbström (Grubba)  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); } }
d41c192020-09-27Henrik Grubbström (Grubba)  if (!tmp2) { free_type(tmp); return NULL; }
1af9632020-10-03Henrik Grubbström (Grubba) 
5bafbd2020-09-28Henrik Grubbström (Grubba)  type_stack_mark(); push_finished_type(tmp); push_finished_type(tmp2);
1af9632020-10-03Henrik Grubbström (Grubba)  push_reverse_type(T_AND);
d41c192020-09-27Henrik Grubbström (Grubba)  free_type(tmp); free_type(tmp2);
5bafbd2020-09-28Henrik Grubbström (Grubba)  return pop_unfinished_type();
d41c192020-09-27Henrik Grubbström (Grubba)  } /* NB: Complex types from this point onwards are containers, * and the voidable property does not propagate into them. */ avoidable = aflags & PT_FLAG_CMP_VOIDABLE; aflags &= ~PT_FLAG_CMP_VOIDABLE; bvoidable = bflags & PT_FLAG_CMP_VOIDABLE; bflags &= ~PT_FLAG_CMP_VOIDABLE; /* Check implicit casting. */ loop: switch(TWOT(a->type & PIKE_T_MASK, b->type & PIKE_T_MASK)) { case TWOT(T_PROGRAM, T_FUNCTION): case TWOT(T_PROGRAM, T_MANY): aret = a->car; a = low_object_lfun_type(aret, LFUN_CREATE); if (!a) { a = void_function_type_string; } goto loop; case TWOT(T_FUNCTION, T_PROGRAM): case TWOT(T_MANY, T_PROGRAM): bret = b->car; b = low_object_lfun_type(bret, LFUN_CREATE); if (!b) { b = void_function_type_string; } goto loop; case TWOT(T_OBJECT, T_FUNCTION): case TWOT(T_OBJECT, T_MANY): case TWOT(T_OBJECT, T_PROGRAM): case TWOT(T_OBJECT, PIKE_T_TRANSITIVE): a = low_object_lfun_type(a, LFUN_CALL); if (!a) return NULL; goto loop; case TWOT(T_FUNCTION, T_OBJECT): case TWOT(T_MANY, T_OBJECT): case TWOT(T_PROGRAM, T_OBJECT): case TWOT(PIKE_T_TRANSITIVE, T_OBJECT): b = low_object_lfun_type(b, LFUN_CALL); if (!b) return NULL; goto loop; case TWOT(PIKE_T_TRANSITIVE, T_FUNCTION): case TWOT(PIKE_T_TRANSITIVE, T_MANY): case TWOT(PIKE_T_TRANSITIVE, T_PROGRAM): case TWOT(PIKE_T_TRANSITIVE, PIKE_T_TRANSITIVE):
4f759e2022-04-11Henrik Grubbström (Grubba)  tmp = expand_transitive_remap(a, NULL, 0);
d41c192020-09-27Henrik Grubbström (Grubba)  ret = low_intersect_types(tmp, b, remap, aflags, bflags, remap_flags); free_type(tmp); return ret; case TWOT(T_FUNCTION, PIKE_T_TRANSITIVE): case TWOT(T_MANY, PIKE_T_TRANSITIVE): case TWOT(T_PROGRAM, PIKE_T_TRANSITIVE):
4f759e2022-04-11Henrik Grubbström (Grubba)  tmp = expand_transitive_remap(b, NULL, 0);
d41c192020-09-27Henrik Grubbström (Grubba)  ret = low_intersect_types(a, tmp, remap, aflags, bflags, remap_flags); free_type(tmp); return ret; case TWOT(T_FUNCTION, PIKE_T_OPERATOR): case TWOT(PIKE_T_OPERATOR, T_FUNCTION): type_stack_mark(); push_finished_type(a); push_finished_type(b); push_reverse_type(T_AND); return pop_unfinished_type(); case TWOT(T_FUNCTION, T_FUNCTION): case TWOT(T_FUNCTION, T_MANY): case TWOT(T_MANY, T_FUNCTION): case TWOT(T_MANY, T_MANY): /* NB: For simplicity in the (common case) * many(assign(m, mixed), m), * we expand the many node (as required) to * function(assign(m, mixed), many(assign(m, mixed), m)), * and leave it to the evaluator to join the multiple * assignments with or. The alternative (and stricter) would * be to allocate a new marker for each step of the expansion * and to have explicit or nodes: * function(assign(m1, mixed), many(assign(m2, mixed), or(m1, m2))). */ { int nargs; type_stack_mark(); type_stack_mark(); /* To keep track of the number of args. */ while(1) { /* Invariant: * a->type and b->type are either T_FUNCTION or T_MANY. */ enum pt_cmp_flags avoidable = 0; enum pt_cmp_flags bvoidable = 0; /* Check the argument. */ /* NB: The MANY argument is always voidable. */ if (a->type == T_MANY) avoidable |= PT_FLAG_CMP_VOIDABLE; if (b->type == T_MANY) bvoidable |= PT_FLAG_CMP_VOIDABLE; tmp = low_intersect_types(a->car, b->car, remap, aflags | avoidable, bflags | bvoidable, remap_flags); if (!tmp) { if (avoidable && bvoidable) { /* NB: The VOIDABLE flag only affects comparisons with * explicit void. If both arguments have implicit void, * and nothing other in common, we arrive here. */ push_type(T_VOID); } else { goto function_fail; } } push_finished_type(tmp); free_type(tmp); if (avoidable && bvoidable) { /* Time to check the return types. */ if (!aret) aret = a->cdr; if (!bret) bret = b->cdr; tmp = low_intersect_types(aret, bret, remap, aflags, bflags, remap_flags); if (!tmp) goto function_fail; nargs = pop_stack_mark(); push_finished_type(tmp); free_type(tmp); nargs--; push_reverse_type(T_MANY); while (nargs--) { push_reverse_type(T_FUNCTION); } return pop_unfinished_type(); } /* Advance to the next argument. */ if (a->type == T_FUNCTION) { a = a->cdr; } if (b->type == T_FUNCTION) { b = b->cdr; } if ((a->type != T_FUNCTION) && (a->type != T_MANY)) { if (aret) { Pike_fatal("Unsupported type operation.\n"); } break; } if ((b->type != T_FUNCTION) && (b->type != T_MANY)) { if (bret) { Pike_fatal("Unsupported type operation.\n"); } break; } } nargs = pop_stack_mark(); /* Either of a and/or b is a complex type. */
c97a452021-12-17Henrik Grubbström (Grubba)  tmp = remap_markers(a, remap, remap_flags);
d41c192020-09-27Henrik Grubbström (Grubba)  push_finished_type(tmp); free_type(tmp);
c97a452021-12-17Henrik Grubbström (Grubba)  tmp = remap_markers(b, remap, remap_flags);
d41c192020-09-27Henrik Grubbström (Grubba)  push_finished_type(tmp); free_type(tmp); push_reverse_type(T_AND); while (nargs--) { push_reverse_type(T_FUNCTION); } return pop_unfinished_type(); function_fail: compiler_discard_type(); pop_stack_mark(); return NULL; } case TWOT(T_VOID, T_ZERO): /* Return zero. */ add_ref(b); return b; case TWOT(T_ZERO, T_VOID): /* Return zero. */ add_ref(a); return a; case TWOT(T_ZERO, T_INT): if ((CAR_TO_INT(b) <= 0) && (CDR_TO_INT(b) >= 0)) { add_ref(a); return a; } return NULL; case TWOT(T_INT, T_ZERO): if ((CAR_TO_INT(a) <= 0) && (CDR_TO_INT(a) >= 0)) { add_ref(b); return b; } return NULL; /* T_TYPE and T_PROGRAM are essentially the same thing. */ case TWOT(T_TYPE, T_TYPE): case TWOT(T_TYPE, T_PROGRAM): case TWOT(T_PROGRAM, T_TYPE): case TWOT(T_PROGRAM, T_PROGRAM): tmp = low_intersect_types(a->car, b->car, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); if (a->type == b->type) { push_type(a->type); } else { push_type(T_TYPE); } free_type(tmp); return pop_unfinished_type(); case TWOT(T_TYPE, T_FUNCTION): case TWOT(T_TYPE, T_MANY): case TWOT(T_TYPE, PIKE_T_TRANSITIVE): type_stack_mark(); push_finished_type(a->car); push_type(T_VOID); push_type(T_MANY); push_type(T_MIXED); push_type(T_FUNCTION); tmp = pop_unfinished_type(); ret = low_intersect_types(tmp, b, remap, aflags, bflags, remap_flags); free_type(tmp); return ret; case TWOT(T_FUNCTION, T_TYPE): case TWOT(T_MANY, T_TYPE): case TWOT(PIKE_T_TRANSITIVE, T_TYPE): type_stack_mark(); push_finished_type(b->car); push_type(T_VOID); push_type(T_MANY); push_type(T_MIXED); push_type(T_FUNCTION); tmp = pop_unfinished_type(); ret = low_intersect_types(a, tmp, remap, aflags, bflags, remap_flags); free_type(tmp); return ret; #if 0 /* FIXME: */ case PIKE_T_RING: #endif } if (a->type == T_VOID) { if (bvoidable) { add_ref(a); return a; } return NULL; } if (b->type == T_VOID) { if (avoidable) { add_ref(b); return b; } return NULL; } if (a->type == T_MIXED) {
c97a452021-12-17Henrik Grubbström (Grubba)  return remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
d41c192020-09-27Henrik Grubbström (Grubba)  } if (b->type == T_MIXED) {
c97a452021-12-17Henrik Grubbström (Grubba)  return remap_markers(a, remap, remap_flags);
d41c192020-09-27Henrik Grubbström (Grubba)  } if (a->type == T_NOT) { if (b->type == T_NOT) { /* DeMorgan and(not(a), not(b)) <==> not(or(a, b)) */ type_stack_mark();
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(a->car, remap, remap_flags); push_remap_markers(b->car, remap,
003e122020-10-05Henrik Grubbström (Grubba)  remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
d41c192020-09-27Henrik Grubbström (Grubba)  push_type(T_OR); push_type(T_NOT); return pop_unfinished_type(); } /* NB: Swapped argument order! */ return low_subtract_types(b, a->car, remap, bflags, aflags, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); } if (b->type == T_NOT) { return low_subtract_types(a, b->car, remap, aflags, bflags, remap_flags); }
9b9e7c2020-10-06Henrik Grubbström (Grubba)  switch(a->type) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int marker = remap_marker(remap, a->type, remap_flags); if (!marker) return NULL;
c97a452021-12-17Henrik Grubbström (Grubba)  tmp = remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
9b9e7c2020-10-06Henrik Grubbström (Grubba)  if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_type(marker); push_reverse_type(T_AND); free_type(tmp); return pop_unfinished_type(); } } switch(b->type) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int marker = remap_marker(remap, b->type, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS); if (!marker) return NULL;
c97a452021-12-17Henrik Grubbström (Grubba)  tmp = remap_markers(a, remap, remap_flags);
9b9e7c2020-10-06Henrik Grubbström (Grubba)  if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_type(marker); push_reverse_type(T_AND); free_type(tmp); return pop_unfinished_type(); } }
d41c192020-09-27Henrik Grubbström (Grubba)  if (a->type != b->type) { if (((a->type & PIKE_T_MASK) == PIKE_T_OPERATOR) || ((b->type & PIKE_T_MASK) == PIKE_T_OPERATOR)) { type_stack_mark();
c97a452021-12-17Henrik Grubbström (Grubba)  push_remap_markers(a, remap, remap_flags); push_remap_markers(b, remap, remap_flags ^ PT_FLAG_REMAP_SWAP_MARKERS);
d41c192020-09-27Henrik Grubbström (Grubba)  push_reverse_type(T_AND); return pop_unfinished_type(); } return NULL; } switch(a->type) { case T_VOID: case T_ZERO: case T_FLOAT: /* Not reached. Should be handled by the a == b test at * the beginning of the function. */ Pike_fatal("Type hashing has duplicates.\n"); return NULL; case T_INT: { INT32 i1,i2; INT32 upper_bound, lower_bound; i1 = CDR_TO_INT(a); i2 = CDR_TO_INT(b); upper_bound = MINIMUM(i1,i2); i1 = CAR_TO_INT(a); i2 = CAR_TO_INT(b); lower_bound = MAXIMUM(i1,i2); if (upper_bound < lower_bound) { /* No overlap! */ return NULL; } type_stack_mark(); push_int_type(lower_bound, upper_bound); return pop_unfinished_type(); } case T_ARRAY: case T_MAPPING: case T_STRING: tmp = low_intersect_types(a->car, b->car, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; tmp2 = low_intersect_types(a->cdr, b->cdr, remap, aflags, bflags, remap_flags); if (!tmp2) { free_type(tmp); return NULL; } type_stack_mark(); push_finished_type(tmp); push_finished_type(tmp2); push_reverse_type(a->type); free_type(tmp); free_type(tmp2); return pop_unfinished_type(); case T_MULTISET: case T_PROGRAM: case T_TYPE: tmp = low_intersect_types(a->car, b->car, remap, aflags, bflags, remap_flags); if (!tmp) return NULL; type_stack_mark(); push_finished_type(tmp); push_type(a->type); return pop_unfinished_type(); case T_OBJECT: if (!a->cdr) { add_ref(b); return b; } if (!b->cdr) { add_ref(a); return a; } if (a->cdr == b->cdr) { /* We know that they differ due to the a == b test at * the befinning of the function. The only way they * can differ is that car differs. There are only two * valid values for car, so select the stricter (ie 'is-a') */ type_stack_mark(); push_object_type(1, CDR_TO_INT(a)); return pop_unfinished_type(); } if (a->car && b->car) { /* This is only possible if a->cdr == b->cdr, but that is * handled above. */ return NULL; } { struct program *ap = id_to_program(CDR_TO_INT(a)); struct program *bp = id_to_program(CDR_TO_INT(b)); if (!b->car && implements(ap, bp)) { add_ref(a); return a; } if (!a->car && implements(bp, ap)) { add_ref(b); return b; } if ((a->car == b->car) && is_compatible(ap, bp)) { /* Both car must be 0 due to test above. * It is possible to implement a class that * implements both of the classes. */ type_stack_mark(); push_finished_type(a); push_finished_type(b); push_reverse_type(T_AND); return pop_unfinished_type(); } return NULL; } } /* Leaf type. */ add_ref(a); return a; } struct pike_type *intersect_types(struct pike_type *a, struct pike_type *b, enum pt_cmp_flags aflags, enum pt_cmp_flags bflags, enum pt_remap_flags remap_flags) { struct remap_state remap;
c97a452021-12-17Henrik Grubbström (Grubba)  struct pike_type *and_res; INIT_REMAP_STATE(remap);
d41c192020-09-27Henrik Grubbström (Grubba) 
c97a452021-12-17Henrik Grubbström (Grubba)  and_res = low_intersect_types(a, b, &remap, aflags, bflags, remap_flags);
d41c192020-09-27Henrik Grubbström (Grubba) 
c97a452021-12-17Henrik Grubbström (Grubba)  EXIT_REMAP_STATE(remap); return and_res;
d41c192020-09-27Henrik Grubbström (Grubba) }
71a9672001-03-03Henrik Grubbström (Grubba) /* * match two type strings, return zero if they don't match, and return * the part of 'a' that _did_ match if it did. */
2fad8e2005-11-08Henrik Grubbström (Grubba) static struct pike_type *low_match_types2(struct pike_type *a, struct pike_type *b, int flags);
71a9672001-03-03Henrik Grubbström (Grubba) static struct pike_type *low_match_types(struct pike_type *a, struct pike_type *b, int flags) {
72ef9c2020-08-19Henrik Grubbström (Grubba)  struct pike_type *ret = NULL; DECLARE_CYCLIC(); #ifdef PIKE_TYPE_DEBUG
71a9672001-03-03Henrik Grubbström (Grubba)  int e; char *s; if (l_flag>2) {
1283982015-10-11Henrik Grubbström (Grubba)  fprintf(stderr, "%*slow_match_types(", indent*2, ""); simple_describe_type(a); fprintf(stderr, ",\n"); fprintf(stderr, "%*s%s", indent*2, "", " "); simple_describe_type(b); fprintf(stderr, ",\n"); fprintf(stderr, "%*s%s", indent*2, "", " ");
71a9672001-03-03Henrik Grubbström (Grubba)  if (flags) { int f = 0; if (flags & A_EXACT) {
1283982015-10-11Henrik Grubbström (Grubba)  fprintf(stderr, "A_EXACT");
71a9672001-03-03Henrik Grubbström (Grubba)  f = 1; } if (flags & B_EXACT) { if (f) {
1283982015-10-11Henrik Grubbström (Grubba)  fprintf(stderr, " | ");
71a9672001-03-03Henrik Grubbström (Grubba)  }
1283982015-10-11Henrik Grubbström (Grubba)  fprintf(stderr, "B_EXACT");
71a9672001-03-03Henrik Grubbström (Grubba)  f = 1; } if (flags & NO_MAX_ARGS) { if (f) {
1283982015-10-11Henrik Grubbström (Grubba)  fprintf(stderr," | ");
71a9672001-03-03Henrik Grubbström (Grubba)  }
1283982015-10-11Henrik Grubbström (Grubba)  fprintf(stderr, "NO_MAX_ARGS");
71a9672001-03-03Henrik Grubbström (Grubba)  f = 1; } if (flags & NO_SHORTCUTS) { if (f) {
1283982015-10-11Henrik Grubbström (Grubba)  fprintf(stderr, " | ");
71a9672001-03-03Henrik Grubbström (Grubba)  }
1283982015-10-11Henrik Grubbström (Grubba)  fprintf(stderr, "NO_SHORTCUTS");
71a9672001-03-03Henrik Grubbström (Grubba)  f = 1; } } else {
1283982015-10-11Henrik Grubbström (Grubba)  fputc('0', stderr);
71a9672001-03-03Henrik Grubbström (Grubba)  }
1283982015-10-11Henrik Grubbström (Grubba)  fprintf(stderr, ");\n");
71a9672001-03-03Henrik Grubbström (Grubba)  indent++; }
72ef9c2020-08-19Henrik Grubbström (Grubba) #endif
71a9672001-03-03Henrik Grubbström (Grubba) 
72ef9c2020-08-19Henrik Grubbström (Grubba)  if ((a == b) || (!a)) { ret = a;
162e882020-08-21Henrik Grubbström (Grubba)  if (ret) add_ref(ret);
72ef9c2020-08-19Henrik Grubbström (Grubba)  } else { ret = BEGIN_CYCLIC(a, b); if (!ret) { SET_CYCLIC_RET(a);
71a9672001-03-03Henrik Grubbström (Grubba) 
72ef9c2020-08-19Henrik Grubbström (Grubba)  ret = low_match_types2(a, b, flags);
162e882020-08-21Henrik Grubbström (Grubba)  } else { add_ref(ret);
72ef9c2020-08-19Henrik Grubbström (Grubba)  } END_CYCLIC(); } #ifdef PIKE_TYPE_DEBUG
71a9672001-03-03Henrik Grubbström (Grubba)  if (l_flag>2) { indent--;
1283982015-10-11Henrik Grubbström (Grubba)  fprintf(stderr, "%*s= ", indent*2, "");
72ef9c2020-08-19Henrik Grubbström (Grubba)  if(ret) simple_describe_type(ret);
71a9672001-03-03Henrik Grubbström (Grubba)  else
1283982015-10-11Henrik Grubbström (Grubba)  fprintf(stderr, "NULL"); fputc('\n', stderr);
71a9672001-03-03Henrik Grubbström (Grubba)  }
72ef9c2020-08-19Henrik Grubbström (Grubba) #endif return ret;
71a9672001-03-03Henrik Grubbström (Grubba) }
474d9e2020-08-29Henrik Grubbström (Grubba) static void push_expand_transitive_type(struct pike_type *cont, struct pike_type *trans, struct pike_type **markers, int num_args) { struct pike_type *tmp; TYPE_STACK_DEBUG("expand_transitive");
010d342022-04-02Henrik Grubbström (Grubba)  switch(cont?(cont->type & PIKE_T_MASK):PIKE_T_UNKNOWN) { case PIKE_T_UNKNOWN: if (!trans) { push_type(PIKE_T_UNKNOWN); } else { /* A car of __unknown__ is short-hand for having it identical * to the cdr. */ push_expand_transitive_type(trans, trans, markers, num_args); } break;
474d9e2020-08-29Henrik Grubbström (Grubba)  case T_OR: case T_AND: push_expand_transitive_type(cont->cdr, trans, markers, num_args); push_expand_transitive_type(cont->car, trans, markers, num_args); push_type(cont->type); break; case PIKE_T_FUNCTION: /* * transitive(function(a, b, ...:c), X) * * ==> * * function(a, @transitive(function(b, ...:c), X) */ push_expand_transitive_type(cont->cdr, trans, markers, num_args + 1); push_finished_type(cont->car); push_type(cont->type); break; case T_MANY: if (num_args) {
4f759e2022-04-11Henrik Grubbström (Grubba)  /* No need to expand further for now. */
474d9e2020-08-29Henrik Grubbström (Grubba)  push_finished_type(trans); push_finished_type(cont); push_type(PIKE_T_TRANSITIVE); } else { /* Two cases: * * transitive(function(:x), function(x, a, b, ...: c)) * * ==> * * function(:x) | expand(transitive(function(a, b, ...: c), * function(x, a, b, ...:c))) * * And * * transitive(function(t...:x), function(x, a, b, ...: c)) * * ==> * * function(t...:x) | * function(t, @transitive(function(t...:x), * function(x, a, b, c, ...:c)))) | * expand(transitive(function(a, b, ...: c), * function(x, a, b, ...:c))) */ DECLARE_CYCLIC();
eccb9d2020-09-11Henrik Grubbström (Grubba)  push_finished_type_with_markers(cont, markers, 0);
474d9e2020-08-29Henrik Grubbström (Grubba)  if (!BEGIN_CYCLIC(cont, trans)) { SET_CYCLIC_RET(1); /* Check many arg. */ push_finished_type_with_markers(cont->car, markers, 0);
be352e2022-03-30Henrik Grubbström (Grubba)  if (peek_type_stack() != void_type_string) {
474d9e2020-08-29Henrik Grubbström (Grubba)  push_finished_type(trans); push_finished_type(cont); push_type(PIKE_T_TRANSITIVE); push_reverse_type(PIKE_T_FUNCTION); push_type(T_OR); } else { compiler_discard_top_type(); } push_finished_type_with_markers(cont->cdr, markers, 0); tmp = low_new_check_call(trans, peek_type_stack(), 0, NULL); compiler_discard_top_type(); if (tmp) { /* Valid recursion. */ push_expand_transitive_type(tmp, trans, markers, 0); free_type(tmp); push_type(T_OR); } } END_CYCLIC(); } break;
14b0e02022-04-03Henrik Grubbström (Grubba)  case PIKE_T_OPERATOR: if (num_args) { /* No need to expand futher for now. */ push_finished_type(trans); push_finished_type(cont); push_type(PIKE_T_TRANSITIVE); } else { /* We have no idea. */ push_type(PIKE_T_MIXED); } break;
474d9e2020-08-29Henrik Grubbström (Grubba)  case PIKE_T_MIXED: push_type(PIKE_T_MIXED); break;
14b0e02022-04-03Henrik Grubbström (Grubba)  case T_VOID: push_type(T_VOID); break;
474d9e2020-08-29Henrik Grubbström (Grubba)  default: /* Unsupported. */ fprintf(stderr, "Attempting to expand unsupported type: "); simple_describe_type(cont); fprintf(stderr, "\n"); push_finished_type(function_type_string); Pike_fatal("Attempt to expand unsupported type: %d\n", cont->type); break; } } /* Partially expand transitive types, so that eg matching * against function types works as expected. */ static struct pike_type *expand_transitive(struct pike_type *fun, struct pike_type **markers, int flags) { struct pike_type *ret_type; struct pike_type *cont_type; assert(fun->type == PIKE_T_TRANSITIVE);
4f759e2022-04-11Henrik Grubbström (Grubba)  assert(markers);
474d9e2020-08-29Henrik Grubbström (Grubba)  type_stack_mark(); push_expand_transitive_type(fun->car, fun->cdr, markers, 0); return pop_unfinished_type(); }
71a9672001-03-03Henrik Grubbström (Grubba) static struct pike_type *low_match_types2(struct pike_type *a, struct pike_type *b, int flags) { int correct_args;
162e882020-08-21Henrik Grubbström (Grubba)  struct pike_type *ret = NULL; struct pike_type *tmp;
71a9672001-03-03Henrik Grubbström (Grubba) 
dd29f42008-05-06Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG
203e412007-04-05Henrik Grubbström (Grubba)  fatal_check_c_stack(1024);
dd29f42008-05-06Henrik Grubbström (Grubba) #endif
203e412007-04-05Henrik Grubbström (Grubba) 
fb1c4e2021-02-10Henrik Grubbström (Grubba)  if (!a) { if (b) { add_ref(b); return b; } return NULL; } else if (!b) { add_ref(a); return a; }
9e5e9b2020-09-16Henrik Grubbström (Grubba)  switch(a->type & PIKE_T_MASK)
71a9672001-03-03Henrik Grubbström (Grubba)  { case T_AND: ret = low_match_types(a->car, b, flags); if(!ret) return 0;
162e882020-08-21Henrik Grubbström (Grubba)  free_type(ret);
71a9672001-03-03Henrik Grubbström (Grubba)  return low_match_types(a->cdr, b, flags); case T_OR: ret = low_match_types(a->car, b, flags); if(ret && !(flags & NO_SHORTCUTS)) return ret; if(ret) {
162e882020-08-21Henrik Grubbström (Grubba)  struct pike_type *t = low_match_types(a->cdr, b, flags); if (t) {
042e0a2020-08-24Henrik Grubbström (Grubba)  type_stack_mark(); push_finished_type(ret); push_finished_type(t); push_type(T_OR); free_type(ret);
162e882020-08-21Henrik Grubbström (Grubba)  free_type(t);
042e0a2020-08-24Henrik Grubbström (Grubba)  ret = pop_unfinished_type();
162e882020-08-21Henrik Grubbström (Grubba)  }
71a9672001-03-03Henrik Grubbström (Grubba)  return ret; }else{ return low_match_types(a->cdr, b, flags); }
ce88d62001-03-19Henrik Grubbström (Grubba)  case PIKE_T_RING: return low_match_types(a->car, b, flags);
790d032007-05-09Henrik Grubbström (Grubba)  case PIKE_T_SCOPE:
f62c412001-03-05Henrik Grubbström (Grubba)  case PIKE_T_NAME:
9129122007-04-21Henrik Grubbström (Grubba)  case PIKE_T_ATTRIBUTE:
f62c412001-03-05Henrik Grubbström (Grubba)  return low_match_types(a->cdr, b, flags);
71a9672001-03-03Henrik Grubbström (Grubba)  case T_NOT:
162e882020-08-21Henrik Grubbström (Grubba)  ret = low_match_types(a->car, b, (flags ^ B_EXACT ) | NO_MAX_ARGS); if (ret) { free_type(ret);
71a9672001-03-03Henrik Grubbström (Grubba)  return 0;
162e882020-08-21Henrik Grubbström (Grubba)  }
81abe22022-03-17Henrik Grubbström (Grubba)  /* We know that a->car and b do not overlap, it is thus safe * to use mixed|void in place of a to get proper values for * any markers in b. */ return low_match_types(any_type_string, b, flags);
71a9672001-03-03Henrik Grubbström (Grubba) 
3360ff2009-03-04Henrik Grubbström (Grubba)  case T_ASSIGN: { int m = CAR_TO_INT(a);
71a9672001-03-03Henrik Grubbström (Grubba)  ret = low_match_types(a->cdr, b, flags);
3360ff2009-03-04Henrik Grubbström (Grubba)  if(ret && (!a_markers[m] || b->type != T_VOID))
71a9672001-03-03Henrik Grubbström (Grubba)  {
6a18902021-11-23Henrik Grubbström (Grubba)  struct pike_type *filtered_b = NULL;
9e6f6f2001-03-18Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if ((m < 0) || (m > 9)) {
0aa8592021-11-11Henrik Grubbström (Grubba)  Pike_fatal("marker out of range: $%d\n", m);
9e6f6f2001-03-18Henrik Grubbström (Grubba)  } #endif /* PIKE_DEBUG */
71a9672001-03-03Henrik Grubbström (Grubba)  type_stack_mark();
838c212007-04-27Henrik Grubbström (Grubba)  push_finished_type_with_markers(b, b_markers, 0);
71a9672001-03-03Henrik Grubbström (Grubba)  tmp = pop_unfinished_type();
6a18902021-11-23Henrik Grubbström (Grubba)  filtered_b = type_binop(PT_BINOP_AND, tmp, a->cdr, PT_FLAG_CMP_NULLABLE, PT_FLAG_CMP_NULLABLE, PT_FLAG_REMAP_INHIBIT); free_type(tmp); tmp = filtered_b;
71a9672001-03-03Henrik Grubbström (Grubba)  type_stack_mark(); low_or_pike_types(a_markers[m], tmp, 0); if(a_markers[m]) free_type(a_markers[m]); free_type(tmp); a_markers[m] = pop_unfinished_type(); #ifdef PIKE_TYPE_DEBUG if (l_flag>2) {
1283982015-10-11Henrik Grubbström (Grubba)  fprintf(stderr, "%*sa_markers[%d]=", indent*2, "", m); simple_describe_type(a_markers[m]); fputc('\n', stderr);
71a9672001-03-03Henrik Grubbström (Grubba)  } #endif #ifdef PIKE_DEBUG
be352e2022-03-30Henrik Grubbström (Grubba)  if(a_markers[m] && (a_markers[m]->type == m+'0'))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Cyclic type!\n");
71a9672001-03-03Henrik Grubbström (Grubba) #endif } return ret;
3360ff2009-03-04Henrik Grubbström (Grubba)  }
71a9672001-03-03Henrik Grubbström (Grubba)  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int m = a->type - '0'; if(a_markers[m]) {
203e412007-04-05Henrik Grubbström (Grubba)  struct pike_type *t = a_markers[m];
71a9672001-03-03Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if(a_markers[m]->type == a->type)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Cyclic type!\n");
71a9672001-03-03Henrik Grubbström (Grubba)  if(a_markers[m]->type == T_OR && a_markers[m]->car->type == a->type)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Cyclic type!\n");
71a9672001-03-03Henrik Grubbström (Grubba) #endif
203e412007-04-05Henrik Grubbström (Grubba)  a_markers[m] = NULL;
162e882020-08-21Henrik Grubbström (Grubba)  ret = low_match_types(t, b, flags);
64d8a62007-04-06Henrik Grubbström (Grubba)  if (a_markers[m]) { a_markers[m] = or_pike_types(tmp = a_markers[m], t, 0); free_type(tmp); free_type(t); } else { a_markers[m] = t; }
162e882020-08-21Henrik Grubbström (Grubba)  return ret;
71a9672001-03-03Henrik Grubbström (Grubba)  }
162e882020-08-21Henrik Grubbström (Grubba)  else {
71a9672001-03-03Henrik Grubbström (Grubba)  return low_match_types(mixed_type_string, b, flags);
162e882020-08-21Henrik Grubbström (Grubba)  }
71a9672001-03-03Henrik Grubbström (Grubba)  }
d79bff2020-07-17Henrik Grubbström (Grubba)  case PIKE_T_OPERATOR: {
562fd52021-11-28Henrik Grubbström (Grubba)  /* First match car & cdr against mixed to evaluate markers. * It also applies any related type operators. */ struct pike_type *t; struct pike_type *t1 = low_match_types(a->car, any_type_string, flags); if (a->type & 0x8000) { struct pike_type *t2 = low_match_types(a->cdr, any_type_string, flags); t = apply_type_operator(a->type, t1, t2); free_type(t2); } else { t = apply_type_operator(a->type, t1, a->cdr);
1247b72020-08-15Henrik Grubbström (Grubba)  }
562fd52021-11-28Henrik Grubbström (Grubba)  free_type(t1); if (!t) return NULL;
d79bff2020-07-17Henrik Grubbström (Grubba)  ret = low_match_types(t, b, flags); free_type(t); return ret; }
5fc9642020-08-17Henrik Grubbström (Grubba)  case PIKE_T_TRANSITIVE: {
474d9e2020-08-29Henrik Grubbström (Grubba) #if 1 struct pike_type *t = expand_transitive(a, a_markers, flags); ret = low_match_types(t, b, flags); free_type(t); return ret; #else
5fc9642020-08-17Henrik Grubbström (Grubba)  /* FIXME */
162e882020-08-21Henrik Grubbström (Grubba)  add_ref(a);
5fc9642020-08-17Henrik Grubbström (Grubba)  return a;
474d9e2020-08-29Henrik Grubbström (Grubba) #endif
5fc9642020-08-17Henrik Grubbström (Grubba)  }
71a9672001-03-03Henrik Grubbström (Grubba)  }
9e5e9b2020-09-16Henrik Grubbström (Grubba)  switch(b->type & PIKE_T_MASK)
71a9672001-03-03Henrik Grubbström (Grubba)  { case T_AND: ret = low_match_types(a, b->car, flags); if(!ret) return 0;
162e882020-08-21Henrik Grubbström (Grubba)  free_type(ret);
71a9672001-03-03Henrik Grubbström (Grubba)  return low_match_types(a, b->cdr, flags); case T_OR: ret = low_match_types(a, b->car, flags); if(ret && !(flags & NO_SHORTCUTS)) return ret; if(ret) {
162e882020-08-21Henrik Grubbström (Grubba)  struct pike_type *t = low_match_types(a, b->cdr, flags); if (t) {
042e0a2020-08-24Henrik Grubbström (Grubba)  type_stack_mark(); push_finished_type(ret); push_finished_type(t); push_type(T_OR); free_type(ret);
162e882020-08-21Henrik Grubbström (Grubba)  free_type(t);
042e0a2020-08-24Henrik Grubbström (Grubba)  ret = pop_unfinished_type();
162e882020-08-21Henrik Grubbström (Grubba)  }
71a9672001-03-03Henrik Grubbström (Grubba)  return ret; }else{ return low_match_types(a, b->cdr, flags); }
ce88d62001-03-19Henrik Grubbström (Grubba)  case PIKE_T_RING: return low_match_types(a, b->car, flags);
790d032007-05-09Henrik Grubbström (Grubba)  case PIKE_T_SCOPE:
f62c412001-03-05Henrik Grubbström (Grubba)  case PIKE_T_NAME:
9129122007-04-21Henrik Grubbström (Grubba)  case PIKE_T_ATTRIBUTE:
f62c412001-03-05Henrik Grubbström (Grubba)  return low_match_types(a, b->cdr, flags);
71a9672001-03-03Henrik Grubbström (Grubba)  case T_NOT:
162e882020-08-21Henrik Grubbström (Grubba)  ret = low_match_types(a, b->car, (flags ^ A_EXACT ) | NO_MAX_ARGS); if (ret) { free_type(ret);
71a9672001-03-03Henrik Grubbström (Grubba)  return 0;
162e882020-08-21Henrik Grubbström (Grubba)  }
81abe22022-03-17Henrik Grubbström (Grubba)  /* We know that a and b->car do not overlap, it is thus safe * to use mixed|void in place of b to get proper values for * any markers in a. */ return low_match_types(a, any_type_string, flags);
71a9672001-03-03Henrik Grubbström (Grubba) 
3360ff2009-03-04Henrik Grubbström (Grubba)  case T_ASSIGN: { int m = CAR_TO_INT(b);