diff options
82 files changed, 4006 insertions, 2095 deletions
@@ -10,3 +10,4 @@ Original Authors "mruby developers" are: Masamitsu MURASE Masaki Muranaka Internet Initiative Japan Inc. + Tadashi FUKUZAWA @@ -5,4 +5,42 @@ All the files in this distribution are covered under the MIT license (see the file MITL) except some files mentioned below: -(Currently no items are listed.) +mrbgems/mruby-random/src/mt19937ar.[ch] + + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + Copyright (C) 2005, Mutsuo Saito, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @@ -2,6 +2,7 @@ # Build description. # basic build file for mruby MRUBY_ROOT = File.dirname(File.expand_path(__FILE__)) +MRUBY_BUILD_HOST_IS_CYGWIN = RUBY_PLATFORM.include?('cygwin') # load build systems load "#{MRUBY_ROOT}/tasks/ruby_ext.rake" @@ -9,10 +10,8 @@ load "#{MRUBY_ROOT}/tasks/mruby_build.rake" load "#{MRUBY_ROOT}/tasks/mrbgem_spec.rake" # load configuration file -MRUBY_CONFIGS = ["#{MRUBY_ROOT}/build_config.rb", ENV['MRUBY_CONFIG']].compact -MRUBY_CONFIGS.each do |config| - load config unless config.empty? -end +MRUBY_CONFIG = (ENV['MRUBY_CONFIG'] && ENV['MRUBY_CONFIG'] != '') ? ENV['MRUBY_CONFIG'] : "#{MRUBY_ROOT}/build_config.rb" +load MRUBY_CONFIG # load basic rules MRuby.each_target do |build| @@ -1,6 +1,5 @@ Things to do (Things that are not done yet) -* Here document * Special variables ($1,$2..) * super in aliased methods * BEGIN/END (Were we not supporting this?) diff --git a/build_config.rb b/build_config.rb index f697ec97d..951f4b7a3 100644 --- a/build_config.rb +++ b/build_config.rb @@ -11,27 +11,45 @@ MRuby::Build.new do |conf| # conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master' # conf.gem :git => '[email protected]:masuidrive/mrbgems-example.git', :branch => 'master', :options => '-v' + # Use standard print/puts/p + conf.gem "#{root}/mrbgems/mruby-print" + # Use standard Math module - conf.gem 'mrbgems/mruby-math' + conf.gem "#{root}/mrbgems/mruby-math" # Use standard Time class - conf.gem 'mrbgems/mruby-time' + conf.gem "#{root}/mrbgems/mruby-time" # Use standard Struct class - conf.gem 'mrbgems/mruby-struct' + conf.gem "#{root}/mrbgems/mruby-struct" # Use standard Kernel#sprintf method - conf.gem 'mrbgems/mruby-sprintf' + conf.gem "#{root}/mrbgems/mruby-sprintf" + + # Use extensional Enumerable module + conf.gem "#{root}/mrbgems/mruby-enum-ext" # Use extensional String class - conf.gem 'mrbgems/mruby-string-ext' + conf.gem "#{root}/mrbgems/mruby-string-ext" # Use extensional Numeric class - conf.gem 'mrbgems/mruby-numeric-ext' + conf.gem "#{root}/mrbgems/mruby-numeric-ext" + + # Use extensional Array class + conf.gem "#{root}/mrbgems/mruby-array-ext" + + # Use extensional Hash class + conf.gem "#{root}/mrbgems/mruby-hash-ext" + + # No use eval method + # conf.gem "#{root}/mrbgems/mruby-eval" + + # No use Random module + # conf.gem "#{root}/mrbgems/mruby-random" # Generate binaries # conf.bins = %w(mrbc mruby mirb) - + # C compiler settings # conf.cc do |cc| # cc.command = ENV['CC'] || 'gcc' diff --git a/doc/mrbgems/README.md b/doc/mrbgems/README.md index 6c473b57d..eb6596ec8 100644 --- a/doc/mrbgems/README.md +++ b/doc/mrbgems/README.md @@ -23,6 +23,9 @@ A remote GIT repository location for a GEM is also supported: conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master' + conf.gem :bitbucket => 'mruby/mrbgems-example', :branch => 'master' + +NOTE: ':bitbucket' option supports only git. Hg is unsupported in this version. ## GEM Structure diff --git a/examples/targets/ArduinoDue.rb b/examples/targets/ArduinoDue.rb new file mode 100644 index 000000000..3fad6ecea --- /dev/null +++ b/examples/targets/ArduinoDue.rb @@ -0,0 +1,32 @@ +# Cross Compiling configuration for Arduino Duea +# http://arduino.cc/en/Main/ArduinoBoardDue +# +# Requires Arduino IDE >= 1.5 +MRuby::CrossBuild.new("Arduino Due") do |conf| + toolchain :gcc + + # GNU Linux + ARDUINO_PATH = '/opt/arduino' + BIN_PATH = "#{ARDUINO_PATH}/hardware/tools/g++_arm_none_eabi/bin" + SAM_PATH = "#{ARDUINO_PATH}/hardware/arduino/sam" + TARGET_PATH = "#{SAM_PATH}/variants/arduino_due_x" + + conf.cc do |cc| + cc.command = "#{BIN_PATH}/arm-none-eabi-gcc" + cc.include_paths = ["#{SAM_PATH}/system/libsam -I#{SAM_PATH}/system/CMSIS/CMSIS/Include/", + "#{SAM_PATH}/system/CMSIS/Device/ATMEL/", + "#{SAM_PATH}/cores/arduino -I#{TARGET_PATH}", + "#{MRUBY_ROOT}/include"] + cc.flags << '-g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 ' + + '-Dprintf=iprintf -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=152 -D__SAM3X8E__ -mthumb -DUSB_PID=0x003e -DUSB_VID=0x2341 -DUSBCON' + cc.compile_options = "%{flags} -o %{outfile} -c %{infile}" + end + + conf.archiver do |archiver| + archiver.command = "#{BIN_PATH}/arm-none-eabi-ar" + archiver.archive_options = 'rcs %{outfile} %{objs}' + end + + # No binaries necessary + conf.bins = [] +end diff --git a/include/mrbconf.h b/include/mrbconf.h index b665fb9f7..0caa3f90e 100644 --- a/include/mrbconf.h +++ b/include/mrbconf.h @@ -46,6 +46,12 @@ /* page size of memory pool */ //#define POOL_PAGE_SIZE 16000 +/* initial minimum size for string buffer */ +//#define MRB_STR_BUF_MIN_SIZE 128 + +/* array size for parser buffer */ +//#define MRB_PARSER_BUF_SIZE 1024 + /* -DDISABLE_XXXX to drop following features */ //#define DISABLE_STDIO /* use of stdio */ @@ -64,7 +70,7 @@ # define str_to_mrb_float(buf) strtod(buf, NULL) #endif -#ifdef MRB_INT64 +#if defined(MRB_INT64) # ifdef MRB_NAN_BOXING # error Cannot use NaN boxing when mrb_int is 64bit # else @@ -78,6 +84,11 @@ # define PRIXMRB_INT PRIX64 # define str_to_mrb_int(buf) strtoll(buf, NULL, 10) # endif +#elif defined(MRB_INT16) + typedef int16_t mrb_int; +# define MRB_INT_MIN INT16_MIN +# define MRB_INT_MAX INT16_MAX +# define str_to_mrb_int(buf) strtol(buf, NULL, 10) #else typedef int32_t mrb_int; # define MRB_INT_MIN INT32_MIN @@ -124,8 +135,18 @@ typedef short mrb_sym; # define PRIo64 "I64o" # define PRIx64 "I64x" # define PRIX64 "I64X" +# ifdef __cplusplus +typedef bool mrb_bool; +# else +typedef unsigned int mrb_bool; +# endif #else # include <inttypes.h> +# ifdef __cplusplus +typedef bool mrb_bool; +# else +typedef _Bool mrb_bool; +# endif #endif #ifdef ENABLE_STDIO diff --git a/include/mruby.h b/include/mruby.h index ed746f409..c5c607893 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -32,12 +32,12 @@ extern "C" { #endif -#include <stdlib.h> #include "mrbconf.h" #include "mruby/value.h" typedef int32_t mrb_code; +typedef int32_t mrb_aspec; struct mrb_state; @@ -121,9 +121,9 @@ typedef struct mrb_state { size_t gc_threshold; int gc_interval_ratio; int gc_step_ratio; - unsigned int gc_disabled:1; - unsigned int gc_full:1; - unsigned int is_generational_gc_mode:1; + mrb_bool gc_disabled:1; + mrb_bool gc_full:1; + mrb_bool is_generational_gc_mode:1; size_t majorgc_old_threshold; struct alloca_header *mems; @@ -146,16 +146,17 @@ struct RClass *mrb_define_module(mrb_state *, const char*); mrb_value mrb_singleton_class(mrb_state*, mrb_value); void mrb_include_module(mrb_state*, struct RClass*, struct RClass*); -void mrb_define_method(mrb_state*, struct RClass*, const char*, mrb_func_t,int); -void mrb_define_class_method(mrb_state *, struct RClass *, const char *, mrb_func_t, int); -void mrb_define_singleton_method(mrb_state*, struct RObject*, const char*, mrb_func_t,int); -void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t,int); +void mrb_define_method(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec); +void mrb_define_class_method(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec); +void mrb_define_singleton_method(mrb_state*, struct RObject*, const char*, mrb_func_t, mrb_aspec); +void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec); void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_value); void mrb_undef_method(mrb_state*, struct RClass*, const char*); void mrb_undef_class_method(mrb_state*, struct RClass*, const char*); mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv); struct RClass * mrb_class_new(mrb_state *mrb, struct RClass *super); struct RClass * mrb_module_new(mrb_state *mrb); +int mrb_class_defined(mrb_state *mrb, const char *name); struct RClass * mrb_class_get(mrb_state *mrb, const char *name); struct RClass * mrb_class_obj_get(mrb_state *mrb, const char *name); @@ -166,50 +167,55 @@ struct RClass * mrb_define_class_under(mrb_state *mrb, struct RClass *outer, con struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name); /* required arguments */ -#define ARGS_REQ(n) (((n)&0x1f) << 19) +#define ARGS_REQ(n) ((mrb_aspec)((n)&0x1f) << 19) /* optional arguments */ -#define ARGS_OPT(n) (((n)&0x1f) << 14) +#define ARGS_OPT(n) ((mrb_aspec)((n)&0x1f) << 14) /* rest argument */ -#define ARGS_REST() (1 << 13) +#define ARGS_REST() ((mrb_aspec)(1 << 13)) /* required arguments after rest */ -#define ARGS_POST(n) (((n)&0x1f) << 8) +#define ARGS_POST(n) ((mrb_aspec)((n)&0x1f) << 8) /* keyword arguments (n of keys, kdict) */ -#define ARGS_KEY(n1,n2) ((((n1)&0x1f) << 3) | ((n2)?(1<<2):0)) +#define ARGS_KEY(n1,n2) ((mrb_aspec)((((n1)&0x1f) << 3) | ((n2)?(1<<2):0))) /* block argument */ -#define ARGS_BLOCK() (1 << 1) +#define ARGS_BLOCK() ((mrb_aspec)(1 << 1)) /* accept any number of arguments */ #define ARGS_ANY() ARGS_REST() /* accept no arguments */ -#define ARGS_NONE() 0 +#define ARGS_NONE() ((mrb_aspec)0) int mrb_get_args(mrb_state *mrb, const char *format, ...); mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, int,...); mrb_value mrb_funcall_argv(mrb_state*, mrb_value, mrb_sym, int, mrb_value*); mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, mrb_sym, int, mrb_value*, mrb_value); -mrb_sym mrb_intern(mrb_state*,const char*); -mrb_sym mrb_intern2(mrb_state*,const char*,int); +mrb_sym mrb_intern_cstr(mrb_state*,const char*); +mrb_sym mrb_intern2(mrb_state*,const char*,size_t); mrb_sym mrb_intern_str(mrb_state*,mrb_value); const char *mrb_sym2name(mrb_state*,mrb_sym); -const char *mrb_sym2name_len(mrb_state*,mrb_sym,int*); +const char *mrb_sym2name_len(mrb_state*,mrb_sym,size_t*); mrb_value mrb_str_format(mrb_state *, int, const mrb_value *, mrb_value); +/* For backward compatibility. */ +static inline +mrb_sym mrb_intern(mrb_state *mrb,const char *cstr) +{ + return mrb_intern_cstr(mrb, cstr); +} + void *mrb_malloc(mrb_state*, size_t); void *mrb_calloc(mrb_state*, size_t, size_t); void *mrb_realloc(mrb_state*, void*, size_t); struct RBasic *mrb_obj_alloc(mrb_state*, enum mrb_vtype, struct RClass*); void *mrb_free(mrb_state*, void*); -mrb_value mrb_str_new(mrb_state *mrb, const char *p, int len); /* mrb_str_new */ +mrb_value mrb_str_new(mrb_state *mrb, const char *p, size_t len); mrb_value mrb_str_new_cstr(mrb_state*, const char*); -mrb_value mrb_str_new2(mrb_state *mrb, const char *p); mrb_state* mrb_open(void); mrb_state* mrb_open_allocf(mrb_allocf, void *ud); void mrb_irep_free(mrb_state*, struct mrb_irep*); void mrb_close(mrb_state*); -int mrb_checkstack(mrb_state*,int); mrb_value mrb_top_self(mrb_state *); mrb_value mrb_run(mrb_state*, struct RProc*, mrb_value); @@ -232,11 +238,11 @@ int mrb_gc_arena_save(mrb_state*); void mrb_gc_arena_restore(mrb_state*,int); void mrb_gc_mark(mrb_state*,struct RBasic*); #define mrb_gc_mark_value(mrb,val) do {\ - if (mrb_type(val) >= MRB_TT_OBJECT) mrb_gc_mark((mrb), mrb_object(val));\ + if (mrb_type(val) >= MRB_TT_OBJECT) mrb_gc_mark((mrb), mrb_basic_ptr(val));\ } while (0) void mrb_field_write_barrier(mrb_state *, struct RBasic*, struct RBasic*); #define mrb_field_write_barrier_value(mrb, obj, val) do{\ - if ((val.tt >= MRB_TT_OBJECT)) mrb_field_write_barrier((mrb), (obj), mrb_object(val));\ + if ((val.tt >= MRB_TT_OBJECT)) mrb_field_write_barrier((mrb), (obj), mrb_basic_ptr(val));\ } while (0) void mrb_write_barrier(mrb_state *, struct RBasic*); diff --git a/include/mruby/array.h b/include/mruby/array.h index 7fba4a99c..0419ddb27 100644 --- a/include/mruby/array.h +++ b/include/mruby/array.h @@ -39,9 +39,6 @@ void mrb_ary_decref(mrb_state*, mrb_shared_array*); mrb_value mrb_ary_new_capa(mrb_state*, mrb_int); mrb_value mrb_ary_new(mrb_state *mrb); mrb_value mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals); -/* compatibility macros - soon to be removed */ -#define mrb_ary_new_elts(mrb,size,vals) mrb_ary_new_from_values(mrb,size,vals) -#define mrb_ary_new4(mrb,size,vals) mrb_ary_new_from_values(mrb,size,vals) void mrb_ary_concat(mrb_state*, mrb_value, mrb_value); mrb_value mrb_ary_splat(mrb_state*, mrb_value); void mrb_ary_push(mrb_state*, mrb_value, mrb_value); diff --git a/include/mruby/class.h b/include/mruby/class.h index e2f1bae46..b36c6f7f1 100644 --- a/include/mruby/class.h +++ b/include/mruby/class.h @@ -42,7 +42,7 @@ mrb_class(mrb_state *mrb, mrb_value v) case MRB_TT_MAIN: return mrb->object_class; default: - return mrb_object(v)->c; + return mrb_obj_ptr(v)->c; } } @@ -55,7 +55,7 @@ struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym); struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym); void mrb_define_method_vm(mrb_state*, struct RClass*, mrb_sym, mrb_value); void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, struct RProc *); -void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, int aspec); +void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec); void mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b); struct RClass *mrb_class_outer_module(mrb_state*, struct RClass *); diff --git a/include/mruby/compile.h b/include/mruby/compile.h index 2cbc28321..d8edc32cf 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -12,7 +12,6 @@ extern "C" { #endif #include "mruby.h" -#include <stdio.h> #include <setjmp.h> /* load context */ @@ -21,9 +20,9 @@ typedef struct mrbc_context { int slen; char *filename; short lineno; - int capture_errors:1; - int dump_result:1; - int no_exec:1; + mrb_bool capture_errors:1; + mrb_bool dump_result:1; + mrb_bool no_exec:1; } mrbc_context; mrbc_context* mrbc_context_new(mrb_state *mrb); @@ -59,21 +58,43 @@ struct mrb_parser_message { char* message; }; -/* heredoc parse type */ -enum heredoc_type { - heredoc_type_norm, /* <<EOH */ - heredoc_type_quote, /* <<'EOH' */ +#define STR_FUNC_PARSING 0x01 +#define STR_FUNC_EXPAND 0x02 +#define STR_FUNC_REGEXP 0x04 +#define STR_FUNC_WORD 0x08 +#define STR_FUNC_SYMBOL 0x10 +#define STR_FUNC_ARRAY 0x20 +#define STR_FUNC_HEREDOC 0x40 +#define STR_FUNC_XQUOTE 0x80 + +enum mrb_string_type { + str_not_parsing = (0), + str_squote = (STR_FUNC_PARSING), + str_dquote = (STR_FUNC_PARSING|STR_FUNC_EXPAND), + str_regexp = (STR_FUNC_PARSING|STR_FUNC_REGEXP|STR_FUNC_EXPAND), + str_sword = (STR_FUNC_PARSING|STR_FUNC_WORD|STR_FUNC_ARRAY), + str_dword = (STR_FUNC_PARSING|STR_FUNC_WORD|STR_FUNC_ARRAY|STR_FUNC_EXPAND), + str_ssym = (STR_FUNC_PARSING|STR_FUNC_SYMBOL), + str_ssymbols = (STR_FUNC_PARSING|STR_FUNC_SYMBOL|STR_FUNC_ARRAY), + str_dsymbols = (STR_FUNC_PARSING|STR_FUNC_SYMBOL|STR_FUNC_ARRAY|STR_FUNC_EXPAND), + str_heredoc = (STR_FUNC_PARSING|STR_FUNC_HEREDOC), + str_xquote = (STR_FUNC_PARSING|STR_FUNC_XQUOTE|STR_FUNC_EXPAND), }; + /* heredoc structure */ struct mrb_parser_heredoc_info { - enum heredoc_type type; - int allow_indent:1; - int line_head:1; + mrb_bool allow_indent:1; + mrb_bool line_head:1; + enum mrb_string_type type; const char *term; int term_len; mrb_ast_node *doc; }; +#ifndef MRB_PARSER_BUF_SIZE +# define MRB_PARSER_BUF_SIZE 1024 +#endif + /* parser structure */ struct mrb_parser_state { mrb_state *mrb; @@ -86,8 +107,7 @@ struct mrb_parser_state { int column; enum mrb_lex_state_enum lstate; - int sterm; /* string terminator : ' ' means heredoc */ - int regexp; + mrb_ast_node *lex_strterm; /* (type nest_level beg . end) */ unsigned int cond_stack; unsigned int cmdarg_stack; @@ -97,18 +117,18 @@ struct mrb_parser_state { mrb_ast_node *locals; mrb_ast_node *pb; - char buf[1024]; + char buf[MRB_PARSER_BUF_SIZE]; int bidx; mrb_ast_node *heredocs; /* list of mrb_parser_heredoc_info* */ mrb_ast_node *parsing_heredoc; - int heredoc_starts_nextline:1; - int heredoc_end_now:1; /* for mirb */ + mrb_bool heredoc_starts_nextline:1; + mrb_bool heredoc_end_now:1; /* for mirb */ void *ylval; - int nerr; - int nwarn; + size_t nerr; + size_t nwarn; mrb_ast_node *tree; int capture_errors; diff --git a/include/mruby/dump.h b/include/mruby/dump.h index 8b78e74d0..196eefb3b 100644 --- a/include/mruby/dump.h +++ b/include/mruby/dump.h @@ -12,10 +12,6 @@ extern "C" { #endif #include "mruby.h" -#ifdef ENABLE_STDIO -#include <stdio.h> -#endif -#include <stdint.h> #ifdef ENABLE_STDIO int mrb_dump_irep(mrb_state*,int,FILE*); diff --git a/include/mruby/hash.h b/include/mruby/hash.h index ac28f13fd..baace7567 100644 --- a/include/mruby/hash.h +++ b/include/mruby/hash.h @@ -33,7 +33,7 @@ mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash); /* RHASH_TBL allocates st_table if not available. */ #define RHASH(obj) ((struct RHash*)((obj).value.p)) #define RHASH_TBL(h) (RHASH(h)->ht) -#define RHASH_IFNONE(h) mrb_iv_get(mrb, (h), mrb_intern(mrb, "ifnone")) +#define RHASH_IFNONE(h) mrb_iv_get(mrb, (h), mrb_intern2(mrb, "ifnone", 6)) #define RHASH_PROCDEFAULT(h) RHASH_IFNONE(h) struct kh_ht * mrb_hash_tbl(mrb_state *mrb, mrb_value hash); diff --git a/include/mruby/irep.h b/include/mruby/irep.h index 100afb494..fe732a43a 100644 --- a/include/mruby/irep.h +++ b/include/mruby/irep.h @@ -12,10 +12,10 @@ extern "C" { #endif typedef struct mrb_irep { - int idx:16; - int nlocals:16; - int nregs:16; - int flags:8; + uint16_t idx; + uint16_t nlocals; + uint16_t nregs; + uint8_t flags; mrb_code *iseq; mrb_value *pool; diff --git a/include/mruby/khash.h b/include/mruby/khash.h index 9eddc0bb3..db8048f5a 100644 --- a/include/mruby/khash.h +++ b/include/mruby/khash.h @@ -11,7 +11,7 @@ extern "C" { #endif -#include <stdint.h> +#include "mruby.h" #include <string.h> typedef uint32_t khint_t; @@ -22,7 +22,7 @@ typedef khint_t khiter_t; #endif #define KHASH_MIN_SIZE 8 -#define UPPER_BOUND(x) ((x)>>2|(x>>1)) +#define UPPER_BOUND(x) ((x)>>2|(x)>>1) //extern uint8_t __m[]; @@ -75,6 +75,14 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; void kh_del_##name(kh_##name##_t *h, khint_t x); \ kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h); +static inline void +kh_fill_flags(uint8_t *p, uint8_t c, size_t len) +{ + while (len-- > 0) { + *p++ = c; + } +} + /* define kh_xxx_funcs name: hash name @@ -92,8 +100,8 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; h->upper_bound = UPPER_BOUND(sz); \ h->e_flags = (uint8_t *)mrb_malloc(h->mrb, sizeof(uint8_t)*sz/4); \ h->d_flags = h->e_flags + sz/8; \ - memset(h->e_flags, 0xff, sz/8*sizeof(uint8_t)); \ - memset(h->d_flags, 0x00, sz/8*sizeof(uint8_t)); \ + kh_fill_flags(h->e_flags, 0xff, sz/8); \ + kh_fill_flags(h->d_flags, 0x00, sz/8); \ h->keys = (khkey_t *)mrb_malloc(h->mrb, sizeof(khkey_t)*sz); \ h->vals = (khval_t *)mrb_malloc(h->mrb, sizeof(khval_t)*sz); \ h->mask = sz-1; \ @@ -124,8 +132,8 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; void kh_clear_##name(kh_##name##_t *h) \ { \ if (h && h->e_flags) { \ - memset(h->e_flags, 0xff, h->n_buckets/8*sizeof(uint8_t)); \ - memset(h->d_flags, 0x00, h->n_buckets/8*sizeof(uint8_t)); \ + kh_fill_flags(h->e_flags, 0xff, h->n_buckets/8); \ + kh_fill_flags(h->d_flags, 0x00, h->n_buckets/8); \ h->size = h->n_occupied = 0; \ } \ } \ diff --git a/include/mruby/string.h b/include/mruby/string.h index 4ba4ce544..4efc3c0ff 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -13,8 +13,6 @@ extern "C" { #define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{')) -#define STR_BUF_MIN_SIZE 128 - extern const char mrb_digitmap[]; typedef struct mrb_shared_string { @@ -45,21 +43,21 @@ void mrb_str_decref(mrb_state*, mrb_shared_string*); mrb_value mrb_str_literal(mrb_state*, mrb_value); void mrb_str_concat(mrb_state*, mrb_value, mrb_value); mrb_value mrb_str_plus(mrb_state*, mrb_value, mrb_value); +mrb_value mrb_ptr_to_str(mrb_state *, void *); mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj); mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, int len); /* mrb_str_resize */ mrb_value mrb_string_value(mrb_state *mrb, mrb_value *ptr); /* StringValue */ -mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, int len); +mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len); mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str); mrb_value mrb_str_buf_new(mrb_state *mrb, int capa); -mrb_value mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, int len); +mrb_value mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len); char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr); char *mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr); -int mrb_str_sublen(mrb_state *mrb, mrb_value str, int pos); int mrb_str_offset(mrb_state *mrb, mrb_value str, int pos); mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str); /* mrb_str_dup */ mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self); -mrb_value mrb_str_cat2(mrb_state *mrb, mrb_value str, const char *ptr); +mrb_value mrb_str_cat_cstr(mrb_state *, mrb_value, const char *); mrb_value mrb_str_to_inum(mrb_state *mrb, mrb_value str, int base, int badcheck); double mrb_str_to_dbl(mrb_state *mrb, mrb_value str, int badcheck); mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str); @@ -68,12 +66,18 @@ mrb_value mrb_str_buf_append(mrb_state *mrb, mrb_value str, mrb_value str2); mrb_value mrb_str_inspect(mrb_state *mrb, mrb_value str); int mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2); mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str); -mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, long len); +mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, mrb_int len); mrb_value mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2); int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2); char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str); +/* For backward compatibility */ +static inline mrb_value +mrb_str_cat2(mrb_state *mrb, mrb_value str, const char *ptr) { + return mrb_str_cat_cstr(mrb, str, ptr); +} + #if defined(__cplusplus) } /* extern "C" { */ #endif diff --git a/include/mruby/value.h b/include/mruby/value.h index 1dfa7b975..5730bf909 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -144,7 +144,6 @@ mrb_float_value(mrb_float f) #define mrb_fixnum(o) (o).value.i #define mrb_symbol(o) (o).value.sym -#define mrb_object(o) ((struct RBasic *) (o).value.p) #define mrb_voidp(o) (o).value.p #define mrb_fixnum_p(o) (mrb_type(o) == MRB_TT_FIXNUM) #define mrb_float_p(o) (mrb_type(o) == MRB_TT_FLOAT) @@ -155,12 +154,13 @@ mrb_float_value(mrb_float f) #define mrb_string_p(o) (mrb_type(o) == MRB_TT_STRING) #define mrb_hash_p(o) (mrb_type(o) == MRB_TT_HASH) #define mrb_voidp_p(o) (mrb_type(o) == MRB_TT_VOIDP) -#define mrb_test(o) (mrb_type(o) != MRB_TT_FALSE) +#define mrb_bool(o) (mrb_type(o) != MRB_TT_FALSE) +#define mrb_test(o) mrb_bool(o) #define MRB_OBJECT_HEADER \ enum mrb_vtype tt:8;\ - unsigned int color:3;\ - unsigned int flags:21;\ + uint32_t color:3;\ + uint32_t flags:21;\ struct RClass *c;\ struct RBasic *gcnext @@ -187,7 +187,9 @@ struct RBasic { MRB_OBJECT_HEADER; }; -#define mrb_basic(v) ((struct RBasic*)((v).value.p)) +#define mrb_basic_ptr(v) ((struct RBasic*)((v).value.p)) +/* obsolete macro mrb_basic; will be removed soon */ +#define mrb_basic(v) mrb_basic_ptr(v) struct RObject { MRB_OBJECT_HEADER; @@ -195,6 +197,8 @@ struct RObject { }; #define mrb_obj_ptr(v) ((struct RObject*)((v).value.p)) +/* obsolete macro mrb_object; will be removed soon */ +#define mrb_object(o) mrb_obj_ptr(o) #define mrb_immediate_p(x) (mrb_type(x) <= MRB_TT_MAIN) #define mrb_special_const_p(x) mrb_immediate_p(x) @@ -271,4 +275,20 @@ mrb_undef_value(void) return v; } +static inline mrb_value +mrb_bool_value(mrb_bool boolean) +{ + mrb_value v; + + v.value.i = 1; + if (boolean) { + v.tt = MRB_TT_TRUE; + } + else { + v.tt = MRB_TT_FALSE; + } + + return v; +} + #endif /* MRUBY_OBJECT_H */ diff --git a/include/mruby/variable.h b/include/mruby/variable.h index a1f52217d..f699f5dfd 100644 --- a/include/mruby/variable.h +++ b/include/mruby/variable.h @@ -36,16 +36,16 @@ mrb_value mrb_vm_const_get(mrb_state*, mrb_sym); void mrb_vm_const_set(mrb_state*, mrb_sym, mrb_value); mrb_value mrb_const_get(mrb_state*, mrb_value, mrb_sym); void mrb_const_set(mrb_state*, mrb_value, mrb_sym, mrb_value); -int mrb_const_defined(mrb_state*, mrb_value, mrb_sym); +mrb_bool mrb_const_defined(mrb_state*, mrb_value, mrb_sym); void mrb_const_remove(mrb_state*, mrb_value, mrb_sym); mrb_value mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym); void mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v); -int mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym); +mrb_bool mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym); void mrb_obj_iv_ifnone(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v); mrb_value mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym); void mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v); -int mrb_iv_defined(mrb_state*, mrb_value, mrb_sym); +mrb_bool mrb_iv_defined(mrb_state*, mrb_value, mrb_sym); mrb_value mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym); void mrb_iv_copy(mrb_state *mrb, mrb_value dst, mrb_value src); int mrb_const_defined_at(mrb_state *mrb, struct RClass *klass, mrb_sym id); @@ -60,8 +60,8 @@ mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym); mrb_value mrb_cv_get(mrb_state *mrb, mrb_value mod, mrb_sym sym); void mrb_mod_cv_set(mrb_state *mrb, struct RClass * c, mrb_sym sym, mrb_value v); void mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v); -int mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym); -int mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym); +mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym); +mrb_bool mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym); /* GC functions */ void mrb_gc_mark_gv(mrb_state*); diff --git a/mrbgems/mruby-array-ext/mrbgem.rake b/mrbgems/mruby-array-ext/mrbgem.rake new file mode 100644 index 000000000..38e0ad267 --- /dev/null +++ b/mrbgems/mruby-array-ext/mrbgem.rake @@ -0,0 +1,4 @@ +MRuby::Gem::Specification.new('mruby-array-ext') do |spec| + spec.license = 'MIT' + spec.authors = 'mruby developers' +end diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb new file mode 100644 index 000000000..b3ff9bfca --- /dev/null +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -0,0 +1,98 @@ +class Array + def uniq! + ary = self.dup + result = [] + while ary.size > 0 + result << ary.shift + ary.delete(result.last) + end + if result.size == self.size + nil + else + self.replace(result) + end + end + + def uniq + ary = self.dup + ary.uniq! + ary + end + + def -(elem) + raise TypeError, "can't convert to Array" unless elem.class == Array + + hash = {} + array = [] + elem.each { |x| hash[x] = true } + self.each { |x| array << x unless hash[x] } + array + end + + def |(elem) + raise TypeError, "can't convert to Array" unless elem.class == Array + + ary = self + elem + ary.uniq! or ary + end + + def &(elem) + raise TypeError, "can't convert to Array" unless elem.class == Array + + hash = {} + array = [] + elem.each{|v| hash[v] = true } + self.each do |v| + if hash[v] + array << v + hash.delete v + end + end + array + end + + def flatten(depth=nil) + ar = [] + self.each do |e| + if e.is_a?(Array) && (depth.nil? || depth > 0) + ar += e.flatten(depth.nil? ? nil : depth - 1) + else + ar << e + end + end + ar + end + + def flatten!(depth=nil) + modified = false + ar = [] + self.each do |e| + if e.is_a?(Array) && (depth.nil? || depth > 0) + ar += e.flatten(depth.nil? ? nil : depth - 1) + modified = true + else + ar << e + end + end + if modified + self.replace(ar) + else + nil + end + end + + def compact + result = self.dup + result.compact! + result + end + + def compact! + result = self.select { |e| e != nil } + if result.size == self.size + nil + else + self.replace(result) + end + end +end diff --git a/mrbgems/mruby-array-ext/src/array.c b/mrbgems/mruby-array-ext/src/array.c new file mode 100644 index 000000000..7d7425efd --- /dev/null +++ b/mrbgems/mruby-array-ext/src/array.c @@ -0,0 +1,140 @@ +#include "mruby.h" +#include "mruby/value.h" +#include "mruby/array.h" + +/* + * call-seq: + * Array.try_convert(obj) -> array or nil + * + * Try to convert <i>obj</i> into an array, using +to_ary+ method. + * Returns converted array or +nil+ if <i>obj</i> cannot be converted + * for any reason. This method can be used to check if an argument is an + * array. + * + * Array.try_convert([1]) #=> [1] + * Array.try_convert("1") #=> nil + * + * if tmp = Array.try_convert(arg) + * # the argument is an array + * elsif tmp = String.try_convert(arg) + * # the argument is a string + * end + * + */ + +static mrb_value +mrb_ary_s_try_convert(mrb_state *mrb, mrb_value self) +{ + mrb_value ary; + + mrb_get_args(mrb, "o", &ary); + return mrb_check_array_type(mrb, ary); +} + +/* + * call-seq: + * ary.assoc(obj) -> new_ary or nil + * + * Searches through an array whose elements are also arrays + * comparing _obj_ with the first element of each contained array + * using obj.==. + * Returns the first contained array that matches (that + * is, the first associated array), + * or +nil+ if no match is found. + * See also <code>Array#rassoc</code>. + * + * s1 = [ "colors", "red", "blue", "green" ] + * s2 = [ "letters", "a", "b", "c" ] + * s3 = "foo" + * a = [ s1, s2, s3 ] + * a.assoc("letters") #=> [ "letters", "a", "b", "c" ] + * a.assoc("foo") #=> nil + */ + +static mrb_value +mrb_ary_assoc(mrb_state *mrb, mrb_value ary) +{ + mrb_int i; + mrb_value v, k; + + mrb_get_args(mrb, "o", &k); + + for (i = 0; i < RARRAY_LEN(ary); ++i) { + v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]); + if (!mrb_nil_p(v) && RARRAY_LEN(v) > 0 && + mrb_equal(mrb, RARRAY_PTR(v)[0], k)) + return v; + } + return mrb_nil_value(); +} + +/* + * call-seq: + * ary.rassoc(obj) -> new_ary or nil + * + * Searches through the array whose elements are also arrays. Compares + * _obj_ with the second element of each contained array using + * <code>==</code>. Returns the first contained array that matches. See + * also <code>Array#assoc</code>. + * + * a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ] + * a.rassoc("two") #=> [2, "two"] + * a.rassoc("four") #=> nil + */ + +static mrb_value +mrb_ary_rassoc(mrb_state *mrb, mrb_value ary) +{ + mrb_int i; + mrb_value v, value; + + mrb_get_args(mrb, "o", &value); + + for (i = 0; i < RARRAY_LEN(ary); ++i) { + v = RARRAY_PTR(ary)[i]; + if (mrb_type(v) == MRB_TT_ARRAY && + RARRAY_LEN(v) > 1 && + mrb_equal(mrb, RARRAY_PTR(v)[1], value)) + return v; + } + return mrb_nil_value(); +} + +/* + * call-seq: + * ary.at(index) -> obj or nil + * + * Returns the element at _index_. A + * negative index counts from the end of +self+. Returns +nil+ + * if the index is out of range. See also <code>Array#[]</code>. + * + * a = [ "a", "b", "c", "d", "e" ] + * a.at(0) #=> "a" + * a.at(-1) #=> "e" + */ + +static mrb_value +mrb_ary_at(mrb_state *mrb, mrb_value ary) +{ + mrb_int pos; + mrb_get_args(mrb, "i", &pos); + + return mrb_ary_entry(ary, pos); +} + +void +mrb_mruby_array_ext_gem_init(mrb_state* mrb) +{ + struct RClass * a = mrb->array_class; + + mrb_define_class_method(mrb, a, "try_convert", mrb_ary_s_try_convert, ARGS_REQ(1)); + + mrb_define_method(mrb, a, "assoc", mrb_ary_assoc, ARGS_REQ(1)); + mrb_define_method(mrb, a, "at", mrb_ary_at, ARGS_REQ(1)); + mrb_define_method(mrb, a, "rassoc", mrb_ary_rassoc, ARGS_REQ(1)); +} + +void +mrb_mruby_array_ext_gem_final(mrb_state* mrb) +{ +} diff --git a/mrbgems/mruby-array-ext/test/array.rb b/mrbgems/mruby-array-ext/test/array.rb new file mode 100644 index 000000000..1c441cec4 --- /dev/null +++ b/mrbgems/mruby-array-ext/test/array.rb @@ -0,0 +1,109 @@ +## +# Array(Ext) Test + +assert("Array::try_convert") do + Array.try_convert([1]) == [1] and + Array.try_convert("1").nil? +end + +assert("Array#assoc") do + s1 = [ "colors", "red", "blue", "green" ] + s2 = [ "letters", "a", "b", "c" ] + s3 = "foo" + a = [ s1, s2, s3 ] + + a.assoc("letters") == [ "letters", "a", "b", "c" ] and + a.assoc("foo").nil? +end + +assert("Array#at") do + a = [ "a", "b", "c", "d", "e" ] + a.at(0) == "a" and a.at(-1) == "e" +end + +assert("Array#rassoc") do + a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ] + + a.rassoc("two") == [2, "two"] and + a.rassoc("four").nil? +end + +assert("Array#uniq!") do + a = [1, 2, 3, 1] + a.uniq! + a == [1, 2, 3] +end + +assert("Array#uniq") do + a = [1, 2, 3, 1] + a.uniq == [1, 2, 3] && a == [1, 2, 3, 1] +end + +assert("Array#-") do + a = [1, 2, 3, 1] + b = [1] + c = 1 + e1 = nil + + begin + a - c + rescue => e1 + end + + (a - b) == [2, 3] and e1.class == TypeError and a == [1, 2, 3, 1] +end + +assert("Array#|") do + a = [1, 2, 3, 1] + b = [1, 4] + c = 1 + e1 = nil + + begin + a | c + rescue => e1 + end + + (a | b) == [1, 2, 3, 4] and e1.class == TypeError and a == [1, 2, 3, 1] +end + +assert("Array#&") do + a = [1, 2, 3, 1] + b = [1, 4] + c = 1 + e1 = nil + + begin + a & c + rescue => e1 + end + + (a & b) == [1] and e1.class == TypeError and a == [1, 2, 3, 1] +end + +assert("Array#flatten") do + [1, 2, "3", {4=>5}, :'6'] == [1, 2, "3", {4=>5}, :'6'].flatten and + [1, 2, 3, 4, 5, 6] == [1, 2, [3, 4, 5], 6].flatten and + [1, 2, 3, 4, 5, 6] == [1, 2, [3, [4, 5], 6]].flatten and + [1, [2, [3, [4, [5, [6]]]]]] == [1, [2, [3, [4, [5, [6]]]]]].flatten(0) and + [1, 2, [3, [4, [5, [6]]]]] == [1, [2, [3, [4, [5, [6]]]]]].flatten(1) and + [1, 2, 3, [4, [5, [6]]]] == [1, [2, [3, [4, [5, [6]]]]]].flatten(2) and + [1, 2, 3, 4, [5, [6]]] == [1, [2, [3, [4, [5, [6]]]]]].flatten(3) and + [1, 2, 3, 4, 5, [6]] == [1, [2, [3, [4, [5, [6]]]]]].flatten(4) and + [1, 2, 3, 4, 5, 6] == [1, [2, [3, [4, [5, [6]]]]]].flatten(5) +end + +assert("Array#flatten!") do + [1, 2, 3, 4, 5, 6] == [1, 2, [3, [4, 5], 6]].flatten! +end + +assert("Array#compact") do + a = [1, nil, "2", nil, :t, false, nil] + a.compact == [1, "2", :t, false] && a == [1, nil, "2", nil, :t, false, nil] +end + +assert("Array#compact!") do + a = [1, nil, "2", nil, :t, false, nil] + a.compact! + a == [1, "2", :t, false] +end diff --git a/mrbgems/mruby-enum-ext/mrbgem.rake b/mrbgems/mruby-enum-ext/mrbgem.rake new file mode 100644 index 000000000..758d298dc --- /dev/null +++ b/mrbgems/mruby-enum-ext/mrbgem.rake @@ -0,0 +1,4 @@ +MRuby::Gem::Specification.new('mruby-enum-ext') do |spec| + spec.license = 'MIT' + spec.authors = 'mruby developers' +end diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb new file mode 100644 index 000000000..f250d39f1 --- /dev/null +++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb @@ -0,0 +1,164 @@ +## +# Enumerable +# +module Enumerable + ## + # call-seq: + # enum.drop(n) -> array + # + # Drops first n elements from <i>enum</i>, and returns rest elements + # in an array. + # + # a = [1, 2, 3, 4, 5, 0] + # a.drop(3) #=> [4, 5, 0] + + def drop(n) + raise TypeError, "expected Integer for 1st argument" unless n.kind_of? Integer + raise ArgumentError, "attempt to drop negative size" if n < 0 + + ary = [] + self.each {|e| n == 0 ? ary << e : n -= 1 } + ary + end + + ## + # call-seq: + # enum.drop_while {|arr| block } -> array + # + # Drops elements up to, but not including, the first element for + # which the block returns +nil+ or +false+ and returns an array + # containing the remaining elements. + # + # a = [1, 2, 3, 4, 5, 0] + # a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0] + + def drop_while(&block) + ary, state = [], false + self.each do |e| + state = true if !state and !block.call(e) + ary << e if state + end + ary + end + + ## + # call-seq: + # enum.take(n) -> array + # + # Returns first n elements from <i>enum</i>. + # + # a = [1, 2, 3, 4, 5, 0] + # a.take(3) #=> [1, 2, 3] + + def take(n) + raise TypeError, "expected Integer for 1st argument" unless n.kind_of? Integer + raise ArgumentError, "attempt to take negative size" if n < 0 + + ary = [] + self.each do |e| + break if ary.size >= n + ary << e + end + ary + end + + ## + # call-seq: + # enum.take_while {|arr| block } -> array + # + # Passes elements to the block until the block returns +nil+ or +false+, + # then stops iterating and returns an array of all prior elements. + # + # + # a = [1, 2, 3, 4, 5, 0] + # a.take_while {|i| i < 3 } #=> [1, 2] + + def take_while(&block) + ary = [] + self.each do |e| + return ary unless block.call(e) + ary << e + end + ary + end + + ## + # call-seq: + # enum.each_cons(n) {...} -> nil + # + # Iterates the given block for each array of consecutive <n> + # elements. + # + # e.g.: + # (1..10).each_cons(3) {|a| p a} + # # outputs below + # [1, 2, 3] + # [2, 3, 4] + # [3, 4, 5] + # [4, 5, 6] + # [5, 6, 7] + # [6, 7, 8] + # [7, 8, 9] + # [8, 9, 10] + + def each_cons(n, &block) + raise TypeError, "expected Integer for 1st argument" unless n.kind_of? Integer + raise ArgumentError, "invalid size" if n <= 0 + + ary = [] + self.each do |e| + ary.shift if ary.size == n + ary << e + block.call(ary.dup) if ary.size == n + end + end + + ## + # call-seq: + # enum.each_slice(n) {...} -> nil + # + # Iterates the given block for each slice of <n> elements. + # + # e.g.: + # (1..10).each_slice(3) {|a| p a} + # # outputs below + # [1, 2, 3] + # [4, 5, 6] + # [7, 8, 9] + # [10] + + def each_slice(n, &block) + raise TypeError, "expected Integer for 1st argument" unless n.kind_of? Integer + raise ArgumentError, "invalid slice size" if n <= 0 + + ary = [] + self.each do |e| + ary << e + if ary.size == n + block.call(ary) + ary = [] + end + end + block.call(ary) unless ary.empty? + end + + ## + # call-seq: + # enum.group_by {| obj | block } -> a_hash + # + # Returns a hash, which keys are evaluated result from the + # block, and values are arrays of elements in <i>enum</i> + # corresponding to the key. + # + # (1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]} + + def group_by(&block) + h = {} + self.each do |e| + key = block.call(e) + h.key?(key) ? (h[key] << e) : (h[key] = [e]) + end + h + end + +end diff --git a/mrbgems/mruby-enum-ext/test/enum.rb b/mrbgems/mruby-enum-ext/test/enum.rb new file mode 100644 index 000000000..aa56cdf84 --- /dev/null +++ b/mrbgems/mruby-enum-ext/test/enum.rb @@ -0,0 +1,44 @@ +## +# Enumerable(Ext) Test + +assert("Enumerable#drop") do + a = [1, 2, 3, 4, 5, 0] + + assert_equal a.drop(3), [4, 5, 0] + assert_equal a.drop(6), [] +end + +assert("Enumerable#drop_while") do + a = [1, 2, 3, 4, 5, 0] + assert_equal a.drop_while {|i| i < 3 }, [3, 4, 5, 0] +end + +assert("Enumerable#take") do + a = [1, 2, 3, 4, 5, 0] + assert_equal a.take(3), [1, 2, 3] +end + +assert("Enumerable#take_while") do + a = [1, 2, 3, 4, 5, 0] + assert_equal a.take_while {|i| i < 3 }, [1, 2] +end + +assert("Enumerable#each_cons") do + a = [] + (1..5).each_cons(3){|e| a << e} + assert_equal a, [[1, 2, 3], [2, 3, 4], [3, 4, 5]] +end + +assert("Enumerable#each_slice") do + a = [] + (1..10).each_slice(3){|e| a << e} + assert_equal a, [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]] +end + +assert("Enumerable#group_by") do + r = (1..6).group_by {|i| i % 3 } + assert_equal r[0], [3, 6] + assert_equal r[1], [1, 4] + assert_equal r[2], [2, 5] +end + diff --git a/mrbgems/mruby-eval/mrbgem.rake b/mrbgems/mruby-eval/mrbgem.rake new file mode 100644 index 000000000..f80cf1b9e --- /dev/null +++ b/mrbgems/mruby-eval/mrbgem.rake @@ -0,0 +1,4 @@ +MRuby::Gem::Specification.new('mruby-eval') do |spec| + spec.license = 'MIT' + spec.authors = 'mruby developers' +end diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c new file mode 100644 index 000000000..039558596 --- /dev/null +++ b/mrbgems/mruby-eval/src/eval.c @@ -0,0 +1,23 @@ +#include "mruby.h" +#include "mruby/compile.h" + +static mrb_value +f_eval(mrb_state *mrb, mrb_value self) +{ + char *s; + int len; + + mrb_get_args(mrb, "s", &s, &len); + return mrb_load_nstring(mrb, s, len); +} + +void +mrb_mruby_eval_gem_init(mrb_state* mrb) +{ + mrb_define_class_method(mrb, mrb->kernel_module, "eval", f_eval, ARGS_REQ(1)); +} + +void +mrb_mruby_eval_gem_final(mrb_state* mrb) +{ +} diff --git a/mrbgems/mruby-hash-ext/mrbgem.rake b/mrbgems/mruby-hash-ext/mrbgem.rake new file mode 100644 index 000000000..3163c8c88 --- /dev/null +++ b/mrbgems/mruby-hash-ext/mrbgem.rake @@ -0,0 +1,4 @@ +MRuby::Gem::Specification.new('mruby-hash-ext') do |spec| + spec.license = 'MIT' + spec.authors = 'mruby developers' +end diff --git a/mrbgems/mruby-hash-ext/mrblib/hash.rb b/mrbgems/mruby-hash-ext/mrblib/hash.rb new file mode 100644 index 000000000..3e1bac0a2 --- /dev/null +++ b/mrbgems/mruby-hash-ext/mrblib/hash.rb @@ -0,0 +1,12 @@ +class Hash + def merge!(other, &block) + if block + other.each_key{|k| + self[k] = (self.has_key?(k))? block.call(k, self[k], other[k]): other[k] + } + else + other.each_key{|k| self[k] = other[k]} + end + self + end +end diff --git a/mrbgems/mruby-hash-ext/test/hash.rb b/mrbgems/mruby-hash-ext/test/hash.rb new file mode 100644 index 000000000..98eb313a4 --- /dev/null +++ b/mrbgems/mruby-hash-ext/test/hash.rb @@ -0,0 +1,20 @@ +## +# Hash(Ext) Test + +assert('Hash#merge!') do + a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' } + b = { 'cba_key' => 'XXX', 'xyz_key' => 'xyz_value' } + + result_1 = a.merge! b + + a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' } + result_2 = a.merge!(b) do |key, original, new| + original + end + + result_1 == {'abc_key' => 'abc_value', 'cba_key' => 'XXX', + 'xyz_key' => 'xyz_value' } and + result_2 == {'abc_key' => 'abc_value', 'cba_key' => 'cba_value', + 'xyz_key' => 'xyz_value' } +end + diff --git a/mrbgems/mruby-print/mrbgem.rake b/mrbgems/mruby-print/mrbgem.rake new file mode 100644 index 000000000..dc7831280 --- /dev/null +++ b/mrbgems/mruby-print/mrbgem.rake @@ -0,0 +1,4 @@ +MRuby::Gem::Specification.new('mruby-print') do |spec| + spec.license = 'MIT' + spec.authors = 'mruby developers' +end diff --git a/mrbgems/mruby-print/mrblib/print.rb b/mrbgems/mruby-print/mrblib/print.rb new file mode 100644 index 000000000..38a10661b --- /dev/null +++ b/mrbgems/mruby-print/mrblib/print.rb @@ -0,0 +1,64 @@ +## +# Kernel +# +# ISO 15.3.1 +module Kernel + ## + # Invoke method +print+ on STDOUT and passing +*args+ + # + # ISO 15.3.1.2.10 + def print(*args) + i = 0 + len = args.size + while i < len + __printstr__ args[i].to_s + i += 1 + end + end + + ## + # Invoke method +puts+ on STDOUT and passing +*args*+ + # + # ISO 15.3.1.2.11 + def puts(*args) + i = 0 + len = args.size + while i < len + s = args[i].to_s + __printstr__ s + __printstr__ "\n" if (s[-1] != "\n") + i += 1 + end + __printstr__ "\n" if len == 0 + nil + end + + ## + # Print human readable object description + # + # ISO 15.3.1.3.34 + def p(*args) + i = 0 + len = args.size + while i < len + __printstr__ args[i].inspect + __printstr__ "\n" + i += 1 + end + args[0] + end + + unless Kernel.respond_to?(:sprintf) + def printf(*args) + raise NotImplementedError.new('printf not available') + end + def sprintf(*args) + raise NotImplementedError.new('sprintf not available') + end + else + def printf(*args) + __printstr__(sprintf(*args)) + nil + end + end +end diff --git a/mrbgems/mruby-print/src/print.c b/mrbgems/mruby-print/src/print.c new file mode 100644 index 000000000..608e3cc2d --- /dev/null +++ b/mrbgems/mruby-print/src/print.c @@ -0,0 +1,44 @@ +#include "mruby.h" +#include "mruby/string.h" +#include <stdio.h> + +static void +printstr(mrb_state *mrb, mrb_value obj) +{ + struct RString *str; + char *s; + int len; + + if (mrb_string_p(obj)) { + str = mrb_str_ptr(obj); + s = str->ptr; + len = str->len; + fwrite(s, len, 1, stdout); + } +} + +/* 15.3.1.2.9 */ +/* 15.3.1.3.34 */ +mrb_value +mrb_printstr(mrb_state *mrb, mrb_value self) +{ + mrb_value argv; + + mrb_get_args(mrb, "o", &argv); + printstr(mrb, argv); + + return argv; +} + +void +mrb_mruby_print_gem_init(mrb_state* mrb) +{ + struct RClass *krn; + krn = mrb->kernel_module; + mrb_define_method(mrb, krn, "__printstr__", mrb_printstr, ARGS_REQ(1)); +} + +void +mrb_mruby_print_gem_final(mrb_state* mrb) +{ +} diff --git a/mrbgems/mruby-random/mrbgem.rake b/mrbgems/mruby-random/mrbgem.rake new file mode 100644 index 000000000..7c2b2ddd5 --- /dev/null +++ b/mrbgems/mruby-random/mrbgem.rake @@ -0,0 +1,4 @@ +MRuby::Gem::Specification.new('mruby-random') do |spec| + spec.license = 'MIT, BSD New(mt19937ar)' + spec.authors = 'mruby developers' +end diff --git a/mrbgems/mruby-random/src/mt19937ar.c b/mrbgems/mruby-random/src/mt19937ar.c new file mode 100644 index 000000000..211aefde9 --- /dev/null +++ b/mrbgems/mruby-random/src/mt19937ar.c @@ -0,0 +1,175 @@ +/* + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + Copyright (C) 2005, Mutsuo Saito, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) +*/ + +#include <stdio.h> +#include "mt19937ar.h" + +/* Period parameters */ +#define N 624 +#define M 397 +#define MATRIX_A 0x9908b0dfUL /* constant vector a */ +#define UPPER_MASK 0x80000000UL /* most significant w-r bits */ +#define LOWER_MASK 0x7fffffffUL /* least significant r bits */ + +static unsigned long mt[N]; /* the array for the state vector */ +static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ + +/* initializes mt[N] with a seed */ +void init_genrand(unsigned long s) +{ + mt[0]= s & 0xffffffffUL; + for (mti=1; mti<N; mti++) { + mt[mti] = + (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array mt[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + mt[mti] &= 0xffffffffUL; + /* for >32 bit machines */ + } +} + +/* initialize by an array with array-length */ +/* init_key is the array for initializing keys */ +/* key_length is its length */ +/* slight change for C++, 2004/2/26 */ +void init_by_array(unsigned long init_key[], int key_length) +{ + int i, j, k; + init_genrand(19650218UL); + i=1; j=0; + k = (N>key_length ? N : key_length); + for (; k; k--) { + mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) + + init_key[j] + j; /* non linear */ + mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ + i++; j++; + if (i>=N) { mt[0] = mt[N-1]; i=1; } + if (j>=key_length) j=0; + } + for (k=N-1; k; k--) { + mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) + - i; /* non linear */ + mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ + i++; + if (i>=N) { mt[0] = mt[N-1]; i=1; } + } + + mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ +} + +/* generates a random number on [0,0xffffffff]-interval */ +unsigned long genrand_int32(void) +{ + unsigned long y; + static unsigned long mag01[2]={0x0UL, MATRIX_A}; + /* mag01[x] = x * MATRIX_A for x=0,1 */ + + if (mti >= N) { /* generate N words at one time */ + int kk; + + if (mti == N+1) /* if init_genrand() has not been called, */ + init_genrand(5489UL); /* a default initial seed is used */ + + for (kk=0;kk<N-M;kk++) { + y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); + mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL]; + } + for (;kk<N-1;kk++) { + y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); + mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL]; + } + y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); + mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; + + mti = 0; + } + + y = mt[mti++]; + + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & 0x9d2c5680UL; + y ^= (y << 15) & 0xefc60000UL; + y ^= (y >> 18); + + return y; +} + +/* generates a random number on [0,0x7fffffff]-interval */ +long genrand_int31(void) +{ + return (long)(genrand_int32()>>1); +} + +/* generates a random number on [0,1]-real-interval */ +double genrand_real1(void) +{ + return genrand_int32()*(1.0/4294967295.0); + /* divided by 2^32-1 */ +} + +/* generates a random number on [0,1)-real-interval */ +double genrand_real2(void) +{ + return genrand_int32()*(1.0/4294967296.0); + /* divided by 2^32 */ +} + +/* generates a random number on (0,1)-real-interval */ +double genrand_real3(void) +{ + return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); + /* divided by 2^32 */ +} + +/* generates a random number on [0,1) with 53-bit resolution*/ +double genrand_res53(void) +{ + unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; + return(a*67108864.0+b)*(1.0/9007199254740992.0); +} +/* These real versions are due to Isaku Wada, 2002/01/09 added */ diff --git a/mrbgems/mruby-random/src/mt19937ar.h b/mrbgems/mruby-random/src/mt19937ar.h new file mode 100644 index 000000000..8b98b8a5b --- /dev/null +++ b/mrbgems/mruby-random/src/mt19937ar.h @@ -0,0 +1,72 @@ +/* + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + Copyright (C) 2005, Mutsuo Saito + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) +*/ + +/* initializes mt[N] with a seed */ +void init_genrand(unsigned long s); + +/* initialize by an array with array-length */ +/* init_key is the array for initializing keys */ +/* key_length is its length */ +/* slight change for C++, 2004/2/26 */ +void init_by_array(unsigned long init_key[], int key_length); + +/* generates a random number on [0,0xffffffff]-interval */ +unsigned long genrand_int32(void); + +/* generates a random number on [0,0x7fffffff]-interval */ +long genrand_int31(void); + +/* These real versions are due to Isaku Wada, 2002/01/09 added */ +/* generates a random number on [0,1]-real-interval */ +double genrand_real1(void); + +/* generates a random number on [0,1)-real-interval */ +double genrand_real2(void); + +/* generates a random number on (0,1)-real-interval */ +double genrand_real3(void); + +/* generates a random number on [0,1) with 53-bit resolution*/ +double genrand_res53(void); diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c new file mode 100644 index 000000000..9b5858a76 --- /dev/null +++ b/mrbgems/mruby-random/src/random.c @@ -0,0 +1,140 @@ +/* +** random.c - Random module +** +** See Copyright Notice in mruby.h +*/ + +#include "mruby.h" +#include "mruby/variable.h" +#include "mt19937ar.h" + +#include <time.h> + +#define RAND_SEED_KEY "$mrb_ext_rand_seed" + +void mt_srand(unsigned long seed) +{ + init_genrand(seed); +} + +unsigned long mt_rand() +{ + return genrand_int32(); +} + +double mt_rand_real() +{ + return genrand_real1(); +} + +mrb_value mrb_random_mt_srand(mrb_state *mrb, mrb_value seed) +{ + if (mrb_nil_p(seed)) { + seed = mrb_fixnum_value(time(NULL) + mt_rand()); + if (mrb_fixnum(seed) < 0) { + seed = mrb_fixnum_value( 0 - mrb_fixnum(seed)); + } + } + + mt_srand((unsigned) mrb_fixnum(seed)); + + return seed; +} + +mrb_value mrb_random_mt_rand(mrb_state *mrb, mrb_value max) +{ + mrb_value value; + + if (mrb_fixnum(max) == 0) { + value = mrb_float_value(mt_rand_real()); + } else { + value = mrb_fixnum_value(mt_rand() % mrb_fixnum(max)); + } + + return value; +} + +static mrb_value mrb_random_rand(mrb_state *mrb, mrb_value self) +{ + mrb_value *argv; + mrb_int argc; + mrb_value max; + + mrb_get_args(mrb, "*", &argv, &argc); + + if (argc == 0) { + max = mrb_fixnum_value(0); + } else if (argc == 1) { + max = argv[0]; + if (!mrb_nil_p(max) && !mrb_fixnum_p(max)) { + max = mrb_check_convert_type(mrb, max, MRB_TT_FIXNUM, "Fixnum", "to_int"); + } + if (!mrb_nil_p(max) && mrb_fixnum(max) < 0) { + max = mrb_fixnum_value(0 - mrb_fixnum(max)); + } + + if (!mrb_fixnum_p(max)) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument type"); + return mrb_nil_value(); + } + } else { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%d for 0..1)", argc); + return mrb_nil_value(); + } + + mrb_value seed = mrb_gv_get(mrb, mrb_intern(mrb, RAND_SEED_KEY)); + if (mrb_nil_p(seed)) + mrb_random_mt_srand(mrb, mrb_nil_value()); + + return mrb_random_mt_rand(mrb, max); +} + +static mrb_value mrb_random_srand(mrb_state *mrb, mrb_value self) +{ + mrb_int argc; + mrb_value *argv; + mrb_value seed; + + mrb_get_args(mrb, "*", &argv, &argc); + + if (argc == 0) { + seed = mrb_nil_value(); + } else if (argc == 1) { + seed = argv[0]; + if (!mrb_nil_p(seed) && !mrb_fixnum_p(seed)) { + seed = mrb_check_convert_type(mrb, seed, MRB_TT_FIXNUM, "Fixnum", "to_int"); + } + if (!mrb_nil_p(seed) && mrb_fixnum(seed) < 0) { + seed = mrb_fixnum_value(0 - mrb_fixnum(seed)); + } + + if (!mrb_fixnum_p(seed)) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument type"); + return mrb_nil_value(); + } + } else { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%d for 0..1)", argc); + return mrb_nil_value(); + } + + seed = mrb_random_mt_srand(mrb, seed); + mrb_value old_seed = mrb_gv_get(mrb, mrb_intern(mrb, RAND_SEED_KEY)); + mrb_gv_set(mrb, mrb_intern(mrb, RAND_SEED_KEY), seed); + + return old_seed; +} + +void mrb_mruby_random_gem_init(mrb_state *mrb) +{ + struct RClass *random; + + random = mrb_define_module(mrb, "Random"); + + mrb_define_class_method(mrb, random, "rand", mrb_random_rand, ARGS_ANY()); + mrb_define_class_method(mrb, random, "srand", mrb_random_srand, ARGS_ANY()); +} + +void mrb_mruby_random_gem_final(mrb_state *mrb) +{ +} + diff --git a/mrbgems/mruby-random/src/random.h b/mrbgems/mruby-random/src/random.h new file mode 100644 index 000000000..3dc5d4e77 --- /dev/null +++ b/mrbgems/mruby-random/src/random.h @@ -0,0 +1,12 @@ +/* +// random.h - Random module +// +// See Copyright Notice in mruby.h +*/ + +#ifndef RANDOM_H +#define RANDOM_H + +void mrb_mruby_random_gem_init(mrb_state *mrb); + +#endif diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index 12ed05d13..8aff03cbf 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -26,7 +26,7 @@ #define BITSPERDIG (sizeof(mrb_int)*CHAR_BIT) #define EXTENDSIGN(n, l) (((~0 << (n)) >> (((n)*(l)) % BITSPERDIG)) & ~(~0 << (n))) -static void fmt_setup(char*,size_t,int,int,int,int); +static void fmt_setup(char*,size_t,int,int,mrb_int,mrb_int); static char* remove_sign_bits(char *str, int base) @@ -78,7 +78,8 @@ static mrb_value mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base) { char buf[64], *b = buf + sizeof buf; - unsigned long val = mrb_fixnum(x); + mrb_int num = mrb_fixnum(x); + unsigned long val = (unsigned long)num; char d; if (base != 2) { @@ -96,7 +97,7 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base) *--b = mrb_digitmap[(int)(val % base)]; } while (val /= base); - if (mrb_fixnum(x) < 0) { + if (num < 0) { b = remove_sign_bits(b, base); switch (base) { case 16: d = 'f'; break; @@ -110,7 +111,7 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base) } } - return mrb_str_new2(mrb, b); + return mrb_str_new_cstr(mrb, b); } #define FNONE 0 @@ -495,10 +496,13 @@ mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt) { const char *p, *end; char *buf; - long blen, bsiz; + mrb_int blen; + mrb_int bsiz; mrb_value result; - int n; - int width, prec, flags = FNONE; + mrb_int n; + mrb_int width; + mrb_int prec; + int flags = FNONE; int nextarg = 1; int posarg = 0; mrb_value nextvalue; @@ -709,7 +713,8 @@ retry: format_s: { mrb_value arg = GETARG(); - long len, slen; + mrb_int len; + mrb_int slen; if (*p == 'p') arg = mrb_inspect(mrb, arg); str = mrb_obj_as_string(mrb, arg); @@ -760,12 +765,12 @@ retry: case 'u': { mrb_value val = GETARG(); char fbuf[32], nbuf[64], *s; - const char *prefix = 0; + const char *prefix = NULL; int sign = 0, dots = 0; char sc = 0; - long v = 0, org_v = 0; + mrb_int v = 0, org_v = 0; int base; - int len; + mrb_int len; switch (*p) { case 'd': @@ -807,7 +812,7 @@ retry: val = mrb_str_to_inum(mrb, val, 0, TRUE); goto bin_retry; case MRB_TT_FIXNUM: - v = (long)mrb_fixnum(val); + v = mrb_fixnum(val); break; default: val = mrb_Integer(mrb, val); @@ -888,7 +893,12 @@ retry: } } } - len = (int)strlen(s); + { + size_t size; + size = strlen(s); + /* PARANOID: assert(size <= MRB_INT_MAX) */ + len = (mrb_int)size; + } if (dots) { prec -= 2; @@ -906,22 +916,26 @@ retry: if (prefix && !prefix[1]) { /* octal */ if (dots) { - prefix = 0; + prefix = NULL; } else if (len == 1 && *s == '0') { len = 0; if (flags & FPREC) prec--; } else if ((flags & FPREC) && (prec > len)) { - prefix = 0; + prefix = NULL; } } else if (len == 1 && *s == '0') { - prefix = 0; + prefix = NULL; } if (prefix) { - width -= (int)strlen(prefix); + size_t size; + size = strlen(prefix); + /* PARANOID: assert(size <= MRB_INT_MAX). + * this check is absolutely paranoid. */ + width -= (mrb_int)size; } if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) { @@ -1064,7 +1078,7 @@ retry: } static void -fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec) +fmt_setup(char *buf, size_t size, int c, int flags, mrb_int width, mrb_int prec) { char *end = buf + size; int n; @@ -1077,12 +1091,12 @@ fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec) if (flags & FSPACE) *buf++ = ' '; if (flags & FWIDTH) { - n = snprintf(buf, end - buf, "%d", width); + n = snprintf(buf, end - buf, "%d", (int)width); buf += n; } if (flags & FPREC) { - n = snprintf(buf, end - buf, ".%d", prec); + n = snprintf(buf, end - buf, ".%d", (int)prec); buf += n; } diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index e21ac77d0..da3200fb9 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -49,7 +49,7 @@ mrb_struct_iv_get(mrb_state *mrb, mrb_value c, const char *name) mrb_value mrb_struct_s_members(mrb_state *mrb, mrb_value klass) { - mrb_value members = struct_ivar_get(mrb, klass, mrb_intern(mrb, "__members__")); + mrb_value members = struct_ivar_get(mrb, klass, mrb_intern2(mrb, "__members__", 11)); if (mrb_nil_p(members)) { mrb_raise(mrb, E_TYPE_ERROR, "uninitialized struct"); @@ -113,7 +113,7 @@ mrb_value mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id) { mrb_value members, slot, *ptr, *ptr_members; - long i, len; + mrb_int i, len; ptr = RSTRUCT_PTR(obj); members = mrb_struct_members(mrb, obj); @@ -167,7 +167,7 @@ mrb_id_attrset(mrb_state *mrb, mrb_sym id) { const char *name; char *buf; - int len; + size_t len; mrb_sym mid; name = mrb_sym2name_len(mrb, id, &len); @@ -185,7 +185,8 @@ static mrb_value mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val) { const char *name; - int i, len; + int i; + size_t len; mrb_sym mid; mrb_value members, slot, *ptr, *ptr_members; @@ -237,7 +238,7 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k { mrb_value nstr, *ptr_members; mrb_sym id; - long i, len; + mrb_int i, len; struct RClass *c; if (mrb_nil_p(name)) { @@ -258,7 +259,7 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k } MRB_SET_INSTANCE_TT(c, MRB_TT_ARRAY); nstr = mrb_obj_value(c); - mrb_iv_set(mrb, nstr, mrb_intern(mrb, "__members__"), members); + mrb_iv_set(mrb, nstr, mrb_intern2(mrb, "__members__", 11), members); mrb_define_class_method(mrb, c, "new", mrb_instance_new, ARGS_ANY()); mrb_define_class_method(mrb, c, "[]", mrb_instance_new, ARGS_ANY()); @@ -289,7 +290,7 @@ mrb_struct_define(mrb_state *mrb, const char *name, ...) char *mem; if (!name) nm = mrb_nil_value(); - else nm = mrb_str_new2(mrb, name); + else nm = mrb_str_new_cstr(mrb, name); ary = mrb_ary_new(mrb); va_start(ar, name); @@ -342,7 +343,7 @@ mrb_struct_s_def(mrb_state *mrb, mrb_value klass) mrb_value name, rest; mrb_value *pargv; int argcnt; - long i; + mrb_int i; mrb_value b, st; mrb_sym id; mrb_value *argv; @@ -393,7 +394,7 @@ num_members(mrb_state *mrb, struct RClass *klass) { mrb_value members; - members = struct_ivar_get(mrb, mrb_obj_value(klass), mrb_intern(mrb, "__members__")); + members = struct_ivar_get(mrb, mrb_obj_value(klass), mrb_intern2(mrb, "__members__", 11)); if (!mrb_array_p(members)) { mrb_raise(mrb, E_TYPE_ERROR, "broken members"); } @@ -445,7 +446,7 @@ inspect_struct(mrb_state *mrb, mrb_value s, int recur) const char *cn = mrb_class_name(mrb, mrb_obj_class(mrb, s)); mrb_value members, str = mrb_str_new(mrb, "#<struct ", 9); mrb_value *ptr, *ptr_members; - long i, len; + mrb_int i, len; if (cn) { mrb_str_append(mrb, str, mrb_str_new_cstr(mrb, cn)); @@ -472,7 +473,7 @@ inspect_struct(mrb_state *mrb, mrb_value s, int recur) id = mrb_symbol(slot); if (mrb_is_local_id(id) || mrb_is_const_id(id)) { const char *name; - int len; + size_t len; name = mrb_sym2name_len(mrb, id, &len); mrb_str_append(mrb, str, mrb_str_new(mrb, name, len)); @@ -532,7 +533,7 @@ static mrb_value mrb_struct_aref_id(mrb_state *mrb, mrb_value s, mrb_sym id) { mrb_value *ptr, members, *ptr_members; - long i, len; + mrb_int i, len; ptr = RSTRUCT_PTR(s); members = mrb_struct_members(mrb, s); @@ -569,7 +570,7 @@ mrb_struct_aref_id(mrb_state *mrb, mrb_value s, mrb_sym id) mrb_value mrb_struct_aref_n(mrb_state *mrb, mrb_value s, mrb_value idx) { - long i; + mrb_int i; if (mrb_string_p(idx) || mrb_symbol_p(idx)) { return mrb_struct_aref_id(mrb, s, mrb_to_id(mrb, idx)); @@ -601,7 +602,7 @@ static mrb_value mrb_struct_aset_id(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val) { mrb_value members, *ptr, *ptr_members; - long i, len; + mrb_int i, len; members = mrb_struct_members(mrb, s); len = RARRAY_LEN(members); @@ -647,7 +648,7 @@ mrb_struct_aset_id(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val) mrb_value mrb_struct_aset(mrb_state *mrb, mrb_value s) { - long i; + mrb_int i; mrb_value idx; mrb_value val; @@ -695,22 +696,35 @@ mrb_struct_equal(mrb_state *mrb, mrb_value s) { mrb_value s2; mrb_value *ptr, *ptr2; - long i, len; + mrb_int i, len; + mrb_bool equal_p; mrb_get_args(mrb, "o", &s2); - if (mrb_obj_equal(mrb, s, s2)) return mrb_true_value(); - if (!strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s)), "Struct")) return mrb_false_value(); - if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) return mrb_false_value(); - if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { + if (mrb_obj_equal(mrb, s, s2)) { + equal_p = 1; + } + else if (!strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s)), "Struct") || + mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) { + equal_p = 0; + } + else if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { mrb_bug("inconsistent struct"); /* should never happen */ + equal_p = 0; /* This substuture is just to suppress warnings. never called. */ } - ptr = RSTRUCT_PTR(s); - ptr2 = RSTRUCT_PTR(s2); - len = RSTRUCT_LEN(s); - for (i=0; i<len; i++) { - if (!mrb_equal(mrb, ptr[i], ptr2[i])) return mrb_false_value(); + else { + ptr = RSTRUCT_PTR(s); + ptr2 = RSTRUCT_PTR(s2); + len = RSTRUCT_LEN(s); + equal_p = 1; + for (i=0; i<len; i++) { + if (!mrb_equal(mrb, ptr[i], ptr2[i])) { + equal_p = 0; + break; + } + } } - return mrb_true_value(); + + return mrb_bool_value(equal_p); } /* 15.2.18.4.12(x) */ @@ -726,23 +740,35 @@ mrb_struct_eql(mrb_state *mrb, mrb_value s) { mrb_value s2; mrb_value *ptr, *ptr2; - long i, len; + mrb_int i, len; + mrb_bool eql_p; mrb_get_args(mrb, "o", &s2); - if (mrb_obj_equal(mrb, s, s2)) return mrb_true_value(); - if (strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s2)), "Struct")) return mrb_false_value(); - if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) return mrb_false_value(); - if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { + if (mrb_obj_equal(mrb, s, s2)) { + eql_p = 1; + } + else if (strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s2)), "Struct") || + mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) { + eql_p = 0; + } + else if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { mrb_bug("inconsistent struct"); /* should never happen */ + eql_p = 0; /* This substuture is just to suppress warnings. never called. */ } - - ptr = RSTRUCT_PTR(s); - ptr2 = RSTRUCT_PTR(s2); - len = RSTRUCT_LEN(s); - for (i=0; i<len; i++) { - if (!mrb_eql(mrb, ptr[i], ptr2[i])) return mrb_false_value(); + else { + ptr = RSTRUCT_PTR(s); + ptr2 = RSTRUCT_PTR(s2); + len = RSTRUCT_LEN(s); + eql_p = 1; + for (i=0; i<len; i++) { + if (!mrb_eql(mrb, ptr[i], ptr2[i])) { + eql_p = 0; + break; + } + } } - return mrb_true_value(); + + return mrb_bool_value(eql_p); } /* diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index ecc9090f1..49af7c0fb 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -6,7 +6,6 @@ #include "mruby.h" -#include <string.h> #include <stdio.h> #include <time.h> #include "mruby/class.h" @@ -87,11 +86,6 @@ timegm(struct tm *tm) * second level. Also, there are only 2 timezones, namely UTC and LOCAL. */ -#ifndef mrb_bool_value -#define mrb_bool_value(val) ((val) ? mrb_true_value() : mrb_false_value()) -#endif - - enum mrb_timezone { MRB_TIMEZONE_NONE = 0, MRB_TIMEZONE_UTC = 1, @@ -130,7 +124,7 @@ mrb_time_free(mrb_state *mrb, void *ptr) static struct mrb_data_type mrb_time_type = { "Time", mrb_time_free }; /** Updates the datetime of a mrb_time based on it's timezone and -seconds setting. Returns self on cussess, NULL of failure. */ +seconds setting. Returns self on success, NULL of failure. */ static struct mrb_time* mrb_time_update_datetime(struct mrb_time *self) { @@ -301,15 +295,14 @@ mrb_time_eq(mrb_state *mrb, mrb_value self) { mrb_value other; struct mrb_time *tm1, *tm2; + mrb_bool eq_p; mrb_get_args(mrb, "o", &other); tm1 = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type); tm2 = (struct mrb_time *)mrb_get_datatype(mrb, other, &mrb_time_type); - if (!tm1 || !tm2) return mrb_false_value(); - if (tm1->sec == tm2->sec && tm1->usec == tm2->usec) { - return mrb_true_value(); - } - return mrb_false_value(); + eq_p = tm1 && tm2 && tm1->sec == tm2->sec && tm1->usec == tm2->usec; + + return mrb_bool_value(eq_p); } static mrb_value @@ -528,6 +521,8 @@ mrb_time_initialize(mrb_state *mrb, mrb_value self) if (tm) { mrb_time_free(mrb, tm); } + DATA_TYPE(self) = &mrb_time_type; + DATA_PTR(self) = NULL; n = mrb_get_args(mrb, "|iiiiiii", &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec); @@ -538,7 +533,6 @@ mrb_time_initialize(mrb_state *mrb, mrb_value self) tm = time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL); } DATA_PTR(self) = tm; - DATA_TYPE(self) = &mrb_time_type; return self; } diff --git a/mrblib/print.rb b/mrblib/print.rb index 68c7837f3..1ae3ae84b 100644 --- a/mrblib/print.rb +++ b/mrblib/print.rb @@ -3,78 +3,16 @@ # # ISO 15.3.1 module Kernel - unless Kernel.respond_to?(:__printstr__) - def print(*a) - raise NotImplementedError.new('print not available') - end - def puts(*a) - raise NotImplementedError.new('puts not available') - end - def p(*a) - raise NotImplementedError.new('p not available') - end - def printf(*args) - raise NotImplementedError.new('printf not available') - end - else - unless Kernel.respond_to?(:sprintf) - def printf(*args) - raise NotImplementedError.new('printf not available') - end - def sprintf(*args) - raise NotImplementedError.new('sprintf not available') - end - end - - - ## - # Invoke method +print+ on STDOUT and passing +*args+ - # - # ISO 15.3.1.2.10 - def print(*args) - i = 0 - len = args.size - while i < len - __printstr__ args[i].to_s - i += 1 - end - end - - ## - # Invoke method +puts+ on STDOUT and passing +*args*+ - # - # ISO 15.3.1.2.11 - def puts(*args) - i = 0 - len = args.size - while i < len - s = args[i].to_s - __printstr__ s - __printstr__ "\n" if (s[-1] != "\n") - i += 1 - end - __printstr__ "\n" if len == 0 - nil - end - - ## - # Print human readable object description - # - # ISO 15.3.1.3.34 - def p(*args) - i = 0 - len = args.size - while i < len - __printstr__ args[i].inspect - __printstr__ "\n" - i += 1 - end - args[0] - end - - def printf(*args) - __printstr__(sprintf(*args)) - nil - end + def print(*a) + raise NotImplementedError.new('print not available') + end + def puts(*a) + raise NotImplementedError.new('puts not available') + end + def p(*a) + raise NotImplementedError.new('p not available') + end + def printf(*args) + raise NotImplementedError.new('printf not available') end end diff --git a/src/array.c b/src/array.c index 5d7b0e690..ba289997f 100644 --- a/src/array.c +++ b/src/array.c @@ -9,6 +9,7 @@ #include <string.h> #include "mruby/string.h" #include "mruby/class.h" +#include "value_array.h" /* SIZE_MAX is not supported by VC++. */ #ifndef SIZE_MAX @@ -301,7 +302,7 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1) a1 = RARRAY(ary1); a2 = RARRAY(ary2); if (a1->len == a2->len && a1->ptr == a2->ptr) return mrb_fixnum_value(0); else { - mrb_sym cmp = mrb_intern(mrb, "<=>"); + mrb_sym cmp = mrb_intern2(mrb, "<=>", 3); len = RARRAY_LEN(ary1); if (len > RARRAY_LEN(ary2)) { @@ -519,7 +520,7 @@ mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item) ary_modify(mrb, a); if (a->aux.capa < a->len + 1) ary_expand_capa(mrb, a, a->len + 1); - memmove(a->ptr + 1, a->ptr, sizeof(mrb_value)*a->len); + value_move(a->ptr + 1, a->ptr, a->len); a->ptr[0] = item; } a->len++; @@ -546,7 +547,7 @@ mrb_ary_unshift_m(mrb_state *mrb, mrb_value self) if (len == 0) return self; if (a->aux.capa < a->len + len) ary_expand_capa(mrb, a, a->len + len); - memmove(a->ptr + len, a->ptr, sizeof(mrb_value)*a->len); + value_move(a->ptr + len, a->ptr, a->len); } array_copy(a->ptr, vals, len); a->len += len; @@ -631,7 +632,7 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val ary_fill_with_nil(a->ptr + a->len, (int)(head - a->len)); } else if (head < a->len) { - memmove(a->ptr + head + argc, a->ptr + tail, sizeof(mrb_value)*(a->len - tail)); + value_move(a->ptr + head + argc, a->ptr + tail, a->len - tail); } for(i = 0; i < argc; i++) { @@ -702,6 +703,7 @@ mrb_ary_aget(mrb_state *mrb, mrb_value self) default: mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); + break; } return mrb_nil_value(); /* dummy to avoid warning : not reach here */ @@ -877,7 +879,7 @@ mrb_ary_empty_p(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); - return ((a->len == 0)? mrb_true_value(): mrb_false_value()); + return mrb_bool_value(a->len == 0); } mrb_value @@ -917,7 +919,7 @@ inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list) mrb_str_buf_cat(mrb, arystr, head, sizeof(head)); for(i=0; i<RARRAY_LEN(ary); i++) { - mrb_int ai = mrb_gc_arena_save(mrb); + int ai = mrb_gc_arena_save(mrb); if (i > 0) { mrb_str_buf_cat(mrb, arystr, sep, sizeof(sep)); @@ -1058,31 +1060,39 @@ static mrb_value mrb_ary_equal(mrb_state *mrb, mrb_value ary1) { mrb_value ary2; + mrb_bool equal_p; mrb_get_args(mrb, "o", &ary2); - if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value(); - if (mrb_special_const_p(ary2)) return mrb_false_value(); - if (!mrb_array_p(ary2)) { - if (!mrb_respond_to(mrb, ary2, mrb_intern(mrb, "to_ary"))) { - return mrb_false_value(); - } - if (mrb_equal(mrb, ary2, ary1)){ - return mrb_true_value(); + if (mrb_obj_equal(mrb, ary1, ary2)) { + equal_p = 1; + } + else if (mrb_special_const_p(ary2)) { + equal_p = 0; + } + else if (!mrb_array_p(ary2)) { + if (!mrb_respond_to(mrb, ary2, mrb_intern2(mrb, "to_ary", 6))) { + equal_p = 0; } else { - return mrb_false_value(); + equal_p = mrb_equal(mrb, ary2, ary1); } } - if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value(); + else if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) { + equal_p = 0; + } else { mrb_int i; + equal_p = 1; for (i=0; i<RARRAY_LEN(ary1); i++) { - if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) - return mrb_false_value(); + if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) { + equal_p = 0; + break; + } } - return mrb_true_value(); } + + return mrb_bool_value(equal_p); } /* 15.2.12.5.34 (x) */ @@ -1098,20 +1108,30 @@ static mrb_value mrb_ary_eql(mrb_state *mrb, mrb_value ary1) { mrb_value ary2; + mrb_bool eql_p; mrb_get_args(mrb, "o", &ary2); - if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value(); - if (!mrb_array_p(ary2)) return mrb_false_value(); - if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value(); + if (mrb_obj_equal(mrb, ary1, ary2)) { + eql_p = 1; + } + else if (!mrb_array_p(ary2)) { + eql_p = 0; + } + else if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) { + eql_p = 0; + } else { mrb_int i; - + eql_p = 1; for (i=0; i<RARRAY_LEN(ary1); i++) { - if (!mrb_eql(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) - return mrb_false_value(); + if (!mrb_eql(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) { + eql_p = 0; + break; + } } - return mrb_true_value(); } + + return mrb_bool_value(eql_p); } void diff --git a/src/class.c b/src/class.c index a3defc2ae..c421376b8 100644 --- a/src/class.c +++ b/src/class.c @@ -7,6 +7,7 @@ #include "mruby.h" #include <stdarg.h> #include <ctype.h> +#include <string.h> #include "mruby/class.h" #include "mruby/proc.h" #include "mruby/string.h" @@ -53,7 +54,7 @@ void mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name) { mrb_obj_iv_set(mrb, (struct RObject*)c, - mrb_intern(mrb, "__classid__"), mrb_symbol_value(name)); + mrb_intern2(mrb, "__classid__", 11), mrb_symbol_value(name)); } #define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c)) @@ -87,7 +88,7 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o) o->c = sc; mrb_field_write_barrier(mrb, (struct RBasic*)o, (struct RBasic*)sc); mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)o); - mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern(mrb, "__attached__"), mrb_obj_value(o)); + mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern2(mrb, "__attached__", 12), mrb_obj_value(o)); } struct RClass* @@ -114,7 +115,7 @@ setup_class(mrb_state *mrb, mrb_value outer, struct RClass *c, mrb_sym id) mrb_name_class(mrb, c, id); mrb_const_set(mrb, outer, id, mrb_obj_value(c)); mrb_obj_iv_set(mrb, (struct RObject*)c, - mrb_intern(mrb, "__outer__"), outer); + mrb_intern2(mrb, "__outer__", 9), outer); } struct RClass* @@ -122,7 +123,7 @@ mrb_class_outer_module(mrb_state *mrb, struct RClass *c) { mrb_value outer; - outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__outer__")); + outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern2(mrb, "__outer__", 9)); if (mrb_nil_p(outer)) return 0; return mrb_class_ptr(outer); } @@ -203,6 +204,12 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id return c; } +int +mrb_class_defined(mrb_state *mrb, const char *name) +{ + return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_intern(mrb, name)); +} + static struct RClass * class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id) { @@ -290,17 +297,19 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RPro } void -mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, int aspec) +mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec) { struct RProc *p; + int ai = mrb_gc_arena_save(mrb); p = mrb_proc_new_cfunc(mrb, func); p->target_class = c; mrb_define_method_raw(mrb, c, mid, p); + mrb_gc_arena_restore(mrb, ai); } void -mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec) +mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec) { mrb_define_method_id(mrb, c, mrb_intern(mrb, name), func, aspec); } @@ -400,6 +409,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) if (argc <= i && !opt) { mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); } + break; } switch (c) { @@ -912,26 +922,26 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v) default: break; } - obj = mrb_object(v); + obj = mrb_basic_ptr(v); prepare_singleton_class(mrb, obj); return mrb_obj_value(obj->c); } void -mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, int aspec) +mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, mrb_aspec aspec) { prepare_singleton_class(mrb, (struct RBasic*)o); mrb_define_method_id(mrb, o->c, mrb_intern(mrb, name), func, aspec); } void -mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec) +mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec) { mrb_define_singleton_method(mrb, (struct RObject*)c, name, func, aspec); } void -mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec) +mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec) { mrb_define_class_method(mrb, c, name, func, aspec); mrb_define_method(mrb, c, name, func, aspec); @@ -1080,9 +1090,7 @@ mrb_bob_init(mrb_state *mrb, mrb_value cv) static mrb_value mrb_bob_not(mrb_state *mrb, mrb_value cv) { - if (mrb_test(cv)) - return mrb_false_value(); - return mrb_true_value(); + return mrb_bool_value(!mrb_test(cv)); } /* 15.3.1.3.30 */ @@ -1130,8 +1138,13 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod) mrb_raise(mrb, E_TYPE_ERROR, "name should be a symbol"); } - inspect = mrb_funcall(mrb, mod, "inspect", 0); - if (RSTRING_LEN(inspect) > 64) { + if (mrb_respond_to(mrb,mod,mrb_intern2(mrb,"inspect",7))){ + inspect = mrb_funcall(mrb, mod, "inspect", 0); + if (RSTRING_LEN(inspect) > 64) { + inspect = mrb_any_to_s(mrb, mod); + } + } + else { inspect = mrb_any_to_s(mrb, mod); } @@ -1176,9 +1189,10 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) { mrb_value path; const char *name; - int len; + size_t len; + mrb_sym classpath = mrb_intern2(mrb, "__classpath__", 13); - path = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__")); + path = mrb_obj_iv_get(mrb, (struct RObject*)c, classpath); if (mrb_nil_p(path)) { struct RClass *outer = mrb_class_outer_module(mrb, c); mrb_sym sym = mrb_class_sym(mrb, c, outer); @@ -1195,7 +1209,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) name = mrb_sym2name_len(mrb, sym, &len); path = mrb_str_new(mrb, name, len); } - mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__"), path); + mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path); } return path; } @@ -1214,10 +1228,9 @@ mrb_class_name(mrb_state *mrb, struct RClass* c) { mrb_value path = mrb_class_path(mrb, c); if (mrb_nil_p(path)) { - char buf[32]; - - snprintf(buf, 32, "#<Class:%p>", c); - path = mrb_str_new_cstr(mrb, buf); + path = mrb_str_new(mrb, "#<Class:", 8); + mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c)); + mrb_str_cat(mrb, path, ">", 1); } return mrb_str_ptr(path)->ptr; } @@ -1336,51 +1349,54 @@ mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const static mrb_value mrb_mod_to_s(mrb_state *mrb, mrb_value klass) { + mrb_value str; + if (mrb_type(klass) == MRB_TT_SCLASS) { - mrb_value s = mrb_str_new(mrb, "#<", 2); - mrb_value v = mrb_iv_get(mrb, klass, mrb_intern(mrb, "__attached__")); + mrb_value v = mrb_iv_get(mrb, klass, mrb_intern2(mrb, "__attached__", 12)); + + str = mrb_str_new(mrb, "#<Class:", 8); - mrb_str_cat2(mrb, s, "Class:"); switch (mrb_type(v)) { case MRB_TT_CLASS: case MRB_TT_MODULE: case MRB_TT_SCLASS: - mrb_str_append(mrb, s, mrb_inspect(mrb, v)); + mrb_str_append(mrb, str, mrb_inspect(mrb, v)); break; default: - mrb_str_append(mrb, s, mrb_any_to_s(mrb, v)); + mrb_str_append(mrb, str, mrb_any_to_s(mrb, v)); break; } - mrb_str_cat2(mrb, s, ">"); - - return s; + mrb_str_cat(mrb, str, ">", 1); } else { + str = mrb_str_buf_new(mrb, 32); struct RClass *c = mrb_class_ptr(klass); - const char *cn = mrb_class_name(mrb, c); - - if (!cn) { - char buf[256]; - int n = 0; + mrb_value path = mrb_class_path(mrb, c); + if (mrb_nil_p(path)) { switch (mrb_type(klass)) { case MRB_TT_CLASS: - n = snprintf(buf, sizeof(buf), "#<Class:%p>", c); + mrb_str_cat(mrb, str, "#<Class:", 8); break; case MRB_TT_MODULE: - n = snprintf(buf, sizeof(buf), "#<Module:%p>", c); + mrb_str_cat(mrb, str, "#<Module:", 9); break; default: + /* Shouldn't be happened? */ + mrb_str_cat(mrb, str, "#<??????:", 9); break; } - return mrb_str_dup(mrb, mrb_str_new(mrb, buf, n)); + mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, c)); + mrb_str_cat(mrb, str, ">", 1); } else { - return mrb_str_dup(mrb, mrb_str_new_cstr(mrb, cn)); + str = path; } } + + return str; } mrb_value @@ -1453,7 +1469,7 @@ static void check_cv_name(mrb_state *mrb, mrb_sym id) { const char *s; - int len; + size_t len; s = mrb_sym2name_len(mrb, id, &len); if (len < 3 || !(s[0] == '@' && s[1] == '@')) { @@ -1480,12 +1496,12 @@ static mrb_value mrb_mod_cvar_defined(mrb_state *mrb, mrb_value mod) { mrb_sym id; + mrb_bool defined_p; mrb_get_args(mrb, "n", &id); check_cv_name(mrb, id); - if(mrb_cv_defined(mrb, mod, id)) - return mrb_true_value(); - return mrb_false_value(); + defined_p = mrb_cv_defined(mrb, mod, id); + return mrb_bool_value(defined_p); } /* 15.2.2.4.17 */ @@ -1621,12 +1637,11 @@ static mrb_value mrb_mod_method_defined(mrb_state *mrb, mrb_value mod) { mrb_sym id; + mrb_bool method_defined_p; mrb_get_args(mrb, "n", &id); - if (mrb_obj_respond_to(mrb_class_ptr(mod), id)) { - return mrb_true_value(); - } - return mrb_false_value(); + method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), id); + return mrb_bool_value(method_defined_p); } static void @@ -1675,7 +1690,7 @@ static void check_const_name(mrb_state *mrb, mrb_sym id) { const char *s; - int len; + size_t len; s = mrb_sym2name_len(mrb, id, &len); if (len < 1 || !ISUPPER(*s)) { @@ -1687,13 +1702,13 @@ mrb_value mrb_mod_const_defined(mrb_state *mrb, mrb_value mod) { mrb_sym id; + mrb_bool const_defined_p; mrb_get_args(mrb, "n", &id); check_const_name(mrb, id); - if(mrb_const_defined(mrb, mod, id)) { - return mrb_true_value(); - } - return mrb_false_value(); + const_defined_p = mrb_const_defined(mrb, mod, id); + + return mrb_bool_value(const_defined_p); } mrb_value @@ -1737,11 +1752,12 @@ static mrb_value mrb_mod_eqq(mrb_state *mrb, mrb_value mod) { mrb_value obj; + mrb_bool eqq; mrb_get_args(mrb, "o", &obj); - if (!mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod))) - return mrb_false_value(); - return mrb_true_value(); + eqq = mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod)); + + return mrb_bool_value(eqq); } void @@ -1789,6 +1805,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, cls, "new", mrb_instance_new, ARGS_ANY()); /* 15.2.3.3.3 */ mrb_define_method(mrb, cls, "inherited", mrb_bob_init, ARGS_REQ(1)); + MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE); mrb_define_method(mrb, mod, "class_variable_defined?", mrb_mod_cvar_defined, ARGS_REQ(1)); /* 15.2.2.4.16 */ mrb_define_method(mrb, mod, "class_variable_get", mrb_mod_cvar_get, ARGS_REQ(1)); /* 15.2.2.4.17 */ mrb_define_method(mrb, mod, "class_variable_set", mrb_mod_cvar_set, ARGS_REQ(2)); /* 15.2.2.4.18 */ diff --git a/src/codegen.c b/src/codegen.c index ed44f1792..5b86c90a9 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -4,8 +4,6 @@ ** See Copyright Notice in mruby.h */ -#define CODEGEN_DUMP - #include "mruby.h" #include "mruby/string.h" #include "mruby/irep.h" @@ -49,7 +47,7 @@ typedef struct scope { int pc; int lastlabel; int ainfo:15; - int mscope:1; + mrb_bool mscope:1; struct loopinfo *loop; int ensure_level; @@ -379,6 +377,7 @@ dispatch(codegen_scope *s, int pc) fprintf(stderr, "bug: dispatch on non JMP op\n"); #endif scope_error(s); + break; } s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff); } @@ -540,11 +539,11 @@ for_body(codegen_scope *s, node *tree) // generate loop variable n2 = tree->car; if (n2->car && !n2->car->cdr && !n2->cdr) { - genop(s, MKOP_Ax(OP_ENTER, 1<<18)); + genop(s, MKOP_Ax(OP_ENTER, 0x40000)); gen_assignment(s, n2->car->car, 1, NOVAL); } else { - genop(s, MKOP_Ax(OP_ENTER, 1<<18)); + genop(s, MKOP_Ax(OP_ENTER, 0x40000)); gen_vmassignment(s, n2, 1, VAL); } codegen(s, tree->cdr->cdr->car, VAL); @@ -559,7 +558,7 @@ for_body(codegen_scope *s, node *tree) s = prev; genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx - base, OP_L_BLOCK)); pop(); - idx = new_msym(s, mrb_intern(s->mrb, "each")); + idx = new_msym(s, mrb_intern2(s->mrb, "each", 4)); genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0)); } @@ -579,7 +578,8 @@ lambda_body(codegen_scope *s, node *tree, int blk) } tree = tree->cdr; if (tree->car) { - int ma, oa, ra, pa, ka, kd, ba, a; + int32_t a; + int ma, oa, ra, pa, ka, kd, ba; int pos, i; node *n, *opt; @@ -594,8 +594,8 @@ lambda_body(codegen_scope *s, node *tree, int blk) ka = kd = 0; ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0; - a = ((ma & 0x1f) << 18) - | ((oa & 0x1f) << 13) + a = ((int32_t)(ma & 0x1f) << 18) + | ((int32_t)(oa & 0x1f) << 13) | ((ra & 1) << 12) | ((pa & 0x1f) << 7) | ((ka & 0x1f) << 2) @@ -690,7 +690,7 @@ static mrb_sym attrsym(codegen_scope *s, mrb_sym a) { const char *name; - int len; + size_t len; char *name2; name = mrb_sym2name_len(s->mrb, a, &len); @@ -789,7 +789,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val) } pop_n(n+1); { - int len; + size_t len; const char *name = mrb_sym2name_len(s->mrb, sym, &len); if (!noop && len == 1 && name[0] == '+') { @@ -955,6 +955,68 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) } static void +gen_send_intern(codegen_scope *s) +{ + pop(); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "intern", 6)), 0)); + push(); +} +static void +gen_literal_array(codegen_scope *s, node *tree, int sym, int val) +{ + if (val) { + int i = 0, j = 0; + + while (tree) { + switch ((intptr_t)tree->car->car) { + case NODE_STR: + if ((tree->cdr == NULL) && ((intptr_t)tree->car->cdr->cdr == 0)) + break; + /* fall through */ + case NODE_BEGIN: + codegen(s, tree->car, VAL); + ++j; + break; + + case NODE_LITERAL_DELIM: + if (j > 0) { + j = 0; + ++i; + if (sym) + gen_send_intern(s); + } + break; + } + if (j >= 2) { + pop(); pop(); + genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); + push(); + j = 1; + } + tree = tree->cdr; + } + if (j > 0) { + j = 0; + ++i; + if (sym) + gen_send_intern(s); + } + pop_n(i); + genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i)); + push(); + } + else { + while (tree) { + switch ((intptr_t)tree->car->car) { + case NODE_BEGIN: case NODE_BLOCK: + codegen(s, tree->car, NOVAL); + } + tree = tree->cdr; + } + } +} + +static void raise_error(codegen_scope *s, const char *msg) { int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg)); @@ -1088,12 +1150,12 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, n4->car, VAL); } else { - genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern(s->mrb, "StandardError")))); + genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern2(s->mrb, "StandardError", 13)))); push(); } genop(s, MKOP_AB(OP_MOVE, cursp(), exc)); pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1)); tmp = new_label(s); genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); pos2 = tmp; @@ -1297,7 +1359,7 @@ codegen(codegen_scope *s, node *tree, int val) if (head) { genop(s, MKOP_AB(OP_MOVE, cursp(), head)); pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1)); } else { pop(); @@ -1491,7 +1553,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_OP_ASGN: { mrb_sym sym = sym(tree->cdr->car); - int len; + size_t len; const char *name = mrb_sym2name_len(s->mrb, sym, &len); int idx; @@ -1638,7 +1700,7 @@ codegen(codegen_scope *s, node *tree, int val) } pop_n(n+1); if (sendv) n = CALL_MAXARGS; - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "call")), n)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "call", 4)), n)); if (val) push(); } break; @@ -1905,7 +1967,7 @@ codegen(codegen_scope *s, node *tree, int val) default: { - int sym = new_msym(s, mrb_intern(s->mrb, "-")); + int sym = new_msym(s, mrb_intern2(s->mrb, "-", 1)); genop(s, MKOP_ABx(OP_LOADI, cursp(), 0)); push(); @@ -1932,9 +1994,7 @@ codegen(codegen_scope *s, node *tree, int val) break; case NODE_HEREDOC: - /*if(tree == NULL){printf("heredoc error 1\n");exit(11);}*/ tree = ((struct mrb_parser_heredoc_info *)tree)->doc; - /*if(tree == NULL){printf("heredoc error 2\n");exit(12);}*/ /* fall through */ case NODE_DSTR: if (val) { @@ -1962,6 +2022,34 @@ codegen(codegen_scope *s, node *tree, int val) } break; + case NODE_WORDS: + gen_literal_array(s, tree, FALSE, val); + break; + + case NODE_SYMBOLS: + gen_literal_array(s, tree, TRUE, val); + break; + + case NODE_XSTR: + if (val) { + char *p = (char*)tree->car; + size_t len = (intptr_t)tree->cdr; + int ai = mrb_gc_arena_save(s->mrb); + int sym = new_sym(s, mrb_intern2(s->mrb, "Kernel", 6)); + int off = new_lit(s, mrb_str_new(s->mrb, p, len)); + + genop(s, MKOP_A(OP_OCLASS, cursp())); + genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); + push(); + genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + pop(); + sym = new_sym(s, mrb_intern2(s->mrb, "`", 1)); + genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1)); + mrb_gc_arena_restore(s->mrb, ai); + push(); + } + break; + case NODE_REGX: if (val) { char *p1 = (char*)tree->car; @@ -1983,7 +2071,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); } pop(); - sym = new_sym(s, mrb_intern(s->mrb, "compile")); + sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7)); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); mrb_gc_arena_restore(s->mrb, ai); push(); @@ -2031,7 +2119,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); } pop(); - sym = new_sym(s, mrb_intern(s->mrb, "compile")); + sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7)); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); mrb_gc_arena_restore(s->mrb, ai); push(); @@ -2060,9 +2148,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_DSYM: codegen(s, tree, val); if (val) { - pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "intern")), 0)); - push(); + gen_send_intern(s); } break; @@ -2098,7 +2184,7 @@ codegen(codegen_scope *s, node *tree, int val) { int a = new_msym(s, sym(tree->car)); int b = new_msym(s, sym(tree->cdr)); - int c = new_msym(s, mrb_intern(s->mrb, "alias_method")); + int c = new_msym(s, mrb_intern2(s->mrb, "alias_method", 12)); genop(s, MKOP_A(OP_TCLASS, cursp())); push(); @@ -2117,7 +2203,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_UNDEF: { - int undef = new_msym(s, mrb_intern(s->mrb, "undef_method")); + int undef = new_msym(s, mrb_intern2(s->mrb, "undef_method", 12)); int num = 0; node *t = tree; @@ -13,7 +13,7 @@ // carry #define CRC_16_CCITT 0x11021ul //x^16+x^12+x^5+1 #define CRC_XOR_PATTERN (CRC_16_CCITT << 8) -#define CRC_CARRY_BIT (1 << 24) +#define CRC_CARRY_BIT (0x01000000) uint16_t calc_crc_16_ccitt(unsigned char *src, int nbytes) diff --git a/src/dump.c b/src/dump.c index ba5a69a56..9666f7562 100644 --- a/src/dump.c +++ b/src/dump.c @@ -279,7 +279,7 @@ get_syms_block_size(mrb_state *mrb, mrb_irep *irep, int type) size += DUMP_SIZE(MRB_DUMP_SIZE_OF_SHORT, type); /* snl(n) */ if (irep->syms[sym_no] != 0) { - int len; + size_t len; name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len); nlen = str_dump_len((char*)name, len, type); @@ -421,9 +421,10 @@ write_syms_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type) uint16_t nlen =0; if (irep->syms[sym_no] != 0) { - int len; + size_t len; name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len); + if (len > UINT16_MAX) goto error_exit; nlen = str_dump_len((char*)name, len, type); if ( nlen > buf_size - 1) { buf_size = nlen + 1; diff --git a/src/error.c b/src/error.c index ed30173bc..f46887465 100644 --- a/src/error.c +++ b/src/error.c @@ -5,7 +5,9 @@ */ #include "mruby.h" +#include <errno.h> #include <stdarg.h> +#include <stdlib.h> #include <setjmp.h> #include <string.h> #include "error.h" @@ -42,7 +44,7 @@ exc_initialize(mrb_state *mrb, mrb_value exc) mrb_value mesg; if (mrb_get_args(mrb, "|o", &mesg) == 1) { - mrb_iv_set(mrb, exc, mrb_intern(mrb, "mesg"), mesg); + mrb_iv_set(mrb, exc, mrb_intern2(mrb, "mesg", 4), mesg); } return exc; } @@ -71,7 +73,7 @@ exc_exception(mrb_state *mrb, mrb_value self) if (argc == 0) return self; if (mrb_obj_equal(mrb, self, a)) return self; exc = mrb_obj_clone(mrb, self); - mrb_iv_set(mrb, exc, mrb_intern(mrb, "mesg"), a); + mrb_iv_set(mrb, exc, mrb_intern2(mrb, "mesg", 4), a); return exc; } @@ -87,9 +89,9 @@ exc_exception(mrb_state *mrb, mrb_value self) static mrb_value exc_to_s(mrb_state *mrb, mrb_value exc) { - mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern(mrb, "mesg")); + mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "mesg", 4)); - if (mrb_nil_p(mesg)) return mrb_str_new2(mrb, mrb_obj_classname(mrb, exc)); + if (mrb_nil_p(mesg)) return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, exc)); return mesg; } @@ -121,32 +123,32 @@ exc_inspect(mrb_state *mrb, mrb_value exc) { mrb_value str, mesg, file, line; - mesg = mrb_attr_get(mrb, exc, mrb_intern(mrb, "mesg")); - file = mrb_attr_get(mrb, exc, mrb_intern(mrb, "file")); - line = mrb_attr_get(mrb, exc, mrb_intern(mrb, "line")); + mesg = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "mesg", 4)); + file = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "file", 4)); + line = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "line", 4)); if (!mrb_nil_p(file) && !mrb_nil_p(line)) { str = file; - mrb_str_cat2(mrb, str, ":"); + mrb_str_cat(mrb, str, ":", 1); mrb_str_append(mrb, str, line); - mrb_str_cat2(mrb, str, ": "); + mrb_str_cat(mrb, str, ": ", 2); if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) { mrb_str_append(mrb, str, mesg); - mrb_str_cat2(mrb, str, " ("); + mrb_str_cat(mrb, str, " (", 2); } - mrb_str_cat2(mrb, str, mrb_obj_classname(mrb, exc)); + mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc)); if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) { - mrb_str_cat2(mrb, str, ")"); + mrb_str_cat(mrb, str, ")", 1); } } else { - str = mrb_str_new2(mrb, mrb_obj_classname(mrb, exc)); + str = mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, exc)); if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) { - mrb_str_cat2(mrb, str, ": "); + mrb_str_cat(mrb, str, ": ", 2); mrb_str_append(mrb, str, mesg); } else { - mrb_str_cat2(mrb, str, ": "); - mrb_str_cat2(mrb, str, mrb_obj_classname(mrb, exc)); + mrb_str_cat(mrb, str, ": ", 2); + mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc)); } } return str; @@ -158,25 +160,29 @@ exc_equal(mrb_state *mrb, mrb_value exc) { mrb_value obj; mrb_value mesg; - mrb_sym id_mesg = mrb_intern(mrb, "mesg"); + mrb_bool equal_p; + mrb_sym id_mesg = mrb_intern2(mrb, "mesg", 4); mrb_get_args(mrb, "o", &obj); - if (mrb_obj_equal(mrb, exc, obj)) return mrb_true_value(); - - if (mrb_obj_class(mrb, exc) != mrb_obj_class(mrb, obj)) { - if (mrb_respond_to(mrb, obj, mrb_intern(mrb, "message"))) { - mesg = mrb_funcall(mrb, obj, "message", 0); - } - else - return mrb_false_value(); + if (mrb_obj_equal(mrb, exc, obj)) { + equal_p = 1; } else { - mesg = mrb_attr_get(mrb, obj, id_mesg); + if (mrb_obj_class(mrb, exc) != mrb_obj_class(mrb, obj)) { + if (mrb_respond_to(mrb, obj, mrb_intern2(mrb, "message", 7))) { + mesg = mrb_funcall(mrb, obj, "message", 0); + } + else + return mrb_false_value(); + } + else { + mesg = mrb_attr_get(mrb, obj, id_mesg); + } + + equal_p = mrb_equal(mrb, mrb_attr_get(mrb, exc, id_mesg), mesg); } - if (!mrb_equal(mrb, mrb_attr_get(mrb, exc, id_mesg), mesg)) - return mrb_false_value(); - return mrb_true_value(); + return mrb_bool_value(equal_p); } static void @@ -185,15 +191,15 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc) mrb_callinfo *ci = mrb->ci; mrb_code *pc = ci->pc; - mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->cibase)); + mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->cibase)); ci--; while (ci >= mrb->cibase) { if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) { mrb_irep *irep = ci->proc->body.irep; if (irep->filename && irep->lines && irep->iseq <= pc && pc < irep->iseq + irep->ilen) { - mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "file"), mrb_str_new_cstr(mrb, irep->filename)); - mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "line"), mrb_fixnum_value(irep->lines[pc - irep->iseq - 1])); + mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "file", 4), mrb_str_new_cstr(mrb, irep->filename)); + mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "line", 4), mrb_fixnum_value(irep->lines[pc - irep->iseq - 1])); return; } } @@ -205,7 +211,7 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc) void mrb_exc_raise(mrb_state *mrb, mrb_value exc) { - mrb->exc = (struct RObject*)mrb_object(exc); + mrb->exc = mrb_obj_ptr(exc); exc_debug_info(mrb, mrb->exc); if (!mrb->jmp) { mrb_p(mrb, exc); @@ -218,7 +224,7 @@ void mrb_raise(mrb_state *mrb, struct RClass *c, const char *msg) { mrb_value mesg; - mesg = mrb_str_new2(mrb, msg); + mesg = mrb_str_new_cstr(mrb, msg); mrb_exc_raise(mrb, mrb_exc_new3(mrb, c, mesg)); } @@ -329,7 +335,7 @@ mrb_bug_errno(const char *mesg, int errno_arg) int sysexit_status(mrb_state *mrb, mrb_value err) { - mrb_value st = mrb_iv_get(mrb, err, mrb_intern(mrb, "status")); + mrb_value st = mrb_iv_get(mrb, err, mrb_intern2(mrb, "status", 6)); return mrb_fixnum(st); } @@ -367,7 +373,7 @@ make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr) n = 1; exception_call: { - mrb_sym exc = mrb_intern(mrb, "exception"); + mrb_sym exc = mrb_intern2(mrb, "exception", 9); if (mrb_respond_to(mrb, argv[0], exc)) { mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1); } @@ -401,7 +407,20 @@ mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv) void mrb_sys_fail(mrb_state *mrb, const char *mesg) { - mrb_raise(mrb, E_RUNTIME_ERROR, mesg); + struct RClass *sce; + mrb_int no; + + no = (mrb_int)errno; + if (mrb_class_defined(mrb, "SystemCallError")) { + sce = mrb_class_get(mrb, "SystemCallError"); + if (mesg != NULL) { + mrb_funcall(mrb, mrb_obj_value(sce), "_sys_fail", 2, mrb_fixnum_value(no), mrb_str_new_cstr(mrb, mesg)); + } else { + mrb_funcall(mrb, mrb_obj_value(sce), "_sys_fail", 1, mrb_fixnum_value(no)); + } + } else { + mrb_raise(mrb, E_RUNTIME_ERROR, mesg); + } } void @@ -197,7 +197,7 @@ struct heap_page { struct heap_page *next; struct heap_page *free_next; struct heap_page *free_prev; - unsigned int old:1; + mrb_bool old:1; RVALUE objects[MRB_HEAP_PAGE_SIZE]; }; @@ -322,7 +322,7 @@ void mrb_gc_protect(mrb_state *mrb, mrb_value obj) { if (mrb_special_const_p(obj)) return; - gc_protect(mrb, mrb_basic(obj)); + gc_protect(mrb, mrb_basic_ptr(obj)); } struct RBasic* @@ -542,7 +542,9 @@ obj_free(mrb_state *mrb, struct RBasic *obj) static void root_scan_phase(mrb_state *mrb) { - int i, j, e; + int j; + size_t i; + size_t e; mrb_callinfo *ci; if (!is_minor_gc(mrb)) { @@ -982,8 +984,8 @@ gc_enable(mrb_state *mrb, mrb_value obj) int old = mrb->gc_disabled; mrb->gc_disabled = FALSE; - if (old) return mrb_true_value(); - return mrb_false_value(); + + return mrb_bool_value(old); } /* @@ -1004,8 +1006,8 @@ gc_disable(mrb_state *mrb, mrb_value obj) int old = mrb->gc_disabled; mrb->gc_disabled = TRUE; - if (old) return mrb_true_value(); - return mrb_false_value(); + + return mrb_bool_value(old); } /* @@ -1101,10 +1103,7 @@ change_gen_gc_mode(mrb_state *mrb, mrb_int enable) static mrb_value gc_generational_mode_get(mrb_state *mrb, mrb_value self) { - if (mrb->is_generational_gc_mode) - return mrb_true_value(); - else - return mrb_false_value(); + return mrb_bool_value(mrb->is_generational_gc_mode); } /* @@ -1124,10 +1123,7 @@ gc_generational_mode_set(mrb_state *mrb, mrb_value self) if (mrb->is_generational_gc_mode != enable) change_gen_gc_mode(mrb, enable); - if (enable) - return mrb_true_value(); - else - return mrb_false_value(); + return mrb_bool_value(enable); } #ifdef GC_TEST @@ -1168,8 +1164,8 @@ test_mrb_field_write_barrier(void) puts("test_mrb_field_write_barrier"); mrb->is_generational_gc_mode = FALSE; - obj = mrb_basic(mrb_ary_new(mrb)); - value = mrb_basic(mrb_str_new_cstr(mrb, "value")); + obj = mrb_basic_ptr(mrb_ary_new(mrb)); + value = mrb_basic_ptr(mrb_str_new_cstr(mrb, "value")); paint_black(obj); paint_partial_white(mrb,value); @@ -1210,15 +1206,15 @@ test_mrb_field_write_barrier(void) { puts("test_mrb_field_write_barrier_value"); - obj = mrb_basic(mrb_ary_new(mrb)); + obj = mrb_basic_ptr(mrb_ary_new(mrb)); mrb_value value = mrb_str_new_cstr(mrb, "value"); paint_black(obj); - paint_partial_white(mrb, mrb_basic(value)); + paint_partial_white(mrb, mrb_basic_ptr(value)); mrb->gc_state = GC_STATE_MARK; mrb_field_write_barrier_value(mrb, obj, value); - gc_assert(is_gray(mrb_basic(value))); + gc_assert(is_gray(mrb_basic_ptr(value))); } mrb_close(mrb); @@ -1231,7 +1227,7 @@ test_mrb_write_barrier(void) struct RBasic *obj; puts("test_mrb_write_barrier"); - obj = mrb_basic(mrb_ary_new(mrb)); + obj = mrb_basic_ptr(mrb_ary_new(mrb)); paint_black(obj); puts(" in GC_STATE_MARK"); @@ -1260,12 +1256,12 @@ test_add_gray_list(void) puts("test_add_gray_list"); change_gen_gc_mode(mrb, FALSE); gc_assert(mrb->gray_list == NULL); - obj1 = mrb_basic(mrb_str_new_cstr(mrb, "test")); + obj1 = mrb_basic_ptr(mrb_str_new_cstr(mrb, "test")); add_gray_list(mrb, obj1); gc_assert(mrb->gray_list == obj1); gc_assert(is_gray(obj1)); - obj2 = mrb_basic(mrb_str_new_cstr(mrb, "test")); + obj2 = mrb_basic_ptr(mrb_str_new_cstr(mrb, "test")); add_gray_list(mrb, obj2); gc_assert(mrb->gray_list == obj2); gc_assert(mrb->gray_list->gcnext == obj1); @@ -1294,12 +1290,12 @@ test_gc_gray_mark(void) puts(" in MRB_TT_ARRAY"); obj_v = mrb_ary_new(mrb); value_v = mrb_str_new_cstr(mrb, "test"); - paint_gray(mrb_basic(obj_v)); - paint_partial_white(mrb, mrb_basic(value_v)); + paint_gray(mrb_basic_ptr(obj_v)); + paint_partial_white(mrb, mrb_basic_ptr(value_v)); mrb_ary_push(mrb, obj_v, value_v); - gray_num = gc_gray_mark(mrb, mrb_basic(obj_v)); - gc_assert(is_black(mrb_basic(obj_v))); - gc_assert(is_gray(mrb_basic(value_v))); + gray_num = gc_gray_mark(mrb, mrb_basic_ptr(obj_v)); + gc_assert(is_black(mrb_basic_ptr(obj_v))); + gc_assert(is_gray(mrb_basic_ptr(value_v))); gc_assert(gray_num == 1); mrb_close(mrb); diff --git a/src/hash.c b/src/hash.c index 728fc0f2f..8de7b55c8 100644 --- a/src/hash.c +++ b/src/hash.c @@ -15,7 +15,7 @@ static inline khint_t mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key) { - khint_t h = mrb_type(key) << 24; + khint_t h = (khint_t)mrb_type(key) << 24; mrb_value h2; h2 = mrb_funcall(mrb, key, "hash", 0, 0); @@ -52,11 +52,15 @@ mrb_gc_mark_ht(mrb_state *mrb, struct RHash *hash) khash_t(ht) *h = hash->ht; if (!h) return; - for (k = kh_begin(h); k != kh_end(h); k++) + for (k = kh_begin(h); k != kh_end(h); k++) { if (kh_exist(h, k)) { - mrb_gc_mark_value(mrb, kh_key(h, k)); - mrb_gc_mark_value(mrb, kh_value(h, k)); + mrb_value key = kh_key(h, k); + mrb_value val = kh_value(h, k); + + mrb_gc_mark_value(mrb, key); + mrb_gc_mark_value(mrb, val); } + } } size_t @@ -258,7 +262,7 @@ mrb_hash_init_core(mrb_state *mrb, mrb_value hash) RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; ifnone = block; } - mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); + mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone); return hash; } @@ -423,7 +427,7 @@ mrb_hash_set_default(mrb_state *mrb, mrb_value hash) mrb_get_args(mrb, "o", &ifnone); mrb_hash_modify(mrb, hash); - mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); + mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone); RHASH(hash)->flags &= ~(MRB_HASH_PROC_DEFAULT); return ifnone; @@ -474,7 +478,7 @@ mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash) mrb_get_args(mrb, "o", &ifnone); mrb_hash_modify(mrb, hash); - mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); + mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone); RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; return ifnone; @@ -755,7 +759,7 @@ mrb_hash_replace(mrb_state *mrb, mrb_value hash) else { ifnone = RHASH_IFNONE(hash2); } - mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); + mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone); return hash; } @@ -797,13 +801,16 @@ static mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self) { khash_t(ht) *h = RHASH_TBL(self); + mrb_bool empty_p; if (h) { - if (kh_size(h) == 0) - return mrb_true_value(); - return mrb_false_value(); + empty_p = (kh_size(h) == 0); } - return mrb_true_value(); + else { + empty_p = 1; + } + + return mrb_bool_value(empty_p); } /* 15.2.13.4.11 */ @@ -887,7 +894,7 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur) ai = mrb_gc_arena_save(mrb); - if (RSTRING_LEN(str) > 1) mrb_str_cat2(mrb, str, ", "); + if (RSTRING_LEN(str) > 1) mrb_str_cat(mrb, str, ", ", 2); str2 = mrb_inspect(mrb, kh_key(h,k)); mrb_str_append(mrb, str, str2); @@ -1006,14 +1013,17 @@ mrb_hash_has_keyWithKey(mrb_state *mrb, mrb_value hash, mrb_value key) { khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; + mrb_bool result; if (h) { k = kh_get(ht, h, key); - if (k != kh_end(h)) - return mrb_true_value(); + result = (k != kh_end(h)); + } + else { + result = 0; } - return mrb_false_value(); + return mrb_bool_value(result); } /* 15.2.13.4.13 */ @@ -1094,7 +1104,7 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql) if (mrb_obj_equal(mrb, hash1, hash2)) return mrb_true_value(); if (!mrb_hash_p(hash2)) { - if (!mrb_respond_to(mrb, hash2, mrb_intern(mrb, "to_hash"))) { + if (!mrb_respond_to(mrb, hash2, mrb_intern2(mrb, "to_hash", 7))) { return mrb_false_value(); } if (eql) @@ -1105,8 +1115,7 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql) h1 = RHASH_TBL(hash1); h2 = RHASH_TBL(hash2); if (!h1) { - if (!h2) return mrb_true_value(); - return mrb_false_value(); + return mrb_bool_value(!h2); } if (!h2) return mrb_false_value(); if (kh_size(h1) != kh_size(h2)) return mrb_false_value(); diff --git a/src/init.c b/src/init.c index 0d1a24881..e97c72d68 100644 --- a/src/init.c +++ b/src/init.c @@ -21,7 +21,6 @@ void mrb_init_hash(mrb_state*); void mrb_init_numeric(mrb_state*); void mrb_init_range(mrb_state*); void mrb_init_gc(mrb_state*); -void mrb_init_print(mrb_state*); void mrb_init_math(mrb_state*); void mrb_init_mrblib(mrb_state*); void mrb_init_mrbgems(mrb_state*); @@ -48,9 +47,6 @@ mrb_init_core(mrb_state *mrb) mrb_init_numeric(mrb); DONE; mrb_init_range(mrb); DONE; mrb_init_gc(mrb); DONE; -#ifdef ENABLE_STDIO - mrb_init_print(mrb); DONE; -#endif mrb_init_mrblib(mrb); DONE; #ifndef DISABLE_GEMS mrb_init_mrbgems(mrb); DONE; diff --git a/src/kernel.c b/src/kernel.c index 7187a125d..0c746d987 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -29,7 +29,7 @@ typedef enum { int mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj) { - struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern(mrb, "to_s")); + struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern2(mrb, "to_s", 4)); if (me && MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s)) return TRUE; return FALSE; @@ -96,28 +96,24 @@ static mrb_value mrb_obj_equal_m(mrb_state *mrb, mrb_value self) { mrb_value arg; + mrb_bool eql_p; mrb_get_args(mrb, "o", &arg); - if (mrb_obj_equal(mrb, self, arg)) { - return mrb_true_value(); - } - else { - return mrb_false_value(); - } + eql_p = mrb_obj_equal(mrb, self, arg); + + return mrb_bool_value(eql_p); } static mrb_value mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self) { mrb_value arg; + mrb_bool eql_p; mrb_get_args(mrb, "o", &arg); - if (mrb_equal(mrb, self, arg)) { - return mrb_false_value(); - } - else { - return mrb_true_value(); - } + eql_p = mrb_obj_equal(mrb, self, arg); + + return mrb_bool_value(!eql_p); } /* 15.3.1.3.2 */ @@ -133,14 +129,12 @@ static mrb_value mrb_equal_m(mrb_state *mrb, mrb_value self) { mrb_value arg; + mrb_bool equal_p; mrb_get_args(mrb, "o", &arg); - if (mrb_equal(mrb, self, arg)){ - return mrb_true_value(); - } - else { - return mrb_false_value(); - } + equal_p = mrb_equal(mrb, self, arg); + + return mrb_bool_value(equal_p); } /* 15.3.1.3.3 */ @@ -225,21 +219,28 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) { mrb_callinfo *ci = mrb->ci; mrb_value *bp; + mrb_bool given_p; bp = mrb->stbase + ci->stackidx + 1; ci--; - if (ci <= mrb->cibase) return mrb_false_value(); - /* block_given? called within block; check upper scope */ - if (ci->proc->env && ci->proc->env->stack) { - if (ci->proc->env->stack == mrb->stbase || mrb_nil_p(ci->proc->env->stack[1])) - return mrb_false_value(); - return mrb_true_value(); + if (ci <= mrb->cibase) { + given_p = 0; } - if (ci->argc > 0) { - bp += ci->argc; + else { + /* block_given? called within block; check upper scope */ + if (ci->proc->env && ci->proc->env->stack) { + given_p = !(ci->proc->env->stack == mrb->stbase || + mrb_nil_p(ci->proc->env->stack[1])); + } + else { + if (ci->argc > 0) { + bp += ci->argc; + } + given_p = !mrb_nil_p(*bp); + } } - if (mrb_nil_p(*bp)) return mrb_false_value(); - return mrb_true_value(); + + return mrb_bool_value(given_p); } /* 15.3.1.3.7 */ @@ -263,7 +264,7 @@ mrb_obj_class_m(mrb_state *mrb, mrb_value self) struct RClass* mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) { - struct RClass *klass = mrb_basic(obj)->c; + struct RClass *klass = mrb_basic_ptr(obj)->c; if (klass->tt != MRB_TT_SCLASS) return klass; @@ -282,7 +283,7 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) clone->super = klass->super; if (klass->iv) { mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass)); - mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern(mrb, "__attached__"), obj); + mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern2(mrb, "__attached__", 12), obj); } if (klass->mt) { clone->mt = kh_copy(mt, mrb, klass->mt); @@ -518,6 +519,7 @@ mrb_obj_instance_eval(mrb_state *mrb, mrb_value self) default: cv = mrb_singleton_class(mrb, self); c = mrb_class_ptr(cv); + break; } return mrb_yield_internal(mrb, b, 0, 0, self, c); } @@ -541,21 +543,19 @@ static mrb_value obj_is_instance_of(mrb_state *mrb, mrb_value self) { mrb_value arg; + mrb_bool instance_of_p; mrb_get_args(mrb, "o", &arg); - if (mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg))){ - return mrb_true_value(); - } - else { - return mrb_false_value(); - } + instance_of_p = mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg)); + + return mrb_bool_value(instance_of_p); } static void check_iv_name(mrb_state *mrb, mrb_sym id) { const char *s; - int len; + size_t len; s = mrb_sym2name_len(mrb, id, &len); if (len < 2 || !(s[0] == '@' && s[1] != '@')) { @@ -585,12 +585,13 @@ mrb_value mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self) { mrb_sym mid; + mrb_bool defined_p; mrb_get_args(mrb, "n", &mid); check_iv_name(mrb, mid); - if (mrb_obj_iv_defined(mrb, mrb_obj_ptr(self), mid)) - return mrb_true_value(); - return mrb_false_value(); + defined_p = mrb_obj_iv_defined(mrb, mrb_obj_ptr(self), mid); + + return mrb_bool_value(defined_p); } /* 15.3.1.3.21 */ @@ -687,14 +688,12 @@ mrb_value mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self) { mrb_value arg; + mrb_bool kind_of_p; mrb_get_args(mrb, "o", &arg); - if (mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg))) { - return mrb_true_value(); - } - else { - return mrb_false_value(); - } + kind_of_p = mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg)); + + return mrb_bool_value(kind_of_p); } static void @@ -929,8 +928,9 @@ mrb_f_raise(mrb_state *mrb, mrb_value self) /* fall through */ default: exc = mrb_make_exception(mrb, argc, a); - mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern(mrb, "lastpc"), mrb_voidp_value(mrb->ci->pc)); + mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(mrb->ci->pc)); mrb_exc_raise(mrb, exc); + break; } return mrb_nil_value(); /* not reached */ } @@ -1000,15 +1000,17 @@ obj_respond_to(mrb_state *mrb, mrb_value self) int argc; mrb_value mid, priv; mrb_sym id; + mrb_bool respond_to_p; mrb_get_args(mrb, "*", &argv, &argc); mid = argv[0]; if (argc > 1) priv = argv[1]; else priv = mrb_nil_value(); id = mrb_to_id(mrb, mid); - if (basic_obj_respond_to(mrb, self, id, !mrb_test(priv))) - return mrb_true_value(); - return mrb_false_value(); + + respond_to_p = basic_obj_respond_to(mrb, self, id, !mrb_test(priv)); + + return mrb_bool_value(respond_to_p); } /* 15.3.1.3.45 */ diff --git a/src/keywords b/src/keywords index be5324875..9cb86608c 100644 --- a/src/keywords +++ b/src/keywords @@ -8,43 +8,43 @@ static const struct kwtable *reserved_word(const char *, unsigned int); struct kwtable; %% __ENCODING__, {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END -__LINE__, {keyword__LINE__, keyword__LINE__}, EXPR_END -__FILE__, {keyword__FILE__, keyword__FILE__}, EXPR_END -BEGIN, {keyword_BEGIN, keyword_BEGIN}, EXPR_END -END, {keyword_END, keyword_END}, EXPR_END -alias, {keyword_alias, keyword_alias}, EXPR_FNAME -and, {keyword_and, keyword_and}, EXPR_VALUE -begin, {keyword_begin, keyword_begin}, EXPR_BEG -break, {keyword_break, keyword_break}, EXPR_MID -case, {keyword_case, keyword_case}, EXPR_VALUE -class, {keyword_class, keyword_class}, EXPR_CLASS -def, {keyword_def, keyword_def}, EXPR_FNAME -do, {keyword_do, keyword_do}, EXPR_BEG -else, {keyword_else, keyword_else}, EXPR_BEG -elsif, {keyword_elsif, keyword_elsif}, EXPR_VALUE -end, {keyword_end, keyword_end}, EXPR_END -ensure, {keyword_ensure, keyword_ensure}, EXPR_BEG -false, {keyword_false, keyword_false}, EXPR_END -for, {keyword_for, keyword_for}, EXPR_VALUE -if, {keyword_if, modifier_if}, EXPR_VALUE -in, {keyword_in, keyword_in}, EXPR_VALUE -module, {keyword_module, keyword_module}, EXPR_VALUE -next, {keyword_next, keyword_next}, EXPR_MID -nil, {keyword_nil, keyword_nil}, EXPR_END -not, {keyword_not, keyword_not}, EXPR_ARG -or, {keyword_or, keyword_or}, EXPR_VALUE -redo, {keyword_redo, keyword_redo}, EXPR_END -rescue, {keyword_rescue, modifier_rescue}, EXPR_MID -retry, {keyword_retry, keyword_retry}, EXPR_END -return, {keyword_return, keyword_return}, EXPR_MID -self, {keyword_self, keyword_self}, EXPR_END -super, {keyword_super, keyword_super}, EXPR_ARG -then, {keyword_then, keyword_then}, EXPR_BEG -true, {keyword_true, keyword_true}, EXPR_END -undef, {keyword_undef, keyword_undef}, EXPR_FNAME -unless, {keyword_unless, modifier_unless}, EXPR_VALUE -until, {keyword_until, modifier_until}, EXPR_VALUE -when, {keyword_when, keyword_when}, EXPR_VALUE -while, {keyword_while, modifier_while}, EXPR_VALUE -yield, {keyword_yield, keyword_yield}, EXPR_ARG +__FILE__, {keyword__FILE__, keyword__FILE__}, EXPR_END +__LINE__, {keyword__LINE__, keyword__LINE__}, EXPR_END +BEGIN, {keyword_BEGIN, keyword_BEGIN}, EXPR_END +END, {keyword_END, keyword_END}, EXPR_END +alias, {keyword_alias, keyword_alias}, EXPR_FNAME +and, {keyword_and, keyword_and}, EXPR_VALUE +begin, {keyword_begin, keyword_begin}, EXPR_BEG +break, {keyword_break, keyword_break}, EXPR_MID +case, {keyword_case, keyword_case}, EXPR_VALUE +class, {keyword_class, keyword_class}, EXPR_CLASS +def, {keyword_def, keyword_def}, EXPR_FNAME +do, {keyword_do, keyword_do}, EXPR_BEG +else, {keyword_else, keyword_else}, EXPR_BEG +elsif, {keyword_elsif, keyword_elsif}, EXPR_VALUE +end, {keyword_end, keyword_end}, EXPR_END +ensure, {keyword_ensure, keyword_ensure}, EXPR_BEG +false, {keyword_false, keyword_false}, EXPR_END +for, {keyword_for, keyword_for}, EXPR_VALUE +if, {keyword_if, modifier_if}, EXPR_VALUE +in, {keyword_in, keyword_in}, EXPR_VALUE +module, {keyword_module, keyword_module}, EXPR_VALUE +next, {keyword_next, keyword_next}, EXPR_MID +nil, {keyword_nil, keyword_nil}, EXPR_END +not, {keyword_not, keyword_not}, EXPR_ARG +or, {keyword_or, keyword_or}, EXPR_VALUE +redo, {keyword_redo, keyword_redo}, EXPR_END +rescue, {keyword_rescue, modifier_rescue}, EXPR_MID +retry, {keyword_retry, keyword_retry}, EXPR_END +return, {keyword_return, keyword_return}, EXPR_MID +self, {keyword_self, keyword_self}, EXPR_END +super, {keyword_super, keyword_super}, EXPR_ARG +then, {keyword_then, keyword_then}, EXPR_BEG +true, {keyword_true, keyword_true}, EXPR_END +undef, {keyword_undef, keyword_undef}, EXPR_FNAME +unless, {keyword_unless, modifier_unless}, EXPR_VALUE +until, {keyword_until, modifier_until}, EXPR_VALUE +when, {keyword_when, keyword_when}, EXPR_VALUE +while, {keyword_while, modifier_while}, EXPR_VALUE +yield, {keyword_yield, keyword_yield}, EXPR_ARG %% diff --git a/src/lex.def b/src/lex.def index 5223aac1b..ea456a843 100644 --- a/src/lex.def +++ b/src/lex.def @@ -1,4 +1,4 @@ -/* ANSI-C code produced by gperf version 3.0.4 */ +/* ANSI-C code produced by gperf version 3.0.3 */ /* Command-line: gperf -L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k'1,3,$' src/keywords */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ @@ -44,10 +44,12 @@ struct kwtable; #define MAX_HASH_VALUE 50 /* maximum key range = 43, duplicates = 0 */ -#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) || defined(__GNUC_STDC_INLINE__) -inline -#elif defined(__GNUC__) +#ifdef __GNUC__ __inline +#else +#ifdef __cplusplus +inline +#endif #endif static unsigned int hash (register const char *str, register unsigned int len) @@ -98,7 +100,7 @@ hash (register const char *str, register unsigned int len) #ifdef __GNUC__ __inline -#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +#ifdef __GNUC_STDC_INLINE__ __attribute__ ((__gnu_inline__)) #endif #endif @@ -109,87 +111,87 @@ mrb_reserved_word (register const char *str, register unsigned int len) { {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, #line 18 "src/keywords" - {"break", {keyword_break, keyword_break}, EXPR_MID}, + {"break", {keyword_break, keyword_break}, EXPR_MID}, #line 23 "src/keywords" - {"else", {keyword_else, keyword_else}, EXPR_BEG}, + {"else", {keyword_else, keyword_else}, EXPR_BEG}, #line 33 "src/keywords" - {"nil", {keyword_nil, keyword_nil}, EXPR_END}, + {"nil", {keyword_nil, keyword_nil}, EXPR_END}, #line 26 "src/keywords" - {"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG}, + {"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG}, #line 25 "src/keywords" - {"end", {keyword_end, keyword_end}, EXPR_END}, + {"end", {keyword_end, keyword_end}, EXPR_END}, #line 42 "src/keywords" - {"then", {keyword_then, keyword_then}, EXPR_BEG}, + {"then", {keyword_then, keyword_then}, EXPR_BEG}, #line 34 "src/keywords" - {"not", {keyword_not, keyword_not}, EXPR_ARG}, + {"not", {keyword_not, keyword_not}, EXPR_ARG}, #line 27 "src/keywords" - {"false", {keyword_false, keyword_false}, EXPR_END}, + {"false", {keyword_false, keyword_false}, EXPR_END}, #line 40 "src/keywords" - {"self", {keyword_self, keyword_self}, EXPR_END}, + {"self", {keyword_self, keyword_self}, EXPR_END}, #line 24 "src/keywords" - {"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE}, + {"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE}, #line 37 "src/keywords" - {"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID}, + {"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID}, #line 43 "src/keywords" - {"true", {keyword_true, keyword_true}, EXPR_END}, + {"true", {keyword_true, keyword_true}, EXPR_END}, #line 46 "src/keywords" - {"until", {keyword_until, modifier_until}, EXPR_VALUE}, + {"until", {keyword_until, modifier_until}, EXPR_VALUE}, #line 45 "src/keywords" - {"unless", {keyword_unless, modifier_unless}, EXPR_VALUE}, + {"unless", {keyword_unless, modifier_unless}, EXPR_VALUE}, #line 39 "src/keywords" - {"return", {keyword_return, keyword_return}, EXPR_MID}, + {"return", {keyword_return, keyword_return}, EXPR_MID}, #line 21 "src/keywords" - {"def", {keyword_def, keyword_def}, EXPR_FNAME}, + {"def", {keyword_def, keyword_def}, EXPR_FNAME}, #line 16 "src/keywords" - {"and", {keyword_and, keyword_and}, EXPR_VALUE}, + {"and", {keyword_and, keyword_and}, EXPR_VALUE}, #line 22 "src/keywords" - {"do", {keyword_do, keyword_do}, EXPR_BEG}, + {"do", {keyword_do, keyword_do}, EXPR_BEG}, #line 49 "src/keywords" - {"yield", {keyword_yield, keyword_yield}, EXPR_ARG}, + {"yield", {keyword_yield, keyword_yield}, EXPR_ARG}, #line 28 "src/keywords" - {"for", {keyword_for, keyword_for}, EXPR_VALUE}, + {"for", {keyword_for, keyword_for}, EXPR_VALUE}, #line 44 "src/keywords" - {"undef", {keyword_undef, keyword_undef}, EXPR_FNAME}, + {"undef", {keyword_undef, keyword_undef}, EXPR_FNAME}, #line 35 "src/keywords" - {"or", {keyword_or, keyword_or}, EXPR_VALUE}, + {"or", {keyword_or, keyword_or}, EXPR_VALUE}, #line 30 "src/keywords" - {"in", {keyword_in, keyword_in}, EXPR_VALUE}, + {"in", {keyword_in, keyword_in}, EXPR_VALUE}, #line 47 "src/keywords" - {"when", {keyword_when, keyword_when}, EXPR_VALUE}, + {"when", {keyword_when, keyword_when}, EXPR_VALUE}, #line 38 "src/keywords" - {"retry", {keyword_retry, keyword_retry}, EXPR_END}, + {"retry", {keyword_retry, keyword_retry}, EXPR_END}, #line 29 "src/keywords" - {"if", {keyword_if, modifier_if}, EXPR_VALUE}, + {"if", {keyword_if, modifier_if}, EXPR_VALUE}, #line 19 "src/keywords" - {"case", {keyword_case, keyword_case}, EXPR_VALUE}, + {"case", {keyword_case, keyword_case}, EXPR_VALUE}, #line 36 "src/keywords" - {"redo", {keyword_redo, keyword_redo}, EXPR_END}, + {"redo", {keyword_redo, keyword_redo}, EXPR_END}, #line 32 "src/keywords" - {"next", {keyword_next, keyword_next}, EXPR_MID}, + {"next", {keyword_next, keyword_next}, EXPR_MID}, #line 41 "src/keywords" - {"super", {keyword_super, keyword_super}, EXPR_ARG}, + {"super", {keyword_super, keyword_super}, EXPR_ARG}, #line 31 "src/keywords" - {"module", {keyword_module, keyword_module}, EXPR_VALUE}, + {"module", {keyword_module, keyword_module}, EXPR_VALUE}, #line 17 "src/keywords" - {"begin", {keyword_begin, keyword_begin}, EXPR_BEG}, -#line 11 "src/keywords" - {"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END}, + {"begin", {keyword_begin, keyword_begin}, EXPR_BEG}, #line 12 "src/keywords" - {"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END}, + {"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END}, +#line 11 "src/keywords" + {"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END}, #line 10 "src/keywords" {"__ENCODING__", {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END}, #line 14 "src/keywords" - {"END", {keyword_END, keyword_END}, EXPR_END}, + {"END", {keyword_END, keyword_END}, EXPR_END}, #line 15 "src/keywords" - {"alias", {keyword_alias, keyword_alias}, EXPR_FNAME}, + {"alias", {keyword_alias, keyword_alias}, EXPR_FNAME}, #line 13 "src/keywords" - {"BEGIN", {keyword_BEGIN, keyword_BEGIN}, EXPR_END}, + {"BEGIN", {keyword_BEGIN, keyword_BEGIN}, EXPR_END}, {""}, #line 20 "src/keywords" - {"class", {keyword_class, keyword_class}, EXPR_CLASS}, + {"class", {keyword_class, keyword_class}, EXPR_CLASS}, {""}, {""}, #line 48 "src/keywords" - {"while", {keyword_while, modifier_while}, EXPR_VALUE} + {"while", {keyword_while, modifier_while}, EXPR_VALUE} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) diff --git a/src/load.c b/src/load.c index 84c21c186..fcffcd9de 100644 --- a/src/load.c +++ b/src/load.c @@ -4,6 +4,7 @@ ** See Copyright Notice in mruby.h */ +#include <stdlib.h> #include <string.h> #include "mruby/dump.h" @@ -683,7 +684,7 @@ static void irep_error(mrb_state *mrb, int n) { static const char msg[] = "irep load error"; - mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1)); + mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1)); } #ifdef ENABLE_STDIO diff --git a/src/node.h b/src/node.h index e12672bfe..df27c431f 100644 --- a/src/node.h +++ b/src/node.h @@ -65,6 +65,8 @@ enum node_type { NODE_SYM, NODE_STR, NODE_DSTR, + NODE_XSTR, + NODE_DXSTR, NODE_REGX, NODE_DREGX, NODE_DREGX_ONCE, @@ -106,6 +108,9 @@ enum node_type { NODE_DSYM, NODE_ATTRASGN, NODE_HEREDOC, + NODE_LITERAL_DELIM, + NODE_WORDS, + NODE_SYMBOLS, NODE_LAST }; diff --git a/src/numeric.c b/src/numeric.c index 61b9a2f73..1e089c970 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -9,17 +9,15 @@ #include "mruby/string.h" #include "mruby/array.h" +#include <float.h> #include <math.h> #include <assert.h> +#include <stdlib.h> #if defined(__FreeBSD__) && __FreeBSD__ < 4 #include <floatingpoint.h> #endif -#ifdef HAVE_FLOAT_H -#include <float.h> -#endif - #ifdef HAVE_IEEEFP_H #include <ieeefp.h> #endif @@ -165,6 +163,99 @@ num_abs(mrb_state *mrb, mrb_value num) * representation. */ +mrb_value +mrb_flo_to_str(mrb_state *mrb, mrb_float n, int max_digit) +{ + mrb_value result; + + if (max_digit > 40) { + mrb_raise(mrb, E_RANGE_ERROR, "Too large max_digit."); + } + + if (isnan(n)) { + result = mrb_str_new(mrb, "NaN", 3); + } + else if (isinf(n)) { + if (n < 0) { + result = mrb_str_new(mrb, "-inf", 4); + } + else { + result = mrb_str_new(mrb, "inf", 3); + } + } + else { + int digit; + int m; + int exp; + int e = 0; + char s[48]; + char *c = &s[0]; + + if (n < 0) { + n = -n; + *(c++) = '-'; + } + + exp = log10(n); + + if ((exp < 0 ? -exp : exp) > max_digit) { + /* exponent representation */ + e = 1; + m = exp; + if (m < 0) { + m -= 1; + } + n = n / pow(10.0, m); + m = 0; + } + else { + /* un-exponent (normal) representation */ + m = exp; + if (m < 0) { + m = 0; + } + } + + /* puts digits */ + while (max_digit >= 0) { + mrb_float weight = pow(10.0, m); + digit = floor(n / weight + FLT_EPSILON); + *(c++) = '0' + digit; + n -= (digit * weight); + max_digit--; + if (m-- == 0) { + *(c++) = '.'; + } + else if (m < -1 && n < FLT_EPSILON) { + break; + } + } + + if (e) { + *(c++) = 'e'; + if (exp > 0) { + *(c++) = '+'; + } else { + *(c++) = '-'; + exp = -exp; + } + + if (exp >= 100) { + mrb_raise(mrb, E_RANGE_ERROR, "Too large expornent."); + } + + *(c++) = '0' + exp / 10; + *(c++) = '0' + exp % 10; + } + + *c = '\0'; + + result = mrb_str_new(mrb, &s[0], c - &s[0]); + } + + return result; +} + /* 15.2.9.3.16(x) */ /* * call-seq: @@ -179,27 +270,11 @@ num_abs(mrb_state *mrb, mrb_value num) static mrb_value flo_to_s(mrb_state *mrb, mrb_value flt) { - char buf[32]; - int n; - - mrb_float value = mrb_float(flt); - - if (isinf(value)) { - static const char s[2][5] = { "-inf", "inf" }; - static const int n[] = { 4, 3 }; - int idx; - idx = (value < 0) ? 0 : 1; - return mrb_str_new(mrb, s[idx], n[idx]); - } else if(isnan(value)) - return mrb_str_new(mrb, "NaN", 3); - #ifdef MRB_USE_FLOAT - n = sprintf(buf, "%.7g", value); + return mrb_flo_to_str(mrb, mrb_float(flt), 7); #else - n = sprintf(buf, "%.14g", value); + return mrb_flo_to_str(mrb, mrb_float(flt), 14); #endif - assert(n >= 0); - return mrb_str_new(mrb, buf, n); } /* 15.2.9.3.2 */ @@ -305,15 +380,17 @@ static mrb_value num_eql(mrb_state *mrb, mrb_value x) { mrb_value y; + mrb_bool eql_p; mrb_get_args(mrb, "o", &y); - if (mrb_type(x) != mrb_type(y)) return mrb_false_value(); - if (mrb_equal(mrb, x, y)) { - return mrb_true_value(); + if (mrb_type(x) != mrb_type(y)) { + eql_p = 0; } else { - return mrb_false_value(); + eql_p = mrb_equal(mrb, x, y); } + + return mrb_bool_value(eql_p); } static mrb_value @@ -355,7 +432,7 @@ flo_eq(mrb_state *mrb, mrb_value x) return num_equal(mrb, x, y); } a = mrb_float(x); - return (a == b)?mrb_true_value():mrb_false_value(); + return mrb_bool_value(a == b); } /* 15.2.8.3.18 */ @@ -370,7 +447,8 @@ flo_hash(mrb_state *mrb, mrb_value num) { mrb_float d; char *c; - int i, hash; + size_t i; + int hash; d = (mrb_float)mrb_fixnum(num); /* normalize -0.0 to 0.0 */ @@ -436,10 +514,11 @@ static mrb_value flo_finite_p(mrb_state *mrb, mrb_value num) { mrb_float value = mrb_float(num); + mrb_bool finite_p; - if (isinf(value) || isnan(value)) - return mrb_false_value(); - return mrb_true_value(); + finite_p = !(isinf(value) || isnan(value)); + + return mrb_bool_value(finite_p); } /* 15.2.9.3.10 */ @@ -848,19 +927,15 @@ static mrb_value fix_equal(mrb_state *mrb, mrb_value x) { mrb_value y; + mrb_bool equal_p; mrb_get_args(mrb, "o", &y); - if (mrb_obj_equal(mrb, x, y)) return mrb_true_value(); - switch (mrb_type(y)) { - case MRB_TT_FLOAT: - if ((mrb_float)mrb_fixnum(x) == mrb_float(y)) - return mrb_true_value(); - /* fall through */ - case MRB_TT_FIXNUM: - default: - return mrb_false_value(); - } + equal_p = mrb_obj_equal(mrb, x, y) || + (mrb_type(y) == MRB_TT_FLOAT && + (mrb_float)mrb_fixnum(x) == mrb_float(y)); + + return mrb_bool_value(equal_p); } /* 15.2.8.3.8 */ diff --git a/src/object.c b/src/object.c index 0d1cc85b9..5cf165000 100644 --- a/src/object.c +++ b/src/object.c @@ -5,7 +5,6 @@ */ #include "mruby.h" -#include <string.h> #include "mruby/string.h" #include "mruby/class.h" #include "mruby/numeric.h" @@ -115,7 +114,8 @@ true_and(mrb_state *mrb, mrb_value obj) int obj2; mrb_get_args(mrb, "b", &obj2); - return obj2 ? mrb_true_value() : mrb_false_value(); + + return mrb_bool_value(obj2); } /* 15.2.5.3.2 */ @@ -134,7 +134,7 @@ true_xor(mrb_state *mrb, mrb_value obj) int obj2; mrb_get_args(mrb, "b", &obj2); - return obj2 ? mrb_false_value() : mrb_true_value(); + return mrb_bool_value(!obj2); } /* 15.2.5.3.3 */ @@ -227,7 +227,7 @@ false_xor(mrb_state *mrb, mrb_value obj) int obj2; mrb_get_args(mrb, "b", &obj2); - return obj2 ? mrb_true_value() : mrb_false_value(); + return mrb_bool_value(obj2); } /* 15.2.4.3.3 */ @@ -247,7 +247,7 @@ false_or(mrb_state *mrb, mrb_value obj) int obj2; mrb_get_args(mrb, "b", &obj2); - return obj2 ? mrb_true_value() : mrb_false_value(); + return mrb_bool_value(obj2); } /* 15.2.6.3.3 */ @@ -439,8 +439,15 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) mrb_value mrb_any_to_s(mrb_state *mrb, mrb_value obj) { + mrb_value str = mrb_str_buf_new(mrb, 20); const char *cname = mrb_obj_classname(mrb, obj); - return mrb_sprintf(mrb, "#<%s:%p>", cname, mrb_voidp(obj)); + + mrb_str_buf_cat(mrb, str, "#<", 2); + mrb_str_cat2(mrb, str, cname); + mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_voidp(obj))); + mrb_str_buf_cat(mrb, str, ">", 1); + + return str; } /* diff --git a/src/opcode.h b/src/opcode.h index d77e2451f..b4f843116 100644 --- a/src/opcode.h +++ b/src/opcode.h @@ -7,12 +7,15 @@ #ifndef OPCODE_H #define OPCODE_H -#define MAXARG_Bx ((1<<16)-1) +#define MAXARG_Bx (0xffff) #define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */ -/* instructions OP:A:B:C = 7:9:9:7 (32 bits) */ -/* OP:A:Bx = 7:9:16 */ -/* OP:Ax = 7:25 */ +/* instructions: packed 32 bit */ +/* ------------------------------- */ +/* A:B:C:OP = 9: 9: 7: 7 */ +/* A:Bx:OP = 9:16: 7 */ +/* Ax:OP = 25: 7 */ +/* A:Bz:Cz:OP = 9:14: 2: 7 */ #define GET_OPCODE(i) ((int)(((mrb_code)(i)) & 0x7f)) #define GETARG_A(i) ((int)((((mrb_code)(i)) >> 23) & 0x1ff)) @@ -20,19 +23,19 @@ #define GETARG_C(i) ((int)((((mrb_code)(i)) >> 7) & 0x7f)) #define GETARG_Bx(i) ((int)((((mrb_code)(i)) >> 7) & 0xffff)) #define GETARG_sBx(i) ((int)(GETARG_Bx(i)-MAXARG_sBx)) -#define GETARG_Ax(i) ((int)((((mrb_code)(i)) >> 7) & 0x1ffffff)) -#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+n2)) & (((1<<n1)-1)))) -#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<n2)-1)))) +#define GETARG_Ax(i) ((int32_t)((((mrb_code)(i)) >> 7) & 0x1ffffff)) +#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+(n2))) & (((1<<(n1))-1)))) +#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<(n2))-1)))) #define GETARG_b(i) GETARG_UNPACK_b(i,14,2) #define GETARG_c(i) GETARG_UNPACK_c(i,14,2) #define MKOPCODE(op) ((op) & 0x7f) -#define MKARG_A(c) (((c) & 0x1ff) << 23) -#define MKARG_B(c) (((c) & 0x1ff) << 14) +#define MKARG_A(c) ((mrb_code)((c) & 0x1ff) << 23) +#define MKARG_B(c) ((mrb_code)((c) & 0x1ff) << 14) #define MKARG_C(c) (((c) & 0x7f) << 7) -#define MKARG_Bx(v) (((v) & 0xffff) << 7) +#define MKARG_Bx(v) ((mrb_code)((v) & 0xffff) << 7) #define MKARG_sBx(v) MKARG_Bx((v)+MAXARG_sBx) -#define MKARG_Ax(v) (((v) & 0x1ffffff) << 7) +#define MKARG_Ax(v) ((mrb_code)((v) & 0x1ffffff) << 7) #define MKARG_PACK(b,n1,c,n2) ((((b) & ((1<<n1)-1)) << (7+n2))|(((c) & ((1<<n2)-1)) << 7)) #define MKARG_bc(b,c) MKARG_PACK(b,14,c,2) diff --git a/src/parse.y b/src/parse.y index 62393a0bb..29ea34c59 100644 --- a/src/parse.y +++ b/src/parse.y @@ -25,6 +25,7 @@ #include <errno.h> #include <ctype.h> #include <string.h> +#include <stdlib.h> #define YYLEX_PARAM p @@ -60,13 +61,27 @@ typedef unsigned int stack_type; #define sym(x) ((mrb_sym)(intptr_t)(x)) #define nsym(x) ((node*)(intptr_t)(x)) -static mrb_sym +static inline mrb_sym intern_gen(parser_state *p, const char *s) { return mrb_intern(p->mrb, s); } #define intern(s) intern_gen(p,(s)) +static inline mrb_sym +intern_gen2(parser_state *p, const char *s, size_t len) +{ + return mrb_intern2(p->mrb, s, len); +} +#define intern2(s,len) intern_gen2(p,(s),(len)) + +static inline mrb_sym +intern_gen_c(parser_state *p, const char c) +{ + return mrb_intern2(p->mrb, &c, 1); +} +#define intern_c(c) intern_gen_c(p,(c)) + static void cons_free_gen(parser_state *p, node *cons) { @@ -701,6 +716,20 @@ new_dstr(parser_state *p, node *a) return cons((node*)NODE_DSTR, a); } +// (:str . (s . len)) +static node* +new_xstr(parser_state *p, const char *s, int len) +{ + return cons((node*)NODE_XSTR, cons((node*)strndup(s, len), (node*)(intptr_t)len)); +} + +// (:xstr . a) +static node* +new_dxstr(parser_state *p, node *a) +{ + return cons((node*)NODE_DXSTR, a); +} + // (:dsym . a) static node* new_dsym(parser_state *p, node *a) @@ -749,6 +778,26 @@ new_bv(parser_state *p, mrb_sym id) { } +static node* +new_literal_delim(parser_state *p) +{ + return cons((node*)NODE_LITERAL_DELIM, 0); +} + +// (:words . a) +static node* +new_words(parser_state *p, node *a) +{ + return cons((node*)NODE_WORDS, a); +} + +// (:symbols . a) +static node* +new_symbols(parser_state *p, node *a) +{ + return cons((node*)NODE_SYMBOLS, a); +} + // xxx ----------------------------- // (:call a op) @@ -843,48 +892,21 @@ var_reference(parser_state *p, node *lhs) return lhs; } +typedef enum mrb_string_type string_type; static node* -heredoc_start_sb(parser_state *p, const char* term, size_t term_len, enum heredoc_type type, int allow_indent) -{ - node *newnode = new_heredoc(p); - parser_heredoc_info *inf = (parser_heredoc_info*)newnode->cdr; - inf->term = term; - inf->term_len = term_len; - inf->type = type; - inf->allow_indent = allow_indent; - inf->line_head = TRUE; - inf->doc = NULL; - p->heredocs = push(p->heredocs, newnode); - if (p->parsing_heredoc == NULL) { - node *c = p->heredocs; - while (c->cdr) - c = c->cdr; - p->parsing_heredoc = c; - } - p->heredoc_starts_nextline = TRUE; - p->lstate = EXPR_END; - return newnode; -} - -static node* -heredoc_start(parser_state *p, node *beg, node *str, enum heredoc_type type) +new_strterm(parser_state *p, string_type type, int term, int paren) { - char *bs = (char*)beg->cdr->car; - int allow_indent = (bs[2] == '-'); - const char *s = (char*)str->cdr->car; - size_t len = (intptr_t)str->cdr->cdr; - return heredoc_start_sb(p, s, len, type, allow_indent); + return cons((node*)(intptr_t)type, cons((node*)0, cons((node*)(intptr_t)paren, (node*)(intptr_t)term))); } -static node* -heredoc_start_sym(parser_state *p, node *beg, mrb_sym sym, enum heredoc_type type) +static void +end_strterm(parser_state *p) { - char *bs = (char*)beg->cdr->car; - int allow_indent = (bs[2] == '-'); - int len; - const char *s = mrb_sym2name_len(p->mrb, sym, &len); - return heredoc_start_sb(p, s, len, type, allow_indent); + cons_free(p->lex_strterm->cdr->cdr); + cons_free(p->lex_strterm->cdr); + cons_free(p->lex_strterm); + p->lex_strterm = NULL; } parser_heredoc_info * @@ -904,19 +926,19 @@ heredoc_end(parser_state *p) if (p->parsing_heredoc == NULL) { p->lstate = EXPR_BEG; p->cmd_start = TRUE; - p->sterm = 0; + end_strterm(p); p->heredoc_end_now = TRUE; } else { - p->sterm = ' '; /* next heredoc */ + /* next heredoc */ + p->lex_strterm->car = (node*)(intptr_t)parsing_heredoc_inf(p)->type; } } - +#define is_strterm_type(p,str_func) ((int)(intptr_t)((p)->lex_strterm->car) & (str_func)) // xxx ----------------------------- %} -%expect 2 %pure_parser %parse-param {parser_state *p} %lex-param {parser_state *p} @@ -980,12 +1002,12 @@ heredoc_end(parser_state *p) keyword__ENCODING__ %token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL -%token <nd> tINTEGER tFLOAT tCHAR tREGEXP -%token <nd> tSTRING tSTRING_PART +%token <nd> tINTEGER tFLOAT tCHAR tXSTRING tREGEXP +%token <nd> tSTRING tSTRING_PART tSTRING_MID %token <nd> tNTH_REF tBACK_REF %token <num> tREGEXP_END -%type <nd> singleton string string_interp regexp +%type <nd> singleton string string_rep string_interp xstring regexp %type <nd> literal numeric cpath symbol %type <nd> top_compstmt top_stmts top_stmt %type <nd> bodystmt compstmt stmts stmt expr arg primary command command_call method_call @@ -1004,7 +1026,7 @@ heredoc_end(parser_state *p) %type <nd> mlhs mlhs_list mlhs_post mlhs_basic mlhs_item mlhs_node mlhs_inner %type <id> fsym sym basic_symbol operation operation2 operation3 %type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg -%type <nd> heredoc heredoc_rep heredoc_interp +%type <nd> heredoc words symbols %token tUPLUS /* unary+ */ %token tUMINUS /* unary- */ @@ -1033,10 +1055,10 @@ heredoc_end(parser_state *p) %token tSTAR /* * */ %token tAMPER /* & */ %token tLAMBDA /* -> */ -%token tSYMBEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG -%token tSTRING_BEG tSTRING_DVAR tLAMBEG +%token tSYMBEG tREGEXP_BEG tWORDS_BEG tSYMBOLS_BEG +%token tSTRING_BEG tXSTRING_BEG tSTRING_DVAR tLAMBEG %token <nd> tHEREDOC_BEG /* <<, <<- */ -%token tHEREDOC_END +%token tHEREDOC_END tLITERAL_DELIM /* * precedence table @@ -1096,7 +1118,7 @@ top_compstmt : top_stmts opt_terms ; top_stmts : none - { + { $$ = new_begin(p, 0); } | top_stmt @@ -1159,7 +1181,7 @@ compstmt : stmts opt_terms ; stmts : none - { + { $$ = new_begin(p, 0); } | stmt @@ -1220,7 +1242,7 @@ stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym } | primary_value '[' opt_call_args rbracket tOP_ASGN command_call { - $$ = new_op_asgn(p, new_call(p, $1, intern("[]"), $3), $5, $6); + $$ = new_op_asgn(p, new_call(p, $1, intern2("[]",2), $3), $5, $6); } | primary_value '.' tIDENTIFIER tOP_ASGN command_call { @@ -1459,7 +1481,7 @@ mlhs_node : variable } | primary_value '[' opt_call_args rbracket { - $$ = new_call(p, $1, intern("[]"), $3); + $$ = new_call(p, $1, intern2("[]",2), $3); } | primary_value '.' tIDENTIFIER { @@ -1498,7 +1520,7 @@ lhs : variable } | primary_value '[' opt_call_args rbracket { - $$ = new_call(p, $1, intern("[]"), $3); + $$ = new_call(p, $1, intern2("[]",2), $3); } | primary_value '.' tIDENTIFIER { @@ -1581,34 +1603,35 @@ undef_list : fsym } ; -op : '|' { $$ = intern("|"); } - | '^' { $$ = intern("^"); } - | '&' { $$ = intern("&"); } - | tCMP { $$ = intern("<=>"); } - | tEQ { $$ = intern("=="); } - | tEQQ { $$ = intern("==="); } - | tMATCH { $$ = intern("=~"); } - | tNMATCH { $$ = intern("!~"); } - | '>' { $$ = intern(">"); } - | tGEQ { $$ = intern(">="); } - | '<' { $$ = intern("<"); } - | tLEQ { $$ = intern("<="); } - | tNEQ { $$ = intern("!="); } - | tLSHFT { $$ = intern("<<"); } - | tRSHFT { $$ = intern(">>"); } - | '+' { $$ = intern("+"); } - | '-' { $$ = intern("-"); } - | '*' { $$ = intern("*"); } - | tSTAR { $$ = intern("*"); } - | '/' { $$ = intern("/"); } - | '%' { $$ = intern("%"); } - | tPOW { $$ = intern("**"); } - | '!' { $$ = intern("!"); } - | '~' { $$ = intern("~"); } - | tUPLUS { $$ = intern("+@"); } - | tUMINUS { $$ = intern("-@"); } - | tAREF { $$ = intern("[]"); } - | tASET { $$ = intern("[]="); } +op : '|' { $$ = intern_c('|'); } + | '^' { $$ = intern_c('^'); } + | '&' { $$ = intern_c('&'); } + | tCMP { $$ = intern2("<=>",3); } + | tEQ { $$ = intern2("==",2); } + | tEQQ { $$ = intern2("===",3); } + | tMATCH { $$ = intern2("=~",2); } + | tNMATCH { $$ = intern2("!~",2); } + | '>' { $$ = intern_c('>'); } + | tGEQ { $$ = intern2(">=",2); } + | '<' { $$ = intern_c('<'); } + | tLEQ { $$ = intern2("<=",2); } + | tNEQ { $$ = intern2("!=",2); } + | tLSHFT { $$ = intern2("<<",2); } + | tRSHFT { $$ = intern2(">>",2); } + | '+' { $$ = intern_c('+'); } + | '-' { $$ = intern_c('-'); } + | '*' { $$ = intern_c('*'); } + | tSTAR { $$ = intern_c('*'); } + | '/' { $$ = intern_c('/'); } + | '%' { $$ = intern_c('%'); } + | tPOW { $$ = intern2("**",2); } + | '!' { $$ = intern_c('!'); } + | '~' { $$ = intern_c('~'); } + | tUPLUS { $$ = intern2("+@",2); } + | tUMINUS { $$ = intern2("-@",2); } + | tAREF { $$ = intern2("[]",2); } + | tASET { $$ = intern2("[]=",3); } + | '`' { $$ = intern_c('`'); } ; reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__ @@ -1643,7 +1666,7 @@ arg : lhs '=' arg } | primary_value '[' opt_call_args rbracket tOP_ASGN arg { - $$ = new_op_asgn(p, new_call(p, $1, intern("[]"), $3), $5, $6); + $$ = new_op_asgn(p, new_call(p, $1, intern2("[]",2), $3), $5, $6); } | primary_value '.' tIDENTIFIER tOP_ASGN arg { @@ -1942,6 +1965,7 @@ mrhs : args ',' arg_value primary : literal | string + | xstring | regexp | heredoc | var_ref @@ -2281,7 +2305,7 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg { $$ = new_args(p, $1, $3, 0, $5, $6); } - | f_arg ',' f_rest_arg opt_f_block_arg + | f_arg ',' f_rest_arg opt_f_block_arg { $$ = new_args(p, $1, 0, $3, 0, $4); } @@ -2413,7 +2437,7 @@ block_call : command do_block yyerror(p, "block given to yield"); } else { - call_with_block(p, $1, $2); + call_with_block(p, $1, $2); } $$ = $1; } @@ -2451,11 +2475,11 @@ method_call : operation paren_args } | primary_value '.' paren_args { - $$ = new_call(p, $1, intern("call"), $3); + $$ = new_call(p, $1, intern2("call",4), $3); } | primary_value tCOLON2 paren_args { - $$ = new_call(p, $1, intern("call"), $3); + $$ = new_call(p, $1, intern2("call",4), $3); } | keyword_super paren_args { @@ -2467,7 +2491,7 @@ method_call : operation paren_args } | primary_value '[' opt_call_args rbracket { - $$ = new_call(p, $1, intern("[]"), $3); + $$ = new_call(p, $1, intern2("[]",2), $3); } ; @@ -2547,6 +2571,8 @@ opt_ensure : keyword_ensure compstmt literal : numeric | symbol + | words + | symbols ; string : tCHAR @@ -2555,65 +2581,62 @@ string : tCHAR { $$ = $2; } - | tSTRING_BEG string_interp tSTRING + | tSTRING_BEG string_rep tSTRING { $$ = new_dstr(p, push($2, $3)); } ; -string_interp : tSTRING_PART +string_rep : string_interp + | string_rep string_interp { - $<num>$ = p->sterm; - p->sterm = 0; + $$ = append($1, $2); } - compstmt - '}' + ; + +string_interp : tSTRING_MID { - p->sterm = $<num>2; - $$ = list2($1, $3); + $$ = list1($1); } - | string_interp - tSTRING_PART + | tSTRING_PART { - $<num>$ = p->sterm; - p->sterm = 0; + $<nd>$ = p->lex_strterm; + p->lex_strterm = NULL; } compstmt '}' { - p->sterm = $<num>3; - $$ = push(push($1, $2), $4); + p->lex_strterm = $<nd>2; + $$ = list2($1, $3); + } + | tLITERAL_DELIM + { + $$ = list1(new_literal_delim(p)); } ; -regexp : tREGEXP_BEG tREGEXP +xstring : tXSTRING_BEG tXSTRING { $$ = $2; } - | tREGEXP_BEG string_interp tREGEXP + | tXSTRING_BEG string_rep tXSTRING { - $$ = new_dregx(p, $2, $3); + $$ = new_dxstr(p, push($2, $3)); } ; -heredoc : tHEREDOC_BEG tSTRING_BEG tSTRING - { - $$ = heredoc_start(p, $1, $3, heredoc_type_norm); - } - | tHEREDOC_BEG tSTRING - { - $$ = heredoc_start(p, $1, $2, heredoc_type_quote); - } - | tHEREDOC_BEG tIDENTIFIER +regexp : tREGEXP_BEG tREGEXP { - $$ = heredoc_start_sym(p, $1, $2, heredoc_type_norm); + $$ = $2; } - | tHEREDOC_BEG tCONSTANT + | tREGEXP_BEG string_rep tREGEXP { - $$ = heredoc_start_sym(p, $1, $2, heredoc_type_norm); + $$ = new_dregx(p, $2, $3); } ; +heredoc : tHEREDOC_BEG + ; opt_heredoc_bodies : none | heredoc_bodies @@ -2625,42 +2648,27 @@ heredoc_bodies : heredoc_body heredoc_body : tHEREDOC_END { - /* assert(parsing_heredoc_inf(p) != NULL); */ parsing_heredoc_inf(p)->doc = list1(new_str(p, "", 0)); heredoc_end(p); } - | heredoc_rep tHEREDOC_END + | string_rep tHEREDOC_END { - /* assert(parsing_heredoc_inf(p) != NULL); */ parsing_heredoc_inf(p)->doc = $1; heredoc_end(p); } ; -heredoc_rep : heredoc_interp - | heredoc_rep heredoc_interp +words : tWORDS_BEG tSTRING { - $$ = append($1, $2); + $$ = new_words(p, list1($2)); } - ; - -heredoc_interp : tSTRING + | tWORDS_BEG string_rep tSTRING { - $$ = list1($1); - } - | tSTRING_PART - { - $<num>$ = p->sterm; - p->sterm = 0; - } - compstmt - '}' - { - p->sterm = $<num>2; - $$ = list2($1, $3); + $$ = new_words(p, push($2, $3)); } ; + symbol : basic_symbol { $$ = new_sym(p, $1); @@ -2693,6 +2701,16 @@ sym : fname } ; +symbols : tSYMBOLS_BEG tSTRING + { + $$ = new_symbols(p, list1($2)); + } + | tSYMBOLS_BEG string_rep tSTRING + { + $$ = new_symbols(p, push($2, $3)); + } + ; + numeric : tINTEGER | tFLOAT | tUMINUS_NUM tINTEGER %prec tLOWEST @@ -3007,6 +3025,8 @@ singleton : var_ref switch ((enum node_type)(int)(intptr_t)$3->car) { case NODE_STR: case NODE_DSTR: + case NODE_XSTR: + case NODE_DXSTR: case NODE_DREGX: case NODE_MATCH: case NODE_FLOAT: @@ -3232,7 +3252,6 @@ nextc(parser_state *p) else { c = (unsigned char)*p->s++; } - /* if (c == '\n') { } */ /* heredoc treated in parser_yylex() */ } p->column++; return c; @@ -3315,7 +3334,7 @@ skips(parser_state *p, const char *s) int len = strlen(s); while (len--) { - nextc(p); + nextc(p); } return TRUE; } @@ -3326,23 +3345,6 @@ skips(parser_state *p, const char *s) return FALSE; } -#define STR_FUNC_ESCAPE 0x01 -#define STR_FUNC_EXPAND 0x02 -#define STR_FUNC_REGEXP 0x04 -#define STR_FUNC_QWORDS 0x08 -#define STR_FUNC_SYMBOL 0x10 -#define STR_FUNC_INDENT 0x20 - -enum string_type { - str_squote = (0), - str_dquote = (STR_FUNC_EXPAND), - str_xquote = (STR_FUNC_EXPAND), - str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND), - str_sword = (STR_FUNC_QWORDS), - str_dword = (STR_FUNC_QWORDS|STR_FUNC_EXPAND), - str_ssym = (STR_FUNC_SYMBOL), - str_dsym = (STR_FUNC_SYMBOL|STR_FUNC_EXPAND) -}; static int newtok(parser_state *p) @@ -3354,7 +3356,7 @@ newtok(parser_state *p) static void tokadd(parser_state *p, int c) { - if (p->bidx < 1024) { + if (p->bidx < MRB_PARSER_BUF_SIZE) { p->buf[p->bidx++] = c; } } @@ -3368,7 +3370,7 @@ toklast(parser_state *p) static void tokfix(parser_state *p) { - if (p->bidx >= 1024) { + if (p->bidx >= MRB_PARSER_BUF_SIZE) { yyerror(p, "string too long (truncated)"); } p->buf[p->bidx] = '\0'; @@ -3393,34 +3395,38 @@ toklen(parser_state *p) #define IS_LABEL_POSSIBLE() ((p->lstate == EXPR_BEG && !cmd_state) || IS_ARG()) #define IS_LABEL_SUFFIX(n) (peek_n(p, ':',(n)) && !peek_n(p, ':', (n)+1)) -static unsigned long +static int scan_oct(const int *start, int len, int *retlen) { const int *s = start; - unsigned long retval = 0; + int retval = 0; + /* assert(len <= 3) */ while (len-- && *s >= '0' && *s <= '7') { retval <<= 3; retval |= *s++ - '0'; } *retlen = s - start; + return retval; } -static unsigned long +static int scan_hex(const int *start, int len, int *retlen) { static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF"; register const int *s = start; - register unsigned long retval = 0; + register int retval = 0; char *tmp; - while (len-- && *s && (tmp = (char *)strchr(hexdigit, *s))) { + /* assert(len <= 2) */ + while (len-- && *s && (tmp = strchr(hexdigit, *s))) { retval <<= 4; retval |= (tmp - hexdigit) & 15; s++; } *retlen = s - start; + return retval; } @@ -3457,19 +3463,19 @@ read_escape(parser_state *p) case '0': case '1': case '2': case '3': /* octal constant */ case '4': case '5': case '6': case '7': { - int buf[3]; - int i; + int buf[3]; + int i; - buf[0] = c; - for (i=1; i<3; i++) { + buf[0] = c; + for (i=1; i<3; i++) { buf[i] = nextc(p); if (buf[i] == -1) goto eof; - if (buf[i] < '0' || '7' < buf[i]) { - pushback(p, buf[i]); - break; - } - } - c = scan_oct(buf, i, &i); + if (buf[i] < '0' || '7' < buf[i]) { + pushback(p, buf[i]); + break; + } + } + c = scan_oct(buf, i, &i); } return c; @@ -3479,33 +3485,25 @@ read_escape(parser_state *p) int i; for (i=0; i<2; i++) { - buf[i] = nextc(p); - if (buf[i] == -1) goto eof; - if (!isxdigit(buf[i])) { - pushback(p, buf[i]); - break; - } + buf[i] = nextc(p); + if (buf[i] == -1) goto eof; + if (!isxdigit(buf[i])) { + pushback(p, buf[i]); + break; + } } c = scan_hex(buf, i, &i); if (i == 0) { - yyerror(p, "Invalid escape character syntax"); - return 0; + yyerror(p, "Invalid escape character syntax"); + return 0; } } return c; case 'b': /* backspace */ - if (p->regexp) { - tokadd(p, '\\'); - return 'b'; - } return '\010'; case 's': /* space */ - if (p->regexp) { - tokadd(p, '\\'); - return 's'; - } return ' '; case 'M': @@ -3543,57 +3541,154 @@ read_escape(parser_state *p) return '\0'; default: - if (p->regexp) { - tokadd(p, '\\'); - } return c; } } + static int -parse_string(parser_state *p, int term) +parse_string(parser_state *p) { int c; + string_type type = (string_type)(intptr_t)p->lex_strterm->car; + int nest_level = (intptr_t)p->lex_strterm->cdr->car; + int beg = (intptr_t)p->lex_strterm->cdr->cdr->car; + int end = (intptr_t)p->lex_strterm->cdr->cdr->cdr; + parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL; newtok(p); - while ((c = nextc(p)) != term) { - if (c == -1) { + while ((c = nextc(p)) != end || nest_level != 0) { + if (hinf && (c == '\n' || c == -1)) { + int line_head; + tokadd(p, '\n'); + tokfix(p); + p->lineno++; + p->column = 0; + line_head = hinf->line_head; + hinf->line_head = TRUE; + if (line_head) { + /* check whether end of heredoc */ + const char *s = tok(p); + int len = toklen(p); + if (hinf->allow_indent) { + while (ISSPACE(*s) && len > 0) { + ++s; + --len; + } + } + if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) { + return tHEREDOC_END; + } + } + if (c == -1) { + char buf[256]; + snprintf(buf, sizeof(buf), "can't find string \"%s\" anywhere before EOF", hinf->term); + yyerror(p, buf); + return 0; + } + yylval.nd = new_str(p, tok(p), toklen(p)); + return tSTRING_MID; + } + if (c == -1) { yyerror(p, "unterminated string meets end of file"); return 0; } + else if (c == beg) { + nest_level++; + p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level; + } + else if (c == end) { + nest_level--; + p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level; + } else if (c == '\\') { c = nextc(p); - if (c == term) { - tokadd(p, c); - } - else { - pushback(p, c); - tokadd(p, read_escape(p)); + if (type & STR_FUNC_EXPAND) { + if (c == end || c == beg) { + tokadd(p, c); + } + else if ((c == '\n') && (type & STR_FUNC_ARRAY)) { + p->lineno++; + p->column = 0; + tokadd(p, '\n'); + } + else { + pushback(p, c); + + if(type & STR_FUNC_REGEXP) + tokadd(p, '\\'); + + tokadd(p, read_escape(p)); + if (hinf) + hinf->line_head = FALSE; + } + } else { + if (c != beg && c != end) { + switch (c) { + case '\n': + p->lineno++; + p->column = 0; + break; + + case '\\': + break; + + default: + if (! ISSPACE(c)) + tokadd(p, '\\'); + } + } + tokadd(p, c); } continue; } - if (c == '#') { + else if ((c == '#') && (type & STR_FUNC_EXPAND)) { c = nextc(p); if (c == '{') { - tokfix(p); - p->lstate = EXPR_BEG; - p->sterm = term; - p->cmd_start = TRUE; - yylval.nd = new_str(p, tok(p), toklen(p)); - return tSTRING_PART; + tokfix(p); + p->lstate = EXPR_BEG; + p->cmd_start = TRUE; + yylval.nd = new_str(p, tok(p), toklen(p)); + if (hinf) + hinf->line_head = FALSE; + return tSTRING_PART; } tokadd(p, '#'); pushback(p, c); continue; } + if ((type & STR_FUNC_ARRAY) && ISSPACE(c)) { + if (toklen(p) == 0) { + do { + if (c == '\n') { + p->lineno++; + p->column = 0; + } + } while (ISSPACE(c = nextc(p))); + pushback(p, c); + return tLITERAL_DELIM; + } else { + pushback(p, c); + tokfix(p); + yylval.nd = new_str(p, tok(p), toklen(p)); + return tSTRING_MID; + } + } + tokadd(p, c); - } + + } tokfix(p); p->lstate = EXPR_END; - p->sterm = 0; + end_strterm(p); - if (p->regexp) { + if (type & STR_FUNC_XQUOTE) { + yylval.nd = new_xstr(p, tok(p), toklen(p)); + return tXSTRING; + } + + if (type & STR_FUNC_REGEXP) { int f = 0; int c; char *s = strndup(tok(p), toklen(p)); @@ -3613,14 +3708,13 @@ parse_string(parser_state *p, int term) char msg[128]; tokfix(p); snprintf(msg, sizeof(msg), "unknown regexp option%s - %s", - toklen(p) > 1 ? "s" : "", tok(p)); + toklen(p) > 1 ? "s" : "", tok(p)); yyerror(p, msg); } if (f & 1) strcat(flag, "i"); if (f & 2) strcat(flag, "x"); if (f & 4) strcat(flag, "m"); yylval.nd = new_regx(p, s, strdup(flag)); - p->regexp = 0; return tREGEXP; } @@ -3628,128 +3722,78 @@ parse_string(parser_state *p, int term) yylval.nd = new_str(p, tok(p), toklen(p)); return tSTRING; } + -static node* -qstring_node(parser_state *p, int beg, int end) +static int +heredoc_identifier(parser_state *p) { int c; - int nest_level = 0; - - newtok(p); - while ((c = nextc(p)) != end || nest_level != 0) { - if (c == -1) { - yyerror(p, "unterminated string meets end of file"); - return 0; - } - else if (c == beg) { - nest_level++; - } - else if (c == end) { - nest_level--; - } - else if (c == '\\') { - c = nextc(p); - if (c != beg && c != end) { - switch (c) { - case '\n': - p->lineno++; - p->column = 0; - continue; - - case '\\': - c = '\\'; - break; - - default: - tokadd(p, '\\'); - } - } - } - tokadd(p, c); + int type = str_heredoc; + int indent = FALSE; + int quote = FALSE; + node *newnode; + parser_heredoc_info *info; + + c = nextc(p); + if (ISSPACE(c) || c == '=') { + pushback(p, c); + return 0; } - - tokfix(p); - p->lstate = EXPR_END; - return new_str(p, tok(p), toklen(p)); -} - -static int -parse_qstring(parser_state *p, int beg, int end) -{ - node *nd = qstring_node(p, beg, end); - - if (nd) { - yylval.nd = nd; - return tSTRING; + if (c == '-') { + indent = TRUE; + c = nextc(p); } - return 0; -} - -static int -parse_heredoc_line(parser_state *p) -{ - parser_heredoc_info *inf = parsing_heredoc_inf(p); - /* assert(inf != NULL); */ - int c; - int line_head; - - newtok(p); - while ((c = nextc(p)) != '\n') { - if (c == -1) - break; - if (inf->type != heredoc_type_quote) { - if (c == '\\') { - tokadd(p, read_escape(p)); - inf->line_head = FALSE; - continue; - } - if (c == '#') { - c = nextc(p); - if (c == '{') { - tokfix(p); - p->lstate = EXPR_BEG; - p->sterm = ' '; - p->cmd_start = TRUE; - yylval.nd = new_str(p, tok(p), toklen(p)); - inf->line_head = FALSE; - return tSTRING_PART; - } - tokadd(p, '#'); - pushback(p, c); - continue; + if (c == '\'' || c == '"') { + int term = c; + if (c == '\'') + quote = TRUE; + newtok(p); + while ((c = nextc(p)) != -1 && c != term) { + if (c == '\n') { + c = -1; + break; } + tokadd(p, c); } - tokadd(p, c); - } - tokadd(p, '\n'); - tokfix(p); - p->lineno++; - p->column = 0; - line_head = inf->line_head; - inf->line_head = TRUE; - if (line_head) { - /* check whether end of heredoc */ - const char *s = tok(p); - int len = toklen(p); - if (inf->allow_indent) { - while (ISSPACE(*s) && len > 0) { - ++s; - --len; - } + if (c == -1) { + yyerror(p, "unterminated here document identifier"); + return 0; } - if ((len-1 == inf->term_len) && (strncmp(s, inf->term, len-1) == 0)) { - return tHEREDOC_END; + } else { + if (! identchar(c)) { + pushback(p, c); + if (indent) pushback(p, '-'); + return 0; } + newtok(p); + do { + tokadd(p, c); + } while ((c = nextc(p)) != -1 && identchar(c)); + pushback(p, c); } - if (c == -1) { - char buf[256]; - snprintf(buf, sizeof(buf), "can't find string \"%s\" anywhere before EOF", inf->term); - yyerror(p, buf); - return 0; + tokfix(p); + newnode = new_heredoc(p); + info = (parser_heredoc_info*)newnode->cdr; + info->term = strndup(tok(p), toklen(p)); + info->term_len = toklen(p); + if (! quote) + type |= STR_FUNC_EXPAND; + info->type = type; + info->allow_indent = indent; + info->line_head = TRUE; + info->doc = NULL; + p->heredocs = push(p->heredocs, newnode); + if (p->parsing_heredoc == NULL) { + node *n = p->heredocs; + while (n->cdr) + n = n->cdr; + p->parsing_heredoc = n; } + p->heredoc_starts_nextline = TRUE; + p->lstate = EXPR_END; - yylval.nd = new_str(p, tok(p), toklen(p)); - return tSTRING; + yylval.nd = newnode; + return tHEREDOC_BEG; } static int @@ -3765,17 +3809,18 @@ static int parser_yylex(parser_state *p) { register int c; - int c2; int space_seen = 0; int cmd_state; enum mrb_lex_state_enum last_state; int token_column; - if ((p->sterm == ' ') && (p->parsing_heredoc != NULL) && (! p->heredoc_starts_nextline)) { - return parse_heredoc_line(p); - } - if (p->sterm) { - return parse_string(p, p->sterm); + if (p->lex_strterm) { + if (is_strterm_type(p, STR_FUNC_HEREDOC)) { + if ((p->parsing_heredoc != NULL) && (! p->heredoc_starts_nextline)) + return parse_string(p); + } + else + return parse_string(p); } cmd_state = p->cmd_start; p->cmd_start = FALSE; @@ -3800,7 +3845,7 @@ parser_yylex(parser_state *p) case '\n': p->heredoc_starts_nextline = FALSE; if (p->parsing_heredoc != NULL) { - p->sterm = ' '; + p->lex_strterm = new_strterm(p, parsing_heredoc_inf(p)->type, 0, 0); goto normal_newline; } switch (p->lstate) { @@ -3819,19 +3864,19 @@ parser_yylex(parser_state *p) switch (c) { case ' ': case '\t': case '\f': case '\r': case '\13': /* '\v' */ - space_seen = 1; - break; + space_seen = 1; + break; case '.': - if ((c = nextc(p)) != '.') { - pushback(p, c); - pushback(p, '.'); - goto retry; - } + if ((c = nextc(p)) != '.') { + pushback(p, c); + pushback(p, '.'); + goto retry; + } case -1: /* EOF */ - goto normal_newline; + goto normal_newline; default: - pushback(p, c); - goto normal_newline; + pushback(p, c); + goto normal_newline; } } normal_newline: @@ -3842,29 +3887,29 @@ parser_yylex(parser_state *p) case '*': if ((c = nextc(p)) == '*') { if ((c = nextc(p)) == '=') { - yylval.id = intern("**"); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern2("**",2); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); c = tPOW; } else { if (c == '=') { - yylval.id = intern("*"); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern_c('*'); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); if (IS_SPCARG(c)) { - yywarning(p, "`*' interpreted as argument prefix"); - c = tSTAR; + yywarning(p, "`*' interpreted as argument prefix"); + c = tSTAR; } else if (IS_BEG()) { - c = tSTAR; + c = tSTAR; } else { - c = '*'; + c = '*'; } } if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { @@ -3879,7 +3924,7 @@ parser_yylex(parser_state *p) if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { p->lstate = EXPR_ARG; if (c == '@') { - return '!'; + return '!'; } } else { @@ -3897,7 +3942,7 @@ parser_yylex(parser_state *p) case '=': if (p->column == 1) { if (peeks(p, "begin\n")) { - skips(p, "\n=end\n"); + skips(p, "\n=end\n"); goto retry; } } @@ -3908,7 +3953,7 @@ parser_yylex(parser_state *p) } if ((c = nextc(p)) == '=') { if ((c = nextc(p)) == '=') { - return tEQQ; + return tEQQ; } pushback(p, c); return tEQ; @@ -3926,45 +3971,34 @@ parser_yylex(parser_state *p) last_state = p->lstate; c = nextc(p); if (c == '<' && - p->lstate != EXPR_DOT && - p->lstate != EXPR_CLASS && - !IS_END() && - (!IS_ARG() || space_seen)) { - /* heredocument check */ - newtok(p); tokadd(p, '<'); tokadd(p, '<'); - c2 = nextc(p); - if (c2 == '-') { - tokadd(p, c2); - c2 = nextc(p); - } - pushback(p, c2); - if (!ISSPACE(c2)) { - tokfix(p); - yylval.nd = new_str(p, tok(p), toklen(p)); - p->lstate = EXPR_DOT; - return tHEREDOC_BEG; - } + p->lstate != EXPR_DOT && + p->lstate != EXPR_CLASS && + !IS_END() && + (!IS_ARG() || space_seen)) { + int token = heredoc_identifier(p); + if (token) + return token; } if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { p->lstate = EXPR_ARG; } else { p->lstate = EXPR_BEG; if (p->lstate == EXPR_CLASS) { - p->cmd_start = TRUE; + p->cmd_start = TRUE; } } if (c == '=') { if ((c = nextc(p)) == '>') { - return tCMP; + return tCMP; } pushback(p, c); return tLEQ; } if (c == '<') { if ((c = nextc(p)) == '=') { - yylval.id = intern("<<"); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern2("<<",2); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); return tLSHFT; @@ -3983,9 +4017,9 @@ parser_yylex(parser_state *p) } if (c == '>') { if ((c = nextc(p)) == '=') { - yylval.id = intern(">>"); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern2(">>",2); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); return tRSHFT; @@ -3994,11 +4028,27 @@ parser_yylex(parser_state *p) return '>'; case '"': - p->sterm = '"'; + p->lex_strterm = new_strterm(p, str_dquote, '"', 0); return tSTRING_BEG; case '\'': - return parse_qstring(p, '\'', '\''); + p->lex_strterm = new_strterm(p, str_squote, '\'', 0); + return parse_string(p); + + case '`': + if (p->lstate == EXPR_FNAME) { + p->lstate = EXPR_ENDFN; + return '`'; + } + if (p->lstate == EXPR_DOT) { + if (cmd_state) + p->lstate = EXPR_CMDARG; + else + p->lstate = EXPR_ARG; + return '`'; + } + p->lex_strterm = new_strterm(p, str_xquote, '`', 0); + return tXSTRING_BEG; case '?': if (IS_END()) { @@ -4012,35 +4062,35 @@ parser_yylex(parser_state *p) } if (isspace(c)) { if (!IS_ARG()) { - int c2; - switch (c) { - case ' ': - c2 = 's'; - break; - case '\n': - c2 = 'n'; - break; - case '\t': - c2 = 't'; - break; - case '\v': - c2 = 'v'; - break; - case '\r': - c2 = 'r'; - break; - case '\f': - c2 = 'f'; - break; - default: - c2 = 0; - break; - } - if (c2) { - char buf[256]; - snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2); - yyerror(p, buf); - } + int c2; + switch (c) { + case ' ': + c2 = 's'; + break; + case '\n': + c2 = 'n'; + break; + case '\t': + c2 = 't'; + break; + case '\v': + c2 = 'v'; + break; + case '\r': + c2 = 'r'; + break; + case '\f': + c2 = 'f'; + break; + default: + c2 = 0; + break; + } + if (c2) { + char buf[256]; + snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2); + yyerror(p, buf); + } } ternary: pushback(p, c); @@ -4053,20 +4103,20 @@ parser_yylex(parser_state *p) int c2 = nextc(p); pushback(p, c2); if ((isalnum(c2) || c2 == '_')) { - goto ternary; + goto ternary; } } if (c == '\\') { c = nextc(p); if (c == 'u') { #if 0 - tokadd_utf8(p); + tokadd_utf8(p); #endif } else { - pushback(p, c); - c = read_escape(p); - tokadd(p, c); + pushback(p, c); + c = read_escape(p); + tokadd(p, c); } } else { @@ -4081,15 +4131,15 @@ parser_yylex(parser_state *p) if ((c = nextc(p)) == '&') { p->lstate = EXPR_BEG; if ((c = nextc(p)) == '=') { - yylval.id = intern("&&"); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern2("&&",2); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); return tANDOP; } else if (c == '=') { - yylval.id = intern("&"); + yylval.id = intern_c('&'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4115,15 +4165,15 @@ parser_yylex(parser_state *p) if ((c = nextc(p)) == '|') { p->lstate = EXPR_BEG; if ((c = nextc(p)) == '=') { - yylval.id = intern("||"); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern2("||",2); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); return tOROP; } if (c == '=') { - yylval.id = intern("|"); + yylval.id = intern_c('|'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4141,13 +4191,13 @@ parser_yylex(parser_state *p) if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { p->lstate = EXPR_ARG; if (c == '@') { - return tUPLUS; + return tUPLUS; } pushback(p, c); return '+'; } if (c == '=') { - yylval.id = intern("+"); + yylval.id = intern_c('+'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4155,8 +4205,8 @@ parser_yylex(parser_state *p) p->lstate = EXPR_BEG; pushback(p, c); if (c != -1 && ISDIGIT(c)) { - c = '+'; - goto start_num; + c = '+'; + goto start_num; } return tUPLUS; } @@ -4169,13 +4219,13 @@ parser_yylex(parser_state *p) if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { p->lstate = EXPR_ARG; if (c == '@') { - return tUMINUS; + return tUMINUS; } pushback(p, c); return '-'; } if (c == '=') { - yylval.id = intern("-"); + yylval.id = intern_c('-'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4187,7 +4237,7 @@ parser_yylex(parser_state *p) p->lstate = EXPR_BEG; pushback(p, c); if (c != -1 && ISDIGIT(c)) { - return tUMINUS_NUM; + return tUMINUS_NUM; } return tUMINUS; } @@ -4199,7 +4249,7 @@ parser_yylex(parser_state *p) p->lstate = EXPR_BEG; if ((c = nextc(p)) == '.') { if ((c = nextc(p)) == '.') { - return tDOT3; + return tDOT3; } pushback(p, c); return tDOT2; @@ -4221,218 +4271,218 @@ parser_yylex(parser_state *p) p->lstate = EXPR_END; token_column = newtok(p); if (c == '-' || c == '+') { - tokadd(p, c); - c = nextc(p); + tokadd(p, c); + c = nextc(p); } if (c == '0') { #define no_digits() do {yyerror(p,"numeric literal without digits"); return 0;} while (0) - int start = toklen(p); - c = nextc(p); - if (c == 'x' || c == 'X') { - /* hexadecimal */ - c = nextc(p); - if (c != -1 && ISXDIGIT(c)) { - do { - if (c == '_') { - if (nondigit) break; - nondigit = c; - continue; - } - if (!ISXDIGIT(c)) break; - nondigit = 0; - tokadd(p, tolower(c)); - } while ((c = nextc(p)) != -1); - } - pushback(p, c); - tokfix(p); - if (toklen(p) == start) { - no_digits(); - } - else if (nondigit) goto trailing_uc; - yylval.nd = new_int(p, tok(p), 16); - return tINTEGER; - } - if (c == 'b' || c == 'B') { - /* binary */ - c = nextc(p); - if (c == '0' || c == '1') { - do { - if (c == '_') { - if (nondigit) break; - nondigit = c; - continue; - } - if (c != '0' && c != '1') break; - nondigit = 0; - tokadd(p, c); - } while ((c = nextc(p)) != -1); - } - pushback(p, c); - tokfix(p); - if (toklen(p) == start) { - no_digits(); - } - else if (nondigit) goto trailing_uc; - yylval.nd = new_int(p, tok(p), 2); - return tINTEGER; - } - if (c == 'd' || c == 'D') { - /* decimal */ - c = nextc(p); - if (c != -1 && ISDIGIT(c)) { - do { - if (c == '_') { - if (nondigit) break; - nondigit = c; - continue; - } - if (!ISDIGIT(c)) break; - nondigit = 0; - tokadd(p, c); - } while ((c = nextc(p)) != -1); - } - pushback(p, c); - tokfix(p); - if (toklen(p) == start) { - no_digits(); - } - else if (nondigit) goto trailing_uc; - yylval.nd = new_int(p, tok(p), 10); - return tINTEGER; - } - if (c == '_') { - /* 0_0 */ - goto octal_number; - } - if (c == 'o' || c == 'O') { - /* prefixed octal */ - c = nextc(p); - if (c == -1 || c == '_' || !ISDIGIT(c)) { - no_digits(); - } - } - if (c >= '0' && c <= '7') { - /* octal */ - octal_number: - do { - if (c == '_') { - if (nondigit) break; - nondigit = c; - continue; - } - if (c < '0' || c > '9') break; - if (c > '7') goto invalid_octal; - nondigit = 0; - tokadd(p, c); - } while ((c = nextc(p)) != -1); - - if (toklen(p) > start) { - pushback(p, c); - tokfix(p); - if (nondigit) goto trailing_uc; - yylval.nd = new_int(p, tok(p), 8); - return tINTEGER; - } - if (nondigit) { - pushback(p, c); - goto trailing_uc; - } - } - if (c > '7' && c <= '9') { - invalid_octal: - yyerror(p, "Invalid octal digit"); - } - else if (c == '.' || c == 'e' || c == 'E') { - tokadd(p, '0'); - } - else { - pushback(p, c); - yylval.nd = new_int(p, "0", 10); - return tINTEGER; - } + int start = toklen(p); + c = nextc(p); + if (c == 'x' || c == 'X') { + /* hexadecimal */ + c = nextc(p); + if (c != -1 && ISXDIGIT(c)) { + do { + if (c == '_') { + if (nondigit) break; + nondigit = c; + continue; + } + if (!ISXDIGIT(c)) break; + nondigit = 0; + tokadd(p, tolower(c)); + } while ((c = nextc(p)) != -1); + } + pushback(p, c); + tokfix(p); + if (toklen(p) == start) { + no_digits(); + } + else if (nondigit) goto trailing_uc; + yylval.nd = new_int(p, tok(p), 16); + return tINTEGER; + } + if (c == 'b' || c == 'B') { + /* binary */ + c = nextc(p); + if (c == '0' || c == '1') { + do { + if (c == '_') { + if (nondigit) break; + nondigit = c; + continue; + } + if (c != '0' && c != '1') break; + nondigit = 0; + tokadd(p, c); + } while ((c = nextc(p)) != -1); + } + pushback(p, c); + tokfix(p); + if (toklen(p) == start) { + no_digits(); + } + else if (nondigit) goto trailing_uc; + yylval.nd = new_int(p, tok(p), 2); + return tINTEGER; + } + if (c == 'd' || c == 'D') { + /* decimal */ + c = nextc(p); + if (c != -1 && ISDIGIT(c)) { + do { + if (c == '_') { + if (nondigit) break; + nondigit = c; + continue; + } + if (!ISDIGIT(c)) break; + nondigit = 0; + tokadd(p, c); + } while ((c = nextc(p)) != -1); + } + pushback(p, c); + tokfix(p); + if (toklen(p) == start) { + no_digits(); + } + else if (nondigit) goto trailing_uc; + yylval.nd = new_int(p, tok(p), 10); + return tINTEGER; + } + if (c == '_') { + /* 0_0 */ + goto octal_number; + } + if (c == 'o' || c == 'O') { + /* prefixed octal */ + c = nextc(p); + if (c == -1 || c == '_' || !ISDIGIT(c)) { + no_digits(); + } + } + if (c >= '0' && c <= '7') { + /* octal */ + octal_number: + do { + if (c == '_') { + if (nondigit) break; + nondigit = c; + continue; + } + if (c < '0' || c > '9') break; + if (c > '7') goto invalid_octal; + nondigit = 0; + tokadd(p, c); + } while ((c = nextc(p)) != -1); + + if (toklen(p) > start) { + pushback(p, c); + tokfix(p); + if (nondigit) goto trailing_uc; + yylval.nd = new_int(p, tok(p), 8); + return tINTEGER; + } + if (nondigit) { + pushback(p, c); + goto trailing_uc; + } + } + if (c > '7' && c <= '9') { + invalid_octal: + yyerror(p, "Invalid octal digit"); + } + else if (c == '.' || c == 'e' || c == 'E') { + tokadd(p, '0'); + } + else { + pushback(p, c); + yylval.nd = new_int(p, "0", 10); + return tINTEGER; + } } for (;;) { - switch (c) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - nondigit = 0; - tokadd(p, c); - break; - - case '.': - if (nondigit) goto trailing_uc; - if (seen_point || seen_e) { - goto decode_num; - } - else { - int c0 = nextc(p); - if (c0 == -1 || !ISDIGIT(c0)) { - pushback(p, c0); - goto decode_num; - } - c = c0; - } - tokadd(p, '.'); - tokadd(p, c); - is_float++; - seen_point++; - nondigit = 0; - break; - - case 'e': - case 'E': - if (nondigit) { - pushback(p, c); - c = nondigit; - goto decode_num; - } - if (seen_e) { - goto decode_num; - } - tokadd(p, c); - seen_e++; - is_float++; - nondigit = c; - c = nextc(p); - if (c != '-' && c != '+') continue; - tokadd(p, c); - nondigit = c; - break; - - case '_': /* `_' in number just ignored */ - if (nondigit) goto decode_num; - nondigit = c; - break; - - default: - goto decode_num; - } - c = nextc(p); + switch (c) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + nondigit = 0; + tokadd(p, c); + break; + + case '.': + if (nondigit) goto trailing_uc; + if (seen_point || seen_e) { + goto decode_num; + } + else { + int c0 = nextc(p); + if (c0 == -1 || !ISDIGIT(c0)) { + pushback(p, c0); + goto decode_num; + } + c = c0; + } + tokadd(p, '.'); + tokadd(p, c); + is_float++; + seen_point++; + nondigit = 0; + break; + + case 'e': + case 'E': + if (nondigit) { + pushback(p, c); + c = nondigit; + goto decode_num; + } + if (seen_e) { + goto decode_num; + } + tokadd(p, c); + seen_e++; + is_float++; + nondigit = c; + c = nextc(p); + if (c != '-' && c != '+') continue; + tokadd(p, c); + nondigit = c; + break; + + case '_': /* `_' in number just ignored */ + if (nondigit) goto decode_num; + nondigit = c; + break; + + default: + goto decode_num; + } + c = nextc(p); } decode_num: pushback(p, c); if (nondigit) { trailing_uc: - yyerror_i(p, "trailing `%c' in number", nondigit); + yyerror_i(p, "trailing `%c' in number", nondigit); } tokfix(p); if (is_float) { - double d; - char *endp; - - errno = 0; - d = strtod(tok(p), &endp); - if (d == 0 && endp == tok(p)) { - yywarning_s(p, "corrupted float value %s", tok(p)); - } - else if (errno == ERANGE) { - yywarning_s(p, "float %s out of range", tok(p)); - errno = 0; - } - yylval.nd = new_float(p, tok(p)); - return tFLOAT; + double d; + char *endp; + + errno = 0; + d = strtod(tok(p), &endp); + if (d == 0 && endp == tok(p)) { + yywarning_s(p, "corrupted float value %s", tok(p)); + } + else if (errno == ERANGE) { + yywarning_s(p, "float %s out of range", tok(p)); + errno = 0; + } + yylval.nd = new_float(p, tok(p)); + return tFLOAT; } yylval.nd = new_int(p, tok(p), 10); return tINTEGER; @@ -4454,8 +4504,8 @@ parser_yylex(parser_state *p) c = nextc(p); if (c == ':') { if (IS_BEG() || p->lstate == EXPR_CLASS || IS_SPCARG(-1)) { - p->lstate = EXPR_BEG; - return tCOLON3; + p->lstate = EXPR_BEG; + return tCOLON3; } p->lstate = EXPR_DOT; return tCOLON2; @@ -4471,25 +4521,17 @@ parser_yylex(parser_state *p) case '/': if (IS_BEG()) { -#if 0 p->lex_strterm = new_strterm(p, str_regexp, '/', 0); -#endif - p->regexp = 1; - p->sterm = '/'; return tREGEXP_BEG; } if ((c = nextc(p)) == '=') { - yylval.id = intern("/"); + yylval.id = intern_c('/'); p->lstate = EXPR_BEG; return tOP_ASGN; } pushback(p, c); if (IS_SPCARG(c)) { -#if 0 p->lex_strterm = new_strterm(p, str_regexp, '/', 0); -#endif - p->regexp = 1; - p->sterm = '/'; return tREGEXP_BEG; } if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { @@ -4501,7 +4543,7 @@ parser_yylex(parser_state *p) case '^': if ((c = nextc(p)) == '=') { - yylval.id = intern("^"); + yylval.id = intern_c('^'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4524,7 +4566,7 @@ parser_yylex(parser_state *p) case '~': if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { if ((c = nextc(p)) != '@') { - pushback(p, c); + pushback(p, c); } p->lstate = EXPR_ARG; } @@ -4551,11 +4593,11 @@ parser_yylex(parser_state *p) if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { p->lstate = EXPR_ARG; if ((c = nextc(p)) == ']') { - if ((c = nextc(p)) == '=') { - return tASET; - } - pushback(p, c); - return tAREF; + if ((c = nextc(p)) == '=') { + return tASET; + } + pushback(p, c); + return tAREF; } pushback(p, c); return '['; @@ -4604,92 +4646,77 @@ parser_yylex(parser_state *p) case '%': if (IS_BEG()) { - int beg = 0, term; -#if 0 + int term; int paren; -#endif c = nextc(p); quotation: if (c == -1 || !ISALNUM(c)) { - term = c; - c = 'Q'; + term = c; + c = 'Q'; } else { - beg = term = nextc(p); - if (isalnum(term)) { - yyerror(p, "unknown type of %string"); - return 0; - } + term = nextc(p); + if (isalnum(term)) { + yyerror(p, "unknown type of %string"); + return 0; + } } if (c == -1 || term == -1) { - yyerror(p, "unterminated quoted string meets end of file"); - return 0; + yyerror(p, "unterminated quoted string meets end of file"); + return 0; } -#if 0 paren = term; -#endif if (term == '(') term = ')'; else if (term == '[') term = ']'; else if (term == '{') term = '}'; else if (term == '<') term = '>'; - p->sterm = term; -#if 0 else paren = 0; -#endif switch (c) { case 'Q': -#if 0 - p->lex_strterm = new_strterm(p, str_dquote, term, paren); -#endif - return tSTRING_BEG; + p->lex_strterm = new_strterm(p, str_dquote, term, paren); + return tSTRING_BEG; case 'q': -#if 0 - p->lex_strterm = new_strterm(p, str_squote, term, paren); -#endif - p->sterm = 0; - return parse_qstring(p, beg, term); + p->lex_strterm = new_strterm(p, str_squote, term, paren); + return parse_string(p); case 'W': -#if 0 - p->lex_strterm = new_strterm(p, str_dword, term, paren); -#endif - do {c = nextc(p);} while (isspace(c)); - pushback(p, c); - return tWORDS_BEG; + p->lex_strterm = new_strterm(p, str_dword, term, paren); + return tWORDS_BEG; case 'w': -#if 0 - p->lex_strterm = new_strterm(p, str_sword, term, paren); -#endif - do {c = nextc(p);} while (isspace(c)); - pushback(p, c); - return tQWORDS_BEG; + p->lex_strterm = new_strterm(p, str_sword, term, paren); + return tWORDS_BEG; + + case 'x': + p->lex_strterm = new_strterm(p, str_xquote, term, paren); + return tXSTRING_BEG; case 'r': -#if 0 - p->lex_strterm = new_strterm(p, str_regexp, term, paren); -#endif - p->regexp = 1; - p->sterm = term; - return tREGEXP_BEG; + p->lex_strterm = new_strterm(p, str_regexp, term, paren); + return tREGEXP_BEG; case 's': -#if 0 - p->lex_strterm = new_strterm(p, str_ssym, term, paren); -#endif - p->lstate = EXPR_FNAME; - return tSYMBEG; + p->lex_strterm = new_strterm(p, str_ssym, term, paren); + return tSYMBEG; + + case 'I': + p->lex_strterm = new_strterm(p, str_dsymbols, term, paren); + return tSYMBOLS_BEG; + + case 'i': + p->lex_strterm = new_strterm(p, str_ssymbols, term, paren); + return tSYMBOLS_BEG; default: - yyerror(p, "unknown type of %string"); - return 0; + yyerror(p, "unknown type of %string"); + return 0; } } if ((c = nextc(p)) == '=') { - yylval.id = intern("%"); + yylval.id = intern_c('%'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4751,9 +4778,9 @@ parser_yylex(parser_state *p) case '\'': /* $': string after last match */ case '+': /* $+: string matches last pattern */ if (last_state == EXPR_FNAME) { - tokadd(p, '$'); - tokadd(p, c); - goto gvar; + tokadd(p, '$'); + tokadd(p, c); + goto gvar; } yylval.nd = new_back_ref(p, c); return tBACK_REF; @@ -4762,8 +4789,8 @@ parser_yylex(parser_state *p) case '4': case '5': case '6': case '7': case '8': case '9': do { - tokadd(p, c); - c = nextc(p); + tokadd(p, c); + c = nextc(p); } while (c != -1 && isdigit(c)); pushback(p, c); if (last_state == EXPR_FNAME) goto gvar; @@ -4773,8 +4800,8 @@ parser_yylex(parser_state *p) default: if (!identchar(c)) { - pushback(p, c); - return '$'; + pushback(p, c); + return '$'; } case '0': tokadd(p, '$'); @@ -4791,10 +4818,10 @@ parser_yylex(parser_state *p) } if (c != -1 && isdigit(c)) { if (p->bidx == 1) { - yyerror_i(p, "`@%c' is not allowed as an instance variable name", c); + yyerror_i(p, "`@%c' is not allowed as an instance variable name", c); } else { - yyerror_i(p, "`@@%c' is not allowed as a class variable name", c); + yyerror_i(p, "`@@%c' is not allowed as a class variable name", c); } return 0; } @@ -4852,95 +4879,95 @@ parser_yylex(parser_state *p) case '@': p->lstate = EXPR_END; if (tok(p)[1] == '@') - result = tCVAR; + result = tCVAR; else - result = tIVAR; + result = tIVAR; break; default: if (toklast(p) == '!' || toklast(p) == '?') { - result = tFID; + result = tFID; } else { - if (p->lstate == EXPR_FNAME) { - if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') && - (!peek(p, '=') || (peek_n(p, '>', 1)))) { - result = tIDENTIFIER; - tokadd(p, c); - tokfix(p); - } - else { - pushback(p, c); - } - } - if (result == 0 && isupper((int)tok(p)[0])) { - result = tCONSTANT; - } - else { - result = tIDENTIFIER; - } + if (p->lstate == EXPR_FNAME) { + if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') && + (!peek(p, '=') || (peek_n(p, '>', 1)))) { + result = tIDENTIFIER; + tokadd(p, c); + tokfix(p); + } + else { + pushback(p, c); + } + } + if (result == 0 && isupper((int)tok(p)[0])) { + result = tCONSTANT; + } + else { + result = tIDENTIFIER; + } } if (IS_LABEL_POSSIBLE()) { - if (IS_LABEL_SUFFIX(0)) { - p->lstate = EXPR_BEG; - nextc(p); - tokfix(p); - yylval.id = intern(tok(p)); - return tLABEL; - } + if (IS_LABEL_SUFFIX(0)) { + p->lstate = EXPR_BEG; + nextc(p); + tokfix(p); + yylval.id = intern(tok(p)); + return tLABEL; + } } if (p->lstate != EXPR_DOT) { - const struct kwtable *kw; - - /* See if it is a reserved word. */ - kw = mrb_reserved_word(tok(p), toklen(p)); - if (kw) { - enum mrb_lex_state_enum state = p->lstate; - p->lstate = kw->state; - if (state == EXPR_FNAME) { - yylval.id = intern(kw->name); - return kw->id[0]; - } - if (p->lstate == EXPR_BEG) { - p->cmd_start = TRUE; - } - if (kw->id[0] == keyword_do) { - if (p->lpar_beg && p->lpar_beg == p->paren_nest) { - p->lpar_beg = 0; - p->paren_nest--; - return keyword_do_LAMBDA; - } - if (COND_P()) return keyword_do_cond; - if (CMDARG_P() && state != EXPR_CMDARG) - return keyword_do_block; - if (state == EXPR_ENDARG || state == EXPR_BEG) - return keyword_do_block; - return keyword_do; - } - if (state == EXPR_BEG || state == EXPR_VALUE) - return kw->id[0]; - else { - if (kw->id[0] != kw->id[1]) - p->lstate = EXPR_BEG; - return kw->id[1]; - } - } + const struct kwtable *kw; + + /* See if it is a reserved word. */ + kw = mrb_reserved_word(tok(p), toklen(p)); + if (kw) { + enum mrb_lex_state_enum state = p->lstate; + p->lstate = kw->state; + if (state == EXPR_FNAME) { + yylval.id = intern(kw->name); + return kw->id[0]; + } + if (p->lstate == EXPR_BEG) { + p->cmd_start = TRUE; + } + if (kw->id[0] == keyword_do) { + if (p->lpar_beg && p->lpar_beg == p->paren_nest) { + p->lpar_beg = 0; + p->paren_nest--; + return keyword_do_LAMBDA; + } + if (COND_P()) return keyword_do_cond; + if (CMDARG_P() && state != EXPR_CMDARG) + return keyword_do_block; + if (state == EXPR_ENDARG || state == EXPR_BEG) + return keyword_do_block; + return keyword_do; + } + if (state == EXPR_BEG || state == EXPR_VALUE) + return kw->id[0]; + else { + if (kw->id[0] != kw->id[1]) + p->lstate = EXPR_BEG; + return kw->id[1]; + } + } } if (IS_BEG() || p->lstate == EXPR_DOT || IS_ARG()) { - if (cmd_state) { - p->lstate = EXPR_CMDARG; - } - else { - p->lstate = EXPR_ARG; - } + if (cmd_state) { + p->lstate = EXPR_CMDARG; + } + else { + p->lstate = EXPR_ARG; + } } else if (p->lstate == EXPR_FNAME) { - p->lstate = EXPR_ENDFN; + p->lstate = EXPR_ENDFN; } else { - p->lstate = EXPR_END; + p->lstate = EXPR_END; } } { @@ -4949,7 +4976,7 @@ parser_yylex(parser_state *p) yylval.id = ident; #if 0 if (last_state != EXPR_DOT && islower(tok(p)[0]) && lvar_defined(ident)) { - p->lstate = EXPR_END; + p->lstate = EXPR_END; } #endif } @@ -5021,7 +5048,7 @@ mrb_parser_parse(parser_state *p, mrbc_context *c) p->cmd_start = TRUE; p->in_def = p->in_single = FALSE; p->nerr = p->nwarn = 0; - p->sterm = 0; + p->lex_strterm = NULL; parser_init_cxt(p, c); yyparse(p); @@ -5064,6 +5091,7 @@ mrb_parser_new(mrb_state *mrb) yydebug = 1; #endif + p->lex_strterm = NULL; p->heredocs = p->parsing_heredoc = NULL; return p; @@ -5153,13 +5181,13 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c) n = snprintf(buf, sizeof(buf), "line %d: %s\n", p->error_buffer[0].lineno, p->error_buffer[0].message); - mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n)); + mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n)); mrb_parser_free(p); return mrb_undef_value(); } else { static const char msg[] = "syntax error"; - mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SYNTAX_ERROR, msg, sizeof(msg) - 1)); + mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, msg, sizeof(msg) - 1)); mrb_parser_free(p); return mrb_undef_value(); } @@ -5168,7 +5196,7 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c) mrb_parser_free(p); if (n < 0) { static const char msg[] = "codegen error"; - mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1)); + mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1)); return mrb_nil_value(); } if (c) { @@ -5269,23 +5297,23 @@ parser_dump(mrb_state *mrb, node *tree, int offset) dump_prefix(offset+1); printf("rescue:\n"); while (n2) { - node *n3 = n2->car; - if (n3->car) { - dump_prefix(offset+2); - printf("handle classes:\n"); - dump_recur(mrb, n3->car, offset+3); - } - if (n3->cdr->car) { - dump_prefix(offset+2); - printf("exc_var:\n"); - parser_dump(mrb, n3->cdr->car, offset+3); - } - if (n3->cdr->cdr->car) { - dump_prefix(offset+2); - printf("rescue body:\n"); - parser_dump(mrb, n3->cdr->cdr->car, offset+3); - } - n2 = n2->cdr; + node *n3 = n2->car; + if (n3->car) { + dump_prefix(offset+2); + printf("handle classes:\n"); + dump_recur(mrb, n3->car, offset+3); + } + if (n3->cdr->car) { + dump_prefix(offset+2); + printf("exc_var:\n"); + parser_dump(mrb, n3->cdr->car, offset+3); + } + if (n3->cdr->cdr->car) { + dump_prefix(offset+2); + printf("rescue body:\n"); + parser_dump(mrb, n3->cdr->cdr->car, offset+3); + } + n2 = n2->cdr; } } tree = tree->cdr; @@ -5318,40 +5346,40 @@ parser_dump(mrb_state *mrb, node *tree, int offset) node *n = tree->car; if (n->car) { - dump_prefix(offset+1); - printf("mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); + dump_prefix(offset+1); + printf("mandatory args:\n"); + dump_recur(mrb, n->car, offset+2); } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("optional args:\n"); - { - node *n2 = n->car; - - while (n2) { - dump_prefix(offset+2); - printf("%s=", mrb_sym2name(mrb, sym(n2->car->car))); - parser_dump(mrb, n2->car->cdr, 0); - n2 = n2->cdr; - } - } + dump_prefix(offset+1); + printf("optional args:\n"); + { + node *n2 = n->car; + + while (n2) { + dump_prefix(offset+2); + printf("%s=", mrb_sym2name(mrb, sym(n2->car->car))); + parser_dump(mrb, n2->car->cdr, 0); + n2 = n2->cdr; + } + } } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car))); + dump_prefix(offset+1); + printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car))); } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("post mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); + dump_prefix(offset+1); + printf("post mandatory args:\n"); + dump_recur(mrb, n->car, offset+2); } n = n->cdr; if (n) { - dump_prefix(offset+1); - printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); + dump_prefix(offset+1); + printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); } } dump_prefix(offset+1); @@ -5431,25 +5459,25 @@ parser_dump(mrb_state *mrb, node *tree, int offset) node *n2 = tree->car; if (n2->car) { - dump_prefix(offset+2); - printf("pre:\n"); - dump_recur(mrb, n2->car, offset+3); + dump_prefix(offset+2); + printf("pre:\n"); + dump_recur(mrb, n2->car, offset+3); } n2 = n2->cdr; if (n2) { - if (n2->car) { - dump_prefix(offset+2); - printf("rest:\n"); - parser_dump(mrb, n2->car, offset+3); - } - n2 = n2->cdr; - if (n2) { - if (n2->car) { - dump_prefix(offset+2); - printf("post:\n"); - dump_recur(mrb, n2->car, offset+3); - } - } + if (n2->car) { + dump_prefix(offset+2); + printf("rest:\n"); + parser_dump(mrb, n2->car, offset+3); + } + n2 = n2->cdr; + if (n2) { + if (n2->car) { + dump_prefix(offset+2); + printf("post:\n"); + dump_recur(mrb, n2->car, offset+3); + } + } } } tree = tree->cdr; @@ -5468,17 +5496,17 @@ parser_dump(mrb_state *mrb, node *tree, int offset) node *n2 = tree->car; if (n2 && (n2->car || n2->cdr)) { - dump_prefix(offset+1); - printf("local variables:\n"); - dump_prefix(offset+2); - while (n2) { - if (n2->car) { - if (n2 != tree->car) printf(", "); - printf("%s", mrb_sym2name(mrb, sym(n2->car))); - } - n2 = n2->cdr; - } - printf("\n"); + dump_prefix(offset+1); + printf("local variables:\n"); + dump_prefix(offset+2); + while (n2) { + if (n2->car) { + if (n2 != tree->car) printf(", "); + printf("%s", mrb_sym2name(mrb, sym(n2->car))); + } + n2 = n2->cdr; + } + printf("\n"); } } tree = tree->cdr; @@ -5499,9 +5527,9 @@ parser_dump(mrb_state *mrb, node *tree, int offset) printf("args:\n"); dump_recur(mrb, tree->car, offset+2); if (tree->cdr) { - dump_prefix(offset+1); - printf("block:\n"); - parser_dump(mrb, tree->cdr, offset+2); + dump_prefix(offset+1); + printf("block:\n"); + parser_dump(mrb, tree->cdr, offset+2); } } break; @@ -5572,31 +5600,31 @@ parser_dump(mrb_state *mrb, node *tree, int offset) node *n2 = tree->car; if (n2->car) { - dump_prefix(offset+2); - printf("pre:\n"); - dump_recur(mrb, n2->car, offset+3); + dump_prefix(offset+2); + printf("pre:\n"); + dump_recur(mrb, n2->car, offset+3); } n2 = n2->cdr; if (n2) { - if (n2->car) { - dump_prefix(offset+2); - printf("rest:\n"); - if (n2->car == (node*)-1) { - dump_prefix(offset+2); - printf("(empty)\n"); - } - else { - parser_dump(mrb, n2->car, offset+3); - } - } - n2 = n2->cdr; - if (n2) { - if (n2->car) { - dump_prefix(offset+2); - printf("post:\n"); - dump_recur(mrb, n2->car, offset+3); - } - } + if (n2->car) { + dump_prefix(offset+2); + printf("rest:\n"); + if (n2->car == (node*)-1) { + dump_prefix(offset+2); + printf("(empty)\n"); + } + else { + parser_dump(mrb, n2->car, offset+3); + } + } + n2 = n2->cdr; + if (n2) { + if (n2->car) { + dump_prefix(offset+2); + printf("post:\n"); + dump_recur(mrb, n2->car, offset+3); + } + } } } dump_prefix(offset+1); @@ -5623,9 +5651,9 @@ parser_dump(mrb_state *mrb, node *tree, int offset) printf("args:\n"); dump_recur(mrb, tree->car, offset+2); if (tree->cdr) { - dump_prefix(offset+1); - printf("block:\n"); - parser_dump(mrb, tree->cdr, offset+2); + dump_prefix(offset+1); + printf("block:\n"); + parser_dump(mrb, tree->cdr, offset+2); } } break; @@ -5731,6 +5759,15 @@ parser_dump(mrb_state *mrb, node *tree, int offset) dump_recur(mrb, tree, offset+1); break; + case NODE_XSTR: + printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr); + break; + + case NODE_DXSTR: + printf("NODE_DXSTR\n"); + dump_recur(mrb, tree, offset+1); + break; + case NODE_REGX: printf("NODE_REGX /%s/%s\n", (char*)tree->car, (char*)tree->cdr); break; @@ -5766,8 +5803,8 @@ parser_dump(mrb_state *mrb, node *tree, int offset) case NODE_ALIAS: printf("NODE_ALIAS %s %s:\n", - mrb_sym2name(mrb, sym(tree->car)), - mrb_sym2name(mrb, sym(tree->cdr))); + mrb_sym2name(mrb, sym(tree->car)), + mrb_sym2name(mrb, sym(tree->cdr))); break; case NODE_UNDEF: @@ -5775,8 +5812,8 @@ parser_dump(mrb_state *mrb, node *tree, int offset) { node *t = tree; while (t) { - printf(" %s", mrb_sym2name(mrb, sym(t->car))); - t = t->cdr; + printf(" %s", mrb_sym2name(mrb, sym(t->car))); + t = t->cdr; } } printf(":\n"); @@ -5844,17 +5881,17 @@ parser_dump(mrb_state *mrb, node *tree, int offset) node *n2 = tree->car; if (n2 && (n2->car || n2->cdr)) { - dump_prefix(offset+1); - printf("local variables:\n"); - dump_prefix(offset+2); - while (n2) { - if (n2->car) { - if (n2 != tree->car) printf(", "); - printf("%s", mrb_sym2name(mrb, sym(n2->car))); - } - n2 = n2->cdr; - } - printf("\n"); + dump_prefix(offset+1); + printf("local variables:\n"); + dump_prefix(offset+2); + while (n2) { + if (n2->car) { + if (n2 != tree->car) printf(", "); + printf("%s", mrb_sym2name(mrb, sym(n2->car))); + } + n2 = n2->cdr; + } + printf("\n"); } } tree = tree->cdr; @@ -5862,40 +5899,40 @@ parser_dump(mrb_state *mrb, node *tree, int offset) node *n = tree->car; if (n->car) { - dump_prefix(offset+1); - printf("mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); + dump_prefix(offset+1); + printf("mandatory args:\n"); + dump_recur(mrb, n->car, offset+2); } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("optional args:\n"); - { - node *n2 = n->car; - - while (n2) { - dump_prefix(offset+2); - printf("%s=", mrb_sym2name(mrb, sym(n2->car->car))); - parser_dump(mrb, n2->car->cdr, 0); - n2 = n2->cdr; - } - } + dump_prefix(offset+1); + printf("optional args:\n"); + { + node *n2 = n->car; + + while (n2) { + dump_prefix(offset+2); + printf("%s=", mrb_sym2name(mrb, sym(n2->car->car))); + parser_dump(mrb, n2->car->cdr, 0); + n2 = n2->cdr; + } + } } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car))); + dump_prefix(offset+1); + printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car))); } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("post mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); + dump_prefix(offset+1); + printf("post mandatory args:\n"); + dump_recur(mrb, n->car, offset+2); } n = n->cdr; if (n) { - dump_prefix(offset+1); - printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); + dump_prefix(offset+1); + printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); } } parser_dump(mrb, tree->cdr->car, offset+1); @@ -5912,40 +5949,40 @@ parser_dump(mrb_state *mrb, node *tree, int offset) node *n = tree->car; if (n->car) { - dump_prefix(offset+1); - printf("mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); + dump_prefix(offset+1); + printf("mandatory args:\n"); + dump_recur(mrb, n->car, offset+2); } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("optional args:\n"); - { - node *n2 = n->car; - - while (n2) { - dump_prefix(offset+2); - printf("%s=", mrb_sym2name(mrb, sym(n2->car->car))); - parser_dump(mrb, n2->car->cdr, 0); - n2 = n2->cdr; - } - } + dump_prefix(offset+1); + printf("optional args:\n"); + { + node *n2 = n->car; + + while (n2) { + dump_prefix(offset+2); + printf("%s=", mrb_sym2name(mrb, sym(n2->car->car))); + parser_dump(mrb, n2->car->cdr, 0); + n2 = n2->cdr; + } + } } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car))); + dump_prefix(offset+1); + printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car))); } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("post mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); + dump_prefix(offset+1); + printf("post mandatory args:\n"); + dump_recur(mrb, n->car, offset+2); } n = n->cdr; if (n) { - dump_prefix(offset+1); - printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); + dump_prefix(offset+1); + printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); } } tree = tree->cdr; diff --git a/src/print.c b/src/print.c index 9d8a751f7..5367781f5 100644 --- a/src/print.c +++ b/src/print.c @@ -34,29 +34,6 @@ mrb_p(mrb_state *mrb, mrb_value obj) #endif } -/* 15.3.1.2.9 */ -/* 15.3.1.3.34 */ -mrb_value -mrb_printstr(mrb_state *mrb, mrb_value self) -{ - mrb_value argv; - - mrb_get_args(mrb, "o", &argv); - printstr(mrb, argv); - - return argv; -} - -void -mrb_init_print(mrb_state *mrb) -{ - struct RClass *krn; - - krn = mrb->kernel_module; - - mrb_define_method(mrb, krn, "__printstr__", mrb_printstr, ARGS_REQ(1)); -} - void mrb_show_version(mrb_state *mrb) { diff --git a/src/range.c b/src/range.c index 59bf445aa..fb4d975e7 100644 --- a/src/range.c +++ b/src/range.c @@ -8,7 +8,6 @@ #include "mruby/class.h" #include "mruby/range.h" #include "mruby/string.h" -#include <string.h> #define RANGE_CLASS (mrb_class_obj_get(mrb, "Range")) @@ -92,7 +91,7 @@ mrb_range_excl(mrb_state *mrb, mrb_value range) { struct RRange *r = mrb_range_ptr(range); - return r->excl ? mrb_true_value() : mrb_false_value(); + return mrb_bool_value(r->excl); } static void @@ -153,25 +152,30 @@ mrb_range_eq(mrb_state *mrb, mrb_value range) struct RRange *rr; struct RRange *ro; mrb_value obj; + mrb_bool eq_p; mrb_get_args(mrb, "o", &obj); - if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value(); - - /* same class? */ - if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) - return mrb_false_value(); - - rr = mrb_range_ptr(range); - ro = mrb_range_ptr(obj); - if (!mrb_obj_equal(mrb, rr->edges->beg, ro->edges->beg)) - return mrb_false_value(); - if (!mrb_obj_equal(mrb, rr->edges->end, ro->edges->end)) - return mrb_false_value(); - if (rr->excl != ro->excl) - return mrb_false_value(); + if (mrb_obj_equal(mrb, range, obj)) { + eq_p = 1; + } + else if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) { /* same class? */ + eq_p = 0; + } + else { + rr = mrb_range_ptr(range); + ro = mrb_range_ptr(obj); + if (!mrb_obj_equal(mrb, rr->edges->beg, ro->edges->beg) || + !mrb_obj_equal(mrb, rr->edges->end, ro->edges->end) || + rr->excl != ro->excl) { + eq_p = 0; + } + else { + eq_p = 1; + } + } - return mrb_true_value(); + return mrb_bool_value(eq_p); } static int @@ -228,21 +232,17 @@ mrb_range_include(mrb_state *mrb, mrb_value range) mrb_value val; struct RRange *r = mrb_range_ptr(range); mrb_value beg, end; + mrb_bool include_p; mrb_get_args(mrb, "o", &val); beg = r->edges->beg; end = r->edges->end; - if (r_le(mrb, beg, val)) { - /* beg <= val */ - if (r->excl) { - if (r_gt(mrb, end, val)) return mrb_true_value(); /* end > val */ - } - else { - if (r_ge(mrb, end, val)) return mrb_true_value(); /* end >= val */ - } - } - return mrb_false_value(); + include_p = r_le(mrb, beg, val) && /* beg <= val */ + ((r->excl && r_gt(mrb, end, val)) || /* end > val */ + (r_ge(mrb, end, val))); /* end >= val */ + + return mrb_bool_value(include_p); } /* @@ -385,23 +385,34 @@ range_eql(mrb_state *mrb, mrb_value range) { mrb_value obj; struct RRange *r, *o; + mrb_bool eql_p; mrb_get_args(mrb, "o", &obj); - if (mrb_obj_equal(mrb, range, obj)) - return mrb_true_value(); - if (!mrb_obj_is_kind_of(mrb, obj, RANGE_CLASS)) - return mrb_false_value(); - - r = mrb_range_ptr(range); - if (mrb_type(obj) != MRB_TT_RANGE) return mrb_false_value(); - o = mrb_range_ptr(obj); - if (!mrb_eql(mrb, r->edges->beg, o->edges->beg)) - return mrb_false_value(); - if (!mrb_eql(mrb, r->edges->end, o->edges->end)) - return mrb_false_value(); - if (r->excl != o->excl) - return mrb_false_value(); - return mrb_true_value(); + if (mrb_obj_equal(mrb, range, obj)) { + eql_p = 1; + } + else if (!mrb_obj_is_kind_of(mrb, obj, RANGE_CLASS)) { + eql_p = 0; + } + else { + r = mrb_range_ptr(range); + if (mrb_type(obj) != MRB_TT_RANGE) { + eql_p = 0; + } + else { + o = mrb_range_ptr(obj); + if (!mrb_eql(mrb, r->edges->beg, o->edges->beg) || + !mrb_eql(mrb, r->edges->end, o->edges->end) || + (r->excl != o->excl)) { + eql_p = 0; + } + else { + eql_p = 1; + } + } + } + + return mrb_bool_value(eql_p); } /* 15.2.14.4.15(x) */ diff --git a/src/state.c b/src/state.c index b6805a4a4..7b5bd1002 100644 --- a/src/state.c +++ b/src/state.c @@ -7,6 +7,7 @@ #include "mruby.h" #include "mruby/irep.h" #include "mruby/variable.h" +#include <stdlib.h> #include <string.h> void mrb_init_heap(mrb_state*); @@ -53,6 +54,7 @@ mrb_alloca(mrb_state *mrb, size_t size) struct alloca_header *p; p = (struct alloca_header*) mrb_malloc(mrb, sizeof(struct alloca_header)+size); + if (p == NULL) return NULL; p->next = mrb->mems; mrb->mems = p; return (void*)p->buf; @@ -61,9 +63,12 @@ mrb_alloca(mrb_state *mrb, size_t size) static void mrb_alloca_free(mrb_state *mrb) { - struct alloca_header *p = mrb->mems; + struct alloca_header *p; struct alloca_header *tmp; + if (mrb == NULL) return; + p = mrb->mems; + while (p) { tmp = p; p = p->next; @@ -134,7 +139,7 @@ mrb_add_irep(mrb_state *mrb) mrb->irep_capa = max; } else if (mrb->irep_capa <= mrb->irep_len) { - int i; + size_t i; size_t old_capa = mrb->irep_capa; while (mrb->irep_capa <= mrb->irep_len) { mrb->irep_capa *= 2; diff --git a/src/string.c b/src/string.c index cfef5730c..09777ac69 100644 --- a/src/string.c +++ b/src/string.c @@ -6,6 +6,8 @@ #include "mruby.h" +#include <stddef.h> +#include <stdlib.h> #include <string.h> #include "mruby/string.h" #include "mruby/class.h" @@ -20,19 +22,13 @@ const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; static mrb_value str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2); -static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len); +static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len); #define RESIZE_CAPA(s,capacity) do {\ s->ptr = (char *)mrb_realloc(mrb, s->ptr, (capacity)+1);\ s->aux.capa = capacity;\ } while (0) -static const char* -_obj_classname(mrb_state *mrb, mrb_value obj) -{ - return mrb_class_name(mrb, mrb_obj_class(mrb, obj)); -} - void mrb_str_decref(mrb_state *mrb, mrb_shared_string *shared) { @@ -56,11 +52,11 @@ str_modify(mrb_state *mrb, struct RString *s) } else { char *ptr, *p; - long len; + mrb_int len; p = s->ptr; len = s->len; - ptr = (char *)mrb_malloc(mrb, len+1); + ptr = (char *)mrb_malloc(mrb, (size_t)len + 1); if (p) { memcpy(ptr, p, len); } @@ -104,21 +100,6 @@ str_mod_check(mrb_state *mrb, mrb_value str, char *p, mrb_int len) #define mrb_obj_alloc_string(mrb) ((struct RString*)mrb_obj_alloc((mrb), MRB_TT_STRING, (mrb)->string_class)) -static struct RString* -str_alloc(mrb_state *mrb, struct RClass *c) -{ - struct RString* s; - - s = mrb_obj_alloc_string(mrb); - - s->c = c; - s->ptr = 0; - s->len = 0; - s->aux.capa = 0; - - return s; -} - /* char offset to byte offset */ int mrb_str_offset(mrb_state *mrb, mrb_value str, int pos) @@ -129,8 +110,9 @@ mrb_str_offset(mrb_state *mrb, mrb_value str, int pos) static struct RString* str_new(mrb_state *mrb, const char *p, int len) { - struct RString *s = str_alloc(mrb, mrb->string_class); + struct RString *s; + s = mrb_obj_alloc_string(mrb); s->len = len; s->aux.capa = len; s->ptr = (char *)mrb_malloc(mrb, len+1); @@ -156,6 +138,10 @@ mrb_str_new_empty(mrb_state *mrb, mrb_value str) return mrb_obj_value(s); } +#ifndef MRB_STR_BUF_MIN_SIZE +# define MRB_STR_BUF_MIN_SIZE 128 +#endif + mrb_value mrb_str_buf_new(mrb_state *mrb, int capa) { @@ -163,8 +149,8 @@ mrb_str_buf_new(mrb_state *mrb, int capa) s = mrb_obj_alloc_string(mrb); - if (capa < STR_BUF_MIN_SIZE) { - capa = STR_BUF_MIN_SIZE; + if (capa < MRB_STR_BUF_MIN_SIZE) { + capa = MRB_STR_BUF_MIN_SIZE; } s->len = 0; s->aux.capa = capa; @@ -175,9 +161,11 @@ mrb_str_buf_new(mrb_state *mrb, int capa) } static void -str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len) +str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len) { - long capa, total, off = -1; + mrb_int capa; + mrb_int total; + ptrdiff_t off = -1; str_modify(mrb, s); if (ptr >= s->ptr && ptr <= s->ptr + s->len) { @@ -185,13 +173,13 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len) } if (len == 0) return; capa = s->aux.capa; - if (s->len >= INT_MAX - len) { + if (s->len >= MRB_INT_MAX - len) { mrb_raise(mrb, E_ARGUMENT_ERROR, "string sizes too big"); } total = s->len+len; if (capa <= total) { while (total > capa) { - if (capa + 1 >= INT_MAX / 2) { + if (capa + 1 >= MRB_INT_MAX / 2) { capa = (total + 4095) / 4096; break; } @@ -208,7 +196,7 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len) } mrb_value -mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, int len) +mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len) { if (len == 0) return str; str_buf_cat(mrb, mrb_str_ptr(str), ptr, len); @@ -216,7 +204,7 @@ mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, int len) } mrb_value -mrb_str_new(mrb_state *mrb, const char *p, int len) +mrb_str_new(mrb_state *mrb, const char *p, size_t len) { struct RString *s; @@ -224,17 +212,6 @@ mrb_str_new(mrb_state *mrb, const char *p, int len) return mrb_obj_value(s); } -mrb_value -mrb_str_new2(mrb_state *mrb, const char *ptr) -{ - struct RString *s; - if (!ptr) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "NULL pointer given"); - } - s = str_new(mrb, ptr, strlen(ptr)); - return mrb_obj_value(s); -} - /* * call-seq: (Caution! NULL string) * String.new(str="") => new_str @@ -246,11 +223,23 @@ mrb_value mrb_str_new_cstr(mrb_state *mrb, const char *p) { struct RString *s; - int len = strlen(p); + size_t len; + + if (p) { + len = strlen(p); + if ((mrb_int)len < 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "argument too big"); + } + } + else { + len = 0; + } s = mrb_obj_alloc_string(mrb); s->ptr = (char *)mrb_malloc(mrb, len+1); - memcpy(s->ptr, p, len); + if (p) { + memcpy(s->ptr, p, len); + } s->ptr[len] = 0; s->len = len; s->aux.capa = len; @@ -263,6 +252,10 @@ mrb_str_to_cstr(mrb_state *mrb, mrb_value str0) { mrb_value str; + if (!mrb_string_p(str0)) { + mrb_raise(mrb, E_TYPE_ERROR, "expected String"); + } + str = mrb_str_new(mrb, RSTRING_PTR(str0), RSTRING_LEN(str0)); if (strlen(RSTRING_PTR(str)) != RSTRING_LEN(str)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte"); @@ -302,7 +295,7 @@ mrb_str_literal(mrb_state *mrb, mrb_value str) struct RString *s, *orig; mrb_shared_string *shared; - s = str_alloc(mrb, mrb->string_class); + s = mrb_obj_alloc_string(mrb); orig = mrb_str_ptr(str); if (!(orig->flags & MRB_STR_SHARED)) { str_make_shared(mrb, mrb_str_ptr(str)); @@ -311,6 +304,7 @@ mrb_str_literal(mrb_state *mrb, mrb_value str) shared->refcnt++; s->ptr = shared->ptr; s->len = shared->len; + s->aux.capa = 0; s->aux.shared = shared; s->flags |= MRB_STR_SHARED; @@ -446,7 +440,7 @@ mrb_str_times(mrb_state *mrb, mrb_value self) if (times < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument"); } - if (times && INT_MAX/times < RSTRING_LEN(self)) { + if (times && MRB_INT_MAX / times < RSTRING_LEN(self)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "argument too big"); } @@ -532,10 +526,10 @@ mrb_str_cmp_m(mrb_state *mrb, mrb_value str1) mrb_get_args(mrb, "o", &str2); if (!mrb_string_p(str2)) { - if (!mrb_respond_to(mrb, str2, mrb_intern(mrb, "to_s"))) { + if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "to_s", 4))) { return mrb_nil_value(); } - else if (!mrb_respond_to(mrb, str2, mrb_intern(mrb, "<=>"))) { + else if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "<=>", 3))) { return mrb_nil_value(); } else { @@ -557,8 +551,9 @@ mrb_str_cmp_m(mrb_state *mrb, mrb_value str1) static int str_eql(mrb_state *mrb, const mrb_value str1, const mrb_value str2) { - const long len = RSTRING_LEN(str1); + const size_t len = RSTRING_LEN(str1); + /* assert(SIZE_MAX >= MRB_INT_MAX) */ if (len != RSTRING_LEN(str2)) return FALSE; if (memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), len) == 0) return TRUE; @@ -571,7 +566,7 @@ mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2) if (mrb_obj_equal(mrb, str1, str2)) return TRUE; if (!mrb_string_p(str2)) { if (mrb_nil_p(str2)) return FALSE; - if (!mrb_respond_to(mrb, str2, mrb_intern(mrb, "to_str"))) { + if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "to_str", 6))) { return FALSE; } str2 = mrb_funcall(mrb, str2, "to_str", 0); @@ -595,11 +590,12 @@ static mrb_value mrb_str_equal_m(mrb_state *mrb, mrb_value str1) { mrb_value str2; + mrb_bool equal_p; mrb_get_args(mrb, "o", &str2); - if (mrb_str_equal(mrb, str1, str2)) - return mrb_true_value(); - return mrb_false_value(); + equal_p = mrb_str_equal(mrb, str1, str2); + + return mrb_bool_value(equal_p); } /* ---------------------------------- */ mrb_value @@ -657,8 +653,8 @@ mrb_str_match(mrb_state *mrb, mrb_value self/* x */) return mrb_nil_value(); } -static inline long -mrb_memsearch_qs(const unsigned char *xs, long m, const unsigned char *ys, long n) +static inline mrb_int +mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n) { const unsigned char *x = xs, *xe = xs + m; const unsigned char *y = ys; @@ -677,8 +673,8 @@ mrb_memsearch_qs(const unsigned char *xs, long m, const unsigned char *ys, long return -1; } -static int -mrb_memsearch(const void *x0, int m, const void *y0, int n) +static mrb_int +mrb_memsearch(const void *x0, mrb_int m, const void *y0, mrb_int n) { const unsigned char *x = (const unsigned char *)x0, *y = (const unsigned char *)y0; @@ -705,7 +701,8 @@ mrb_str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset) { mrb_int pos; char *s, *sptr; - int len, slen; + mrb_int len, slen; + len = RSTRING_LEN(str); slen = RSTRING_LEN(sub); if (offset < 0) { @@ -739,9 +736,9 @@ mrb_str_dup(mrb_state *mrb, mrb_value str) static mrb_value mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx) { - long idx; + mrb_int idx; - if (!strcmp(_obj_classname(mrb, indx), REGEXP_CLASS)) { + if (!strcmp(mrb_obj_classname(mrb, indx), REGEXP_CLASS)) { mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); } switch (mrb_type(indx)) { @@ -920,7 +917,8 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str) mrb_value rs; mrb_int newline; char *p, *pp; - long len, rslen; + mrb_int rslen; + mrb_int len; struct RString *s = mrb_str_ptr(str); str_modify(mrb, s); @@ -1131,9 +1129,7 @@ mrb_str_empty_p(mrb_state *mrb, mrb_value self) { struct RString *s = mrb_str_ptr(self); - if (s->len == 0) - return mrb_true_value(); - return mrb_false_value(); + return mrb_bool_value(s->len == 0); } /* 15.2.10.5.17 */ @@ -1147,17 +1143,16 @@ static mrb_value mrb_str_eql(mrb_state *mrb, mrb_value self) { mrb_value str2; + mrb_bool eql_p; mrb_get_args(mrb, "o", &str2); - if (mrb_type(str2) != MRB_TT_STRING) - return mrb_false_value(); - if (str_eql(mrb, self, str2)) - return mrb_true_value(); - return mrb_false_value(); + eql_p = (mrb_type(str2) == MRB_TT_STRING) && str_eql(mrb, self, str2); + + return mrb_bool_value(eql_p); } static mrb_value -mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len) +mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) { struct RString *orig, *s; mrb_shared_string *shared; @@ -1176,7 +1171,7 @@ mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len) } mrb_value -mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, int len) +mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) { mrb_value str2; @@ -1267,7 +1262,7 @@ mrb_str_hash(mrb_state *mrb, mrb_value str) { /* 1-8-7 */ struct RString *s = mrb_str_ptr(str); - long len = s->len; + mrb_int len = s->len; char *p = s->ptr; mrb_int key = 0; @@ -1311,18 +1306,20 @@ mrb_str_include(mrb_state *mrb, mrb_value self) { mrb_int i; mrb_value str2; + mrb_bool include_p; mrb_get_args(mrb, "o", &str2); if (mrb_type(str2) == MRB_TT_FIXNUM) { - if (memchr(RSTRING_PTR(self), mrb_fixnum(str2), RSTRING_LEN(self))) - return mrb_true_value(); - return mrb_false_value(); + include_p = memchr(RSTRING_PTR(self), mrb_fixnum(str2), RSTRING_LEN(self)); + } + else { + mrb_string_value(mrb, &str2); + i = mrb_str_index(mrb, self, str2, 0); + + include_p = (i != -1); } - mrb_string_value(mrb, &str2); - i = mrb_str_index(mrb, self, str2, 0); - if (i == -1) return mrb_false_value(); - return mrb_true_value(); + return mrb_bool_value(include_p); } /* 15.2.10.5.22 */ @@ -1381,7 +1378,7 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str) switch (mrb_type(sub)) { case MRB_TT_FIXNUM: { int c = mrb_fixnum(sub); - long len = RSTRING_LEN(str); + mrb_int len = RSTRING_LEN(str); unsigned char *p = (unsigned char*)RSTRING_PTR(str); for (;pos<len;pos++) { @@ -1396,7 +1393,7 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str) tmp = mrb_check_string_type(mrb, sub); if (mrb_nil_p(tmp)) { mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %s given", - _obj_classname(mrb, sub)); + mrb_obj_classname(mrb, sub)); } sub = tmp; } @@ -1404,10 +1401,10 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str) case MRB_TT_STRING: pos = mrb_str_index(mrb, str, sub, pos); break; - } + } - if (pos == -1) return mrb_nil_value(); - return mrb_fixnum_value(pos); + if (pos == -1) return mrb_nil_value(); + return mrb_fixnum_value(pos); } #define STR_REPLACE_SHARED_MIN 10 @@ -1532,6 +1529,36 @@ mrb_obj_as_string(mrb_state *mrb, mrb_value obj) } mrb_value +mrb_ptr_to_str(mrb_state *mrb, void *p) +{ + struct RString *p_str; + char *p1; + char *p2; + intptr_t n = (intptr_t)p; + + p_str = str_new(mrb, NULL, 2 + sizeof(uintptr_t) * CHAR_BIT / 4); + p1 = p_str->ptr; + *p1++ = '0'; + *p1++ = 'x'; + p2 = p1; + + do { + *p2++ = mrb_digitmap[n % 16]; + n /= 16; + } while (n > 0); + *p2 = '\0'; + p_str->len = (mrb_int)(p2 - p_str->ptr); + + while (p1 < p2) { + const char c = *p1; + *p1++ = *--p2; + *p2 = c; + } + + return mrb_obj_value(p_str); +} + +mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str) { return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str"); @@ -1637,7 +1664,7 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos) char *s, *sbeg, *t; struct RString *ps = mrb_str_ptr(str); struct RString *psub = mrb_str_ptr(sub); - long len = psub->len; + mrb_int len = psub->len; /* substring longer than string */ if (ps->len < len) return -1; @@ -1661,15 +1688,6 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos) } } -#ifdef INCLUDE_ENCODING -/* byte offset to char offset */ -int -mrb_str_sublen(mrb_state *mrb, mrb_value str, long pos) -{ - return pos; -} -#endif //INCLUDE_ENCODING - /* 15.2.10.5.31 */ /* * call-seq: @@ -1728,7 +1746,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str) switch (mrb_type(sub)) { case MRB_TT_FIXNUM: { int c = mrb_fixnum(sub); - long len = RSTRING_LEN(str); + mrb_int len = RSTRING_LEN(str); unsigned char *p = (unsigned char*)RSTRING_PTR(str); for (pos=len;pos>=0;pos--) { @@ -1865,7 +1883,9 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) int argc; mrb_value spat = mrb_nil_value(); enum {awk, string, regexp} split_type = string; - long beg, end, i = 0, lim_p; + long i = 0, lim_p; + mrb_int beg; + mrb_int end; mrb_int lim = 0; mrb_value result, tmp; @@ -1934,7 +1954,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) char *ptr = RSTRING_PTR(str); char *temp = ptr; char *eptr = RSTRING_END(str); - long slen = RSTRING_LEN(spat); + mrb_int slen = RSTRING_LEN(spat); if (slen == 0) { int ai = mrb_gc_arena_save(mrb); @@ -1972,7 +1992,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) mrb_ary_push(mrb, result, tmp); } if (!lim_p && lim == 0) { - long len; + mrb_int len; while ((len = RARRAY_LEN(result)) > 0 && (tmp = RARRAY_PTR(result)[len-1], RSTRING_LEN(tmp) == 0)) mrb_ary_pop(mrb, result); @@ -2054,7 +2074,8 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) char *end; char sign = 1; int c; - unsigned long val; + unsigned long n; + mrb_int val; #undef ISDIGIT #define ISDIGIT(c) ('0' <= (c) && (c) <= '9') @@ -2158,19 +2179,18 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) return mrb_fixnum_value(0); } - val = strtoul((char*)str, &end, base); - + n = strtoul((char*)str, &end, base); + if (n > MRB_INT_MAX) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%s) too big for integer", str); + } + val = n; if (badcheck) { if (end == str) goto bad; /* no number */ while (*end && ISSPACE(*end)) end++; if (*end) goto bad; /* trailing garbage */ } - if (sign) return mrb_fixnum_value(val); - else { - long result = -(long)val; - return mrb_fixnum_value(result); - } + return mrb_fixnum_value(sign ? val : -val); bad: mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for number(%s)", str); /* not reached */ @@ -2440,7 +2460,7 @@ mrb_str_upcase(mrb_state *mrb, mrb_value self) mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str) { - long len; + mrb_int len; const char *p, *pend; char *q; struct RString *result; @@ -2542,7 +2562,7 @@ mrb_str_dump(mrb_state *mrb, mrb_value str) } mrb_value -mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, long len) +mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, mrb_int len) { if (len < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "negative string size (or size too big)"); @@ -2552,7 +2572,7 @@ mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, long len) } mrb_value -mrb_str_cat2(mrb_state *mrb, mrb_value str, const char *ptr) +mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr) { return mrb_str_cat(mrb, str, ptr, strlen(ptr)); } diff --git a/src/symbol.c b/src/symbol.c index 72a5bea6b..243cb4b5d 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -10,10 +10,11 @@ #include "mruby/string.h" #include <ctype.h> +#include <limits.h> /* ------------------------------------------------------ */ typedef struct symbol_name { - int len; + size_t len; const char *name; } symbol_name; @@ -35,7 +36,7 @@ KHASH_DECLARE(n2s, symbol_name, mrb_sym, 1) KHASH_DEFINE (n2s, symbol_name, mrb_sym, 1, sym_hash_func, sym_hash_equal) /* ------------------------------------------------------ */ mrb_sym -mrb_intern2(mrb_state *mrb, const char *name, int len) +mrb_intern2(mrb_state *mrb, const char *name, size_t len) { khash_t(n2s) *h = mrb->name2sym; symbol_name sname; @@ -61,7 +62,7 @@ mrb_intern2(mrb_state *mrb, const char *name, int len) } mrb_sym -mrb_intern(mrb_state *mrb, const char *name) +mrb_intern_cstr(mrb_state *mrb, const char *name) { return mrb_intern2(mrb, name, strlen(name)); } @@ -72,8 +73,9 @@ mrb_intern_str(mrb_state *mrb, mrb_value str) return mrb_intern2(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); } +/* lenp must be a pointer to a size_t variable */ const char* -mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, int *lenp) +mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, size_t *lenp) { khash_t(n2s) *h = mrb->name2sym; khiter_t k; @@ -156,10 +158,12 @@ static mrb_value sym_equal(mrb_state *mrb, mrb_value sym1) { mrb_value sym2; + mrb_bool equal_p; mrb_get_args(mrb, "o", &sym2); - if (mrb_obj_equal(mrb, sym1, sym2)) return mrb_true_value(); - return mrb_false_value(); + equal_p = mrb_obj_equal(mrb, sym1, sym2); + + return mrb_bool_value(equal_p); } /* 15.2.11.3.2 */ @@ -178,7 +182,7 @@ mrb_sym_to_s(mrb_state *mrb, mrb_value sym) { mrb_sym id = mrb_symbol(sym); const char *p; - int len; + size_t len; p = mrb_sym2name_len(mrb, id, &len); return mrb_str_new(mrb, p, len); @@ -198,7 +202,7 @@ mrb_sym_to_s(mrb_state *mrb, mrb_value sym) static mrb_value sym_to_sym(mrb_state *mrb, mrb_value sym) { - return sym; + return sym; } /* 15.2.11.3.5(x) */ @@ -222,106 +226,107 @@ sym_to_sym(mrb_state *mrb, mrb_value sym) static int is_special_global_name(const char* m) { - switch (*m) { - case '~': case '*': case '$': case '?': case '!': case '@': - case '/': case '\\': case ';': case ',': case '.': case '=': - case ':': case '<': case '>': case '\"': - case '&': case '`': case '\'': case '+': - case '0': - ++m; - break; - case '-': - ++m; - if (is_identchar(*m)) m += 1; - break; - default: - if (!ISDIGIT(*m)) return FALSE; - do ++m; while (ISDIGIT(*m)); - } - return !*m; + switch (*m) { + case '~': case '*': case '$': case '?': case '!': case '@': + case '/': case '\\': case ';': case ',': case '.': case '=': + case ':': case '<': case '>': case '\"': + case '&': case '`': case '\'': case '+': + case '0': + ++m; + break; + case '-': + ++m; + if (is_identchar(*m)) m += 1; + break; + default: + if (!ISDIGIT(*m)) return FALSE; + do ++m; while (ISDIGIT(*m)); + break; + } + return !*m; } static int symname_p(const char *name) { - const char *m = name; - int localid = FALSE; - - if (!m) return FALSE; - switch (*m) { - case '\0': - return FALSE; - - case '$': - if (is_special_global_name(++m)) return TRUE; - goto id; - - case '@': - if (*++m == '@') ++m; - goto id; - - case '<': - switch (*++m) { - case '<': ++m; break; - case '=': if (*++m == '>') ++m; break; - default: break; - } - break; + const char *m = name; + int localid = FALSE; + + if (!m) return FALSE; + switch (*m) { + case '\0': + return FALSE; + + case '$': + if (is_special_global_name(++m)) return TRUE; + goto id; + + case '@': + if (*++m == '@') ++m; + goto id; + + case '<': + switch (*++m) { + case '<': ++m; break; + case '=': if (*++m == '>') ++m; break; + default: break; + } + break; - case '>': - switch (*++m) { - case '>': case '=': ++m; break; - default: break; - } - break; + case '>': + switch (*++m) { + case '>': case '=': ++m; break; + default: break; + } + break; - case '=': - switch (*++m) { - case '~': ++m; break; - case '=': if (*++m == '=') ++m; break; - default: return FALSE; - } - break; - - case '*': - if (*++m == '*') ++m; - break; - case '!': - if (*++m == '=') ++m; - break; - case '+': case '-': - if (*++m == '@') ++m; - break; - case '|': - if (*++m == '|') ++m; - break; - case '&': - if (*++m == '&') ++m; - break; - - case '^': case '/': case '%': case '~': case '`': - ++m; - break; - - case '[': - if (*++m != ']') return FALSE; - if (*++m == '=') ++m; - break; - - default: - localid = !ISUPPER(*m); + case '=': + switch (*++m) { + case '~': ++m; break; + case '=': if (*++m == '=') ++m; break; + default: return FALSE; + } + break; + + case '*': + if (*++m == '*') ++m; + break; + case '!': + if (*++m == '=') ++m; + break; + case '+': case '-': + if (*++m == '@') ++m; + break; + case '|': + if (*++m == '|') ++m; + break; + case '&': + if (*++m == '&') ++m; + break; + + case '^': case '/': case '%': case '~': case '`': + ++m; + break; + + case '[': + if (*++m != ']') return FALSE; + if (*++m == '=') ++m; + break; + + default: + localid = !ISUPPER(*m); id: - if (*m != '_' && !ISALPHA(*m)) return FALSE; - while (is_identchar(*m)) m += 1; - if (localid) { - switch (*m) { - case '!': case '?': case '=': ++m; - default: break; + if (*m != '_' && !ISALPHA(*m)) return FALSE; + while (is_identchar(*m)) m += 1; + if (localid) { + switch (*m) { + case '!': case '?': case '=': ++m; + default: break; } } - break; - } - return *m ? FALSE : TRUE; + break; + } + return *m ? FALSE : TRUE; } static mrb_value @@ -329,7 +334,7 @@ sym_inspect(mrb_state *mrb, mrb_value sym) { mrb_value str; const char *name; - int len; + size_t len; mrb_sym id = mrb_symbol(sym); name = mrb_sym2name_len(mrb, id, &len); @@ -346,7 +351,7 @@ sym_inspect(mrb_state *mrb, mrb_value sym) const char* mrb_sym2name(mrb_state *mrb, mrb_sym sym) { - int len; + size_t len; const char *name = mrb_sym2name_len(mrb, sym, &len); if (!name) return NULL; @@ -374,7 +379,8 @@ sym_cmp(mrb_state *mrb, mrb_value s1) if (sym1 == sym2) return mrb_fixnum_value(0); else { const char *p1, *p2; - int len, len1, len2, retval; + int retval; + size_t len, len1, len2; p1 = mrb_sym2name_len(mrb, sym1, &len1); p2 = mrb_sym2name_len(mrb, sym2, &len2); diff --git a/src/value_array.h b/src/value_array.h new file mode 100644 index 000000000..cabd2426d --- /dev/null +++ b/src/value_array.h @@ -0,0 +1,27 @@ +#ifndef MRB_VALUE_ARRAY_H__ +#define MRB_VALUE_ARRAY_H__ + +#include "mruby.h" + +static inline void +value_move(mrb_value *s1, const mrb_value *s2, size_t n) +{ + if (s1 > s2 && s1 < s2 + n) + { + s1 += n; + s2 += n; + while (n-- > 0) { + *--s1 = *--s2; + } + } + else if (s1 != s2) { + while (n-- > 0) { + *s1++ = *s2++; + } + } + else { + /* nothing to do. */ + } +} + +#endif /* MRB_VALUE_ARRAY_H__ */ diff --git a/src/variable.c b/src/variable.c index 8715505c3..c191b2be2 100644 --- a/src/variable.c +++ b/src/variable.c @@ -28,8 +28,8 @@ typedef struct segment { typedef struct iv_tbl { segment *rootseg; - int size; - int last_len; + size_t size; + size_t last_len; } iv_tbl; static iv_tbl* @@ -52,8 +52,8 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) segment *seg = t->rootseg; segment *prev = NULL; segment *matched_seg = NULL; - int matched_idx = 0; - int i; + size_t matched_idx = 0; + size_t i; while (seg) { for (i=0; i<MRB_SEGMENT_SIZE; i++) { @@ -102,11 +102,11 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) return; } -static int +static mrb_bool iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) { segment *seg; - int i; + size_t i; seg = t->rootseg; while (seg) { @@ -126,11 +126,11 @@ iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) return FALSE; } -static int +static mrb_bool iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) { segment *seg; - int i; + size_t i; seg = t->rootseg; while (seg) { @@ -152,11 +152,12 @@ iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) return FALSE; } -static int +static mrb_bool iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) { segment *seg; - int i, n; + size_t i; + int n; seg = t->rootseg; while (seg) { @@ -181,11 +182,11 @@ iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) return TRUE; } -static int +static size_t iv_size(mrb_state *mrb, iv_tbl *t) { segment *seg; - int size = 0; + size_t size = 0; if (!t) return 0; if (t->size > 0) return t->size; @@ -208,7 +209,7 @@ iv_copy(mrb_state *mrb, iv_tbl *t) segment *seg; iv_tbl *t2; - int i; + size_t i; seg = t->rootseg; t2 = iv_new(mrb); @@ -273,7 +274,7 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) kh_value(h, k) = val; } -static int +static mrb_bool iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) { khash_t(iv) *h = &t->h; @@ -287,7 +288,7 @@ iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) return FALSE; } -static int +static mrb_bool iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) { khash_t(iv) *h = &t->h; @@ -305,7 +306,7 @@ iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) return FALSE; } -static int +static mrb_bool iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) { khash_t(iv) *h = &t->h; @@ -326,7 +327,7 @@ iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) return TRUE; } -static int +static size_t iv_size(mrb_state *mrb, iv_tbl *t) { khash_t(iv) *h = &t->h; @@ -408,7 +409,7 @@ mrb_vm_special_set(mrb_state *mrb, mrb_sym i, mrb_value v) { } -static int +static mrb_bool obj_iv_p(mrb_value obj) { switch (mrb_type(obj)) { @@ -481,7 +482,7 @@ mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v) } } -int +mrb_bool mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym) { iv_tbl *t; @@ -493,7 +494,7 @@ mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym) return FALSE; } -int +mrb_bool mrb_iv_defined(mrb_state *mrb, mrb_value obj, mrb_sym sym) { if (!obj_iv_p(obj)) return FALSE; @@ -520,15 +521,15 @@ inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) { mrb_value str = *(mrb_value*)p; const char *s; - int len; + size_t len; /* need not to show internal data */ if (RSTRING_PTR(str)[0] == '-') { /* first element */ RSTRING_PTR(str)[0] = '#'; - mrb_str_cat2(mrb, str, " "); + mrb_str_cat(mrb, str, " ", 1); } else { - mrb_str_cat2(mrb, str, ", "); + mrb_str_cat(mrb, str, ", ", 2); } s = mrb_sym2name_len(mrb, sym, &len); mrb_str_cat(mrb, str, s, len); @@ -541,13 +542,19 @@ mrb_value mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj) { iv_tbl *t = obj->iv; - int len = iv_size(mrb, t); + size_t len = iv_size(mrb, t); if (len > 0) { const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj)); - mrb_value str = mrb_sprintf(mrb, "-<%s:%p", cn, (void*)obj); + mrb_value str = mrb_str_buf_new(mrb, 30); + + mrb_str_buf_cat(mrb, str, "-<", 2); + mrb_str_cat2(mrb, str, cn); + mrb_str_cat(mrb, str, ":", 1); + mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, obj)); iv_foreach(mrb, t, inspect_i, &str); + mrb_str_cat(mrb, str, ">", 1); return str; } return mrb_any_to_s(mrb, mrb_obj_value(obj)); @@ -586,7 +593,7 @@ iv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) { mrb_value ary; const char* s; - int len; + size_t len; ary = *(mrb_value*)p; s = mrb_sym2name_len(mrb, sym, &len); @@ -630,7 +637,7 @@ cv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) { mrb_value ary; const char* s; - int len; + size_t len; ary = *(mrb_value*)p; s = mrb_sym2name_len(mrb, sym, &len); @@ -727,7 +734,7 @@ mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v) mrb_mod_cv_set(mrb, mrb_class_ptr(mod), sym, v); } -int +mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym) { while (c) { @@ -741,7 +748,7 @@ mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym) return FALSE; } -int +mrb_bool mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym) { return mrb_mod_cv_defined(mrb, mrb_class_ptr(mod), sym); @@ -783,7 +790,7 @@ mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) iv_put(mrb, c->iv, sym, v); } -int +mrb_bool mrb_const_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym) { struct RClass *m = mrb_class_ptr(mod); @@ -813,7 +820,7 @@ const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym) struct RClass *c = base; mrb_value v; iv_tbl *t; - int retry = 0; + mrb_bool retry = 0; mrb_sym cm; L_RETRY: @@ -831,7 +838,7 @@ L_RETRY: goto L_RETRY; } c = base; - cm = mrb_intern(mrb, "const_missing"); + cm = mrb_intern2(mrb, "const_missing", 13); while (c) { if (mrb_respond_to(mrb, mrb_obj_value(c), cm)) { mrb_value name = mrb_symbol_value(sym); @@ -964,7 +971,7 @@ mrb_f_global_variables(mrb_state *mrb, mrb_value self) { iv_tbl *t = mrb->globals; mrb_value ary = mrb_ary_new(mrb); - int i; + size_t i; char buf[3]; if (t) { @@ -979,11 +986,11 @@ mrb_f_global_variables(mrb_state *mrb, mrb_value self) return ary; } -static int -mrb_const_defined_0(mrb_state *mrb, struct RClass *klass, mrb_sym id, int exclude, int recurse) +static mrb_bool +mrb_const_defined_0(mrb_state *mrb, struct RClass *klass, mrb_sym id, mrb_bool exclude, mrb_bool recurse) { struct RClass * tmp; - int mod_retry = 0; + mrb_bool mod_retry = 0; tmp = klass; retry: @@ -1046,7 +1053,7 @@ mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer) { mrb_value name; - name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classid__")); + name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern2(mrb, "__classid__", 11)); if (mrb_nil_p(name)) { if (!outer) return 0; @@ -16,6 +16,7 @@ #include "mruby/class.h" #include "mruby/numeric.h" #include "error.h" +#include "value_array.h" #include <string.h> #include <setjmp.h> @@ -45,7 +46,7 @@ /* Maximum stack depth. Should be set lower on memory constrained systems. The value below allows about 60000 recursive calls in the simplest case. */ #ifndef MRB_STACK_MAX -#define MRB_STACK_MAX ((1<<18) - MRB_STACK_GROWTH) +#define MRB_STACK_MAX (0x40000 - MRB_STACK_GROWTH) #endif #ifdef VM_DEBUG @@ -55,12 +56,20 @@ The value below allows about 60000 recursive calls in the simplest case. */ #endif static inline void -stack_copy(mrb_value *dst, const mrb_value *src, size_t size) +stack_clear(mrb_value *from, size_t count) { - size_t i; + const mrb_value mrb_value_zero = { { 0 } }; + + while(count-- > 0) { + *from++ = mrb_value_zero; + } +} - for (i = 0; i < size; i++) { - dst[i] = src[i]; +static inline void +stack_copy(mrb_value *dst, const mrb_value *src, size_t size) +{ + while (size-- > 0) { + *dst++ = *src++; } } @@ -79,7 +88,7 @@ stack_init(mrb_state *mrb) mrb->ci->target_class = mrb->object_class; } -static void +static inline void envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase) { mrb_callinfo *ci = mrb->cibase; @@ -87,7 +96,7 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase) while (ci <= mrb->ci) { struct REnv *e = ci->env; if (e && e->cioff >= 0) { - int off = e->stack - oldbase; + ptrdiff_t off = e->stack - oldbase; e->stack = newbase + off; } @@ -100,8 +109,9 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase) static void stack_extend(mrb_state *mrb, int room, int keep) { - int size, off; if (mrb->stack + room >= mrb->stend) { + int size, off; + mrb_value *oldbase = mrb->stbase; size = mrb->stend - mrb->stbase; @@ -130,26 +140,18 @@ stack_extend(mrb_state *mrb, int room, int keep) } if (room > keep) { - int i; - for (i=keep; i<room; i++) { #ifndef MRB_NAN_BOXING - static const mrb_value mrb_value_zero = { { 0 } }; - mrb->stack[i] = mrb_value_zero; + stack_clear(&(mrb->stack[keep]), room - keep); #else + int i; + for (i=keep; i<room; i++) { SET_NIL_VALUE(mrb->stack[i]); -#endif } +#endif } } -int -mrb_checkstack(mrb_state *mrb, int size) -{ - stack_extend(mrb, size+1, 1); - return 0; -} - -struct REnv* +static inline struct REnv* uvenv(mrb_state *mrb, int up) { struct REnv *e = mrb->ci->proc->env; @@ -161,25 +163,6 @@ uvenv(mrb_state *mrb, int up) return e; } -static mrb_value -uvget(mrb_state *mrb, int up, int idx) -{ - struct REnv *e = uvenv(mrb, up); - - if (!e) return mrb_nil_value(); - return e->stack[idx]; -} - -static void -uvset(mrb_state *mrb, int up, int idx, mrb_value v) -{ - struct REnv *e = uvenv(mrb, up); - - if (!e) return; - e->stack[idx] = v; - mrb_write_barrier(mrb, (struct RBasic*)e); -} - static inline int is_strict(mrb_state *mrb, struct REnv *e) { @@ -192,7 +175,7 @@ is_strict(mrb_state *mrb, struct REnv *e) return 0; } -struct REnv* +inline struct REnv* top_env(mrb_state *mrb, struct RProc *proc) { struct REnv *e = proc->env; @@ -231,7 +214,7 @@ cipop(mrb_state *mrb) { if (mrb->ci->env) { struct REnv *e = mrb->ci->env; - int len = (int)e->flags; + size_t len = (size_t)e->flags; mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len); e->cioff = -1; @@ -273,14 +256,13 @@ mrb_value mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) { mrb_sym mid = mrb_intern(mrb, name); - va_list ap; - int i; if (argc == 0) { return mrb_funcall_argv(mrb, self, mid, 0, 0); } else if (argc == 1) { mrb_value v; + va_list ap; va_start(ap, argc); v = va_arg(ap, mrb_value); @@ -289,6 +271,8 @@ mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) } else { mrb_value argv[MRB_FUNCALL_ARGC_MAX]; + va_list ap; + int i; if (argc > MRB_FUNCALL_ARGC_MAX) { mrb_raisef(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%d)", MRB_FUNCALL_ARGC_MAX); @@ -306,11 +290,6 @@ mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) mrb_value mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mrb_value *argv, mrb_value blk) { - struct RProc *p; - struct RClass *c; - mrb_sym undef = 0; - mrb_callinfo *ci; - int n; mrb_value val; if (!mrb->jmp) { @@ -323,66 +302,74 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr cipop(mrb); } mrb->jmp = 0; - return mrb_nil_value(); + val = mrb_nil_value(); + } + else { + mrb->jmp = &c_jmp; + /* recursive call */ + val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk); + mrb->jmp = 0; } - mrb->jmp = &c_jmp; - /* recursive call */ - val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk); - mrb->jmp = 0; - return val; - } - - if (!mrb->stack) { - stack_init(mrb); - } - n = mrb->ci->nregs; - if (argc < 0) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%d)", argc); - } - c = mrb_class(mrb, self); - p = mrb_method_search_vm(mrb, &c, mid); - if (!p) { - undef = mid; - mid = mrb_intern(mrb, "method_missing"); - p = mrb_method_search_vm(mrb, &c, mid); - n++; argc++; - } - ci = cipush(mrb); - ci->mid = mid; - ci->proc = p; - ci->stackidx = mrb->stack - mrb->stbase; - ci->argc = argc; - ci->target_class = p->target_class; - if (MRB_PROC_CFUNC_P(p)) { - ci->nregs = argc + 2; } else { - ci->nregs = p->body.irep->nregs + 2; - } - ci->acc = -1; - mrb->stack = mrb->stack + n; + struct RProc *p; + struct RClass *c; + mrb_sym undef = 0; + mrb_callinfo *ci; + int n; - stack_extend(mrb, ci->nregs, 0); - mrb->stack[0] = self; - if (undef) { - mrb->stack[1] = mrb_symbol_value(undef); - stack_copy(mrb->stack+2, argv, argc-1); - } - else if (argc > 0) { - stack_copy(mrb->stack+1, argv, argc); - } - mrb->stack[argc+1] = blk; - - if (MRB_PROC_CFUNC_P(p)) { - int ai = mrb_gc_arena_save(mrb); - val = p->body.func(mrb, self); - mrb_gc_arena_restore(mrb, ai); - mrb_gc_protect(mrb, val); - mrb->stack = mrb->stbase + mrb->ci->stackidx; - cipop(mrb); - } - else { - val = mrb_run(mrb, p, self); + if (!mrb->stack) { + stack_init(mrb); + } + n = mrb->ci->nregs; + if (argc < 0) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%d)", argc); + } + c = mrb_class(mrb, self); + p = mrb_method_search_vm(mrb, &c, mid); + if (!p) { + undef = mid; + mid = mrb_intern2(mrb, "method_missing", 14); + p = mrb_method_search_vm(mrb, &c, mid); + n++; argc++; + } + ci = cipush(mrb); + ci->mid = mid; + ci->proc = p; + ci->stackidx = mrb->stack - mrb->stbase; + ci->argc = argc; + ci->target_class = p->target_class; + if (MRB_PROC_CFUNC_P(p)) { + ci->nregs = argc + 2; + } + else { + ci->nregs = p->body.irep->nregs + 2; + } + ci->acc = -1; + mrb->stack = mrb->stack + n; + + stack_extend(mrb, ci->nregs, 0); + mrb->stack[0] = self; + if (undef) { + mrb->stack[1] = mrb_symbol_value(undef); + stack_copy(mrb->stack+2, argv, argc-1); + } + else if (argc > 0) { + stack_copy(mrb->stack+1, argv, argc); + } + mrb->stack[argc+1] = blk; + + if (MRB_PROC_CFUNC_P(p)) { + int ai = mrb_gc_arena_save(mrb); + val = p->body.func(mrb, self); + mrb_gc_arena_restore(mrb, ai); + mrb_gc_protect(mrb, val); + mrb->stack = mrb->stbase + mrb->ci->stackidx; + cipop(mrb); + } + else { + val = mrb_run(mrb, p, self); + } } return val; } @@ -471,14 +458,14 @@ localjump_error(mrb_state *mrb, localjump_error_kind kind) mrb_str_buf_cat(mrb, msg, lead, sizeof(lead) - 1); mrb_str_buf_cat(mrb, msg, kind_str[kind], kind_str_len[kind]); exc = mrb_exc_new3(mrb, E_LOCALJUMP_ERROR, msg); - mrb->exc = (struct RObject*)mrb_object(exc); + mrb->exc = mrb_obj_ptr(exc); } static void argnum_error(mrb_state *mrb, int num) { char buf[256]; - int len; + size_t len; mrb_value exc; if (mrb->ci->mid) { @@ -491,7 +478,7 @@ argnum_error(mrb_state *mrb, int num) mrb->ci->argc, num); } exc = mrb_exc_new(mrb, E_ARGUMENT_ERROR, buf, len); - mrb->exc = (struct RObject*)mrb_object(exc); + mrb->exc = mrb_obj_ptr(exc); } #ifdef ENABLE_DEBUG @@ -709,14 +696,34 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) CASE(OP_GETUPVAR) { /* A B C R(A) := uvget(B,C) */ + mrb_value *regs_a = regs + GETARG_A(i); + int up = GETARG_C(i); + + struct REnv *e = uvenv(mrb, up); - regs[GETARG_A(i)] = uvget(mrb, GETARG_C(i), GETARG_B(i)); + if (!e) { + *regs_a = mrb_nil_value(); + } + else { + int idx = GETARG_B(i); + *regs_a = e->stack[idx]; + } NEXT; } CASE(OP_SETUPVAR) { /* A B C uvset(B,C,R(A)) */ - uvset(mrb, GETARG_C(i), GETARG_B(i), regs[GETARG_A(i)]); + /* A B C R(A) := uvget(B,C) */ + int up = GETARG_C(i); + + struct REnv *e = uvenv(mrb, up); + + if (e) { + mrb_value *regs_a = regs + GETARG_A(i); + int idx = GETARG_B(i); + e->stack[idx] = *regs_a; + mrb_write_barrier(mrb, (struct RBasic*)e); + } NEXT; } @@ -773,7 +780,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) CASE(OP_RAISE) { /* A raise(R(A)) */ - mrb->exc = (struct RObject*)mrb_object(regs[GETARG_A(i)]); + mrb->exc = mrb_obj_ptr(regs[GETARG_A(i)]); goto L_RAISE; } @@ -842,15 +849,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (!m) { mrb_value sym = mrb_symbol_value(mid); - mid = mrb_intern(mrb, "method_missing"); + mid = mrb_intern2(mrb, "method_missing", 14); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], sym); } else { - memmove(regs+a+2, regs+a+1, sizeof(mrb_value)*(n+1)); + value_move(regs+a+2, regs+a+1, ++n); regs[a+1] = sym; - n++; } } @@ -859,8 +865,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ci->mid = mid; ci->proc = m; ci->stackidx = mrb->stack - mrb->stbase; - ci->argc = n; - if (ci->argc == CALL_MAXARGS) ci->argc = -1; + if (n == CALL_MAXARGS) { + ci->argc = -1; + } + else { + ci->argc = n; + } ci->target_class = c; ci->pc = pc + 1; ci->acc = a; @@ -981,15 +991,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) c = mrb->ci->target_class->super; m = mrb_method_search_vm(mrb, &c, mid); if (!m) { - mid = mrb_intern(mrb, "method_missing"); + mid = mrb_intern2(mrb, "method_missing", 14); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid)); } else { - memmove(regs+a+2, regs+a+1, sizeof(mrb_value)*(n+1)); + value_move(regs+a+2, regs+a+1, ++n); SET_SYM_VALUE(regs[a+1], ci->mid); - n++; } } @@ -998,8 +1007,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ci->mid = mid; ci->proc = m; ci->stackidx = mrb->stack - mrb->stbase; - ci->argc = n; - if (ci->argc == CALL_MAXARGS) ci->argc = -1; + if (n == CALL_MAXARGS) { + ci->argc = -1; + } + else { + ci->argc = n; + } ci->target_class = m->target_class; ci->pc = pc + 1; @@ -1026,7 +1039,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) pool = irep->pool; syms = irep->syms; ci->nregs = irep->nregs; - if (ci->argc < 0) { + if (n == CALL_MAXARGS) { stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3); } else { @@ -1055,7 +1068,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) mrb_value exc; static const char m[] = "super called outside of method"; exc = mrb_exc_new(mrb, E_NOMETHOD_ERROR, m, sizeof(m) - 1); - mrb->exc = (struct RObject*)mrb_object(exc); + mrb->exc = mrb_obj_ptr(exc); goto L_RAISE; } stack = e->stack + 1; @@ -1093,7 +1106,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) CASE(OP_ENTER) { /* Ax arg setup according to flags (24=5:5:1:5:5:1:1) */ /* number of optional arguments times OP_JMP should follow */ - int ax = GETARG_Ax(i); + int32_t ax = GETARG_Ax(i); int m1 = (ax>>18)&0x1f; int o = (ax>>13)&0x1f; int r = (ax>>12)&0x1; @@ -1131,10 +1144,10 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (argc < len) { regs[len+1] = *blk; /* move block */ if (argv0 != argv) { - memmove(®s[1], argv, sizeof(mrb_value)*(argc-m2)); /* m1 + o */ + value_move(®s[1], argv, argc-m2); /* m1 + o */ } if (m2) { - memmove(®s[len-m2+1], &argv[argc-m2], sizeof(mrb_value)*m2); /* m2 */ + value_move(®s[len-m2+1], &argv[argc-m2], m2); /* m2 */ } if (r) { /* r */ regs[m1+o+1] = mrb_ary_new_capa(mrb, 0); @@ -1146,13 +1159,13 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) else { if (argv0 != argv) { regs[len+1] = *blk; /* move block */ - memmove(®s[1], argv, sizeof(mrb_value)*(m1+o)); /* m1 + o */ + value_move(®s[1], argv, m1+o); /* m1 + o */ } if (r) { /* r */ regs[m1+o+1] = mrb_ary_new_from_values(mrb, argc-m1-o-m2, argv+m1+o); } if (m2) { - memmove(®s[m1+o+r+1], &argv[argc-m2], sizeof(mrb_value)*m2); + value_move(®s[m1+o+r+1], &argv[argc-m2], m2); } if (argv0 == argv) { regs[len+1] = *blk; /* move block */ @@ -1183,8 +1196,8 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) L_RAISE: ci = mrb->ci; - mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern(mrb, "lastpc"), mrb_voidp_value(pc)); - mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->cibase)); + mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(pc)); + mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->cibase)); eidx = ci->eidx; if (ci == mrb->cibase) { if (ci->ridx == 0) goto L_STOP; @@ -1300,15 +1313,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (!m) { mrb_value sym = mrb_symbol_value(mid); - mid = mrb_intern(mrb, "method_missing"); + mid = mrb_intern2(mrb, "method_missing", 14); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], sym); } else { - memmove(regs+a+2, regs+a+1, sizeof(mrb_value)*(n+1)); + value_move(regs+a+2, regs+a+1, ++n); regs[a+1] = sym; - n++; } } @@ -1317,11 +1329,15 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ci = mrb->ci; ci->mid = mid; ci->target_class = m->target_class; - ci->argc = n; - if (ci->argc == CALL_MAXARGS) ci->argc = -1; + if (n == CALL_MAXARGS) { + ci->argc = -1; + } + else { + ci->argc = n; + } /* move stack */ - memmove(mrb->stack, ®s[a], (ci->argc+1)*sizeof(mrb_value)); + value_move(mrb->stack, ®s[a], ci->argc+1); if (MRB_PROC_CFUNC_P(m)) { mrb->stack[0] = m->body.func(mrb, recv); @@ -1375,7 +1391,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) #define attr_f value.f #endif -#define TYPES2(a,b) (((((int)(a))<<8)|((int)(b)))&0xffff) +#define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff)) #define OP_MATH_BODY(op,v1,v2) do {\ regs[a].v1 = regs[a].v1 op regs[a+1].v2;\ } while(0) @@ -1389,16 +1405,18 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): { mrb_int x, y, z; + mrb_value *regs_a = regs + a; - x = mrb_fixnum(regs[a]); - y = mrb_fixnum(regs[a+1]); + x = mrb_fixnum(regs_a[0]); + y = mrb_fixnum(regs_a[1]); z = x + y; - if (((x < 0) ^ (y < 0)) == 0 && (x < 0) != (z < 0)) { + if ((x < 0) != (z < 0) && ((x < 0) ^ (y < 0)) == 0) { /* integer overflow */ - SET_FLT_VALUE(regs[a], (mrb_float)x + (mrb_float)y); - break; + SET_FLT_VALUE(regs_a[0], (mrb_float)x + (mrb_float)y); + } + else { + regs_a[0].attr_i = z; } - SET_INT_VALUE(regs[a], z); } break; case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): @@ -1570,28 +1588,30 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) CASE(OP_SUBI) { /* A B C R(A) := R(A)-C (Syms[B]=:+)*/ int a = GETARG_A(i); + mrb_value *regs_a = regs + a; /* need to check if + is overridden */ - switch (mrb_type(regs[a])) { + switch (mrb_type(regs_a[0])) { case MRB_TT_FIXNUM: { - mrb_int x = regs[a].attr_i; + mrb_int x = regs_a[0].attr_i; mrb_int y = GETARG_C(i); mrb_int z = x - y; - if (((x < 0) ^ (y < 0)) != 0 && (x < 0) != (z < 0)) { + if ((x < 0) != (z < 0) && ((x < 0) ^ (y < 0)) != 0) { /* integer overflow */ - SET_FLT_VALUE(regs[a], (mrb_float)x - (mrb_float)y); - break; + SET_FLT_VALUE(regs_a[0], (mrb_float)x - (mrb_float)y); + } + else { + regs_a[0].attr_i = z; } - regs[a].attr_i = z; } break; case MRB_TT_FLOAT: - regs[a].attr_f -= GETARG_C(i); + regs_a[0].attr_f -= GETARG_C(i); break; default: - SET_INT_VALUE(regs[a+1], GETARG_C(i)); + SET_INT_VALUE(regs_a[1], GETARG_C(i)); i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1); goto L_SEND; } @@ -1904,7 +1924,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (!mrb->ci->target_class) { static const char msg[] = "no target class or module"; mrb_value exc = mrb_exc_new(mrb, E_TYPE_ERROR, msg, sizeof(msg) - 1); - mrb->exc = (struct RObject*)mrb_object(exc); + mrb->exc = mrb_obj_ptr(exc); goto L_RAISE; } regs[GETARG_A(i)] = mrb_obj_value(mrb->ci->target_class); @@ -1957,7 +1977,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) else { exc = mrb_exc_new3(mrb, E_LOCALJUMP_ERROR, msg); } - mrb->exc = (struct RObject*)mrb_object(exc); + mrb->exc = mrb_obj_ptr(exc); goto L_RAISE; } } diff --git a/tasks/mrbgem_spec.rake b/tasks/mrbgem_spec.rake index 649f99d0e..4b2ce6499 100644 --- a/tasks/mrbgem_spec.rake +++ b/tasks/mrbgem_spec.rake @@ -145,6 +145,7 @@ module MRuby f.puts %Q[ * This file was generated!] f.puts %Q[ * All manual changes will get lost.] f.puts %Q[ */] + f.puts %Q[#include <stdlib.h>] f.puts %Q[#include "mruby.h"] f.puts %Q[#include "mruby/irep.h"] f.puts %Q[#include "mruby/dump.h"] diff --git a/tasks/mrbgems.rake b/tasks/mrbgems.rake index 17f266105..2d670227f 100644 --- a/tasks/mrbgems.rake +++ b/tasks/mrbgems.rake @@ -9,7 +9,7 @@ MRuby.each_target do # loader all gems self.libmruby << objfile("#{build_dir}/mrbgems/gem_init") file objfile("#{build_dir}/mrbgems/gem_init") => "#{build_dir}/mrbgems/gem_init.c" - file "#{build_dir}/mrbgems/gem_init.c" => MRUBY_CONFIGS.flatten do |t| + file "#{build_dir}/mrbgems/gem_init.c" => [MRUBY_CONFIG] do |t| FileUtils.mkdir_p "#{build_dir}/mrbgems" open(t.name, 'w') do |f| f.puts %Q[/*] diff --git a/tasks/mrbgems_test.rake b/tasks/mrbgems_test.rake index 6ca5eaef2..e725f1c4d 100644 --- a/tasks/mrbgems_test.rake +++ b/tasks/mrbgems_test.rake @@ -68,7 +68,7 @@ MRuby.each_target do f.puts %Q[ ] f.puts %Q[ while(mrb_test(val2)) {] f.puts %Q[ char *str = mrb_string_value_cstr(mrb2, &val2);] - f.puts %Q[ mrb_ary_push(mrb, ary1, mrb_str_new(mrb, str, strlen(str)));] + f.puts %Q[ mrb_ary_push(mrb, ary1, mrb_str_new_cstr(mrb, str));] f.puts %Q[ val2 = mrb_ary_shift(mrb2, ary2);] f.puts %Q[ }] f.puts %Q[ }] diff --git a/tasks/mruby_build.rake b/tasks/mruby_build.rake index 10125701e..e24a8ac61 100644 --- a/tasks/mruby_build.rake +++ b/tasks/mruby_build.rake @@ -128,6 +128,14 @@ module MRuby end end + def cygwin_filename(name) + if name.is_a?(Array) + name.flatten.map { |n| cygwin_filename(n) } + else + '"%s"' % `cygpath -w "#{filename(name)}"`.strip + end + end + def exefile(name) if name.is_a?(Array) name.flatten.map { |n| exefile(n) } @@ -175,7 +183,8 @@ module MRuby unless @gems.empty? puts " Included Gems:" @gems.map do |gem| - puts " #{gem.name}" + gem_version = "- #{gem.version}" if gem.version + puts " #{gem.name} #{gem_version}" puts " - Binaries: #{gem.bins.join(', ')}" unless gem.bins.empty? end end diff --git a/tasks/mruby_build_commands.rake b/tasks/mruby_build_commands.rake index 1e806e5da..b647ccf98 100644 --- a/tasks/mruby_build_commands.rake +++ b/tasks/mruby_build_commands.rake @@ -4,7 +4,7 @@ module MRuby class Command include Rake::DSL extend Forwardable - def_delegators :@build, :filename, :objfile, :libfile, :exefile + def_delegators :@build, :filename, :objfile, :libfile, :exefile, :cygwin_filename attr_accessor :build, :command def initialize(build) @@ -49,7 +49,11 @@ module MRuby def all_flags(_defineds=[], _include_paths=[], _flags=[]) define_flags = [defines, _defineds].flatten.map{ |d| option_define % d } include_path_flags = [include_paths, _include_paths].flatten.map do |f| - option_include_path % filename(f) + if MRUBY_BUILD_HOST_IS_CYGWIN + option_include_path % cygwin_filename(f) + else + option_include_path % filename(f) + end end [flags, define_flags, include_path_flags, _flags].flatten.join(' ') end @@ -61,8 +65,13 @@ module MRuby option_include_path % filename(f) end _pp "CC", infile.relative_path, outfile.relative_path - _run compile_options, { :flags => all_flags(_defineds, _include_paths, _flags), - :infile => filename(infile), :outfile => filename(outfile) } + if MRUBY_BUILD_HOST_IS_CYGWIN + _run compile_options, { :flags => all_flags(_defineds, _include_paths, _flags), + :infile => cygwin_filename(infile), :outfile => cygwin_filename(outfile) } + else + _run compile_options, { :flags => all_flags(_defineds, _include_paths, _flags), + :infile => filename(infile), :outfile => filename(outfile) } + end end def define_rules(build_dir, source_dir='') @@ -127,7 +136,11 @@ module MRuby def all_flags(_library_paths=[], _flags=[]) library_path_flags = [library_paths, _library_paths].flatten.map do |f| - option_library_path % filename(f) + if MRUBY_BUILD_HOST_IS_CYGWIN + option_library_path % cygwin_filename(f) + else + option_library_path % filename(f) + end end [flags, library_path_flags, _flags].flatten.join(' ') end @@ -142,11 +155,19 @@ module MRuby library_path_flags = [library_paths, _library_paths].flatten.map { |f| option_library_path % filename(f) } _pp "LD", outfile.relative_path - _run link_options, { :flags => all_flags(_library_paths, _flags), - :outfile => filename(outfile) , :objs => filename(objfiles).join(' '), - :flags_before_libraries => [flags_before_libraries, _flags_before_libraries].flatten.join(' '), - :flags_after_libraries => [flags_after_libraries, _flags_after_libraries].flatten.join(' '), - :libs => library_flags.join(' ') } + if MRUBY_BUILD_HOST_IS_CYGWIN + _run link_options, { :flags => all_flags(_library_paths, _flags), + :outfile => cygwin_filename(outfile) , :objs => cygwin_filename(objfiles).join(' '), + :flags_before_libraries => [flags_before_libraries, _flags_before_libraries].flatten.join(' '), + :flags_after_libraries => [flags_after_libraries, _flags_after_libraries].flatten.join(' '), + :libs => library_flags.join(' ') } + else + _run link_options, { :flags => all_flags(_library_paths, _flags), + :outfile => filename(outfile) , :objs => filename(objfiles).join(' '), + :flags_before_libraries => [flags_before_libraries, _flags_before_libraries].flatten.join(' '), + :flags_after_libraries => [flags_after_libraries, _flags_after_libraries].flatten.join(' '), + :libs => library_flags.join(' ') } + end end end @@ -162,7 +183,11 @@ module MRuby def run(outfile, objfiles) FileUtils.mkdir_p File.dirname(outfile) _pp "AR", outfile.relative_path - _run archive_options, { :outfile => filename(outfile), :objs => filename(objfiles).join(' ') } + if MRUBY_BUILD_HOST_IS_CYGWIN + _run archive_options, { :outfile => cygwin_filename(outfile), :objs => cygwin_filename(objfiles).join(' ') } + else + _run archive_options, { :outfile => filename(outfile), :objs => filename(objfiles).join(' ') } + end end end diff --git a/tasks/mruby_build_gem.rake b/tasks/mruby_build_gem.rake index 9f5804406..358df1612 100644 --- a/tasks/mruby_build_gem.rake +++ b/tasks/mruby_build_gem.rake @@ -1,7 +1,12 @@ module MRuby module LoadGems def gem(gemdir, &block) - gemdir = load_external_gem(gemdir) if gemdir.is_a?(Hash) + caller_dir = File.expand_path(File.dirname(/^(.*?):\d/.match(caller.first).to_a[1])) + if gemdir.is_a?(Hash) + gemdir = load_external_gem(gemdir) + else + gemdir = File.expand_path(gemdir, caller_dir) + end gemrake = File.join(gemdir, "mrbgem.rake") fail "Can't find #{gemrake}" unless File.exists?(gemrake) @@ -19,6 +24,8 @@ module MRuby def load_external_gem(params) if params[:github] params[:git] = "https://github.com/#{params[:github]}.git" + elsif params[:bitbucket] + params[:git] = "https://bitbucket.org/#{params[:bitbucket]}.git" end if params[:git] diff --git a/tasks/toolchains/androideabi.rake b/tasks/toolchains/androideabi.rake index 9c6d423e2..a69fd1a9d 100644 --- a/tasks/toolchains/androideabi.rake +++ b/tasks/toolchains/androideabi.rake @@ -11,13 +11,115 @@ MRuby::Toolchain.new(:androideabi) do |conf| toolchain :gcc - ANDROID_STANDALONE_TOOLCHAIN = ENV['ANDROID_STANDALONE_TOOLCHAIN'] + '/bin/arm-linux-androideabi-' - SYSROOT = ENV['ANDROID_STANDALONE_TOOLCHAIN'] + '/sysroot' + DEFAULT_ANDROID_TOOLCHAIN = 'gcc' + DEFAULT_ANDROID_TARGET_ARCH = 'arm' + DEFAULT_ANDROID_TARGET_ARCH_ABI = 'armeabi' + DEFAULT_ANDROID_TARGET_PLATFORM = 'android-14' + DEFAULT_GCC_VERSION = '4.6' + DEFAULT_CLANG_VERSION = '3.1' + GCC_COMMON_CFLAGS = %W(-ffunction-sections -funwind-tables -fstack-protector) + GCC_COMMON_LDFLAGS = %W() + + # 'ANDROID_STANDALONE_TOOLCHAIN' or 'ANDROID_NDK_HOME' must be set. + ANDROID_STANDALONE_TOOLCHAIN = ENV['ANDROID_STANDALONE_TOOLCHAIN'] + ANDROID_NDK_HOME = ENV['ANDROID_NDK_HOME'] + + ANDROID_TARGET_ARCH = ENV['ANDROID_TARGET_ARCH'] || DEFAULT_ANDROID_TARGET_ARCH + ANDROID_TARGET_ARCH_ABI = ENV['ANDROID_TARGET_ARCH_ABI'] || DEFAULT_ANDROID_TARGET_ARCH_ABI + ANDROID_TOOLCHAIN = ENV['ANDROID_TOOLCHAIN'] || DEFAULT_ANDROID_TOOLCHAIN + + case ANDROID_TARGET_ARCH.downcase + when 'arch-arm', 'arm' then + toolchain_prefix = 'arm-linux-androideabi-' + when 'arch-x86', 'x86' then + toolchain_prefix = 'i686-linux-android-' + when 'arch-mips', 'mips' then + toolchain_prefix = 'mipsel-linux-android-' + else + # Any other architectures are not supported by Android NDK. + # Notify error. + end + + if ANDROID_STANDALONE_TOOLCHAIN == nil then + if RUBY_PLATFORM.include?('darwin') then + HOST_PLATFORM = 'darwin-x86' + elsif RUBY_PLATFORM.include?('linux') then + HOST_PLATFORM = 'linux-x86' + elsif RUBY_PLATFORM.include?('win') then + HOST_PLATFORM = 'windows' + else + # Unknown host platform. + end + + ANDROID_TARGET_PLATFORM = ENV['ANDROID_TARGET_PLATFORM'] || DEFAULT_ANDROID_TARGET_PLATFORM + + path_to_toolchain = ANDROID_NDK_HOME + '/toolchains/' + path_to_sysroot = ANDROID_NDK_HOME + '/platforms/' + ANDROID_TARGET_PLATFORM + if ANDROID_TOOLCHAIN.downcase == 'gcc' then + case ANDROID_TARGET_ARCH.downcase + when 'arch-arm', 'arm' then + path_to_toolchain += 'arm-linux-androideabi-' + path_to_sysroot += '/arch-arm' + when 'arch-x86', 'x86' then + path_to_toolchain += 'x86-' + path_to_sysroot += '/arch-x86' + when 'arch-mips', 'mips' then + path_to_toolchain += 'mipsel-linux-android-' + path_to_sysroot += '/arch-mips' + else + # Any other architecture are not supported by Android NDK. + end + path_to_toolchain += DEFAULT_GCC_VERSION + '/prebuilt/' + HOST_PLATFORM + else + path_to_toolchain += 'llvm-' + DEFAULT_CLANG_VERSION + '/prebuilt/' + HOST_PLATFORM + end + else + path_to_toolchain = ANDROID_STANDALONE_TOOLCHAIN + path_to_sysroot = ANDROID_STANDALONE_TOOLCHAIN + '/sysroot' + end + + SYSROOT = path_to_sysroot + + case ANDROID_TARGET_ARCH.downcase + when 'arch-arm', 'arm' then + if ANDROID_TARGET_ARCH_ABI.downcase == 'armeabi-v7a' then + ARCH_CFLAGS = %W(-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16) + ARCH_LDFLAGS = %W(-march=armv7-a -Wl,--fix-cortex-a8) + else + ARCH_CFLAGS = %W(-march=armv5te -mtune=xscale -msoft-float) + ARCH_LDFLAGS = %W() + end + when 'arch-x86', 'x86' then + ARCH_CFLAGS = %W() + ARCH_LDFLAGS = %W() + when 'arch-mips', 'mips' then + ARCH_CFLAGS = %W(-fpic -fno-strict-aliasing -finline-functions -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers) + ARCH_LDFLAGS = %W() + else + # Notify error + end + + case ANDROID_TOOLCHAIN.downcase + when 'gcc' then + ANDROID_CC = path_to_toolchain + '/bin/' + toolchain_prefix + 'gcc' + ANDROID_LD = path_to_toolchain + '/bin/' + toolchain_prefix + 'gcc' + ANDROID_AR = path_to_toolchain + '/bin/' + toolchain_prefix + 'ar' + ANDROID_CFLAGS = GCC_COMMON_CFLAGS + %W(-mandroid --sysroot="#{SYSROOT}") + ARCH_CFLAGS + ANDROID_LDFLAGS = GCC_COMMON_LDFLAGS + %W(-mandroid --sysroot="#{SYSROOT}") + ARCH_LDFLAGS + when 'clang' then + # clang is not supported yet. + when 'clang31', 'clang3.1' then + # clang is not supported yet. + else + # Any other toolchains are not supported by Android NDK. + # Notify error. + end [conf.cc, conf.cxx, conf.objc, conf.asm].each do |cc| - cc.command = ENV['CC'] || ANDROID_STANDALONE_TOOLCHAIN + 'gcc' - cc.flags = [ENV['CFLAGS'] || ['--sysroot ' + SYSROOT]] + cc.command = ENV['CC'] || ANDROID_CC + cc.flags = [ENV['CFLAGS'] || ANDROID_CFLAGS] end - conf.linker.command = ENV['LD'] || ANDROID_STANDALONE_TOOLCHAIN + 'gcc' - conf.archiver.command = ENV['AR'] || ANDROID_STANDALONE_TOOLCHAIN + 'ar' + conf.linker.command = ENV['LD'] || ANDROID_LD + conf.linker.flags = [ENV['LDFLAGS'] || ANDROID_LDFLAGS] + conf.archiver.command = ENV['AR'] || ANDROID_AR end diff --git a/test/driver.c b/test/driver.c index 5183145b4..acf79df05 100644 --- a/test/driver.c +++ b/test/driver.c @@ -5,6 +5,8 @@ ** against the current mruby implementation. */ + +#include <stdlib.h> #include <string.h> #include <mruby.h> @@ -17,7 +19,8 @@ void mrb_init_mrbtest(mrb_state *); /* Print a short remark for the user */ -void print_hint(void) +static void +print_hint(void) { printf("mrbtest - Embeddable Ruby Test\n"); printf("\nThis is a very early version, please test and report errors.\n"); @@ -35,13 +38,31 @@ check_error(mrb_state *mrb) return mrb_fixnum_p(ko_test) && mrb_fixnum(ko_test) == 0 && mrb_fixnum_p(kill_test) && mrb_fixnum(kill_test) == 0; } +static int +eval_test(mrb_state *mrb) +{ + mrb_value return_value; + const char *prog = "report()"; + + /* evaluate the test */ + return_value = mrb_load_string(mrb, prog); + /* did an exception occur? */ + if (mrb->exc) { + mrb_p(mrb, return_value); + mrb->exc = 0; + return EXIT_FAILURE; + } + else if (!check_error(mrb)) { + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + int main(int argc, char **argv) { mrb_state *mrb; - mrb_value return_value; - const char *prog = "report()"; - int ret = EXIT_SUCCESS; + int ret; print_hint(); @@ -52,23 +73,13 @@ main(int argc, char **argv) return EXIT_FAILURE; } - if (argc == 2 && strncmp(argv[1], "-v", 2) == 0) { + if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'v') { printf("verbose mode: enable\n\n"); mrb_gv_set(mrb, mrb_intern(mrb, "$mrbtest_verbose"), mrb_true_value()); } mrb_init_mrbtest(mrb); - /* evaluate the test */ - return_value = mrb_load_string(mrb, prog); - /* did an exception occur? */ - if (mrb->exc) { - mrb_p(mrb, return_value); - mrb->exc = 0; - ret = EXIT_FAILURE; - } - else if (!check_error(mrb)) { - ret = EXIT_FAILURE; - } + ret = eval_test(mrb); mrb_close(mrb); return ret; diff --git a/test/init_mrbtest.c b/test/init_mrbtest.c index 6b2219b6f..973029c8f 100644 --- a/test/init_mrbtest.c +++ b/test/init_mrbtest.c @@ -1,3 +1,4 @@ +#include <stdlib.h> #include "mruby.h" #include "mruby/irep.h" #include "mruby/dump.h" diff --git a/test/t/literals.rb b/test/t/literals.rb index 9a6d341d4..f40852ff9 100644 --- a/test/t/literals.rb +++ b/test/t/literals.rb @@ -128,8 +128,137 @@ ZZZ z == "" end -# Not Implemented ATM assert('Literals Array', '8.7.6.4') do +assert('Literals Array', '8.7.6.4') do + a = %W{abc#{1+2}def \}g} + b = %W(abc #{2+3} def \(g) + c = %W[#{3+4}] + d = %W< #{4+5} > + e = %W// + f = %W[[ab cd][ef]] + g = %W{ + ab + #{-1}1 + 2#{2} + } + h = %W(a\nb + test\ abc + c\ +d + x\y x\\y x\\\y) + + test1 = (a == ['abc3def', '}g'] and + b == ['abc', '5', 'def', '(g'] and + c == ['7'] and + d == ['9'] and + e == [] and + f == ['[ab', 'cd][ef]'] and + g == ['ab', '-11', '22'] and + h == ["a\nb", 'test abc', "c\nd", "xy", "x\\y", "x\\y"] + ) + + a = %w{abc#{1+2}def \}g} + b = %w(abc #{2+3} def \(g) + c = %w[#{3+4}] + d = %w< #{4+5} > + e = %w// + f = %w[[ab cd][ef]] + g = %w{ + ab + #{-1}1 + 2#{2} + } + h = %w(a\nb + test\ abc + c\ +d + x\y x\\y x\\\y) + + test2 = (a == ['abc#{1+2}def', '}g'] and + b == ['abc', '#{2+3}', 'def', '(g'] and + c == ['#{3+4}'] and + d == ['#{4+5}'] and + e == [] and + f == ['[ab', 'cd][ef]'] and + g == ['ab', '#{-1}1', '2#{2}'] and + h == ["a\\nb", "test abc", "c\nd", "x\\y", "x\\y", "x\\\\y"] + ) + + test1 and test2 +end + +assert('Literals Array of symbols') do + a = %I{abc#{1+2}def \}g} + b = %I(abc #{2+3} def \(g) + c = %I[#{3+4}] + d = %I< #{4+5} > + e = %I// + f = %I[[ab cd][ef]] + g = %I{ + ab + #{-1}1 + 2#{2} + } + + test1 = (a == [:'abc3def', :'}g'] and + b == [:'abc', :'5', :'def', :'(g'] and + c == [:'7'] and + d == [:'9'] and + e == [] and + f == [:'[ab', :'cd][ef]'] and + g == [:'ab', :'-11', :'22'] + ) + + a = %i{abc#{1+2}def \}g} + b = %i(abc #{2+3} def \(g) + c = %i[#{3+4}] + d = %i< #{4+5} > + e = %i// + f = %i[[ab cd][ef]] + g = %i{ + ab + #{-1}1 + 2#{2} + } + + test2 = (a == [:'abc#{1+2}def', :'}g'] and + b == [:'abc', :'#{2+3}', :'def', :'(g'] and + c == [:'#{3+4}'] and + d == [:'#{4+5}'] and + e == [] and + f == [:'[ab', :'cd][ef]'] and + g == [:'ab', :'#{-1}1', :'2#{2}'] + ) + + test1 and test2 +end + +assert('Literals Symbol', '8.7.6.6') do + # do not compile error + :$asd + :@asd + :@@asd + :asd= + :asd! + :asd? + :+ + :+@ + :if + :BEGIN + + a = :"asd qwe" + b = :'foo bar' + c = :"a#{1+2}b" + d = %s(asd) + e = %s( foo \)) + f = %s[asd \[ +qwe] + g = %s/foo#{1+2}bar/ + h = %s{{foo bar}} + + a == :'asd qwe' and b == :"foo bar" and c == :a3b and d == :asd and + e == :' foo )' and f == :"asd [\nqwe" and g == :'foo#{1+2}bar' and + h == :'{foo bar}' +end # Not Implemented ATM assert('Literals Regular expression', '8.7.6.5') do -# Not Implemented ATM assert('Literals Symbol', '8.7.6.6') do diff --git a/tools/mirb/mirb.c b/tools/mirb/mirb.c index e20de629d..c771535c6 100644 --- a/tools/mirb/mirb.c +++ b/tools/mirb/mirb.c @@ -6,6 +6,7 @@ ** immediately. It's a REPL... */ +#include <stdlib.h> #include <string.h> #include <mruby.h> @@ -38,7 +39,7 @@ is_code_block_open(struct mrb_parser_state *parser) int code_block_open = FALSE; /* check for unterminated string */ - if (parser->sterm) return TRUE; + if (parser->lex_strterm) return TRUE; /* check for heredoc */ if (parser->heredoc_starts_nextline) return TRUE; @@ -132,7 +133,8 @@ is_code_block_open(struct mrb_parser_state *parser) } /* Print a short remark for the user */ -void print_hint(void) +static void +print_hint(void) { printf("mirb - Embeddable Interactive Ruby Shell\n"); printf("\nThis is a very early version, please test and report errors.\n"); @@ -260,6 +262,9 @@ main(void) else { /* no */ printf(" => "); + if (!mrb_respond_to(mrb,result,mrb_intern(mrb,"inspect"))){ + result = mrb_any_to_s(mrb,result); + } p(mrb, result); } } diff --git a/tools/mrbc/mrbc.c b/tools/mrbc/mrbc.c index 698586ec0..09ab2ca1d 100644 --- a/tools/mrbc/mrbc.c +++ b/tools/mrbc/mrbc.c @@ -19,8 +19,8 @@ struct _args { char *filename; char *initname; char *ext; - int check_syntax : 1; - int verbose : 1; + mrb_bool check_syntax : 1; + mrb_bool verbose : 1; }; static void diff --git a/tools/mruby/mruby.c b/tools/mruby/mruby.c index 9d6182238..1caf32b6a 100644 --- a/tools/mruby/mruby.c +++ b/tools/mruby/mruby.c @@ -6,6 +6,7 @@ #include "mruby/dump.h" #include "mruby/variable.h" #include <stdio.h> +#include <stdlib.h> #include <string.h> #ifndef ENABLE_STDIO @@ -26,10 +27,10 @@ void mrb_show_copyright(mrb_state *); struct _args { FILE *rfp; char* cmdline; - int fname : 1; - int mrbfile : 1; - int check_syntax : 1; - int verbose : 1; + mrb_bool fname : 1; + mrb_bool mrbfile : 1; + mrb_bool check_syntax : 1; + mrb_bool verbose : 1; int argc; char** argv; }; @@ -52,7 +53,7 @@ usage(const char *name) printf("Usage: %s [switches] programfile\n", name); while(*p) - printf(" %s\n", *p++); + printf(" %s\n", *p++); } static int @@ -125,7 +126,6 @@ append_cmdline: exit(0); } else return -3; - return 0; default: return -4; } @@ -189,14 +189,14 @@ showcallinfo(mrb_state *mrb) if (irep->filename != NULL) filename = irep->filename; if (irep->lines != NULL) { - mrb_code *pc; + mrb_code *pc; - if (i+1 <= ciidx) { - pc = mrb->cibase[i+1].pc; - } - else { - pc = (mrb_code*)mrb_voidp(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "lastpc"))); - } + if (i+1 <= ciidx) { + pc = mrb->cibase[i+1].pc; + } + else { + pc = (mrb_code*)mrb_voidp(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "lastpc"))); + } if (irep->iseq <= pc && pc < irep->iseq + irep->ilen) { line = irep->lines[pc - irep->iseq - 1]; } @@ -211,19 +211,16 @@ showcallinfo(mrb_state *mrb) method = mrb_sym2name(mrb, ci->mid); if (method) { const char *cn = mrb_class_name(mrb, ci->proc->target_class); - + if (cn) { - printf("\t[%d] %s:%d:in %s%s%s\n", - i, filename, line, cn, sep, method); + printf("\t[%d] %s:%d:in %s%s%s\n", i, filename, line, cn, sep, method); } else { - printf("\t[%d] %s:%d:in %s\n", - i, filename, line, method); + printf("\t[%d] %s:%d:in %s\n", i, filename, line, method); } } else { - printf("\t[%d] %s:%d\n", - i, filename, line); + printf("\t[%d] %s:%d\n", i, filename, line); } } } |
