Skip to content
Snippets Groups Projects
Select Git revision
  • 6bc6ed2f77ebb7d53ac8c38133d5f622a199e629
  • master default protected
  • 9.0
  • 8.0
  • 7.8
  • 7.6
  • 7.4
  • 7.2
  • 7.0
  • 0.6
  • rosuav/latex-markdown-renderer
  • rxnpatch/rxnpatch
  • marcus/gobject-introspection
  • rxnpatch/8.0
  • rosuav/pre-listening-ports
  • nt-tools
  • rosuav/async-annotations
  • rosuav/pgsql-ssl
  • rxnpatch/rxnpatch-broken/2023-10-06T094250
  • grubba/fdlib
  • grubba/wip/sakura/8.0
  • v8.0.2000
  • v8.0.1998
  • v8.0.1996
  • v8.0.1994
  • v8.0.1992
  • v8.0.1990
  • v8.0.1988
  • v8.0.1986
  • rxnpatch/clusters/8.0/2025-04-29T124414
  • rxnpatch/2025-04-29T124414
  • v8.0.1984
  • v8.0.1982
  • v8.0.1980
  • v8.0.1978
  • v8.0.1976
  • v8.0.1974
  • v8.0.1972
  • v8.0.1970
  • v8.0.1968
  • v8.0.1966
41 results

operators.c

Blame
    • Fredrik Hübinette (Hubbe)'s avatar
      cb22562e
      committing · cb22562e
      Fredrik Hübinette (Hubbe) authored
      Rev: README:1.1
      Rev: bin/create_testsuite:1.3
      Rev: bin/hilfe.lpc:1.2
      Rev: bin/rsif:1.2
      Rev: bin/uhttpd.lpc:1.2
      Rev: doc/simulated/open:1.1
      Rev: lib/master.lpc:1.2
      Rev: lib/simulate.lpc:1.4
      Rev: lib/testsuite.lpc:1.3
      Rev: src/BUGS:1.3
      Rev: src/Makefile.in:1.6
      Rev: src/Makefile.in.src:1.2
      Rev: src/README:1.2
      Rev: src/add_efun.c:1.2
      Rev: src/add_efun.h:1.2
      Rev: src/array.c:1.4
      Rev: src/array.h:1.2
      Rev: src/backend.c:1.3
      Rev: src/backend.h:1.2
      Rev: src/builtin_efuns.c:1.2
      Rev: src/builtin_efuns.h:1.2
      Rev: src/call_out.c:1.5
      Rev: src/call_out.h:1.2
      Rev: src/callback.c:1.2
      Rev: src/callback.h:1.2
      Rev: src/config.h:1.6
      Rev: src/configure.in:1.9
      Rev: src/debug.c:1.4
      Rev: src/debug.h:1.4
      Rev: src/docode.c:1.4
      Rev: src/docode.h:1.2
      Rev: src/dynamic_buffer.c:1.3
      Rev: src/dynamic_buffer.h:1.2
      Rev: src/efun.h:1.2
      Rev: src/error.c:1.2
      Rev: src/error.h:1.2
      Rev: src/fd_control.c:1.2
      Rev: src/fd_control.h:1.2
      Rev: src/fsort.c:1.2
      Rev: src/fsort.h:1.2
      Rev: src/global.h:1.2
      Rev: src/hashtable.c:1.2
      Rev: src/hashtable.h:1.2
      Rev: src/interpret.c:1.5
      Rev: src/interpret.h:1.2
      Rev: src/language.y:1.3
      Rev: src/las.c:1.3
      Rev: src/las.h:1.3
      Rev: src/lex.c:1.3
      Rev: src/lex.h:1.2
      Rev: src/list.c:1.3
      Rev: src/list.h:1.2
      Rev: src/lpc_signal.c:1.1
      Rev: src/lpc_signal.h:1.1
      Rev: src/lpc_types.c:1.3
      Rev: src/lpc_types.h:1.2
      Rev: src/machine.h.in:1.3
      Rev: src/macros.h:1.4
      Rev: src/main.c:1.8
      Rev: src/main.h:1.2
      Rev: src/mapping.c:1.4
      Rev: src/mapping.h:1.2
      Rev: src/memory.c:1.3
      Rev: src/memory.h:1.2
      Rev: src/module.c:1.2
      Rev: src/module.h:1.2
      Rev: src/modules/files/Makefile.in:1.3
      Rev: src/modules/files/Makefile.in.src:1.2
      Rev: src/modules/files/configure.in:1.5
      Rev: src/modules/files/datagram.c:1.2
      Rev: src/modules/files/efuns.c:1.4
      Rev: src/modules/files/file.c:1.5
      Rev: src/modules/files/file.h:1.3
      Rev: src/modules/files/file_machine.h.in:1.3
      Rev: src/modules/files/socket.c:1.6
      Rev: src/modules/math/Makefile.in:1.4
      Rev: src/modules/math/Makefile.in.src:1.3
      Rev: src/modules/math/math.c:1.2
      Rev: src/modules/regexp/Makefile.in:1.3
      Rev: src/modules/regexp/Makefile.in.src:1.2
      Rev: src/modules/regexp/glue.c:1.2
      Rev: src/modules/regexp/regexp.h:1.2
      Rev: src/modules/sprintf/Makefile.in:1.3
      Rev: src/modules/sprintf/Makefile.in.src:1.2
      Rev: src/modules/sprintf/sprintf.c:1.2
      Rev: src/object.c:1.3
      Rev: src/object.h:1.2
      Rev: src/opcodes.c:1.6
      Rev: src/opcodes.h:1.2
      Rev: src/operators.c:1.3
      Rev: src/operators.h:1.2
      Rev: src/otable.h:1.2
      Rev: src/port.c:1.9
      Rev: src/port.h:1.4
      Rev: src/program.h:1.2
      Rev: src/rusage.c:1.3
      Rev: src/rusage.h:1.2
      Rev: src/stralloc.c:1.3
      Rev: src/stralloc.h:1.3
      Rev: src/stuff.c:1.2
      Rev: src/stuff.h:1.2
      Rev: src/svalue.c:1.4
      Rev: src/svalue.h:1.2
      Rev: src/todo:1.2
      Rev: src/types.h:1.6
      Rev: src/ualarm.c:1.2
      cb22562e
      History
      committing
      Fredrik Hübinette (Hubbe) authored
      Rev: README:1.1
      Rev: bin/create_testsuite:1.3
      Rev: bin/hilfe.lpc:1.2
      Rev: bin/rsif:1.2
      Rev: bin/uhttpd.lpc:1.2
      Rev: doc/simulated/open:1.1
      Rev: lib/master.lpc:1.2
      Rev: lib/simulate.lpc:1.4
      Rev: lib/testsuite.lpc:1.3
      Rev: src/BUGS:1.3
      Rev: src/Makefile.in:1.6
      Rev: src/Makefile.in.src:1.2
      Rev: src/README:1.2
      Rev: src/add_efun.c:1.2
      Rev: src/add_efun.h:1.2
      Rev: src/array.c:1.4
      Rev: src/array.h:1.2
      Rev: src/backend.c:1.3
      Rev: src/backend.h:1.2
      Rev: src/builtin_efuns.c:1.2
      Rev: src/builtin_efuns.h:1.2
      Rev: src/call_out.c:1.5
      Rev: src/call_out.h:1.2
      Rev: src/callback.c:1.2
      Rev: src/callback.h:1.2
      Rev: src/config.h:1.6
      Rev: src/configure.in:1.9
      Rev: src/debug.c:1.4
      Rev: src/debug.h:1.4
      Rev: src/docode.c:1.4
      Rev: src/docode.h:1.2
      Rev: src/dynamic_buffer.c:1.3
      Rev: src/dynamic_buffer.h:1.2
      Rev: src/efun.h:1.2
      Rev: src/error.c:1.2
      Rev: src/error.h:1.2
      Rev: src/fd_control.c:1.2
      Rev: src/fd_control.h:1.2
      Rev: src/fsort.c:1.2
      Rev: src/fsort.h:1.2
      Rev: src/global.h:1.2
      Rev: src/hashtable.c:1.2
      Rev: src/hashtable.h:1.2
      Rev: src/interpret.c:1.5
      Rev: src/interpret.h:1.2
      Rev: src/language.y:1.3
      Rev: src/las.c:1.3
      Rev: src/las.h:1.3
      Rev: src/lex.c:1.3
      Rev: src/lex.h:1.2
      Rev: src/list.c:1.3
      Rev: src/list.h:1.2
      Rev: src/lpc_signal.c:1.1
      Rev: src/lpc_signal.h:1.1
      Rev: src/lpc_types.c:1.3
      Rev: src/lpc_types.h:1.2
      Rev: src/machine.h.in:1.3
      Rev: src/macros.h:1.4
      Rev: src/main.c:1.8
      Rev: src/main.h:1.2
      Rev: src/mapping.c:1.4
      Rev: src/mapping.h:1.2
      Rev: src/memory.c:1.3
      Rev: src/memory.h:1.2
      Rev: src/module.c:1.2
      Rev: src/module.h:1.2
      Rev: src/modules/files/Makefile.in:1.3
      Rev: src/modules/files/Makefile.in.src:1.2
      Rev: src/modules/files/configure.in:1.5
      Rev: src/modules/files/datagram.c:1.2
      Rev: src/modules/files/efuns.c:1.4
      Rev: src/modules/files/file.c:1.5
      Rev: src/modules/files/file.h:1.3
      Rev: src/modules/files/file_machine.h.in:1.3
      Rev: src/modules/files/socket.c:1.6
      Rev: src/modules/math/Makefile.in:1.4
      Rev: src/modules/math/Makefile.in.src:1.3
      Rev: src/modules/math/math.c:1.2
      Rev: src/modules/regexp/Makefile.in:1.3
      Rev: src/modules/regexp/Makefile.in.src:1.2
      Rev: src/modules/regexp/glue.c:1.2
      Rev: src/modules/regexp/regexp.h:1.2
      Rev: src/modules/sprintf/Makefile.in:1.3
      Rev: src/modules/sprintf/Makefile.in.src:1.2
      Rev: src/modules/sprintf/sprintf.c:1.2
      Rev: src/object.c:1.3
      Rev: src/object.h:1.2
      Rev: src/opcodes.c:1.6
      Rev: src/opcodes.h:1.2
      Rev: src/operators.c:1.3
      Rev: src/operators.h:1.2
      Rev: src/otable.h:1.2
      Rev: src/port.c:1.9
      Rev: src/port.h:1.4
      Rev: src/program.h:1.2
      Rev: src/rusage.c:1.3
      Rev: src/rusage.h:1.2
      Rev: src/stralloc.c:1.3
      Rev: src/stralloc.h:1.3
      Rev: src/stuff.c:1.2
      Rev: src/stuff.h:1.2
      Rev: src/svalue.c:1.4
      Rev: src/svalue.h:1.2
      Rev: src/todo:1.2
      Rev: src/types.h:1.6
      Rev: src/ualarm.c:1.2
    operators.c 10.66 KiB
    /*\
    ||| This file a part of uLPC, and is copyright by Fredrik Hubinette
    ||| uLPC is distributed as GPL (General Public License)
    ||| See the files COPYING and DISCLAIMER for more information.
    \*/
    #include <math.h>
    #include "global.h"
    #include "interpret.h"
    #include "svalue.h"
    #include "list.h"
    #include "mapping.h"
    #include "array.h"
    #include "stralloc.h"
    #include "opcodes.h"
    #include "operators.h"
    #include "language.h"
    #include "memory.h"
    #include "error.h"
    
    #define COMPARISON(ID,EXPR) \
    void ID() \
    { \
      int i=EXPR; \
      pop_n_elems(2); \
      sp->type=T_INT; \
      sp->u.integer=i; \
      sp++; \
    } 
    
    COMPARISON(f_eq, is_eq(sp-2,sp-1))
    COMPARISON(f_ne,!is_eq(sp-2,sp-1))
    COMPARISON(f_lt, is_lt(sp-2,sp-1))
    COMPARISON(f_le,!is_gt(sp-2,sp-1))
    COMPARISON(f_gt, is_gt(sp-2,sp-1))
    COMPARISON(f_ge,!is_lt(sp-2,sp-1))
    
    void f_sum(INT32 args)
    {
      INT32 e,size;
      TYPE_FIELD types;
    
      types=0;
      for(e=-args;e<0;e++) types|=1<<sp[e].type;
        
      switch(types)
      {
      default:
        if(args)
        {
          switch(sp[-args].type)
          {
          case T_OBJECT:
          case T_PROGRAM:
          case T_FUNCTION:
    	error("Bad argument 1 to summation\n");
          }
        }
        error("Incompatible types to sum() or +\n");
        return; /* compiler hint */
    
      case BIT_STRING:
      {
        struct lpc_string *r;
        char *buf;
    
        if(args==1) return;
        size=0;
    
        for(e=-args;e<0;e++) size+=sp[e].u.string->len;
    
        if(args==2)
        {
          r=add_shared_strings(sp[-2].u.string,sp[-1].u.string);
        }else{
          r=begin_shared_string(size);
          buf=r->str;
          for(e=-args;e<0;e++)
          {
    	MEMCPY(buf,sp[e].u.string->str,sp[e].u.string->len);
    	buf+=sp[e].u.string->len;
          }
          r=end_shared_string(r);
        }
        for(e=-args;e<0;e++)
        {
          free_string(sp[e].u.string);
        }
        sp-=args;
        push_string(r);
        break;
      }
    
      case BIT_STRING | BIT_INT:
      case BIT_STRING | BIT_FLOAT:
      case BIT_STRING | BIT_FLOAT | BIT_INT:
      {
        struct lpc_string *r;
        char *buf,*str;
        size=0;
        for(e=-args;e<0;e++)
        {
          switch(sp[e].type)
          {
          case T_STRING:
    	size+=sp[e].u.string->len;
    	break;
    
          case T_INT:
    	size+=14;
    	break;
    
          case T_FLOAT:
    	size+=22;
    	break;
          }
        }
        str=buf=xalloc(size+1);
        size=0;
        
        for(e=-args;e<0;e++)
        {
          switch(sp[e].type)
          {
          case T_STRING:
    	MEMCPY(buf,sp[e].u.string->str,sp[e].u.string->len);
    	buf+=sp[e].u.string->len;
    	break;
    
          case T_INT:
    	sprintf(buf,"%ld",(long)sp[e].u.integer);
    	buf+=strlen(buf);
    	break;
    
          case T_FLOAT:
    	sprintf(buf,"%f",(double)sp[e].u.float_number);
    	buf+=strlen(buf);
    	break;
          }
        }
        r=make_shared_binary_string(str,buf-str);
        free(str);
        pop_n_elems(args);
        push_string(r);
        break;
      }
    
      case BIT_INT:
        size=0;
        for(e=-args; e<0; e++) size+=sp[e].u.integer;
        sp-=args-1;
        sp[-1].u.integer=size;
        break;
    
      case BIT_FLOAT:
      {
        FLOAT_TYPE sum;
        sum=0.0;
        for(e=-args; e<0; e++) sum+=sp[e].u.float_number;
        sp-=args-1;
        sp[-1].u.float_number=sum;
        break;
      }
    
      case BIT_ARRAY:
      {
        struct array *a;
        a=add_arrays(sp-args,args);
        pop_n_elems(args);
        push_array(a);
        break;
      }
    
      case BIT_MAPPING:
      {
        struct mapping *m;
    
        m = add_mappings(sp - args, args);
        pop_n_elems(args);
        push_mapping(m);
        break;
      }
    
      case BIT_LIST:
      {
        struct list *l;
    
        l = add_lists(sp - args, args);
        pop_n_elems(args);
        push_list(l);
        break;
      }
      }
    }
    
    void f_add() { f_sum(2); }
    
    void f_subtract()
    {
      if (sp[-2].type != sp[-1].type )
        error("Subtract on different types.\n");
    
      switch(sp[-1].type)
      {
      case T_ARRAY:
      {
        struct array *a;
    
        check_array_for_destruct(sp[-2].u.array);
        check_array_for_destruct(sp[-1].u.array);
        a = subtract_arrays(sp[-2].u.array, sp[-1].u.array);
        pop_n_elems(2);
        push_array(a);
        return;
      }
    
      case T_MAPPING:
      {
        struct mapping *m;
        m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping,OP_SUB);
        pop_n_elems(2);
        push_mapping(m);
        return;
      }
    
      case T_LIST:
      {
        struct list *l;
        l=merge_lists(sp[-2].u.list, sp[-1].u.list, OP_SUB);
        pop_n_elems(2);
        push_list(l);
        return;
      }
    
      case T_FLOAT:
        sp--;
        sp[-1].u.float_number -= sp[0].u.float_number;
        return;
    
      case T_INT:
        sp--;
        sp[-1].u.integer -= sp[0].u.integer;
        return;
    
      case T_STRING:
      {
        struct lpc_string *s,*ret;
        sp--;
        s=make_shared_string("");
        ret=string_replace(sp[-1].u.string,sp[0].u.string,s);
        free_string(sp[-1].u.string);
        free_string(sp[0].u.string);
        free_string(s);
        sp[-1].u.string=ret;
        return;
      }
    
      default:
        error("Bad argument 1 to subtraction.\n");
      }
    }
    
    void f_and()
    {
      if(sp[-1].type != sp[-2].type)
        error("Bitwise and on different types.\n");
    
      switch(sp[-2].type)
      {
      case T_INT:
        sp--;
        sp[-1].u.integer &= sp[0].u.integer;
        break;
    
      case T_MAPPING:
      {
        struct mapping *m;
        m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping, OP_AND);
        pop_n_elems(2);
        push_mapping(m);
        return;
      }
    
      case T_LIST:
      {
        struct list *l;
        l=merge_lists(sp[-2].u.list, sp[-1].u.list, OP_AND);
        pop_n_elems(2);
        push_list(l);
        return;
      }
        
      case T_ARRAY:
      {
        struct array *a;
        a=and_arrays(sp[-2].u.array, sp[-1].u.array);
        pop_n_elems(2);
        push_array(a);
        return;
      }
      default:
        error("Bitwise and on illegal type.\n");
      }
    }
    
    void f_or()
    {
      if(sp[-1].type != sp[-2].type)
        error("Bitwise or on different types.\n");
    
      switch(sp[-2].type)
      {
      case T_INT:
        sp--;
        sp[-1].u.integer |= sp[0].u.integer;
        break;
    
      case T_MAPPING:
      {
        struct mapping *m;
        m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping, OP_OR);
        pop_n_elems(2);
        push_mapping(m);
        return;
      }
    
      case T_LIST:
      {
        struct list *l;
        l=merge_lists(sp[-2].u.list, sp[-1].u.list, OP_OR);
        pop_n_elems(2);
        push_list(l);
        return;
      }
        
      case T_ARRAY:
      {
        struct array *a;
        a=merge_array_without_order(sp[-2].u.array, sp[-1].u.array, OP_OR);
        pop_n_elems(2);
        push_array(a);
        return;
      }
    
      default:
        error("Bitwise or on illegal type.\n");
      }
    }
    
    void f_xor()
    {
      if(sp[-1].type != sp[-2].type)
        error("Bitwise xor on different types.\n");
    
      switch(sp[-2].type)
      {
      case T_INT:
        sp--;
        sp[-1].u.integer ^= sp[0].u.integer;
        break;
    
      case T_MAPPING:
      {
        struct mapping *m;
        m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping, OP_XOR);
        pop_n_elems(2);
        push_mapping(m);
        return;
      }
    
      case T_LIST:
      {
        struct list *l;
        l=merge_lists(sp[-2].u.list, sp[-1].u.list, OP_XOR);
        pop_n_elems(2);
        push_list(l);
        return;
      }
        
      case T_ARRAY:
      {
        struct array *a;
        a=merge_array_without_order(sp[-2].u.array, sp[-1].u.array, OP_XOR);
        pop_n_elems(2);
        push_array(a);
        return;
      }
      default:
        error("Bitwise xor on illegal type.\n");
      }
    }
    
    void f_lsh()
    {
      if(sp[-2].type != T_INT) error("Bad argument 1 to <<\n");
      if(sp[-1].type != T_INT) error("Bad argument 2 to <<\n");
      sp--;
      sp[-1].u.integer <<= sp[0].u.integer;
    }
    
    void f_rsh()
    {
      if(sp[-2].type != T_INT) error("Bad argument 1 to >>\n"); 
      if(sp[-1].type != T_INT) error("Bad argument 2 to >>\n");
      sp--;
      sp[-1].u.integer >>= sp[0].u.integer;
    }
    
    void f_multiply()
    {
      switch(sp[-2].type)
      {
      case T_ARRAY:
        if(sp[-1].type!=T_STRING)
        {
          error("Bad argument 2 to multiply.\n");
        }else{
          struct lpc_string *ret;
          sp--;
          ret=implode(sp[-1].u.array,sp[0].u.string);
          free_string(sp[0].u.string);
          free_array(sp[-1].u.array);
          sp[-1].type=T_STRING;
          sp[-1].u.string=ret;
          return;
        }
    
      case T_FLOAT:
        if(sp[-1].type!=T_FLOAT) error("Bad argument 2 to multiply.\n");
        sp--;
        sp[-1].u.float_number *= sp[0].u.float_number;
        return;
    
      case T_INT:
        if(sp[-1].type!=T_INT) error("Bad argument 2 to multiply.\n");
        sp--;
        sp[-1].u.integer *= sp[0].u.integer;
        return;
    
      default:
        error("Bad argument 1 to multiply.\n");
      }
    }
    
    void f_divide()
    {
      if(sp[-2].type!=sp[-1].type)
        error("Division on different types.\n");
    
      switch(sp[-2].type)
      {
      case T_STRING:
      {
        struct array *ret;
        sp--;
        ret=explode(sp[-1].u.string,sp[0].u.string);
        free_string(sp[-1].u.string);
        free_string(sp[0].u.string);
        sp[-1].type=T_ARRAY;
        sp[-1].u.array=ret;
        return;
      }
    
      case T_FLOAT:
        if(sp[-1].u.float_number == 0.0)
          error("Division by zero.\n");
        sp--;
        sp[-1].u.float_number /= sp[0].u.float_number;
        return;
    
      case T_INT:
        if (sp[-1].u.integer == 0)
          error("Division by zero\n");
        sp--;
        sp[-1].u.integer /= sp[0].u.integer;
        return;
        
      default:
        error("Bad argument 1 to divide.\n");
      }
    }
    
    void f_mod()
    {
      if(sp[-2].type != sp[-1].type)
        error("Modulo on different types.\n");
    
      switch(sp[-1].type)
      {
      case T_FLOAT:
      {
        FLOAT_TYPE foo;
        if(sp[-1].u.float_number == 0.0)
          error("Modulo by zero.\n");
        sp--;
        foo=sp[-1].u.float_number / sp[0].u.float_number;
        foo=sp[-1].u.float_number - sp[0].u.float_number * floor(foo);
        sp[-1].u.float_number=foo;
        return;
      }
      case T_INT:
        if (sp[-1].u.integer == 0) error("Modulo by zero.\n");
        sp--;
        sp[-1].u.integer %= sp[0].u.integer;
        return;
    
      default:
        error("Bad argument 1 to modulo.\n");
      }
    }
    
    void f_not()
    {
      if(sp[-1].type==T_INT)
      {
        sp[-1].u.integer = !sp[-1].u.integer;
      }else{
        pop_stack();
        sp->type=T_INT;
        sp->u.integer=0;
        sp++;
      }
    }
    
    void f_compl()
    {
      if (sp[-1].type != T_INT) error("Bad argument to ~\n");
      sp[-1].u.integer = ~ sp[-1].u.integer;
    }
    
    void f_negate()
    {
      switch(sp[-1].type)
      {
      case T_FLOAT:
        sp[-1].u.float_number=-sp[-1].u.float_number;
        return;
        
      case T_INT:
        sp[-1].u.integer = - sp[-1].u.integer;
        return;
    
      default: 
        error("Bad argument to unary minus\n");
      }
    }
    
    
    void f_range()
    {
      INT32 from,to;
      if(sp[-2].type != T_INT)
        error("Bad argument 1 to [ .. ]\n");
    
      if(sp[-1].type != T_INT)
        error("Bad argument 2 to [ .. ]\n");
    
      from=sp[-2].u.integer;
      if(from<0) from=0;
      to=sp[-1].u.integer;
      if(to<from-1) to=from-1;
      sp-=2;
    
      switch(sp[-1].type)
      {
      case T_STRING:
      {
        struct lpc_string *s;
        if(to>=sp[-1].u.string->len-1)
        {
          if(from==0) return;
          to=sp[-1].u.string->len-1;
    
          if(from>to+1) from=to+1;
        }
    
        s=make_shared_binary_string(sp[-1].u.string->str+from,to-from+1);
        free_string(sp[-1].u.string);
        sp[-1].u.string=s;
        break;
      }
    
      case T_ARRAY:
      {
        struct array *a;
        if(to>=sp[-1].u.array->size-1)
        {
          to=sp[-1].u.array->size-1;
    
          if(from>to+1) from=to+1;
        }
    
        a=slice_array(sp[-1].u.array,from,to+1);
        free_array(sp[-1].u.array);
        sp[-1].u.array=a;
        break;
      }
        
      default:
        error("[ .. ] can only be done on strings and arrays.\n");
      }
    }