summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--AUTHORS3
-rw-r--r--CMakeLists.txt9
-rw-r--r--Makefile17
-rw-r--r--benchmark/ao-render.rb315
-rw-r--r--benchmark/bm_so_lists.rb47
-rw-r--r--cmake/Toolchain-OpenWRT-ANY.cmake13
-rw-r--r--cmake/Toolchain-Ubuntu-gnueabi.cmake.sample29
-rw-r--r--cmake/Toolchain-Ubuntu-gnueabihf.cmake.sample29
-rw-r--r--include/mrbconf.h66
-rw-r--r--include/mruby.h54
-rw-r--r--include/mruby/array.h35
-rw-r--r--include/mruby/class.h15
-rw-r--r--include/mruby/compile.h49
-rw-r--r--include/mruby/hash.h18
-rw-r--r--include/mruby/khash.h144
-rw-r--r--include/mruby/numeric.h7
-rw-r--r--include/mruby/object.h2
-rw-r--r--include/mruby/proc.h4
-rw-r--r--include/mruby/string.h25
-rw-r--r--include/mruby/struct.h3
-rw-r--r--include/mruby/variable.h20
-rw-r--r--mrblib/Makefile17
-rw-r--r--mrblib/class.rb26
-rw-r--r--mrblib/error.rb50
-rw-r--r--mrblib/hash.rb56
-rw-r--r--mrblib/kernel.rb36
-rw-r--r--mrblib/print.rb105
-rw-r--r--mrblib/string.rb23
-rw-r--r--mrblib/struct.rb78
-rw-r--r--mruby/HelloMRuby/hello_mruby.c9
-rw-r--r--src/Makefile17
-rw-r--r--src/array.c508
-rw-r--r--src/cdump.c51
-rw-r--r--src/class.c560
-rw-r--r--src/codegen.c479
-rw-r--r--src/compar.c35
-rw-r--r--src/dump.c59
-rw-r--r--src/error.c187
-rw-r--r--src/error.h3
-rw-r--r--src/etc.c216
-rw-r--r--src/gc.c147
-rw-r--r--src/gc.h54
-rw-r--r--src/hash.c106
-rw-r--r--src/init.c16
-rw-r--r--src/kernel.c480
-rw-r--r--src/load.c64
-rw-r--r--src/math.c119
-rw-r--r--src/node.h26
-rw-r--r--src/numeric.c305
-rw-r--r--src/object.c51
-rw-r--r--src/opcode.h18
-rw-r--r--src/parse.y553
-rw-r--r--src/pool.c23
-rw-r--r--src/print.c32
-rw-r--r--src/proc.c70
-rw-r--r--src/range.c144
-rw-r--r--src/re.c56
-rw-r--r--src/re.h1
-rw-r--r--src/regcomp.c8
-rw-r--r--src/regenc.c8
-rw-r--r--src/regerror.c4
-rw-r--r--src/regexec.c4
-rw-r--r--src/regparse.c8
-rw-r--r--src/sprintf.c52
-rw-r--r--src/st.c12
-rw-r--r--src/state.c7
-rw-r--r--src/string.c512
-rw-r--r--src/struct.c220
-rw-r--r--src/symbol.c173
-rw-r--r--src/time.c282
-rw-r--r--src/variable.c188
-rw-r--r--src/vm.c284
-rw-r--r--test/Makefile17
-rw-r--r--test/assert.rb13
-rw-r--r--test/driver.c39
-rw-r--r--test/t/argumenterror.rb5
-rw-r--r--test/t/array.rb69
-rw-r--r--test/t/basicobject.rb11
-rw-r--r--test/t/bs_block.rb12
-rw-r--r--test/t/class.rb115
-rw-r--r--test/t/comparable.rb56
-rw-r--r--test/t/exception.rb62
-rw-r--r--test/t/false.rb12
-rw-r--r--test/t/float.rb60
-rw-r--r--test/t/hash.rb43
-rw-r--r--test/t/indexerror.rb5
-rw-r--r--test/t/integer.rb4
-rw-r--r--test/t/kernel.rb261
-rw-r--r--test/t/math.rb172
-rw-r--r--test/t/module.rb101
-rw-r--r--test/t/nameerror.rb4
-rw-r--r--test/t/nomethoderror.rb5
-rw-r--r--test/t/numeric.rb4
-rw-r--r--test/t/object.rb5
-rw-r--r--test/t/proc.rb4
-rw-r--r--test/t/range.rb4
-rw-r--r--test/t/rangeerror.rb5
-rw-r--r--test/t/standarderror.rb5
-rw-r--r--test/t/string.rb24
-rw-r--r--test/t/struct.rb69
-rw-r--r--test/t/symbol.rb4
-rw-r--r--test/t/syntax.rb47
-rw-r--r--test/t/time.rb222
-rw-r--r--test/t/true.rb12
-rw-r--r--test/t/typeerror.rb5
-rw-r--r--tools/mirb/Makefile13
-rw-r--r--tools/mirb/mirb.c60
-rw-r--r--tools/mrbc/Makefile17
-rw-r--r--tools/mrbc/mrbc.c60
-rw-r--r--tools/mruby/Makefile17
-rw-r--r--tools/mruby/mruby.c111
-rw-r--r--tools/xpcat/xpcat.c2
-rw-r--r--xcode/mruby.xcodeproj/project.pbxproj137
113 files changed, 5826 insertions, 3513 deletions
diff --git a/AUTHORS b/AUTHORS
index c64e1846d..bba8b8a66 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -6,3 +6,6 @@ Original Authors "mruby developers" are:
Daniel Bovensiepen
Jon Maken
Bjorn De Meyer
+ Yuichiro MASUI
+ Masamitsu MURASE
+ Masaki Muranaka
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ee97ad8b4..c8b252d2d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -33,12 +33,13 @@ project(mruby C)
# TODO stop polluting source tree with CMakeFiles/ and CMakeCache.txt
# on build location check failure
# Make sure we are not trying to generate in in-tree build unless building
-# with a MSVC IDE where it's OK.
-if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE)
+# with an MSVC or Xcode IDE where it's OK.
+if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT (MSVC_IDE OR XCODE))
message(FATAL_ERROR
"\nIn-source builds are not allowed as CMake would overwrite the "
- "Makefiles distributed with mruby. Please change to the 'build' "
- "subdirectory and run CMake from there.")
+ "Makefiles distributed with mruby. Delete any created 'CMakeFiles' "
+ "subdirectory and 'CMakeCache.txt' file from the current directory, "
+ "change to the 'build' subdirectory, and re-run CMake from there.")
endif()
if(COMMAND cmake_policy)
diff --git a/Makefile b/Makefile
index e7408d793..a960fc14a 100644
--- a/Makefile
+++ b/Makefile
@@ -7,12 +7,19 @@ export LL = gcc
export AR = ar
export YACC = bison
-DEBUG_MODE = 1
-ifeq ($(DEBUG_MODE),1)
-CFLAGS = -g -O3
-else
-CFLAGS = -O3
+ifeq ($(strip $(COMPILE_MODE)),)
+ # default compile option
+ COMPILE_MODE = debug
+endif
+
+ifeq ($(COMPILE_MODE),debug)
+ CFLAGS = -g -O3
+else ifeq ($(COMPILE_MODE),release)
+ CFLAGS = -O3
+else ifeq ($(COMPILE_MODE),small)
+ CFLAGS = -Os
endif
+
ALL_CFLAGS = -Wall -Werror-implicit-function-declaration $(CFLAGS)
ifeq ($(OS),Windows_NT)
MAKE_FLAGS = --no-print-directory CC=$(CC) LL=$(LL) ALL_CFLAGS='$(ALL_CFLAGS)'
diff --git a/benchmark/ao-render.rb b/benchmark/ao-render.rb
new file mode 100644
index 000000000..793804a7b
--- /dev/null
+++ b/benchmark/ao-render.rb
@@ -0,0 +1,315 @@
+# AO render benchmark
+# Original program (C) Syoyo Fujita in Javascript (and other languages)
+# http://lucille.atso-net.jp/blog/?p=642
+# http://lucille.atso-net.jp/blog/?p=711
+# Ruby(yarv2llvm) version by Hideki Miura
+# mruby version by Hideki Miura
+#
+
+IMAGE_WIDTH = 256
+IMAGE_HEIGHT = 256
+NSUBSAMPLES = 2
+NAO_SAMPLES = 8
+
+module Rand
+ # Use xorshift
+ @@x = 123456789
+ @@y = 362436069
+ @@z = 521288629
+ @@w = 88675123
+ BNUM = 1 << 29
+ BNUMF = BNUM.to_f
+ def self.rand
+ x = @@x
+ t = x ^ ((x & 0xfffff) << 11)
+ w = @@w
+ @@x, @@y, @@z = @@y, @@z, w
+ w = @@w = (w ^ (w >> 19) ^ (t ^ (t >> 8)))
+ (w % BNUM) / BNUMF
+ end
+end
+
+class Vec
+ def initialize(x, y, z)
+ @x = x
+ @y = y
+ @z = z
+ end
+
+ def x=(v); @x = v; end
+ def y=(v); @y = v; end
+ def z=(v); @z = v; end
+ def x; @x; end
+ def y; @y; end
+ def z; @z; end
+
+ def vadd(b)
+ Vec.new(@x + b.x, @y + b.y, @z + b.z)
+ end
+
+ def vsub(b)
+ Vec.new(@x - b.x, @y - b.y, @z - b.z)
+ end
+
+ def vcross(b)
+ Vec.new(@y * b.z - @z * b.y,
+ @z * b.x - @x * b.z,
+ @x * b.y - @y * b.x)
+ end
+
+ def vdot(b)
+ r = @x * b.x + @y * b.y + @z * b.z
+ r
+ end
+
+ def vlength
+ Math.sqrt(@x * @x + @y * @y + @z * @z)
+ end
+
+ def vnormalize
+ len = vlength
+ v = Vec.new(@x, @y, @z)
+ if len > 1.0e-17 then
+ v.x = v.x / len
+ v.y = v.y / len
+ v.z = v.z / len
+ end
+ v
+ end
+end
+
+
+class Sphere
+ def initialize(center, radius)
+ @center = center
+ @radius = radius
+ end
+
+ def center; @center; end
+ def radius; @radius; end
+
+ def intersect(ray, isect)
+ rs = ray.org.vsub(@center)
+ b = rs.vdot(ray.dir)
+ c = rs.vdot(rs) - (@radius * @radius)
+ d = b * b - c
+ if d > 0.0 then
+ t = - b - Math.sqrt(d)
+
+ if t > 0.0 and t < isect.t then
+ isect.t = t
+ isect.hit = true
+ isect.pl = Vec.new(ray.org.x + ray.dir.x * t,
+ ray.org.y + ray.dir.y * t,
+ ray.org.z + ray.dir.z * t)
+ n = isect.pl.vsub(@center)
+ isect.n = n.vnormalize
+ end
+ end
+ end
+end
+
+class Plane
+ def initialize(p, n)
+ @p = p
+ @n = n
+ end
+
+ def intersect(ray, isect)
+ v = ray.dir.vdot(@n)
+ v0 = v
+ if v < 0.0 then
+ v0 = -v
+ end
+ if v0 < 1.0e-17 then
+ return
+ end
+
+ t = -(ray.org.vdot(@n) + d) / v
+
+ if t > 0.0 and t < isect.t then
+ isect.hit = true
+ isect.t = t
+ isect.n = @n
+ isect.pl = Vec.new(ray.org.x + t * ray.dir.x,
+ ray.org.y + t * ray.dir.y,
+ ray.org.z + t * ray.dir.z)
+ end
+ end
+end
+
+class Ray
+ def initialize(org, dir)
+ @org = org
+ @dir = dir
+ end
+
+ def org; @org; end
+ def org=(v); @org = v; end
+ def dir; @dir; end
+ def dir=(v); @dir = v; end
+end
+
+class Isect
+ def initialize
+ @t = 10000000.0
+ @hit = false
+ @pl = Vec.new(0.0, 0.0, 0.0)
+ @n = Vec.new(0.0, 0.0, 0.0)
+ end
+
+ def t; @t; end
+ def t=(v); @t = v; end
+ def hit; @hit; end
+ def hit=(v); @hit = v; end
+ def pl; @pl; end
+ def pl=(v); @pl = v; end
+ def n; @n; end
+ def n=(v); @n = v; end
+end
+
+def clamp(f)
+ i = f * 255.5
+ if i > 255.0 then
+ i = 255.0
+ end
+ if i < 0.0 then
+ i = 0.0
+ end
+ i.to_i
+end
+
+def otherBasis(basis, n)
+ basis[2] = Vec.new(n.x, n.y, n.z)
+ basis[1] = Vec.new(0.0, 0.0, 0.0)
+
+ if n.x < 0.6 and n.x > -0.6 then
+ basis[1].x = 1.0
+ elsif n.y < 0.6 and n.y > -0.6 then
+ basis[1].y = 1.0
+ elsif n.z < 0.6 and n.z > -0.6 then
+ basis[1].z = 1.0
+ else
+ basis[1].x = 1.0
+ end
+
+ basis[0] = basis[1].vcross(basis[2])
+ basis[0] = basis[0].vnormalize
+
+ basis[1] = basis[2].vcross(basis[0])
+ basis[1] = basis[1].vnormalize
+end
+
+class Scene
+ def initialize
+ @spheres = Array.new
+ @spheres[0] = Sphere.new(Vec.new(-2.0, 0.0, -3.5), 0.5)
+ @spheres[1] = Sphere.new(Vec.new(-0.5, 0.0, -3.0), 0.5)
+ @spheres[2] = Sphere.new(Vec.new(1.0, 0.0, -2.2), 0.5)
+ @plane = Plane.new(Vec.new(0.0, -0.5, 0.0), Vec.new(0.0, 1.0, 0.0))
+ end
+
+ def ambient_occlusion(isect)
+ basis = Array.new(3)
+ otherBasis(basis, isect.n)
+
+ ntheta = NAO_SAMPLES
+ nphi = NAO_SAMPLES
+ eps = 0.0001
+ occlusion = 0.0
+
+ p0 = Vec.new(isect.pl.x + eps * isect.n.x,
+ isect.pl.y + eps * isect.n.y,
+ isect.pl.z + eps * isect.n.z)
+ nphi.times do |j|
+ ntheta.times do |i|
+ r = Rand::rand
+ phi = 2.0 * 3.14159265 * Rand::rand
+ x = Math.cos(phi) * Math.sqrt(1.0 - r)
+ y = Math.sin(phi) * Math.sqrt(1.0 - r)
+ z = Math.sqrt(r)
+
+ rx = x * basis[0].x + y * basis[1].x + z * basis[2].x
+ ry = x * basis[0].y + y * basis[1].y + z * basis[2].y
+ rz = x * basis[0].z + y * basis[1].z + z * basis[2].z
+
+ raydir = Vec.new(rx, ry, rz)
+ ray = Ray.new(p0, raydir)
+
+ occisect = Isect.new
+ @spheres[0].intersect(ray, occisect)
+ @spheres[1].intersect(ray, occisect)
+ @spheres[2].intersect(ray, occisect)
+ @plane.intersect(ray, occisect)
+ if occisect.hit then
+ occlusion = occlusion + 1.0
+ else
+ 0.0
+ end
+ end
+ end
+
+ occlusion = (ntheta.to_f * nphi.to_f - occlusion) / (ntheta.to_f * nphi.to_f)
+ Vec.new(occlusion, occlusion, occlusion)
+ end
+
+ def render(w, h, nsubsamples)
+ cnt = 0
+ nsf = nsubsamples.to_f
+ h.times do |y|
+ w.times do |x|
+ rad = Vec.new(0.0, 0.0, 0.0)
+
+ # Subsmpling
+ nsubsamples.times do |v|
+ nsubsamples.times do |u|
+ cnt = cnt + 1
+ wf = w.to_f
+ hf = h.to_f
+ xf = x.to_f
+ yf = y.to_f
+ uf = u.to_f
+ vf = v.to_f
+
+ px = (xf + (uf / nsf) - (wf / 2.0)) / (wf / 2.0)
+ py = -(yf + (vf / nsf) - (hf / 2.0)) / (hf / 2.0)
+
+ eye = Vec.new(px, py, -1.0).vnormalize
+
+ ray = Ray.new(Vec.new(0.0, 0.0, 0.0), eye)
+
+ isect = Isect.new
+ @spheres[0].intersect(ray, isect)
+ @spheres[1].intersect(ray, isect)
+ @spheres[2].intersect(ray, isect)
+ @plane.intersect(ray, isect)
+ if isect.hit then
+ col = ambient_occlusion(isect)
+ rad.x = rad.x + col.x
+ rad.y = rad.y + col.y
+ rad.z = rad.z + col.z
+ else
+ 0.0
+ end
+ end
+ end
+
+ r = rad.x / (nsf * nsf)
+ g = rad.y / (nsf * nsf)
+ b = rad.z / (nsf * nsf)
+ printf("%c", clamp(r))
+ printf("%c", clamp(g))
+ printf("%c", clamp(b))
+ end
+ end
+ end
+end
+
+# File.open("ao.ppm", "w") do |fp|
+ printf("P6\n")
+ printf("%d %d\n", IMAGE_WIDTH, IMAGE_HEIGHT)
+ printf("255\n", IMAGE_WIDTH, IMAGE_HEIGHT)
+ Scene.new.render(IMAGE_WIDTH, IMAGE_HEIGHT, NSUBSAMPLES)
+# Scene.new.render(256, 256, 2)
+# end
diff --git a/benchmark/bm_so_lists.rb b/benchmark/bm_so_lists.rb
new file mode 100644
index 000000000..f8d26797a
--- /dev/null
+++ b/benchmark/bm_so_lists.rb
@@ -0,0 +1,47 @@
+#from http://www.bagley.org/~doug/shootout/bench/lists/lists.ruby
+
+NUM = 300
+SIZE = 10000
+
+def test_lists()
+ # create a list of integers (Li1) from 1 to SIZE
+ li1 = (1..SIZE).to_a
+ # copy the list to li2 (not by individual items)
+ li2 = li1.dup
+ # remove each individual item from left side of li2 and
+ # append to right side of li3 (preserving order)
+ li3 = Array.new
+ while (not li2.empty?)
+ li3.push(li2.shift)
+ end
+ # li2 must now be empty
+ # remove each individual item from right side of li3 and
+ # append to right side of li2 (reversing list)
+ while (not li3.empty?)
+ li2.push(li3.pop)
+ end
+ # li3 must now be empty
+ # reverse li1 in place
+ li1.reverse!
+ # check that first item is now SIZE
+ if li1[0] != SIZE then
+ p "not SIZE"
+ 0
+ else
+ # compare li1 and li2 for equality
+ if li1 != li2 then
+ return(0)
+ else
+ # return the length of the list
+ li1.length
+ end
+ end
+end
+
+i = 0
+while i<NUM
+ i+=1
+ result = test_lists()
+end
+
+result
diff --git a/cmake/Toolchain-OpenWRT-ANY.cmake b/cmake/Toolchain-OpenWRT-ANY.cmake
new file mode 100644
index 000000000..888c51ebe
--- /dev/null
+++ b/cmake/Toolchain-OpenWRT-ANY.cmake
@@ -0,0 +1,13 @@
+# Toolchain file for building with OpenWRT Toolchain for ANY OpenWRT Target.
+# Following prequisition are necessary:
+# - latest cmake version
+# - mruby OpenWRT Package file (not yet in distribution)
+
+# Switch to Cross Compile by setting the system name
+SET(CMAKE_SYSTEM_NAME Linux)
+
+# We show CMAKE the compiler, the rest will be guessed by the Toolchain
+SET(CMAKE_C_COMPILER "$ENV{OPENWRT_TOOLCHAIN}/bin/$ENV{OPENWRT_TARGETCC}")
+
+# We define an own release flag so that we can adapt the optimal C_FLAGS
+SET(CMAKE_C_FLAGS_OPENWRT "$ENV{OPENWRT_TARGETFLAGS}")
diff --git a/cmake/Toolchain-Ubuntu-gnueabi.cmake.sample b/cmake/Toolchain-Ubuntu-gnueabi.cmake.sample
new file mode 100644
index 000000000..bf29a5cad
--- /dev/null
+++ b/cmake/Toolchain-Ubuntu-gnueabi.cmake.sample
@@ -0,0 +1,29 @@
+# Sample toolchain file for building for ARM from an Ubuntu Linux system.
+#
+# Typical usage:
+# 1) install cross compiler: `sudo apt-get install gcc-arm-linux-gnueabi`
+# 2) cp cmake/Toolchain-Ubuntu-gnueabi.cmake.sample ~/Toolchain-Ubuntu-gnueabi.cmake
+# 3) tweak toolchain values as needed
+# 4) cd build
+# 5) cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-Ubuntu-gnueabi.cmake ..
+
+# name of the target OS on which the built artifacts will run and the
+# toolchain prefix. if target is an embedded system without an OS, set
+# CMAKE_SYSTEM_NAME to `Generic`
+set(CMAKE_SYSTEM_NAME Linux)
+set(TOOLCHAIN_PREFIX arm-linux-gnueabi)
+
+# cross compilers to use for C
+set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
+
+# target environment on the build host system
+# set 1st to dir with the cross compiler's C/C++ headers/libs
+# set 2nd to dir containing personal cross development headers/libs
+set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX} ~/crossdev/eabi)
+
+# modify default behavior of FIND_XXX() commands to
+# search for headers/libs in the target environment and
+# search for programs in the build host environment
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
diff --git a/cmake/Toolchain-Ubuntu-gnueabihf.cmake.sample b/cmake/Toolchain-Ubuntu-gnueabihf.cmake.sample
new file mode 100644
index 000000000..2d7f2769c
--- /dev/null
+++ b/cmake/Toolchain-Ubuntu-gnueabihf.cmake.sample
@@ -0,0 +1,29 @@
+# Sample toolchain file for building for ARM (w/hw float support) from an Ubuntu Linux system.
+#
+# Typical usage:
+# 1) install cross compiler: `sudo apt-get install gcc-arm-linux-gnueabihf`
+# 2) cp cmake/Toolchain-Ubuntu-gnueabihf.cmake.sample ~/Toolchain-Ubuntu-gnueabihf.cmake
+# 3) tweak toolchain values as needed
+# 4) cd build
+# 5) cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-Ubuntu-gnueabihf.cmake ..
+
+# name of the target OS on which the built artifacts will run and the
+# toolchain prefix. if target is an embedded system without an OS, set
+# CMAKE_SYSTEM_NAME to `Generic`
+set(CMAKE_SYSTEM_NAME Linux)
+set(TOOLCHAIN_PREFIX arm-linux-gnueabihf)
+
+# cross compilers to use for C
+set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
+
+# target environment on the build host system
+# set 1st to dir with the cross compiler's C/C++ headers/libs
+# set 2nd to dir containing personal cross development headers/libs
+set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX} ~/crossdev/eabihf)
+
+# modify default behavior of FIND_XXX() commands to
+# search for headers/libs in the target environment and
+# search for programs in the build host environment
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
diff --git a/include/mrbconf.h b/include/mrbconf.h
index e90b685bb..20f49ec29 100644
--- a/include/mrbconf.h
+++ b/include/mrbconf.h
@@ -8,7 +8,41 @@
#define MRUBYCONF_H
#include <stdint.h>
-#undef MRB_USE_FLOAT
+
+/* configuration options: */
+/* add -DMRB_USE_FLOAT to use float instead of double for floating point numbers */
+//#define MRB_USE_FLOAT
+
+/* argv max size in mrb_funcall */
+//#define MRB_FUNCALL_ARGC_MAX 16
+
+/* number of object per heap page */
+//#define MRB_HEAP_PAGE_SIZE 1024
+
+/* initial size for IV khash */
+//#define MRB_IV_INITIAL_SIZE 8
+
+/* default size of khash table bucket */
+//#define KHASH_DEFAULT_SIZE 32
+
+/* allocated memory address alignment */
+//#define POOL_ALIGNMENT 4
+
+/* page size of memory pool */
+//#define POOL_PAGE_SIZE 16000
+
+/* -DDISABLE_XXXX to drop the feature */
+#define DISABLE_REGEXP /* regular expression classes */
+//#define DISABLE_SPRINTF /* Kernel.sprintf method */
+//#define DISABLE_MATH /* Math functions */
+//#define DISABLE_TIME /* Time class */
+//#define DISABLE_STRUCT /* Struct class */
+//#define DISABLE_STDIO /* use of stdio */
+
+#undef HAVE_UNISTD_H /* WINDOWS */
+#define HAVE_UNISTD_H /* LINUX */
+
+/* end of configuration */
#ifdef MRB_USE_FLOAT
typedef float mrb_float;
@@ -19,20 +53,26 @@ typedef double mrb_float;
typedef int mrb_int;
typedef intptr_t mrb_sym;
-#define readint(p,base) strtol((p),NULL,(base))
-
-#undef INCLUDE_ENCODING /* not use encoding classes (ascii only) */
-//#define INCLUDE_ENCODING /* use UTF-8 encoding classes */
-
-#undef INCLUDE_REGEXP /* not use regular expression classes */
-//#define INCLUDE_REGEXP /* use regular expression classes */
-#ifdef INCLUDE_REGEXP
-# define INCLUDE_ENCODING /* Regexp depends Encoding */
+/* define ENABLE_XXXX from DISABLE_XXX */
+#ifndef DISABLE_REGEXP
+#define ENABLE_REGEXP
+#endif
+#ifndef DISABLE_SPRINTF
+#define ENABLE_SPRINTF
+#endif
+#ifndef DISABLE_MATH
+#define ENABLE_MATH
+#endif
+#ifndef DISABLE_TIME
+#define ENABLE_TIME
+#endif
+#ifndef DISABLE_STRUCT
+#define ENABLE_STRUCT
+#endif
+#ifndef DISABLE_STDIO
+#define ENABLE_STDIO
#endif
-
-#undef HAVE_UNISTD_H /* WINDOWS */
-#define HAVE_UNISTD_H /* LINUX */
#ifndef FALSE
# define FALSE 0
diff --git a/include/mruby.h b/include/mruby.h
index 3bbc6e6cc..451b4eb8b 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -60,9 +60,7 @@ enum mrb_vtype {
MRB_TT_FILE, /* 21 */
MRB_TT_ENV, /* 22 */
MRB_TT_DATA, /* 23 */
- MRB_TT_THREAD, /* 24 */
- MRB_TT_THREADGRP, /* 25 */
- MRB_TT_MAXDEFINE /* 26 */
+ MRB_TT_MAXDEFINE /* 24 */
};
typedef struct mrb_value {
@@ -83,7 +81,7 @@ typedef struct mrb_value {
#define mrb_symbol(o) (o).value.sym
#define mrb_object(o) ((struct RBasic *) (o).value.p)
#define FIXNUM_P(o) ((o).tt == MRB_TT_FIXNUM)
-#define UNDEF_P(o) ((o).tt == MRB_TT_UNDEF)
+#define mrb_undef_p(o) ((o).tt == MRB_TT_UNDEF)
#include "mruby/object.h"
@@ -147,7 +145,7 @@ mrb_obj_value(void *p)
}
static inline mrb_value
-mrb_false_value()
+mrb_false_value(void)
{
mrb_value v;
@@ -157,7 +155,7 @@ mrb_false_value()
}
static inline mrb_value
-mrb_nil_value()
+mrb_nil_value(void)
{
mrb_value v;
@@ -167,7 +165,7 @@ mrb_nil_value()
}
static inline mrb_value
-mrb_true_value()
+mrb_true_value(void)
{
mrb_value v;
@@ -177,7 +175,7 @@ mrb_true_value()
}
static inline mrb_value
-mrb_undef_value()
+mrb_undef_value(void)
{
mrb_value v;
@@ -192,7 +190,9 @@ struct mrb_state;
typedef void* (*mrb_allocf) (struct mrb_state *mrb, void*, size_t);
-#define MRB_ARENA_SIZE 1024 //256 up kusuda 2011/04/30
+#ifndef MRB_ARENA_SIZE
+#define MRB_ARENA_SIZE 1024
+#endif
#define ruby_debug (mrb_nil_value())
#define ruby_verbose (mrb_nil_value())
@@ -279,7 +279,8 @@ typedef struct mrb_state {
struct RClass *eException_class;
struct RClass *eStandardError_class;
- struct RClass *eRuntimeError_class;
+
+ void *ud; /* auxiliary data */
} mrb_state;
typedef mrb_value (*mrb_func_t)(mrb_state *mrb, mrb_value);
@@ -295,10 +296,10 @@ void mrb_define_singleton_method(mrb_state*, struct RObject*, const char*, mrb_f
void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t,int);
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);
-struct RClass * mrb_class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym name);
struct RClass * mrb_class_get(mrb_state *mrb, const char *name);
struct RClass * mrb_class_obj_get(mrb_state *mrb, const char *name);
@@ -329,10 +330,13 @@ struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *outer, co
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, const char*, int, mrb_value*);
-mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, const char*, int, mrb_value*, mrb_value);
+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_str(mrb_state*,mrb_value);
const char *mrb_sym2name(mrb_state*,mrb_sym);
+const char *mrb_sym2name_len(mrb_state*,mrb_sym,int*);
mrb_value mrb_str_format(mrb_state *, int, const mrb_value *, mrb_value);
void *mrb_malloc(mrb_state*, size_t);
@@ -353,8 +357,8 @@ int mrb_checkstack(mrb_state*,int);
mrb_value mrb_top_self(mrb_state *);
mrb_value mrb_run(mrb_state*, struct RProc*, mrb_value);
-mrb_value mrb_p(mrb_state*, mrb_value);
-int mrb_obj_id(mrb_value obj);
+void mrb_p(mrb_state*, mrb_value);
+mrb_int mrb_obj_id(mrb_value obj);
mrb_sym mrb_to_id(mrb_state *mrb, mrb_value name);
int mrb_obj_equal(mrb_state*, mrb_value, mrb_value);
@@ -416,13 +420,16 @@ mrb_value mrb_check_funcall(mrb_state *mrb, mrb_value recv, mrb_sym mid, int arg
#define ISXDIGIT(c) (ISASCII(c) && isxdigit((int)(unsigned char)(c)))
#endif
+mrb_value mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len);
+void mrb_exc_raise(mrb_state *mrb, mrb_value exc);
+
int mrb_block_given_p(void);
void mrb_raise(mrb_state *mrb, struct RClass *c, const char *fmt, ...);
void rb_raise(struct RClass *c, const char *fmt, ...);
void mrb_warn(const char *fmt, ...);
-void mrb_warning(const char *fmt, ...);
void mrb_bug(const char *fmt, ...);
+#define E_RUNTIME_ERROR (mrb_class_obj_get(mrb, "RuntimeError"))
#define E_TYPE_ERROR (mrb_class_obj_get(mrb, "TypeError"))
#define E_ARGUMENT_ERROR (mrb_class_obj_get(mrb, "ArgumentError"))
#define E_INDEX_ERROR (mrb_class_obj_get(mrb, "IndexError"))
@@ -431,13 +438,9 @@ void mrb_bug(const char *fmt, ...);
#define E_NOMETHOD_ERROR (mrb_class_obj_get(mrb, "NoMethodError"))
#define E_SCRIPT_ERROR (mrb_class_obj_get(mrb, "ScriptError"))
#define E_SYNTAX_ERROR (mrb_class_obj_get(mrb, "SyntaxError"))
-#define E_LOAD_ERROR (mrb_class_obj_get(mrb, "LoadError"))
-#define E_SYSTEMCALL_ERROR (mrb_class_obj_get(mrb, "SystemCallError"))
#define E_LOCALJUMP_ERROR (mrb_class_obj_get(mrb, "LocalJumpError"))
#define E_REGEXP_ERROR (mrb_class_obj_get(mrb, "RegexpError"))
-#define E_ZERODIVISION_ERROR (mrb_class_obj_get(mrb, "ZeroDivisionError"))
-#define E_ENCODING_ERROR (mrb_class_obj_get(mrb, "EncodingError"))
#define E_NOTIMP_ERROR (mrb_class_obj_get(mrb, "NotImplementedError"))
#define E_FLOATDOMAIN_ERROR (mrb_class_obj_get(mrb, "FloatDomainError"))
@@ -462,20 +465,9 @@ NUM2CHR(mrb_value x)
mrb_value mrb_yield(mrb_state *mrb, mrb_value v, mrb_value blk);
mrb_value mrb_yield_argv(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv);
-mrb_value mrb_yield_with_self(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self);
mrb_value mrb_class_new_instance(mrb_state *mrb, int, mrb_value*, struct RClass *);
mrb_value mrb_class_new_instance_m(mrb_state *mrb, mrb_value klass);
-mrb_value mrb_exec_recursive(mrb_state *mrb, mrb_value(*)(mrb_state *, mrb_value, mrb_value, int),mrb_value,void *);
-
-#ifndef xmalloc
-#define xmalloc malloc
-#define xrealloc realloc
-#define xcalloc calloc
-#define xfree free
-#endif
-
-void mrb_garbage_collect(mrb_state *mrb);
void mrb_gc_protect(mrb_state *mrb, mrb_value obj);
mrb_value mrb_to_int(mrb_state *mrb, mrb_value val);
void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t);
diff --git a/include/mruby/array.h b/include/mruby/array.h
index e2acee535..bc10d8919 100644
--- a/include/mruby/array.h
+++ b/include/mruby/array.h
@@ -11,11 +11,20 @@
extern "C" {
#endif
+struct mrb_shared_array {
+ int refcnt;
+ mrb_value *ptr;
+ int len;
+};
+
struct RArray {
MRUBY_OBJECT_HEADER;
- size_t len;
- size_t capa;
- mrb_value *buf;
+ int len;
+ union {
+ int capa;
+ struct mrb_shared_array *shared;
+ } aux;
+ mrb_value *ptr;
};
#define mrb_ary_ptr(v) ((struct RArray*)((v).value.p))
@@ -23,30 +32,28 @@ struct RArray {
#define RARRAY(v) ((struct RArray*)((v).value.p))
#define RARRAY_LEN(a) (RARRAY(a)->len)
-#define RARRAY_PTR(a) (RARRAY(a)->buf)
+#define RARRAY_PTR(a) (RARRAY(a)->ptr)
+#define MRB_ARY_SHARED 256
-mrb_value mrb_ary_new_capa(mrb_state*, size_t);
+void mrb_ary_decref(mrb_state*, struct mrb_shared_array*);
+mrb_value mrb_ary_new_capa(mrb_state*, int);
mrb_value mrb_ary_new(mrb_state *mrb);
-mrb_value mrb_ary_new_elts(mrb_state *mrb, long n, const mrb_value *elts);
+mrb_value mrb_ary_new_elts(mrb_state *mrb, int n, const mrb_value *elts);
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);
mrb_value mrb_ary_pop(mrb_state *mrb, mrb_value ary);
-mrb_value mrb_ary_new_from_values(mrb_state *mrb, size_t size, mrb_value *vals);
+mrb_value mrb_ary_new_from_values(mrb_state *mrb, int size, mrb_value *vals);
mrb_value mrb_ary_aget(mrb_state *mrb, mrb_value self);
mrb_value mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n);
void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val);
int mrb_ary_len(mrb_state *mrb, mrb_value ary);
-mrb_value mrb_ary_replace_m(mrb_state *mrb, mrb_value self);
-void mrb_ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, size_t len);
+void mrb_ary_replace(mrb_state *mrb, mrb_value a, mrb_value b);
mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self);
mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item);
-mrb_value mrb_ary_new4(mrb_state *mrb, long n, const mrb_value *elts);
+mrb_value mrb_ary_new4(mrb_state *mrb, int n, const mrb_value *elts);
mrb_value mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr);
-mrb_value mrb_ary_entry(mrb_value ary, long offset);
-void mrb_mem_clear(mrb_value *mem, long size);
-mrb_value mrb_ary_tmp_new(mrb_state *mrb, long capa);
-mrb_value mrb_ary_sort(mrb_state *mrb, mrb_value ary);
+mrb_value mrb_ary_entry(mrb_value ary, int offset);
mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self);
#if defined(__cplusplus)
diff --git a/include/mruby/class.h b/include/mruby/class.h
index 0afd331b0..2cc90310e 100644
--- a/include/mruby/class.h
+++ b/include/mruby/class.h
@@ -28,7 +28,7 @@ mrb_class(mrb_state *mrb, mrb_value v)
{
switch (mrb_type(v)) {
case MRB_TT_FALSE:
- if (v.value.p)
+ if (v.value.i)
return mrb->false_class;
return mrb->nil_class;
case MRB_TT_TRUE:
@@ -40,14 +40,7 @@ mrb_class(mrb_state *mrb, mrb_value v)
case MRB_TT_FLOAT:
return mrb->float_class;
-#ifdef INCLUDE_REGEXP
-// case MRB_TT_REGEX:
-// return mrb->regex_class;
-// case MRB_TT_MATCH:
-// return mrb->match_class;
-// case MRB_TT_DATA:
-// return mrb->encode_class;
-#else
+#ifdef ENABLE_REGEXP
case MRB_TT_REGEX:
case MRB_TT_MATCH:
mrb_raise(mrb, E_TYPE_ERROR, "type mismatch: %s given",
@@ -78,6 +71,10 @@ struct RClass* mrb_class_real(struct RClass* cl);
void mrb_obj_call_init(mrb_state *mrb, mrb_value obj, int argc, mrb_value *argv);
+void mrb_gc_mark_mt(mrb_state*, struct RClass*);
+size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
+void mrb_gc_free_mt(mrb_state*, struct RClass*);
+
#if defined(__cplusplus)
} /* extern "C" { */
#endif
diff --git a/include/mruby/compile.h b/include/mruby/compile.h
index b41eed57e..aae1b06b1 100644
--- a/include/mruby/compile.h
+++ b/include/mruby/compile.h
@@ -15,12 +15,27 @@ extern "C" {
#include <stdio.h>
#include <setjmp.h>
+/* load context */
+typedef struct mrbc_context {
+ mrb_sym *syms;
+ int slen;
+ char *filename;
+ int lineno;
+ int capture_errors:1;
+ int dump_result:1;
+ int no_exec:1;
+} mrbc_context;
+
+mrbc_context* mrbc_context_new(mrb_state *mrb);
+void mrbc_context_free(mrb_state *mrb, mrbc_context *cxt);
+const char *mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s);
+
+/* AST node structure */
typedef struct mrb_ast_node {
struct mrb_ast_node *car, *cdr;
} mrb_ast_node;
-#include <stdio.h>
-
+/* lexer states */
enum mrb_lex_state_enum {
EXPR_BEG, /* ignore newline, +/- is a sign. */
EXPR_END, /* newline significant, +/- is an operator. */
@@ -36,21 +51,23 @@ enum mrb_lex_state_enum {
EXPR_MAX_STATE
};
+/* saved error message */
struct mrb_parser_message {
int lineno;
int column;
char* message;
};
+/* parser structure */
struct mrb_parser_state {
mrb_state *mrb;
struct mrb_pool *pool;
mrb_ast_node *cells;
const char *s, *send;
FILE *f;
+ char *filename;
int lineno;
int column;
- const char *filename;
enum mrb_lex_state_enum lstate;
int sterm;
@@ -59,6 +76,8 @@ struct mrb_parser_state {
unsigned int cmdarg_stack;
int paren_nest;
int lpar_beg;
+ int in_def, in_single, cmd_start;
+ mrb_ast_node *locals;
mrb_ast_node *pb;
char buf[1024];
@@ -66,9 +85,6 @@ struct mrb_parser_state {
mrb_ast_node *heredoc;
- int in_def, in_single, cmd_start;
- mrb_ast_node *locals;
-
void *ylval;
int nerr;
@@ -82,21 +98,24 @@ struct mrb_parser_state {
jmp_buf jmp;
};
-/* parser structure */
struct mrb_parser_state* mrb_parser_new(mrb_state*);
+void mrb_parser_free(struct mrb_parser_state*);
const char *mrb_parser_filename(struct mrb_parser_state*, const char*);
-int mrb_parser_lineno(struct mrb_parser_state*, int);
-void mrb_parser_parse(struct mrb_parser_state*);
+void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*);
/* utility functions */
-struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*);
-struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*);
-struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,size_t);
+struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*);
+struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*);
+struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,int,mrbc_context*);
int mrb_generate_code(mrb_state*, mrb_ast_node*);
-int mrb_compile_file(mrb_state*,FILE*);
-int mrb_compile_string(mrb_state*,char*);
-int mrb_compile_nstring(mrb_state*,char*,size_t);
+/* program load functions */
+mrb_value mrb_load_file(mrb_state*,FILE*);
+mrb_value mrb_load_string(mrb_state *mrb, const char *s);
+mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, int len);
+mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt);
+mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *cxt);
+mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *cxt);
#if defined(__cplusplus)
} /* extern "C" { */
diff --git a/include/mruby/hash.h b/include/mruby/hash.h
index 1bbd9bd97..f3755eb25 100644
--- a/include/mruby/hash.h
+++ b/include/mruby/hash.h
@@ -17,27 +17,20 @@ struct RHash {
struct kh_ht *ht;
};
-#define mrb_hash_end(h) st_hash_end(h)
-#define mrb_hash_uint(h, i) st_hash_uint(h, i)
-
#define mrb_hash_ptr(v) ((struct RHash*)((v).value.p))
#define mrb_hash_value(p) mrb_obj_value((void*)(p))
-mrb_value mrb_hash_new_capa(mrb_state*, size_t);
-mrb_value mrb_hash_new(mrb_state *mrb, int capa);
+mrb_value mrb_hash_new_capa(mrb_state*, int);
+mrb_value mrb_hash_new(mrb_state *mrb);
void mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val);
mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key);
-mrb_value mrb_hash_getWithDef(mrb_state *mrb, mrb_value hash, mrb_value vkey, mrb_value def);
-mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key);
+mrb_value mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def);
mrb_value mrb_hash(mrb_state *mrb, mrb_value obj);
-mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value self);
/* 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_SIZE(h) (RHASH_TBL(h)->size)
-#define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 0)
#define RHASH_IFNONE(h) mrb_iv_get(mrb, (h), mrb_intern(mrb, "ifnone"))
#define RHASH_PROCDEFAULT(h) RHASH_IFNONE(h)
struct kh_ht * mrb_hash_tbl(mrb_state *mrb, mrb_value hash);
@@ -47,6 +40,11 @@ struct kh_ht * mrb_hash_tbl(mrb_state *mrb, mrb_value hash);
mrb_value mrb_obj_is_proc(mrb_value proc);
+/* GC functions */
+void mrb_gc_mark_ht(mrb_state*, struct RHash*);
+size_t mrb_gc_mark_ht_size(mrb_state*, struct RHash*);
+void mrb_gc_free_ht(mrb_state*, struct RHash*);
+
#if defined(__cplusplus)
} /* extern "C" { */
#endif
diff --git a/include/mruby/khash.h b/include/mruby/khash.h
index 06c451e44..16a35c3d5 100644
--- a/include/mruby/khash.h
+++ b/include/mruby/khash.h
@@ -12,13 +12,16 @@ extern "C" {
#endif
#include <stdint.h>
-#include <stdlib.h>
#include <string.h>
typedef uint32_t khint_t;
typedef khint_t khiter_t;
-#define INITIAL_HASH_SIZE 32
+#ifndef KHASH_DEFAULT_SIZE
+# define KHASH_DEFAULT_SIZE 32
+#endif
+#define KHASH_MIN_SIZE 8
+
#define UPPER_BOUND(x) ((x)>>2|(x>>1))
//extern uint8_t __m[];
@@ -30,18 +33,24 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
#define __ac_isempty(e_flag, d_flag, i) (e_flag[(i)/8]&__m[(i)%8])
#define __ac_isdel(e_flag, d_flag, i) (d_flag[(i)/8]&__m[(i)%8])
#define __ac_iseither(e_flag, d_flag, i) (__ac_isempty(e_flag,d_flag,i)||__ac_isdel(e_flag,d_flag,i))
-
-
-/* struct kh_xxx
+#define khash_power2(v) do { \
+ v--;\
+ v |= v >> 1;\
+ v |= v >> 2;\
+ v |= v >> 4;\
+ v |= v >> 8;\
+ v |= v >> 16;\
+ v++;\
+} while (0);
+
+/* declare struct kh_xxx and kh_xxx_funcs
name: ash name
khkey_t: key data type
khval_t: value data type
- kh_is_map: (not implemented / not used in RiteVM )
- __hash_func: hash function
- __hash_equal: hash comparation function
+ kh_is_map: (not implemented / not used in RiteVM)
*/
-#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
+#define KHASH_DECLARE(name, khkey_t, khval_t, kh_is_map) \
typedef struct kh_##name { \
khint_t n_buckets; \
khint_t size; \
@@ -55,7 +64,28 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
khint_t inc; \
mrb_state *mrb; \
} kh_##name##_t; \
- static void kh_alloc_##name(kh_##name##_t *h) \
+ void kh_alloc_##name(kh_##name##_t *h); \
+ kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size); \
+ kh_##name##_t *kh_init_##name(mrb_state *mrb); \
+ void kh_destroy_##name(kh_##name##_t *h); \
+ void kh_clear_##name(kh_##name##_t *h); \
+ khint_t kh_get_##name(kh_##name##_t *h, khkey_t key); \
+ khint_t kh_put_##name(kh_##name##_t *h, khkey_t key); \
+ void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
+ void kh_del_##name(kh_##name##_t *h, khint_t x); \
+ kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h);
+
+/* define kh_xxx_funcs
+
+ name: ash name
+ khkey_t: key data type
+ khval_t: value data type
+ kh_is_map: (not implemented / not used in RiteVM)
+ __hash_func: hash function
+ __hash_equal: hash comparation function
+*/
+#define KHASH_DEFINE(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
+ void kh_alloc_##name(kh_##name##_t *h) \
{ \
khint_t sz = h->n_buckets; \
h->size = h->n_occupied = 0; \
@@ -69,52 +99,53 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
h->mask = sz-1; \
h->inc = sz/2-1; \
} \
- static inline kh_##name##_t *kh_init_##name(mrb_state *mrb){ \
+ kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size) { \
kh_##name##_t *h = (kh_##name##_t*)mrb_calloc(mrb, 1, sizeof(kh_##name##_t)); \
- h->n_buckets = INITIAL_HASH_SIZE; \
+ if (size < KHASH_MIN_SIZE) \
+ size = KHASH_MIN_SIZE; \
+ khash_power2(size); \
+ h->n_buckets = size; \
h->mrb = mrb; \
kh_alloc_##name(h); \
return h; \
} \
- static inline void kh_destroy_##name(kh_##name##_t *h) \
+ kh_##name##_t *kh_init_##name(mrb_state *mrb){ \
+ return kh_init_##name##_size(mrb, KHASH_DEFAULT_SIZE); \
+ } \
+ void kh_destroy_##name(kh_##name##_t *h) \
{ \
- if( h ){ \
+ if (h) { \
mrb_free(h->mrb, h->keys); \
mrb_free(h->mrb, h->vals); \
mrb_free(h->mrb, h->e_flags); \
mrb_free(h->mrb, h); \
} \
} \
- static inline void kh_clear_##name(kh_##name##_t *h) \
+ void kh_clear_##name(kh_##name##_t *h) \
{ \
- if( h && h->e_flags ){ \
+ 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)); \
h->size = h->n_occupied = 0; \
} \
} \
- static inline khint_t kh_get_##name(kh_##name##_t *h, khkey_t key) \
+ khint_t kh_get_##name(kh_##name##_t *h, khkey_t key) \
{ \
khint_t k = __hash_func(h->mrb,key) & (h->mask); \
- while( !__ac_isempty(h->e_flags, h->d_flags, k) ){ \
- if( !__ac_isdel(h->e_flags, h->d_flags, k) ){ \
- if( __hash_equal(h->mrb,h->keys[k], key) ) return k; \
+ while (!__ac_isempty(h->e_flags, h->d_flags, k)) { \
+ if (!__ac_isdel(h->e_flags, h->d_flags, k)) { \
+ if (__hash_equal(h->mrb,h->keys[k], key)) return k; \
} \
k = (k+h->inc) & (h->mask); \
} \
return h->n_buckets; \
} \
- static inline khint_t kh_put_##name(kh_##name##_t *h, khkey_t key); \
- static void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \
+ void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \
{ \
- if( new_n_buckets<INITIAL_HASH_SIZE ){ \
- new_n_buckets = INITIAL_HASH_SIZE; \
- } else { \
- khint_t limit = new_n_buckets; \
- new_n_buckets = INITIAL_HASH_SIZE; \
- while( new_n_buckets < limit ) new_n_buckets *= 2; \
- } \
- { \
+ if (new_n_buckets < KHASH_MIN_SIZE) \
+ new_n_buckets = KHASH_MIN_SIZE; \
+ khash_power2(new_n_buckets); \
+ { \
uint8_t *old_e_flags = h->e_flags; \
khkey_t *old_keys = h->keys; \
khval_t *old_vals = h->vals; \
@@ -123,32 +154,35 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
h->n_buckets = new_n_buckets; \
kh_alloc_##name(h); \
/* relocate */ \
- for( i=0 ; i<old_n_buckets ; i++ ){ \
- if( !__ac_isempty(old_e_flags, old_d_flags, i) ){ \
- khint_t k = kh_put_##name(h, old_keys[i]); \
- kh_value(h,k) = old_vals[i]; \
- } \
+ for (i=0 ; i<old_n_buckets ; i++) { \
+ if (!__ac_isempty(old_e_flags, old_d_flags, i)) { \
+ khint_t k = kh_put_##name(h, old_keys[i]); \
+ kh_value(h,k) = old_vals[i]; \
+ } \
} \
+ mrb_free(h->mrb, old_e_flags); \
+ mrb_free(h->mrb, old_keys); \
+ mrb_free(h->mrb, old_vals); \
} \
} \
- static inline khint_t kh_put_##name(kh_##name##_t *h, khkey_t key) \
+ khint_t kh_put_##name(kh_##name##_t *h, khkey_t key) \
{ \
khint_t k; \
- if( h->n_occupied >= h->upper_bound ){ \
+ if (h->n_occupied >= h->upper_bound) { \
kh_resize_##name(h, h->n_buckets*2); \
} \
k = __hash_func(h->mrb,key) & (h->mask); \
- while( !__ac_iseither(h->e_flags, h->d_flags, k) ){ \
- if( __hash_equal(h->mrb,h->keys[k], key) ) break; \
+ while (!__ac_iseither(h->e_flags, h->d_flags, k)) { \
+ if (__hash_equal(h->mrb,h->keys[k], key)) break; \
k = (k+h->inc) & (h->mask); \
} \
- if( __ac_isempty(h->e_flags, h->d_flags, k) ) { \
+ if (__ac_isempty(h->e_flags, h->d_flags, k)) { \
/* put at empty */ \
h->keys[k] = key; \
h->e_flags[k/8] &= ~__m[k%8]; \
h->size++; \
h->n_occupied++; \
- } else if( __ac_isdel(h->e_flags, h->d_flags, k) ) { \
+ } else if (__ac_isdel(h->e_flags, h->d_flags, k)) { \
/* put at del */ \
h->keys[k] = key; \
h->d_flags[k/8] &= ~__m[k%8]; \
@@ -156,22 +190,30 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
} \
return k; \
} \
- static inline void kh_del_##name(kh_##name##_t *h, khint_t x) \
+ void kh_del_##name(kh_##name##_t *h, khint_t x) \
{ \
h->d_flags[x/8] |= __m[x%8]; \
h->size--; \
} \
- static inline void kh_debug_##name(kh_##name##_t *h) \
+ kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h) \
{ \
- khint_t i; \
- printf("idx:e_flag:d_flag\n"); \
- for( i=0 ; i<h->n_buckets/8 ; i++ ){ \
- printf("%4d:%02X:%02X\n", i, h->e_flags[i], h->d_flags[i]); \
+ kh_##name##_t *h2; \
+ khiter_t k, k2; \
+ \
+ h2 = kh_init_##name(mrb); \
+ for (k = kh_begin(h); k != kh_end(h); k++) { \
+ if (kh_exist(h, k)) { \
+ k2 = kh_put_##name(h2, kh_key(h, k)); \
+ kh_value(h2, k2) = kh_value(h, k); \
+ } \
} \
- } \
+ return h2; \
+ }
+
#define khash_t(name) kh_##name##_t
+#define kh_init_size(name,mrb,size) kh_init_##name##_size(mrb,size)
#define kh_init(name,mrb) kh_init_##name(mrb)
#define kh_destroy(name, h) kh_destroy_##name(h)
#define kh_clear(name, h) kh_clear_##name(h)
@@ -179,7 +221,7 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
#define kh_put(name, h, k) kh_put_##name(h, k)
#define kh_get(name, h, k) kh_get_##name(h, k)
#define kh_del(name, h, k) kh_del_##name(h, k)
-#define kh_debug(name, h) kh_debug_##name(h)
+#define kh_copy(name, mrb, h) kh_copy_##name(mrb, h)
#define kh_exist(h, x) (!__ac_iseither((h)->e_flags, (h)->d_flags, (x)))
#define kh_key(h, x) ((h)->keys[x])
@@ -203,11 +245,7 @@ static inline khint_t __ac_X31_hash_string(const char *s)
#define kh_str_hash_func(mrb,key) __ac_X31_hash_string(key)
#define kh_str_hash_equal(mrb,a, b) (strcmp(a, b) == 0)
-#define KHASH_MAP_INIT_INT(name, khval_t) \
- KHASH_INIT(name, uint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal)
typedef const char *kh_cstr_t;
-#define KHASH_MAP_INIT_STR(name, khval_t) \
- KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
#if defined(__cplusplus)
} /* extern "C" { */
diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h
index 1bea51152..867aa27d9 100644
--- a/include/mruby/numeric.h
+++ b/include/mruby/numeric.h
@@ -13,15 +13,18 @@ extern "C" {
#include <limits.h>
-#define RSHIFT(x,y) ((x)>>(int)(y))
#define POSFIXABLE(f) ((f) <= INT_MAX)
#define NEGFIXABLE(f) ((f) >= INT_MIN)
#define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f))
mrb_value mrb_flt2big(mrb_state *mrb, mrb_float d);
-void mrb_num_zerodiv(mrb_state *mrb);
mrb_value mrb_fix2str(mrb_state *mrb, mrb_value x, int base);
+mrb_value mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y);
+mrb_value mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y);
+mrb_value mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y);
+mrb_value mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y);
+
#if defined(__cplusplus)
} /* extern "C" { */
#endif
diff --git a/include/mruby/object.h b/include/mruby/object.h
index 495c34083..4be060078 100644
--- a/include/mruby/object.h
+++ b/include/mruby/object.h
@@ -13,7 +13,7 @@ extern "C" {
#define MRUBY_OBJECT_HEADER \
enum mrb_vtype tt:8; \
- int color:3;\
+ unsigned int color:3;\
unsigned int flags:21;\
struct RClass *c;\
struct RBasic *gcnext
diff --git a/include/mruby/proc.h b/include/mruby/proc.h
index 52dc5a98e..f6bef23a5 100644
--- a/include/mruby/proc.h
+++ b/include/mruby/proc.h
@@ -49,6 +49,10 @@ struct RProc {
struct RProc *mrb_proc_new(mrb_state*, mrb_irep*);
struct RProc *mrb_proc_new_cfunc(mrb_state*, mrb_func_t);
struct RProc *mrb_closure_new(mrb_state*, mrb_irep*);
+void mrb_proc_copy(struct RProc *a, struct RProc *b);
+
+#include "mruby/khash.h"
+KHASH_DECLARE(mt, mrb_sym, struct RProc*, 1);
#if defined(__cplusplus)
} /* extern "C" { */
diff --git a/include/mruby/string.h b/include/mruby/string.h
index 39f119ae8..c6f7c4ab5 100644
--- a/include/mruby/string.h
+++ b/include/mruby/string.h
@@ -25,34 +25,33 @@ extern "C" {
extern const char mrb_digitmap[];
+struct mrb_shared_string {
+ int refcnt;
+ char *ptr;
+ int len;
+};
+
struct RString {
MRUBY_OBJECT_HEADER;
int len;
union {
int capa;
- struct RString *shared;
+ struct mrb_shared_string *shared;
} aux;
- char *buf;
+ char *ptr;
};
#define mrb_str_ptr(s) ((struct RString*)((s).value.p))
#define RSTRING(s) ((struct RString*)((s).value.p))
-#define RSTRING_PTR(s) (RSTRING(s)->buf)
+#define RSTRING_PTR(s) (RSTRING(s)->ptr)
#define RSTRING_LEN(s) (RSTRING(s)->len)
#define RSTRING_CAPA(s) (RSTRING(s)->aux.capa)
-#define RSTRING_END(s) (RSTRING(s)->buf + RSTRING(s)->len)
-
+#define RSTRING_END(s) (RSTRING(s)->ptr + RSTRING(s)->len)
#define MRB_STR_SHARED 256
-#define MRB_STR_SHARED_P(s) (FL_ALL(s, MRB_STR_SHARED))
-#define MRB_STR_NOCAPA (MRB_STR_SHARED)
-#define MRB_STR_NOCAPA_P(s) (FL_ANY(s, MRB_STR_NOCAPA))
-#define MRB_STR_UNSET_NOCAPA(s) do {\
- FL_UNSET(s, MRB_STR_NOCAPA);\
-} while (0)
+void mrb_str_decref(mrb_state*, struct 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_obj_to_str(mrb_state*, mrb_value);
mrb_value mrb_str_plus(mrb_state*, mrb_value, mrb_value);
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 */
@@ -78,8 +77,6 @@ int mrb_str_hash_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2);
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_svar(mrb_int cnt);
-mrb_value mrb_str_drop_bytes(mrb_state *mrb, mrb_value str, long len);
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_append(mrb_state *mrb, mrb_value str, mrb_value str2);
diff --git a/include/mruby/struct.h b/include/mruby/struct.h
index 1aee64883..514f66dfe 100644
--- a/include/mruby/struct.h
+++ b/include/mruby/struct.h
@@ -20,9 +20,6 @@ struct RStruct {
#define RSTRUCT_LEN(st) ((int)(RSTRUCT(st)->len))
#define RSTRUCT_PTR(st) (RSTRUCT(st)->ptr)
-mrb_value mrb_yield_values(int n, ...);
-mrb_value mrb_mod_module_eval(mrb_state *mrb, int argc, mrb_value *argv, mrb_value mod);
-
#if defined(__cplusplus)
} /* extern "C" { */
#endif
diff --git a/include/mruby/variable.h b/include/mruby/variable.h
index 880d6217e..e93a77c55 100644
--- a/include/mruby/variable.h
+++ b/include/mruby/variable.h
@@ -14,12 +14,13 @@ extern "C" {
typedef struct global_variable {
int counter;
mrb_value *data;
- mrb_value (*getter)();
- void (*setter)();
+ mrb_value (*getter)(void);
+ void (*setter)(void);
//void (*marker)();
//int block_trace;
//struct trace_var *trace;
} global_variable;
+
struct global_entry {
global_variable *var;
mrb_sym id;
@@ -41,12 +42,23 @@ mrb_value mrb_obj_iv_get(mrb_state*, struct RObject*, mrb_sym);
void mrb_obj_iv_set(mrb_state*, struct RObject*, mrb_sym, mrb_value);
const char * mrb_class2name(mrb_state *mrb, struct RClass* klass);
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); /* mrb_iv_set */
-void mrb_copy_generic_ivar(mrb_value clone, mrb_value obj);
+void mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v);
+mrb_value mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym);
int mrb_const_defined_at(mrb_state *mrb, struct RClass *klass, mrb_sym id);
mrb_value mrb_f_global_variables(mrb_state *mrb, mrb_value self);
mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym);
void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value val);
+mrb_value mrb_obj_instance_variables(mrb_state*, mrb_value);
+
+/* GC functions */
+void mrb_gc_mark_gv(mrb_state*);
+void mrb_gc_free_gv(mrb_state*);
+void mrb_gc_mark_iv(mrb_state*, struct RObject*);
+size_t mrb_gc_mark_iv_size(mrb_state*, struct RObject*);
+void mrb_gc_free_iv(mrb_state*, struct RObject*);
+
+#include "mruby/khash.h"
+KHASH_DECLARE(iv, mrb_sym, mrb_value, 1)
#if defined(__cplusplus)
} /* extern "C" { */
diff --git a/mrblib/Makefile b/mrblib/Makefile
index c7226ddcd..01a5a6198 100644
--- a/mrblib/Makefile
+++ b/mrblib/Makefile
@@ -18,12 +18,19 @@ LIBR := ../lib/libmruby.a
# libraries, includes
INCLUDES = -I../src -I../include
-DEBUG_MODE = 1
-ifeq ($(DEBUG_MODE),1)
-CFLAGS = -g
-else
-CFLAGS = -O3
+ifeq ($(strip $(COMPILE_MODE)),)
+ # default compile option
+ COMPILE_MODE = debug
+endif
+
+ifeq ($(COMPILE_MODE),debug)
+ CFLAGS = -g -O3
+else ifeq ($(COMPILE_MODE),release)
+ CFLAGS = -O3
+else ifeq ($(COMPILE_MODE),small)
+ CFLAGS = -Os
endif
+
ALL_CFLAGS = -Wall -Werror-implicit-function-declaration $(CFLAGS)
ifeq ($(OS),Windows_NT)
MAKE_FLAGS = CC=$(CC) LL=$(LL) ALL_CFLAGS="$(ALL_CFLAGS)"
diff --git a/mrblib/class.rb b/mrblib/class.rb
new file mode 100644
index 000000000..4f268b6c8
--- /dev/null
+++ b/mrblib/class.rb
@@ -0,0 +1,26 @@
+class Module
+ # 15.2.2.4.13
+ def attr_reader(*names)
+ names.each{|name|
+ name2 = ('@'+name.to_s).intern
+ define_method(name){self.instance_variable_get(name2)}
+ }
+ end
+ # 15.2.2.4.14
+ def attr_writer(*names)
+ names.each{|name|
+ name2 = ('@'+name.to_s).intern
+ name = (name.to_s+"=").intern
+ define_method(name){|v|self.instance_variable_set(name2,v)}
+ }
+ end
+ # 15.2.2.4.12
+ def attr_accessor(*names)
+ attr_reader(*names)
+ attr_writer(*names)
+ end
+ # 15.2.2.4.11
+ def attr(name)
+ attr_reader(name)
+ end
+end
diff --git a/mrblib/error.rb b/mrblib/error.rb
index 5660d8235..16e88eefb 100644
--- a/mrblib/error.rb
+++ b/mrblib/error.rb
@@ -12,3 +12,53 @@ class Exception
self.new(*args, &block)
end
end
+
+# ISO 15.2.24
+class ArgumentError < StandardError
+end
+
+# ISO 15.2.25
+class LocalJumpError < StandardError
+end
+
+# ISO 15.2.26
+class RangeError < StandardError
+end
+
+class FloatDomainError < RangeError
+end
+
+# ISO 15.2.26
+class RegexpError < StandardError
+end
+
+# ISO 15.2.29
+class TypeError < StandardError
+end
+
+# ISO 15.2.31
+class NameError < StandardError
+end
+
+# ISO 15.2.32
+class NoMethodError < NameError
+end
+
+# ISO 15.2.33
+class IndexError < StandardError
+end
+
+class KeyError < IndexError
+end
+
+# ISO 15.2.37
+class ScriptError < Exception
+end
+
+# ISO 15.2.38
+class SyntaxError < ScriptError
+end
+
+class NotImplementedError < ScriptError
+end
+
diff --git a/mrblib/hash.rb b/mrblib/hash.rb
index d6ad55e47..7b7b3f8ac 100644
--- a/mrblib/hash.rb
+++ b/mrblib/hash.rb
@@ -80,6 +80,62 @@ class Hash
end
h
end
+
+ # 1.8/1.9 Hash#reject! returns Hash; ISO says nothing.
+ def reject!(&b)
+ keys = []
+ self.each_key{|k|
+ v = self[k]
+ if b.call(k, v)
+ keys.push(k)
+ end
+ }
+ return nil if keys.size == 0
+ keys.each{|k|
+ self.delete(k)
+ }
+ self
+ end
+
+ # 1.8/1.9 Hash#reject returns Hash; ISO says nothing.
+ def reject(&b)
+ h = {}
+ self.each_key{|k|
+ v = self[k]
+ unless b.call(k, v)
+ h[k] = v
+ end
+ }
+ h
+ end
+
+ # 1.9 Hash#select! returns Hash; ISO says nothing.
+ def select!(&b)
+ keys = []
+ self.each_key{|k|
+ v = self[k]
+ unless b.call(k, v)
+ keys.push(k)
+ end
+ }
+ return nil if keys.size == 0
+ keys.each{|k|
+ self.delete(k)
+ }
+ self
+ end
+
+ # 1.9 Hash#select returns Hash; ISO says nothing.
+ def select(&b)
+ h = {}
+ self.each_key{|k|
+ v = self[k]
+ if b.call(k, v)
+ h[k] = v
+ end
+ }
+ h
+ end
end
##
diff --git a/mrblib/kernel.rb b/mrblib/kernel.rb
index e769741b7..ad3bc72f7 100644
--- a/mrblib/kernel.rb
+++ b/mrblib/kernel.rb
@@ -3,17 +3,6 @@
#
# ISO 15.3.1
module Kernel
-
- ##
- # Takes the given block, create a lambda
- # out of it and +call+ it.
- #
- # ISO 15.3.1.2.6
- def self.lambda(&block)
- ### *** TODO *** ###
- block # dummy
- end
-
##
# Calls the given block repetitively.
#
@@ -24,27 +13,14 @@ module Kernel
end
end
- ##
- # Alias for +send+.
- #
- # ISO 15.3.1.3.4
- #def __send__(symbol, *args, &block)
- ### *** TODO *** ###
- #end
-
- # 15.3.1.3.18
- def instance_eval(string=nil, &block)
- ### *** TODO *** ###
- raise "Not implemented yet"
+ # 15.3.1.2.3
+ def self.eval(s)
+ raise NotImplementedError.new("eval not implemented")
end
- ##
- # Alias for +Kernel.lambda+.
- #
- # ISO 15.3.1.3.27
- def lambda(&block)
- ### *** TODO *** ###
- block # dummy
+ # 15.3.1.3.12
+ def eval(s)
+ Kernel.eval(s)
end
##
diff --git a/mrblib/print.rb b/mrblib/print.rb
index 52beb26cb..dea088e2b 100644
--- a/mrblib/print.rb
+++ b/mrblib/print.rb
@@ -3,47 +3,76 @@
#
# 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
+ ##
+ # 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
- 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
- __printstr__ args[i].to_s
- __printstr__ "\n"
- i += 1
- end
- __printstr__ "\n" if len == 0
- 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
+ __printstr__ args[i].to_s
+ __printstr__ "\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]
+ ##
+ # 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))
+ end
end
end
diff --git a/mrblib/string.rb b/mrblib/string.rb
index ad7e1fca1..d09b787da 100644
--- a/mrblib/string.rb
+++ b/mrblib/string.rb
@@ -33,12 +33,15 @@ class String
end
### *** TODO *** ###
+ unless Object.const_defined?(:Regexp)
+ raise NotImplementedError, "gsub not available (yet)"
+ end
end
##
# Replace all matches of +pattern+ with +replacement+.
# Call block (if given) for each match and replace
- # +pattern+ with the value of the block. Modify
+ # +pattern+ with the value of the block. Modify
# +self+ with the final value.
#
# ISO 15.2.10.5.19
@@ -56,15 +59,18 @@ class String
# Calls the given block for each match of +pattern+
# If no block is given return an array with all
# matches of +pattern+.
- #
+ #
# ISO 15.2.10.5.32
def scan(reg, &block)
### *** TODO *** ###
+ unless Object.const_defined?(:Regexp)
+ raise NotImplementedError, "scan not available (yet)"
+ end
end
##
- # Replace only the first match of +pattern+ with
- # +replacement+. Call block (if given) for each
+ # Replace only the first match of +pattern+ with
+ # +replacement+. Call block (if given) for each
# match and replace +pattern+ with the value of the
# block. Return the final value.
#
@@ -75,12 +81,15 @@ class String
end
### *** TODO *** ###
+ unless Object.const_defined?(:Regexp)
+ raise NotImplementedError, "sub not available (yet)"
+ end
end
##
- # Replace only the first match of +pattern+ with
- # +replacement+. Call block (if given) for each
- # match and replace +pattern+ with the value of the
+ # Replace only the first match of +pattern+ with
+ # +replacement+. Call block (if given) for each
+ # match and replace +pattern+ with the value of the
# block. Modify +self+ with the final value.
#
# ISO 15.2.10.5.37
diff --git a/mrblib/struct.rb b/mrblib/struct.rb
index 4b6d767a9..5d0ede90f 100644
--- a/mrblib/struct.rb
+++ b/mrblib/struct.rb
@@ -2,45 +2,49 @@
# Struct
#
# ISO 15.2.18
-class Struct
- ##
- # Calls the given block for each element of +self+
- # and pass the respective element.
- #
- # ISO 15.2.18.4.4
- def each(&block)
- self.class.members.each{|field|
- block.call(self[field])
- }
- self
- end
+if Object.const_defined?(:Struct)
+ class Struct
- ##
- # Calls the given block for each element of +self+
- # and pass the name and value of the respectiev
- # element.
- #
- # ISO 15.2.18.4.5
- def each_pair(&block)
- self.class.members.each{|field|
- block.call(field.to_sym, self[field])
- }
- self
- end
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the respective element.
+ #
+ # ISO 15.2.18.4.4
+ def each(&block)
+ self.class.members.each{|field|
+ block.call(self[field])
+ }
+ self
+ end
- ##
- # Calls the given block for each element of +self+
- # and returns an array with all elements of which
- # block is not false.
- #
- # ISO 15.2.18.4.7
- def select(&block)
- ary = []
- self.class.members.each{|field|
- val = self[field]
- ary.push(val) if block.call(val)
- }
- ary
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the name and value of the respectiev
+ # element.
+ #
+ # ISO 15.2.18.4.5
+ def each_pair(&block)
+ self.class.members.each{|field|
+ block.call(field.to_sym, self[field])
+ }
+ self
+ end
+
+ ##
+ # Calls the given block for each element of +self+
+ # and returns an array with all elements of which
+ # block is not false.
+ #
+ # ISO 15.2.18.4.7
+ def select(&block)
+ ary = []
+ self.class.members.each{|field|
+ val = self[field]
+ ary.push(val) if block.call(val)
+ }
+ ary
+ end
end
end
+
diff --git a/mruby/HelloMRuby/hello_mruby.c b/mruby/HelloMRuby/hello_mruby.c
deleted file mode 100644
index b727c95ec..000000000
--- a/mruby/HelloMRuby/hello_mruby.c
+++ /dev/null
@@ -1,9 +0,0 @@
-//
-// hello_mruby.c
-// mruby
-//
-// Created by Paolo Bosetti on 5/22/12.
-// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
-//
-
-#include <stdio.h>
diff --git a/src/Makefile b/src/Makefile
index 61012ea68..13f80b694 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -19,12 +19,19 @@ OBJS := $(OBJ1) $(OBJ2) $(OBJ3)
# libraries, includes
INCLUDES = -I$(BASEDIR) -I$(BASEDIR)/../include
-DEBUG_MODE = 1
-ifeq ($(DEBUG_MODE),1)
-CFLAGS = -g -O3
-else
-CFLAGS = -O3
+ifeq ($(strip $(COMPILE_MODE)),)
+ # default compile option
+ COMPILE_MODE = debug
endif
+
+ifeq ($(COMPILE_MODE),debug)
+ CFLAGS = -g -O3
+else ifeq ($(COMPILE_MODE),release)
+ CFLAGS = -O3
+else ifeq ($(COMPILE_MODE),small)
+ CFLAGS = -Os
+endif
+
ALL_CFLAGS = -Wall -Werror-implicit-function-declaration $(CFLAGS)
diff --git a/src/array.c b/src/array.c
index 187a8404d..804c946da 100644
--- a/src/array.c
+++ b/src/array.c
@@ -10,15 +10,14 @@
#include "mruby/string.h"
#include "mruby/class.h"
-//#define ARY_DEFAULT_LEN 16
#define ARY_DEFAULT_LEN 4
#define ARY_SHRINK_RATIO 5 /* must be larger than 2 */
-#ifdef LONG_MAX
-# define ARY_MAX_SIZE (LONG_MAX / sizeof(mrb_value))
+#ifdef INT_MAX
+# define ARY_MAX_SIZE (INT_MAX / sizeof(mrb_value))
#endif
static inline mrb_value
-ary_elt(mrb_value ary, long offset)
+ary_elt(mrb_value ary, int offset)
{
if (RARRAY_LEN(ary) == 0) return mrb_nil_value();
if (offset < 0 || RARRAY_LEN(ary) <= offset) {
@@ -28,12 +27,12 @@ ary_elt(mrb_value ary, long offset)
}
static struct RArray*
-ary_new_capa(mrb_state *mrb, size_t capa)
+ary_new_capa(mrb_state *mrb, int capa)
{
struct RArray *a;
- size_t blen;
+ int blen;
-#ifdef LONG_MAX
+#ifdef INT_MAX
if (capa > ARY_MAX_SIZE) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "ary size too big");
}
@@ -47,16 +46,15 @@ ary_new_capa(mrb_state *mrb, size_t capa)
}
a = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class);
- a->buf = mrb_malloc(mrb, blen);
- memset(a->buf, 0, blen);
- a->capa = capa;
+ a->ptr = (mrb_value *)mrb_calloc(mrb, blen, 1);
+ a->aux.capa = capa;
a->len = 0;
return a;
}
mrb_value
-mrb_ary_new_capa(mrb_state *mrb, size_t capa)
+mrb_ary_new_capa(mrb_state *mrb, int capa)
{
struct RArray *a = ary_new_capa(mrb, capa);
return mrb_obj_value(a);
@@ -69,14 +67,14 @@ mrb_ary_new(mrb_state *mrb)
}
mrb_value
-mrb_ary_new_from_values(mrb_state *mrb, size_t size, mrb_value *vals)
+mrb_ary_new_from_values(mrb_state *mrb, int size, mrb_value *vals)
{
mrb_value ary;
struct RArray *a;
ary = mrb_ary_new_capa(mrb, size);
a = mrb_ary_ptr(ary);
- memcpy(a->buf, vals, sizeof(mrb_value)*size);
+ memcpy(a->ptr, vals, sizeof(mrb_value)*size);
a->len = size;
return ary;
@@ -91,22 +89,70 @@ mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr)
return mrb_ary_new_from_values(mrb, 2, arv);
}
-void
-ary_fill_with_nil(mrb_value *buf, size_t size)
+static void
+ary_fill_with_nil(mrb_value *ptr, int size)
{
mrb_value nil = mrb_nil_value();
while((int)(size--)) {
- *buf++ = nil;
+ *ptr++ = nil;
}
}
-void
-mrb_ary_expand_capa(mrb_state *mrb, struct RArray *a, size_t len)
+static void
+ary_modify(mrb_state *mrb, struct RArray *a)
+{
+ if (a->flags & MRB_ARY_SHARED) {
+ struct mrb_shared_array *shared = a->aux.shared;
+
+ if (shared->refcnt == 1 && a->ptr == shared->ptr) {
+ a->ptr = shared->ptr;
+ a->aux.capa = a->len;
+ mrb_free(mrb, shared);
+ }
+ else {
+ mrb_value *ptr, *p;
+ int len;
+
+ p = a->ptr;
+ len = a->len * sizeof(mrb_value);
+ ptr = (mrb_value *)mrb_malloc(mrb, len);
+ if (p) {
+ memcpy(ptr, p, len);
+ }
+ a->ptr = ptr;
+ a->aux.capa = a->len;
+ mrb_ary_decref(mrb, shared);
+ }
+ a->flags &= ~MRB_ARY_SHARED;
+ }
+}
+
+static void
+ary_make_shared(mrb_state *mrb, struct RArray *a)
+{
+ if (!(a->flags & MRB_ARY_SHARED)) {
+ struct mrb_shared_array *shared = (struct mrb_shared_array *)mrb_malloc(mrb, sizeof(struct mrb_shared_array));
+
+ shared->refcnt = 1;
+ if (a->aux.capa > a->len) {
+ a->ptr = shared->ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*a->len+1);
+ }
+ else {
+ shared->ptr = a->ptr;
+ }
+ shared->len = a->len;
+ a->aux.shared = shared;
+ a->flags |= MRB_ARY_SHARED;
+ }
+}
+
+static void
+ary_expand_capa(mrb_state *mrb, struct RArray *a, int len)
{
- size_t capa = a->capa;
+ int capa = a->aux.capa;
-#ifdef LONG_MAX
+#ifdef INT_MAX
if (len > ARY_MAX_SIZE) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
}
@@ -121,20 +167,20 @@ mrb_ary_expand_capa(mrb_state *mrb, struct RArray *a, size_t len)
}
}
-#ifdef LONG_MAX
+#ifdef INT_MAX
if (capa > ARY_MAX_SIZE) capa = ARY_MAX_SIZE; /* len <= capa <= ARY_MAX_SIZE */
#endif
- if (capa > a->capa) {
- a->capa = capa;
- a->buf = mrb_realloc(mrb, a->buf, sizeof(mrb_value)*capa);
+ if (capa > a->aux.capa) {
+ a->aux.capa = capa;
+ a->ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa);
}
}
-void
-mrb_ary_shrink_capa(mrb_state *mrb, struct RArray *a)
+static void
+ary_shrink_capa(mrb_state *mrb, struct RArray *a)
{
- size_t capa = a->capa;
+ int capa = a->aux.capa;
if (capa < ARY_DEFAULT_LEN * 2) return;
if (capa <= a->len * ARY_SHRINK_RATIO) return;
@@ -147,9 +193,9 @@ mrb_ary_shrink_capa(mrb_state *mrb, struct RArray *a)
}
} while(capa > a->len * ARY_SHRINK_RATIO);
- if (capa > a->len && capa < a->capa) {
- a->capa = capa;
- a->buf = mrb_realloc(mrb, a->buf, sizeof(mrb_value)*capa);
+ if (capa > a->len && capa < a->aux.capa) {
+ a->aux.capa = capa;
+ a->ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa);
}
}
@@ -160,29 +206,37 @@ mrb_ary_s_create(mrb_state *mrb, mrb_value self)
int len;
mrb_get_args(mrb, "*", &vals, &len);
- return mrb_ary_new_from_values(mrb, (size_t)len, vals);
+ return mrb_ary_new_from_values(mrb, (int)len, vals);
+}
+
+static void
+ary_concat(mrb_state *mrb, struct RArray *a, mrb_value *ptr, int blen)
+{
+ int len = a->len + blen;
+
+ ary_modify(mrb, a);
+ if (a->aux.capa < len) ary_expand_capa(mrb, a, len);
+ memcpy(a->ptr+a->len, ptr, sizeof(mrb_value)*blen);
+ mrb_write_barrier(mrb, (struct RBasic*)a);
+ a->len = len;
}
void
mrb_ary_concat(mrb_state *mrb, mrb_value self, mrb_value other)
{
- struct RArray *a1 = mrb_ary_ptr(self);
struct RArray *a2 = mrb_ary_ptr(other);
- size_t len = a1->len + a2->len;
- if (a1->capa < len) mrb_ary_expand_capa(mrb, a1, len);
- memcpy(a1->buf+a1->len, a2->buf, sizeof(mrb_value)*a2->len);
- mrb_write_barrier(mrb, (struct RBasic*)a1);
- a1->len = len;
+ ary_concat(mrb, mrb_ary_ptr(self), a2->ptr, a2->len);
}
mrb_value
mrb_ary_concat_m(mrb_state *mrb, mrb_value self)
{
- mrb_value other;
+ mrb_value *ptr;
+ int blen;
- mrb_get_args(mrb, "A", &other);
- mrb_ary_concat(mrb, self, other);
+ mrb_get_args(mrb, "a", &ptr, &blen);
+ ary_concat(mrb, mrb_ary_ptr(self), ptr, blen);
return self;
}
@@ -191,15 +245,16 @@ mrb_ary_plus(mrb_state *mrb, mrb_value self)
{
struct RArray *a1 = mrb_ary_ptr(self);
struct RArray *a2;
- mrb_value other;
mrb_value ary;
+ mrb_value *ptr;
+ int blen;
- mrb_get_args(mrb, "A", &other);
- ary = mrb_ary_new_capa(mrb, a1->len + RARRAY_LEN(other));
+ mrb_get_args(mrb, "a", &ptr, &blen);
+ ary = mrb_ary_new_capa(mrb, a1->len + blen);
a2 = mrb_ary_ptr(ary);
- memcpy(a2->buf, a1->buf, sizeof(mrb_value)*a1->len);
- memcpy(a2->buf + a1->len, RARRAY_PTR(other), sizeof(mrb_value)*RARRAY_LEN(other));
- a2->len = a1->len + RARRAY_LEN(other);
+ memcpy(a2->ptr, a1->ptr, sizeof(mrb_value)*a1->len);
+ memcpy(a2->ptr + a1->len, ptr, sizeof(mrb_value)*blen);
+ a2->len = a1->len + blen;
return ary;
}
@@ -228,12 +283,12 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1)
mrb_value ary2;
struct RArray *a1, *a2;
mrb_value r = mrb_nil_value();
- long i, len;
+ int i, len;
mrb_get_args(mrb, "o", &ary2);
if (mrb_type(ary2) != MRB_TT_ARRAY) return mrb_nil_value();
a1 = RARRAY(ary1); a2 = RARRAY(ary2);
- if (a1->len == a2->len && a1->buf == a2->buf) return mrb_fixnum_value(0);
+ if (a1->len == a2->len && a1->ptr == a2->ptr) return mrb_fixnum_value(0);
else {
len = RARRAY_LEN(ary1);
if (len > RARRAY_LEN(ary2)) {
@@ -248,22 +303,32 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1)
return mrb_fixnum_value((len == 0)? 0: (len > 0)? 1: -1);
}
-void
-mrb_ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, size_t len)
+static void
+ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, int len)
{
- if (a->capa < len) mrb_ary_expand_capa(mrb, a, len);
- memcpy(a->buf, argv, sizeof(mrb_value)*len);
+ ary_modify(mrb, a);
+ if (a->aux.capa < len)
+ ary_expand_capa(mrb, a, len);
+ memcpy(a->ptr, argv, sizeof(mrb_value)*len);
mrb_write_barrier(mrb, (struct RBasic*)a);
a->len = len;
}
+void
+mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other)
+{
+ struct RArray *a2 = mrb_ary_ptr(other);
+
+ ary_replace(mrb, mrb_ary_ptr(self), a2->ptr, a2->len);
+}
+
mrb_value
mrb_ary_replace_m(mrb_state *mrb, mrb_value self)
{
mrb_value other;
- mrb_get_args(mrb, "o", &other);
- mrb_ary_replace(mrb, mrb_ary_ptr(self), RARRAY_PTR(other), RARRAY_LEN(other));
+ mrb_get_args(mrb, "A", &other);
+ mrb_ary_replace(mrb, self, other);
return self;
}
@@ -274,9 +339,8 @@ mrb_ary_times(mrb_state *mrb, mrb_value self)
struct RArray *a1 = mrb_ary_ptr(self);
struct RArray *a2;
mrb_value ary;
- mrb_value *buf;
+ mrb_value *ptr;
mrb_int times;
- //size_t len;
mrb_get_args(mrb, "i", &times);
if (times < 0) {
@@ -286,38 +350,32 @@ mrb_ary_times(mrb_state *mrb, mrb_value self)
ary = mrb_ary_new_capa(mrb, a1->len * times);
a2 = mrb_ary_ptr(ary);
- buf = a2->buf;
+ ptr = a2->ptr;
while(times--) {
- memcpy(buf, a1->buf, sizeof(mrb_value)*(a1->len));
- buf += a1->len;
+ memcpy(ptr, a1->ptr, sizeof(mrb_value)*(a1->len));
+ ptr += a1->len;
a2->len += a1->len;
}
return ary;
}
-static void
-ary_reverse(struct RArray *a)
-{
- mrb_value *p1, *p2;
-
- p1 = a->buf;
- p2 = a->buf + a->len - 1;
-
- while(p1 < p2) {
- mrb_value tmp = *p1;
- *p1++ = *p2;
- *p2-- = tmp;
- }
-}
-
mrb_value
mrb_ary_reverse_bang(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
if (a->len > 1) {
- ary_reverse(a);
+ mrb_value *p1, *p2;
+
+ p1 = a->ptr;
+ p2 = a->ptr + a->len - 1;
+
+ while(p1 < p2) {
+ mrb_value tmp = *p1;
+ *p1++ = *p2;
+ *p2-- = tmp;
+ }
}
return self;
}
@@ -325,33 +383,41 @@ mrb_ary_reverse_bang(mrb_state *mrb, mrb_value self)
mrb_value
mrb_ary_reverse(mrb_state *mrb, mrb_value self)
{
- struct RArray *a = mrb_ary_ptr(self);
+ struct RArray *a = mrb_ary_ptr(self), *b;
mrb_value ary;
ary = mrb_ary_new_capa(mrb, a->len);
+ b = mrb_ary_ptr(ary);
if (a->len > 0) {
- mrb_ary_replace(mrb, mrb_ary_ptr(ary), a->buf, a->len);
- ary_reverse(mrb_ary_ptr(ary));
+ mrb_value *p1, *p2, *e;
+
+ p1 = a->ptr;
+ e = p1 + a->len;
+ p2 = b->ptr + a->len - 1;
+ while(p1 < e) {
+ *p2-- = *p1++;
+ }
+ b->len = a->len;
}
return ary;
}
mrb_value
-mrb_ary_new4(mrb_state *mrb, long n, const mrb_value *elts)
+mrb_ary_new4(mrb_state *mrb, int n, const mrb_value *elts)
{
mrb_value ary;
- ary = mrb_ary_new_capa(mrb, n);//mrb_ary_new2(n);
+ ary = mrb_ary_new_capa(mrb, n);
if (n > 0 && elts) {
memcpy(RARRAY_PTR(ary), elts, sizeof(mrb_value)*n);
- RARRAY_LEN(ary) = n; //ARY_SET_LEN(ary, n);
+ RARRAY_LEN(ary) = n;
}
return ary;
}
mrb_value
-mrb_ary_new_elts(mrb_state *mrb, long n, const mrb_value *elts)
+mrb_ary_new_elts(mrb_state *mrb, int n, const mrb_value *elts)
{
return mrb_ary_new4(mrb, n, elts);
}
@@ -361,22 +427,14 @@ mrb_ary_push(mrb_state *mrb, mrb_value ary, mrb_value elem) /* mrb_ary_push */
{
struct RArray *a = mrb_ary_ptr(ary);
- if (a->len == a->capa) mrb_ary_expand_capa(mrb, a, a->len + 1);
- a->buf[a->len++] = elem;
+ ary_modify(mrb, a);
+ if (a->len == a->aux.capa)
+ ary_expand_capa(mrb, a, a->len + 1);
+ a->ptr[a->len++] = elem;
mrb_write_barrier(mrb, (struct RBasic*)a);
}
mrb_value
-mrb_ary_pop(mrb_state *mrb, mrb_value ary)
-{
- struct RArray *a = mrb_ary_ptr(ary);
-
- if (a->len == 0) return mrb_nil_value();
-
- return a->buf[--a->len];
-}
-
-mrb_value
mrb_ary_push_m(mrb_state *mrb, mrb_value self)
{
mrb_value *argv;
@@ -391,30 +449,45 @@ mrb_ary_push_m(mrb_state *mrb, mrb_value self)
}
mrb_value
-mrb_ary_pop_m(mrb_state *mrb, mrb_value self)
+mrb_ary_pop(mrb_state *mrb, mrb_value ary)
{
- struct RArray *a = mrb_ary_ptr(self);
+ struct RArray *a = mrb_ary_ptr(ary);
- return ((a->len == 0)? mrb_nil_value(): mrb_ary_pop(mrb, self));
+ if (a->len == 0) return mrb_nil_value();
+ return a->ptr[--a->len];
}
+#define ARY_SHIFT_SHARED_MIN 10
+
mrb_value
mrb_ary_shift(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
- mrb_value *buf = a->buf;
- size_t size = a->len;
mrb_value val;
- if (size == 0) return mrb_nil_value();
-
- val = *buf;
- while((int)(--size)) {
- *buf = *(buf+1);
- ++buf;
+ if (a->len == 0) return mrb_nil_value();
+ if (a->flags & MRB_ARY_SHARED) {
+ L_SHIFT:
+ val = a->ptr[0];
+ a->ptr++;
+ a->len--;
+ return val;
}
- --a->len;
+ if (a->len > ARY_SHIFT_SHARED_MIN) {
+ ary_make_shared(mrb, a);
+ goto L_SHIFT;
+ }
+ else {
+ mrb_value *ptr = a->ptr;
+ int size = a->len;
+ val = *ptr;
+ while((int)(--size)) {
+ *ptr = *(ptr+1);
+ ++ptr;
+ }
+ --a->len;
+ }
return val;
}
@@ -427,10 +500,20 @@ mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item)
{
struct RArray *a = mrb_ary_ptr(self);
- if (a->capa < a->len + 1) mrb_ary_expand_capa(mrb, a, a->len + 1);
- memmove(a->buf + 1, a->buf, sizeof(mrb_value)*a->len);
- memcpy(a->buf, &item, sizeof(mrb_value));
- a->len += 1;
+ if ((a->flags & MRB_ARY_SHARED)
+ && a->aux.shared->refcnt == 1 /* shared only referenced from this array */
+ && a->ptr - a->aux.shared->ptr >= 1) /* there's room for unshifted item */ {
+ a->ptr--;
+ a->ptr[0] = item;
+ }
+ else {
+ 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);
+ a->ptr[0] = item;
+ }
+ a->len++;
mrb_write_barrier(mrb, (struct RBasic*)a);
return self;
@@ -444,10 +527,19 @@ mrb_ary_unshift_m(mrb_state *mrb, mrb_value self)
int len;
mrb_get_args(mrb, "*", &vals, &len);
- if (len == 0) return self;
- if (a->capa < a->len + len) mrb_ary_expand_capa(mrb, a, a->len + len);
- memmove(a->buf + len, a->buf, sizeof(mrb_value)*a->len);
- memcpy(a->buf, vals, sizeof(mrb_value)*len);
+ if ((a->flags & MRB_ARY_SHARED)
+ && a->aux.shared->refcnt == 1 /* shared only referenced from this array */
+ && a->ptr - a->aux.shared->ptr >= len) /* there's room for unshifted item */ {
+ a->ptr -= len;
+ }
+ else {
+ ary_modify(mrb, a);
+ 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);
+ }
+ memcpy(a->ptr, vals, sizeof(mrb_value)*len);
a->len += len;
mrb_write_barrier(mrb, (struct RBasic*)a);
@@ -461,9 +553,9 @@ mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n)
/* range check */
if (n < 0) n += a->len;
- if (n < 0 || a->len <= (size_t)n) return mrb_nil_value();
+ if (n < 0 || a->len <= (int)n) return mrb_nil_value();
- return a->buf[n];
+ return a->ptr[n];
}
void
@@ -471,18 +563,22 @@ mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val) /* rb_ary_s
{
struct RArray *a = mrb_ary_ptr(ary);
+ ary_modify(mrb, a);
/* range check */
- if (n < 0) n += a->len;
if (n < 0) {
- mrb_raise(mrb, E_INDEX_ERROR, "index %ld out of array", n - a->len);
+ n += a->len;
+ if (n < 0) {
+ mrb_raise(mrb, E_INDEX_ERROR, "index %ld out of array", n - a->len);
+ }
}
- if (a->len <= (size_t)n) {
- if (a->capa <= (size_t)n) mrb_ary_expand_capa(mrb, a, n + 1);
- ary_fill_with_nil(a->buf + a->len, n + 1 - a->len);
+ if (a->len <= (int)n) {
+ if (a->aux.capa <= (int)n)
+ ary_expand_capa(mrb, a, n + 1);
+ ary_fill_with_nil(a->ptr + a->len, n + 1 - a->len);
a->len = n + 1;
}
- a->buf[n] = val;
+ a->ptr[n] = val;
mrb_write_barrier(mrb, (struct RBasic*)a);
}
@@ -491,14 +587,17 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val
{
struct RArray *a = mrb_ary_ptr(ary);
mrb_int tail;
- size_t size;
+ int size;
mrb_value *argv;
int i, argc;
+ ary_modify(mrb, a);
/* range check */
- if (head < 0) head += a->len;
if (head < 0) {
- mrb_raise(mrb, E_INDEX_ERROR, "index is out of array");
+ head += a->len;
+ if (head < 0) {
+ mrb_raise(mrb, E_INDEX_ERROR, "index is out of array");
+ }
}
tail = head + len;
@@ -515,17 +614,18 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val
if (tail < a->len) size += a->len - tail;
- if (size > a->capa) mrb_ary_expand_capa(mrb, a, size);
+ if (size > a->aux.capa)
+ ary_expand_capa(mrb, a, size);
if (head > a->len) {
- ary_fill_with_nil(a->buf + a->len, (size_t)(head - a->len));
+ ary_fill_with_nil(a->ptr + a->len, (int)(head - a->len));
}
else if (head < a->len) {
- memmove(a->buf + head + argc, a->buf + tail, sizeof(mrb_value)*(a->len - tail));
+ memmove(a->ptr + head + argc, a->ptr + tail, sizeof(mrb_value)*(a->len - tail));
}
for(i = 0; i < argc; i++) {
- *(a->buf + head + i) = *(argv + i);
+ *(a->ptr + head + i) = *(argv + i);
}
a->len = size;
@@ -539,6 +639,32 @@ mrb_ary_alen(mrb_state *mrb, mrb_value ary)
return RARRAY_LEN(ary);
}
+void
+mrb_ary_decref(mrb_state *mrb, struct mrb_shared_array *shared)
+{
+ shared->refcnt--;
+ if (shared->refcnt == 0) {
+ mrb_free(mrb, shared->ptr);
+ mrb_free(mrb, shared);
+ }
+}
+
+static mrb_value
+ary_subseq(mrb_state *mrb, struct RArray *a, int beg, int len)
+{
+ struct RArray *b;
+
+ ary_make_shared(mrb, a);
+ b = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class);
+ b->ptr = a->ptr + beg;
+ b->len = len;
+ b->aux.shared = a->aux.shared;
+ b->aux.shared->refcnt++;
+ b->flags |= MRB_ARY_SHARED;
+
+ return mrb_obj_value(b);
+}
+
mrb_value
mrb_ary_aget(mrb_state *mrb, mrb_value self)
{
@@ -556,13 +682,13 @@ mrb_ary_aget(mrb_state *mrb, mrb_value self)
if (mrb_type(argv[0]) != MRB_TT_FIXNUM) {
mrb_raise(mrb, E_TYPE_ERROR, "expected Fixnum");
}
- len = mrb_fixnum(argv[0]);
if (index < 0) index += a->len;
- if (index < 0 || a->len < (size_t)index) return mrb_nil_value();
- if ((len = mrb_fixnum(argv[0])) < 0) return mrb_nil_value();
- if (a->len == (size_t)index) return mrb_ary_new(mrb);
- if ((size_t)len > a->len - index) len = a->len - index;
- return mrb_ary_new_from_values(mrb, len, a->buf + index);
+ if (index < 0 || a->len < (int)index) return mrb_nil_value();
+ len = mrb_fixnum(argv[0]);
+ if (len < 0) return mrb_nil_value();
+ if (a->len == (int)index) return mrb_ary_new(mrb);
+ if ((int)len > a->len - index) len = a->len - index;
+ return ary_subseq(mrb, a, index, len);
default:
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
@@ -606,24 +732,25 @@ mrb_ary_delete_at(mrb_state *mrb, mrb_value self)
struct RArray *a = mrb_ary_ptr(self);
mrb_int index;
mrb_value val;
- mrb_value *buf;
- size_t len;
+ mrb_value *ptr;
+ int len;
mrb_get_args(mrb, "i", &index);
if (index < 0) index += a->len;
- if (index < 0 || a->len <= (size_t)index) return mrb_nil_value();
+ if (index < 0 || a->len <= (int)index) return mrb_nil_value();
- val = a->buf[index];
+ ary_modify(mrb, a);
+ val = a->ptr[index];
- buf = a->buf + index;
+ ptr = a->ptr + index;
len = a->len - index;
while((int)(--len)) {
- *buf = *(buf+1);
- ++buf;
+ *ptr = *(ptr+1);
+ ++ptr;
}
--a->len;
- mrb_ary_shrink_capa(mrb, a);
+ ary_shrink_capa(mrb, a);
return val;
}
@@ -632,30 +759,27 @@ mrb_value
mrb_ary_first(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
- //mrb_value ary;
- size_t size;
- mrb_value *vals;
- int len;
+ int size;
- mrb_get_args(mrb, "*", &vals, &len);
- if (len > 1) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
+ if (mrb_get_args(mrb, "|i", &size) == 0) {
+ return (a->len > 0)? a->ptr[0]: mrb_nil_value();
+ }
+ if (size < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size");
}
- if (len == 0) return (a->len > 0)? a->buf[0]: mrb_nil_value();
-
- /* len == 1 */
- size = mrb_fixnum(*vals);
if (size > a->len) size = a->len;
- return mrb_ary_new_from_values(mrb, size, a->buf);
+ if (a->flags & MRB_ARY_SHARED) {
+ return ary_subseq(mrb, a, 0, size);
+ }
+ return mrb_ary_new_from_values(mrb, size, a->ptr);
}
mrb_value
mrb_ary_last(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
- //mrb_value ary;
- size_t size;
+ int size;
mrb_value *vals;
int len;
@@ -664,19 +788,25 @@ mrb_ary_last(mrb_state *mrb, mrb_value self)
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
}
- if (len == 0) return (a->len > 0)? a->buf[a->len - 1]: mrb_nil_value();
+ if (len == 0) return (a->len > 0)? a->ptr[a->len - 1]: mrb_nil_value();
/* len == 1 */
size = mrb_fixnum(*vals);
+ if (size < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size");
+ }
if (size > a->len) size = a->len;
- return mrb_ary_new_from_values(mrb, size, a->buf + a->len - size);
+ if ((a->flags & MRB_ARY_SHARED) || size > ARY_DEFAULT_LEN) {
+ return ary_subseq(mrb, a, a->len - size, size);
+ }
+ return mrb_ary_new_from_values(mrb, size, a->ptr + a->len - size);
}
mrb_value
mrb_ary_index_m(mrb_state *mrb, mrb_value self)
{
mrb_value obj;
- long i;
+ int i;
mrb_get_args(mrb, "o", &obj);
for (i = 0; i < RARRAY_LEN(self); i++) {
@@ -691,7 +821,7 @@ mrb_value
mrb_ary_rindex_m(mrb_state *mrb, mrb_value self)
{
mrb_value obj;
- long i;
+ int i;
mrb_get_args(mrb, "o", &obj);
for (i = RARRAY_LEN(self) - 1; i >= 0; i--) {
@@ -727,7 +857,8 @@ mrb_ary_clear(mrb_state *mrb, mrb_value self)
struct RArray *a = mrb_ary_ptr(self);
a->len = 0;
- mrb_ary_shrink_capa(mrb, a);
+ ary_modify(mrb, a);
+ ary_shrink_capa(mrb, a);
return self;
}
@@ -747,7 +878,7 @@ mrb_check_array_type(mrb_state *mrb, mrb_value ary)
}
mrb_value
-mrb_ary_entry(mrb_value ary, long offset)
+mrb_ary_entry(mrb_value ary, int offset)
{
if (offset < 0) {
offset += RARRAY_LEN(ary);
@@ -755,58 +886,43 @@ mrb_ary_entry(mrb_value ary, long offset)
return ary_elt(ary, offset);
}
-void
-mrb_mem_clear(mrb_value *mem, long size)
-{
- while (size--) {
- *mem++ = mrb_nil_value();
- }
-}
-
-mrb_value
-mrb_ary_tmp_new(mrb_state *mrb, long capa)
-{
- return mrb_ary_new_capa(mrb, capa);//ary_new(0, capa);
-}
-
static mrb_value
inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list)
{
- long i;
+ int i;
mrb_value s, arystr;
- char *head = "[";
- char *sep = ", ";
- char *tail = "]";
+ char head[] = { '[' };
+ char sep[] = { ',', ' ' };
+ char tail[] = { ']' };
/* check recursive */
for(i=0; i<RARRAY_LEN(list); i++) {
if (mrb_obj_equal(mrb, ary, RARRAY_PTR(list)[i])) {
- return mrb_str_new2(mrb, "[...]");
+ return mrb_str_new(mrb, "[...]", 5);
}
}
mrb_ary_push(mrb, list, ary);
arystr = mrb_str_buf_new(mrb, 64);
- mrb_str_buf_cat(mrb, arystr, head, strlen(head));
+ mrb_str_buf_cat(mrb, arystr, head, sizeof(head));
for(i=0; i<RARRAY_LEN(ary); i++) {
int ai = mrb_gc_arena_save(mrb);
if (i > 0) {
- mrb_str_buf_cat(mrb, arystr, sep, strlen(sep));
+ mrb_str_buf_cat(mrb, arystr, sep, sizeof(sep));
}
if (mrb_type(RARRAY_PTR(ary)[i]) == MRB_TT_ARRAY) {
s = inspect_ary(mrb, RARRAY_PTR(ary)[i], list);
} else {
s = mrb_inspect(mrb, RARRAY_PTR(ary)[i]);
}
- //mrb_str_buf_append(mrb, arystr, s);
mrb_str_buf_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s));
mrb_gc_arena_restore(mrb, ai);
}
- mrb_str_buf_cat(mrb, arystr, tail, strlen(tail));
+ mrb_str_buf_cat(mrb, arystr, tail, sizeof(tail));
mrb_ary_pop(mrb, list);
return arystr;
@@ -824,7 +940,7 @@ inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list)
static mrb_value
mrb_ary_inspect(mrb_state *mrb, mrb_value ary)
{
- if (RARRAY_LEN(ary) == 0) return mrb_str_new2(mrb, "[]");
+ if (RARRAY_LEN(ary) == 0) return mrb_str_new(mrb, "[]", 2);
#if 0 /* THREAD */
return mrb_exec_recursive(inspect_ary_r, ary, 0);
#else
@@ -835,7 +951,7 @@ mrb_ary_inspect(mrb_state *mrb, mrb_value ary)
static mrb_value
join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list)
{
- long i;
+ int i;
mrb_value result, val, tmp;
/* check recursive */
@@ -851,7 +967,6 @@ join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list)
for(i=0; i<RARRAY_LEN(ary); i++) {
if (i > 0 && !mrb_nil_p(sep)) {
- //mrb_str_buf_append(mrb, result, sep); // segv (encoding error?)
mrb_str_buf_cat(mrb, result, RSTRING_PTR(sep), RSTRING_LEN(sep));
}
@@ -864,7 +979,6 @@ join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list)
case MRB_TT_STRING:
str_join:
- //mrb_str_buf_append(mrb, result, val);
mrb_str_buf_cat(mrb, result, RSTRING_PTR(val), RSTRING_LEN(val));
break;
@@ -898,7 +1012,7 @@ mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep)
/*
* call-seq:
- * ary.join(sep=nil) -> str
+ * ary.join(sep="") -> str
*
* Returns a string created by converting each element of the array to
* a string, separated by <i>sep</i>.
@@ -912,7 +1026,7 @@ mrb_ary_join_m(mrb_state *mrb, mrb_value ary)
{
mrb_value sep = mrb_nil_value();
- mrb_get_args(mrb, "|o", &sep);
+ mrb_get_args(mrb, "|S", &sep);
return mrb_ary_join(mrb, ary, sep);
}
@@ -951,7 +1065,7 @@ mrb_ary_equal(mrb_state *mrb, mrb_value ary1)
}
if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value();
else {
- long i;
+ int i;
for (i=0; i<RARRAY_LEN(ary1); i++) {
if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i)))
@@ -980,7 +1094,7 @@ mrb_ary_eql(mrb_state *mrb, mrb_value ary1)
if (mrb_type(ary2) != MRB_TT_ARRAY) return mrb_false_value();
if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value();
else {
- long i;
+ int i;
for (i=0; i<RARRAY_LEN(ary1); i++) {
if (!mrb_eql(mrb, ary_elt(ary1, i), ary_elt(ary2, i)))
@@ -1010,13 +1124,13 @@ mrb_init_array(mrb_state *mrb)
mrb_define_method(mrb, a, "concat", mrb_ary_concat_m, ARGS_REQ(1)); /* 15.2.12.5.8 */
mrb_define_method(mrb, a, "delete_at", mrb_ary_delete_at, ARGS_REQ(1)); /* 15.2.12.5.9 */
mrb_define_method(mrb, a, "empty?", mrb_ary_empty_p, ARGS_NONE()); /* 15.2.12.5.12 */
- mrb_define_method(mrb, a, "first", mrb_ary_first, ARGS_ANY()); /* 15.2.12.5.13 */
+ mrb_define_method(mrb, a, "first", mrb_ary_first, ARGS_OPT(1)); /* 15.2.12.5.13 */
mrb_define_method(mrb, a, "index", mrb_ary_index_m, ARGS_REQ(1)); /* 15.2.12.5.14 */
mrb_define_method(mrb, a, "initialize_copy", mrb_ary_replace_m, ARGS_REQ(1)); /* 15.2.12.5.16 */
mrb_define_method(mrb, a, "join", mrb_ary_join_m, ARGS_ANY()); /* 15.2.12.5.17 */
mrb_define_method(mrb, a, "last", mrb_ary_last, ARGS_ANY()); /* 15.2.12.5.18 */
mrb_define_method(mrb, a, "length", mrb_ary_size, ARGS_NONE()); /* 15.2.12.5.19 */
- mrb_define_method(mrb, a, "pop", mrb_ary_pop_m, ARGS_NONE()); /* 15.2.12.5.21 */
+ mrb_define_method(mrb, a, "pop", mrb_ary_pop, ARGS_NONE()); /* 15.2.12.5.21 */
mrb_define_method(mrb, a, "push", mrb_ary_push_m, ARGS_ANY()); /* 15.2.12.5.22 */
mrb_define_method(mrb, a, "replace", mrb_ary_replace_m, ARGS_REQ(1)); /* 15.2.12.5.23 */
mrb_define_method(mrb, a, "reverse", mrb_ary_reverse, ARGS_NONE()); /* 15.2.12.5.24 */
@@ -1031,5 +1145,5 @@ mrb_init_array(mrb_state *mrb)
mrb_define_alias(mrb, a, "to_s", "inspect"); /* 15.2.12.5.32 (x) */
mrb_define_method(mrb, a, "==", mrb_ary_equal, ARGS_REQ(1)); /* 15.2.12.5.33 (x) */
mrb_define_method(mrb, a, "eql?", mrb_ary_eql, ARGS_REQ(1)); /* 15.2.12.5.34 (x) */
- mrb_define_method(mrb, a, "<=>", mrb_ary_cmp, ARGS_REQ(1)); /* 15.2.12.5.36 (x) */
+ mrb_define_method(mrb, a, "<=>", mrb_ary_cmp, ARGS_REQ(1)); /* 15.2.12.5.36 (x) */
}
diff --git a/src/cdump.c b/src/cdump.c
index f9525d042..32982e6fe 100644
--- a/src/cdump.c
+++ b/src/cdump.c
@@ -10,7 +10,6 @@
#include "mruby/irep.h"
#include "mruby/string.h"
-#include "re.h"
#define MRB_CDUMP_LINE_LEN 128
@@ -45,7 +44,7 @@ str_format_len(mrb_value str)
char *src;
- for (src = RSTRING_PTR(str); src < RSTRING_END(str);) {
+ for (src = RSTRING_PTR(str); src < RSTRING_END(str); src++) {
switch (*src) {
case 0x07:/* BEL */ /* fall through */
case 0x08:/* BS */ /* fall through */
@@ -58,11 +57,11 @@ str_format_len(mrb_value str)
case 0x27:/* ' */ /* fall through */
case 0x3F:/* ? */ /* fall through */
case 0x5C:/* \ */ /* fall through */
- dump_len += 2; src += 2;
+ dump_len += 2;
break;
default:
- dump_len++; src++;
+ dump_len++;
break;
}
}
@@ -73,22 +72,23 @@ str_format_len(mrb_value str)
static char*
str_to_format(mrb_value str, char *buf)
{
- char *src, *dst;
+ char *src;
+ char *dst;
- for (src = RSTRING_PTR(str), dst = buf; src < RSTRING_END(str);) {
+ for (src = RSTRING_PTR(str), dst = buf; src < RSTRING_END(str); src++) {
switch (*src) {
- case 0x07:/* BEL */ memcpy(dst, "\\a", 2); dst+=2; src+=2; break;
- case 0x08:/* BS */ memcpy(dst, "\\b", 2); dst+=2; src+=2; break;
- case 0x09:/* HT */ memcpy(dst, "\\t", 2); dst+=2; src+=2; break;
- case 0x0A:/* LF */ memcpy(dst, "\\n", 2); dst+=2; src+=2; break;
- case 0x0B:/* VT */ memcpy(dst, "\\v", 2); dst+=2; src+=2; break;
- case 0x0C:/* FF */ memcpy(dst, "\\f", 2); dst+=2; src+=2; break;
- case 0x0D:/* CR */ memcpy(dst, "\\r", 2); dst+=2; src+=2; break;
- case 0x22:/* " */ memcpy(dst, "\\\"", 2); dst+=2; src+=2; break;
- case 0x27:/* ' */ memcpy(dst, "\\\'", 2); dst+=2; src+=2; break;
- case 0x3F:/* ? */ memcpy(dst, "\\\?", 2); dst+=2; src+=2; break;
- case 0x5C:/* \ */ memcpy(dst, "\\\\", 2); dst+=2; src+=2; break;
- default: *dst++ = *src++; break;
+ case 0x07:/* BEL */ *dst++ = '\\'; *dst++ = 'a'; break;
+ case 0x08:/* BS */ *dst++ = '\\'; *dst++ = 'b'; break;
+ case 0x09:/* HT */ *dst++ = '\\'; *dst++ = 't'; break;
+ case 0x0A:/* LF */ *dst++ = '\\'; *dst++ = 'n'; break;
+ case 0x0B:/* VT */ *dst++ = '\\'; *dst++ = 'v'; break;
+ case 0x0C:/* FF */ *dst++ = '\\'; *dst++ = 'f'; break;
+ case 0x0D:/* CR */ *dst++ = '\\'; *dst++ = 'r'; break;
+ case 0x22:/* " */ *dst++ = '\\'; *dst++ = '\"'; break;
+ case 0x27:/* ' */ *dst++ = '\\'; *dst++ = '\''; break;
+ case 0x3F:/* ? */ *dst++ = '\\'; *dst++ = '\?'; break;
+ case 0x5C:/* \ */ *dst++ = '\\'; *dst++ = '\\'; break;
+ default: *dst++ = *src; break;
}
}
@@ -107,10 +107,11 @@ make_cdump_irep(mrb_state *mrb, int irep_no, FILE *f)
return -1;
buf_len = MRB_CDUMP_LINE_LEN;
- if ((buf = mrb_malloc(mrb, buf_len)) == 0 ) {
+ if ((buf = (char *)mrb_malloc(mrb, buf_len)) == 0 ) {
return MRB_CDUMP_GENERAL_FAILURE;
}
+ SOURCE_CODE0 (" ai = mrb->arena_idx;");
SOURCE_CODE0 (" irep = mrb->irep[idx] = mrb_malloc(mrb, sizeof(mrb_irep));");
SOURCE_CODE0 (" irep->idx = idx++;");
SOURCE_CODE (" irep->flags = %d | MRB_ISEQ_NOFREE;", irep->flags);
@@ -137,11 +138,13 @@ make_cdump_irep(mrb_state *mrb, int irep_no, FILE *f)
switch (irep->pool[n].tt) {
case MRB_TT_FLOAT:
SOURCE_CODE(" irep->pool[%d] = mrb_float_value(%.16e);", n, irep->pool[n].value.f); break;
- case MRB_TT_STRING:
+ case MRB_TT_FIXNUM:
+ SOURCE_CODE(" irep->pool[%d] = mrb_fixnum_value(%d);", n, irep->pool[n].value.i); break;
+ case MRB_TT_STRING:
str_len = str_format_len(irep->pool[n]) + 1;
if ( str_len > buf_len ) {
buf_len = str_len;
- if ((buf = mrb_realloc(mrb, buf, buf_len)) == 0 ) {
+ if ((buf = (char *)mrb_realloc(mrb, buf, buf_len)) == 0 ) {
return MRB_CDUMP_GENERAL_FAILURE;
}
}
@@ -154,6 +157,8 @@ make_cdump_irep(mrb_state *mrb, int irep_no, FILE *f)
}
else
SOURCE_CODE0 (" irep->pool = NULL;");
+ SOURCE_CODE0 (" mrb->irep_len = idx;");
+ SOURCE_CODE0 (" mrb->arena_idx = ai;");
SOURCE_CODE0("");
return MRB_CDUMP_OK;
}
@@ -184,6 +189,7 @@ mrb_cdump_irep(mrb_state *mrb, int n, FILE *f,const char *initname)
SOURCE_CODE0("{");
SOURCE_CODE0(" int n = mrb->irep_len;");
SOURCE_CODE0(" int idx = n;");
+ SOURCE_CODE0(" int ai;");
SOURCE_CODE0(" mrb_irep *irep;");
SOURCE_CODE0("");
SOURCE_CODE (" mrb_add_irep(mrb, idx+%d);", irep_num);
@@ -193,9 +199,6 @@ mrb_cdump_irep(mrb_state *mrb, int n, FILE *f,const char *initname)
return -1;
}
- SOURCE_CODE0(" mrb->irep_len = idx;");
- SOURCE_CODE0("");
- SOURCE_CODE0(" extern mrb_value mrb_top_self(mrb_state *mrb);");
SOURCE_CODE0(" mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));");
SOURCE_CODE0("}");
diff --git a/src/class.c b/src/class.c
index b13ab2288..7802c34bd 100644
--- a/src/class.c
+++ b/src/class.c
@@ -15,10 +15,8 @@
#include "mruby/array.h"
#include "error.h"
-#include "mruby/khash.h"
-
-KHASH_MAP_INIT_INT(mt, struct RProc*);
-KHASH_MAP_INIT_INT(iv, mrb_value);
+KHASH_DEFINE(iv, mrb_sym, mrb_value, 1, kh_int_hash_func, kh_int_hash_equal);
+KHASH_DEFINE(mt, mrb_sym, struct RProc*, 1, kh_int_hash_func, kh_int_hash_equal);
typedef struct fc_result {
mrb_sym name;
@@ -28,9 +26,6 @@ typedef struct fc_result {
struct fc_result *prev;
} fcresult_t;
-int kiv_lookup(khash_t(iv) *table, mrb_sym key, mrb_value *value);
-extern struct kh_iv *mrb_class_tbl;
-
void
mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c)
{
@@ -42,7 +37,7 @@ mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c)
if (kh_exist(h, k)){
struct RProc *m = kh_value(h, k);
if (m) {
- paint_black(m);
+ mrb_gc_mark(mrb, (struct RBasic*)m);
}
}
}
@@ -120,7 +115,6 @@ mrb_define_module_id(mrb_state *mrb, mrb_sym name)
{
struct RClass *m = mrb_module_new(mrb);
- m->mt = kh_init(mt, mrb);
mrb_obj_iv_set(mrb, (struct RObject*)mrb->object_class,
name, mrb_obj_value(m));
mrb_name_class(mrb, m, name);
@@ -193,34 +187,60 @@ mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super)
struct RClass*
mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id)
{
- struct RClass *c = 0;
+ struct RClass *c, *s;
if (mrb_const_defined(mrb, outer, id)) {
mrb_value v = mrb_const_get(mrb, outer, id);
+ mrb_check_type(mrb, v, MRB_TT_CLASS);
c = mrb_class_ptr(v);
- if (!mrb_nil_p(super) && (c->tt != MRB_TT_CLASS || c->super != mrb_class_ptr(super))) {
- c = 0;
+ if (!mrb_nil_p(super)) {
+ if (mrb_type(super) != MRB_TT_CLASS) {
+ mrb_raise(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super));
+ }
+
+ if (!c->super || mrb_class_ptr(super) != mrb_class_real(c->super)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "superclass mismatch for class %s", mrb_sym2name(mrb, id));
+ }
}
+
+ return c;
}
- if (!c) {
- struct RClass *s = 0;
- if (!mrb_nil_p(super)) {
- mrb_check_type(mrb, super, MRB_TT_CLASS);
- s = mrb_class_ptr(super);
- }
- if (!s) {
- s = mrb->object_class;
+ if (!mrb_nil_p(super)) {
+ if (mrb_type(super) != MRB_TT_CLASS) {
+ mrb_raise(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super));
}
- c = mrb_class_new(mrb, s);
- setup_class(mrb, outer, c, id);
- mrb_funcall(mrb, mrb_obj_value(s), "inherited", 1, mrb_obj_value(c));
+ s = mrb_class_ptr(super);
+ }
+ else {
+ s = mrb->object_class;
}
+ c = mrb_class_new(mrb, s);
+ setup_class(mrb, outer, c, id);
+ mrb_funcall(mrb, mrb_obj_value(s), "inherited", 1, mrb_obj_value(c));
+
return c;
}
+static struct RClass *
+class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
+{
+ mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
+
+ if (c.tt != MRB_TT_MODULE && c.tt != MRB_TT_CLASS) {
+ mrb_raise(mrb, E_TYPE_ERROR, "%s is not a class/module", mrb_sym2name(mrb, id));
+ }
+ return mrb_class_ptr(c);
+}
+
+struct RClass *
+mrb_class_get(mrb_state *mrb, const char *name)
+{
+ return class_from_sym(mrb, mrb->object_class, mrb_intern(mrb, name));
+}
+
/*!
* Defines a class under the namespace of \a outer.
* \param outer a class which contains the new class.
@@ -244,10 +264,7 @@ mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, s
mrb_sym id = mrb_intern(mrb, name);
if (mrb_const_defined_at(mrb, outer, id)) {
- c = mrb_class_from_sym(mrb, outer, id);
- if (c->tt != MRB_TT_CLASS) {
- mrb_raise(mrb, E_TYPE_ERROR, "%s is not a class", mrb_sym2name(mrb, id));
- }
+ c = class_from_sym(mrb, outer, id);
if (mrb_class_real(c->super) != super) {
mrb_name_error(mrb, id, "%s is already defined", mrb_sym2name(mrb, id));
}
@@ -259,7 +276,6 @@ mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, s
}
c = mrb_class_new(mrb, super);
setup_class(mrb, mrb_obj_value(outer), c, id);
- mrb_const_set(mrb, mrb_obj_value(outer), id, mrb_obj_value(c));
return c;
}
@@ -271,15 +287,11 @@ mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name)
mrb_sym id = mrb_intern(mrb, name);
if (mrb_const_defined_at(mrb, outer, id)) {
- c = mrb_class_from_sym(mrb, outer, id);
- if (c->tt != MRB_TT_MODULE) {
- mrb_raise(mrb, E_TYPE_ERROR, "%s is not a module", mrb_sym2name(mrb, id));
- }
+ c = class_from_sym(mrb, outer, id);
return c;
}
c = mrb_module_new(mrb);
setup_class(mrb, mrb_obj_value(outer), c, id);
- mrb_const_set(mrb, mrb_obj_value(outer), id, mrb_obj_value(c));
return c;
}
@@ -316,10 +328,12 @@ mrb_define_method_vm(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_value b
{
khash_t(mt) *h = c->mt;
khiter_t k;
+ struct RProc *p;
if (!h) h = c->mt = kh_init(mt, mrb);
k = kh_put(mt, h, name);
- kh_value(h, k) = mrb_proc_ptr(body);
+ p = mrb_proc_ptr(body);
+ kh_value(h, k) = p;
}
static mrb_value
@@ -370,6 +384,7 @@ to_hash(mrb_state *mrb, mrb_value val)
a: Array [mrb_value*,int]
f: Float [mrb_float]
i: Integer [mrb_int]
+ n: Symbol [mrb_sym]
&: Block [mrb_value]
*: rest argument [mrb_value*,int]
|: optional
@@ -389,15 +404,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
struct RArray *a = mrb_ary_ptr(mrb->stack[1]);
argc = a->len;
- sp = a->buf;
+ sp = a->ptr;
}
while ((c = *format++)) {
switch (c) {
case '|': case '*': case '&':
break;
default:
- if (argc <= i) {
- if (opt) continue;
+ if (argc <= i && !opt) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
}
}
@@ -408,8 +422,10 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_value *p;
p = va_arg(ap, mrb_value*);
- *p = *sp;
- i++; sp++;
+ if (i < argc) {
+ *p = *sp++;
+ i++;
+ }
}
break;
case 'S':
@@ -417,8 +433,10 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_value *p;
p = va_arg(ap, mrb_value*);
- *p = to_str(mrb, *sp);
- i++; sp++;
+ if (i < argc) {
+ *p = to_str(mrb, *sp++);
+ i++;
+ }
}
break;
case 'A':
@@ -426,8 +444,10 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_value *p;
p = va_arg(ap, mrb_value*);
- *p = to_ary(mrb, *sp);
- i++; sp++;
+ if (i < argc) {
+ *p = to_ary(mrb, *sp++);
+ i++;
+ }
}
break;
case 'H':
@@ -435,8 +455,10 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_value *p;
p = va_arg(ap, mrb_value*);
- *p = to_hash(mrb, *sp);
- i++; sp++;
+ if (i < argc) {
+ *p = to_hash(mrb, *sp++);
+ i++;
+ }
}
break;
case 's':
@@ -446,13 +468,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
char **ps = 0;
int *pl = 0;
- ss = to_str(mrb, *sp);
- s = mrb_str_ptr(ss);
ps = va_arg(ap, char**);
- *ps = s->buf;
pl = va_arg(ap, int*);
- *pl = s->len;
- i++; sp++;
+ if (i < argc) {
+ ss = to_str(mrb, *sp++);
+ s = mrb_str_ptr(ss);
+ *ps = s->ptr;
+ *pl = s->len;
+ i++;
+ }
}
break;
case 'z':
@@ -461,14 +485,16 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
struct RString *s;
char **ps;
- ss = to_str(mrb, *sp);
- s = mrb_str_ptr(ss);
- if (strlen(s->buf) != s->len) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "String contains NUL");
- }
ps = va_arg(ap, char**);
- *ps = s->buf;
- i++; sp++;
+ if (i < argc) {
+ ss = to_str(mrb, *sp++);
+ s = mrb_str_ptr(ss);
+ if (strlen(s->ptr) != s->len) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "String contains NUL");
+ }
+ *ps = s->ptr;
+ i++;
+ }
}
break;
case 'a':
@@ -478,13 +504,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_value **pb;
int *pl;
- aa = to_ary(mrb, *sp);
- a = mrb_ary_ptr(aa);
pb = va_arg(ap, mrb_value**);
- *pb = a->buf;
pl = va_arg(ap, int*);
- *pl = a->len;
- i++; sp++;
+ if (i < argc) {
+ aa = to_ary(mrb, *sp++);
+ a = mrb_ary_ptr(aa);
+ *pb = a->ptr;
+ *pl = a->len;
+ i++;
+ }
}
break;
case 'f':
@@ -492,26 +520,29 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_float *p;
p = va_arg(ap, mrb_float*);
- switch (sp->tt) {
- case MRB_TT_FLOAT:
- *p = mrb_float(*sp);
- break;
- case MRB_TT_FIXNUM:
- *p = (mrb_float)mrb_fixnum(*sp);
- break;
- case MRB_TT_FALSE:
- *p = 0.0;
- break;
- default:
- {
- mrb_value tmp;
-
- tmp = mrb_convert_type(mrb, *sp, MRB_TT_FLOAT, "Float", "to_f");
- *p = mrb_float(tmp);
+ if (i < argc) {
+ switch (sp->tt) {
+ case MRB_TT_FLOAT:
+ *p = mrb_float(*sp);
+ break;
+ case MRB_TT_FIXNUM:
+ *p = (mrb_float)mrb_fixnum(*sp);
+ break;
+ case MRB_TT_FALSE:
+ *p = 0.0;
+ break;
+ default:
+ {
+ mrb_value tmp;
+
+ tmp = mrb_convert_type(mrb, *sp, MRB_TT_FLOAT, "Float", "to_f");
+ *p = mrb_float(tmp);
+ }
+ break;
}
- break;
- }
- i++; sp++;
+ sp++;
+ i++;
+ }
}
break;
case 'i':
@@ -519,37 +550,69 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_int *p;
p = va_arg(ap, mrb_int*);
- switch (sp->tt) {
- case MRB_TT_FIXNUM:
- *p = mrb_fixnum(*sp);
- break;
- case MRB_TT_FLOAT:
- *p = (mrb_int)mrb_float(*sp);
- break;
- case MRB_TT_FALSE:
- *p = 0;
- break;
- default:
- {
- mrb_value tmp;
+ if (i < argc) {
+ switch (sp->tt) {
+ case MRB_TT_FIXNUM:
+ *p = mrb_fixnum(*sp);
+ break;
+ case MRB_TT_FLOAT:
+ {
+ mrb_float f = mrb_float(*sp);
+
+ if (!FIXABLE(f)) {
+ mrb_raise(mrb, E_RANGE_ERROR, "float too big for int");
+ }
+ *p = (mrb_int)f;
+ }
+ break;
+ case MRB_TT_FALSE:
+ *p = 0;
+ break;
+ default:
+ {
+ mrb_value tmp;
+
+ tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int");
+ *p = mrb_fixnum(tmp);
+ }
+ break;
+ }
+ sp++;
+ i++;
+ }
+ }
+ break;
+ case 'n':
+ {
+ mrb_sym *symp;
+
+ symp = va_arg(ap, mrb_sym*);
+ if (i < argc) {
+ mrb_value ss;
- tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int");
- *p = mrb_fixnum(tmp);
+ ss = *sp++;
+ if (mrb_type(ss) == MRB_TT_SYMBOL) {
+ *symp = mrb_symbol(ss);
}
- break;
- }
- i++; sp++;
+ else {
+ *symp = mrb_intern_str(mrb, to_str(mrb, ss));
+ }
+ i++;
+ }
}
break;
case '&':
{
- mrb_value *p, *bp = mrb->stack + 1;
+ mrb_value *p, *bp;
p = va_arg(ap, mrb_value*);
- if (mrb->ci->argc > 0) {
- bp += mrb->ci->argc;
+ if (mrb->ci->argc < 0) {
+ bp = mrb->stack + 2;
}
+ else {
+ bp = mrb->stack + mrb->ci->argc + 1;
+ }
*p = *bp;
}
break;
@@ -579,6 +642,9 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
}
break;
+ default:
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "invalide argument specifier %c", c);
+ break;
}
}
if (!c && argc > i) {
@@ -603,28 +669,120 @@ boot_defclass(mrb_state *mrb, struct RClass *super)
void
mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
{
- struct RClass *ic;
+ struct RClass *ins_pos;
- ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class);
- ic->c = m;
- ic->mt = m->mt;
- ic->iv = m->iv;
- ic->super = c->super;
- c->super = ic;
- mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)ic);
+ ins_pos = c;
+ while (m) {
+ struct RClass *p = c, *ic;
+ int superclass_seen = 0;
+
+ while(p) {
+ if (c != p && p->tt == MRB_TT_CLASS) {
+ superclass_seen = 1;
+ }
+ else if (p->mt == m->mt){
+ if (p->tt == MRB_TT_ICLASS && !superclass_seen) {
+ ins_pos = p;
+ }
+ goto skip;
+ }
+ p = p->super;
+ }
+ ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class);
+ if (m->tt == MRB_TT_ICLASS) {
+ ic->c = m->c;
+ }
+ else {
+ ic->c = m;
+ }
+ ic->mt = m->mt;
+ ic->iv = m->iv;
+ ic->super = ins_pos->super;
+ ins_pos->super = ic;
+ mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ic);
+ ins_pos = ic;
+ skip:
+ m = m->super;
+ }
}
static mrb_value
-mrb_mod_include(mrb_state *mrb, mrb_value klass)
+mrb_mod_append_features(mrb_state *mrb, mrb_value mod)
{
- mrb_value mod;
+ mrb_value klass;
- mrb_get_args(mrb, "o", &mod);
mrb_check_type(mrb, mod, MRB_TT_MODULE);
+ mrb_get_args(mrb, "o", &klass);
mrb_include_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod));
return mod;
}
+static mrb_value
+mrb_mod_include(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value *argv;
+ int argc, i;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ for (i=0; i<argc; i++) {
+ mrb_check_type(mrb, argv[i], MRB_TT_MODULE);
+ }
+ while (argc--) {
+ mrb_funcall(mrb, argv[argc], "append_features", 1, klass);
+ mrb_funcall(mrb, argv[argc], "included", 1, klass);
+ }
+
+ return klass;
+}
+
+static mrb_value
+mrb_mod_ancestors(mrb_state *mrb, mrb_value self)
+{
+ mrb_value result;
+ struct RClass *c = mrb_class_ptr(self);
+
+ result = mrb_ary_new(mrb);
+ while (c) {
+ if (c->tt == MRB_TT_ICLASS) {
+ mrb_ary_push(mrb, result, mrb_obj_value(c->c));
+ }
+ else {
+ mrb_ary_push(mrb, result, mrb_obj_value(c));
+ }
+ c = c->super;
+ }
+
+ return result;
+}
+
+static mrb_value
+mrb_mod_extend_object(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value obj;
+
+ mrb_check_type(mrb, mod, MRB_TT_MODULE);
+ mrb_get_args(mrb, "o", &obj);
+ mrb_include_module(mrb, mrb_class_ptr(mrb_singleton_class(mrb, obj)), mrb_class_ptr(mod));
+ return mod;
+}
+
+static mrb_value
+mrb_mod_included_modules(mrb_state *mrb, mrb_value self)
+{
+ mrb_value result;
+ struct RClass *c = mrb_class_ptr(self);
+
+ result = mrb_ary_new(mrb);
+ while (c) {
+ if (c->tt == MRB_TT_ICLASS) {
+ mrb_ary_push(mrb, result, mrb_obj_value(c->c));
+ }
+ c = c->super;
+ }
+
+ return result;
+}
+
static struct RClass *
mrb_singleton_class_ptr(mrb_state *mrb, struct RClass *c)
{
@@ -648,11 +806,16 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v)
switch (mrb_type(v)) {
case MRB_TT_FALSE:
+ if (mrb_nil_p(v))
+ return mrb_obj_value(mrb->nil_class);
+ return mrb_obj_value(mrb->false_class);
case MRB_TT_TRUE:
+ return mrb_obj_value(mrb->true_class);
case MRB_TT_SYMBOL:
case MRB_TT_FIXNUM:
case MRB_TT_FLOAT:
- return mrb_nil_value(); /* should raise TypeError */
+ mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton");
+ return mrb_nil_value(); /* not reached */
default:
break;
}
@@ -662,15 +825,16 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v)
}
void
-mrb_define_class_method(mrb_state *mrb, struct RClass *c, 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, int aspec)
{
- mrb_define_method_id(mrb, c->c, mrb_intern(mrb, name), func, aspec);
+ o->c = mrb_singleton_class_ptr(mrb, o->c);
+ mrb_define_method_id(mrb, o->c, mrb_intern(mrb, name), func, aspec);
}
void
-mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, 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, int aspec)
{
- mrb_define_method_id(mrb, mrb_singleton_class_ptr(mrb, o->c), mrb_intern(mrb, name), func, aspec);
+ mrb_define_singleton_method(mrb, (struct RObject*)c, name, func, aspec);
}
void
@@ -716,34 +880,48 @@ mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid)
return m;
}
+#ifndef MRB_FUNCALL_ARGC_MAX
+#define MRB_FUNCALL_ARGC_MAX 16
+#endif
+
mrb_value
-mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc,...)
+mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...)
{
- mrb_value args[16];
+ mrb_sym mid = mrb_intern(mrb, name);
va_list ap;
int i;
if (argc == 0) {
- for (i=0; i<5; i++) {
- args[i] = mrb_nil_value();
- }
+ return mrb_funcall_argv(mrb, self, mid, 0, 0);
+ }
+ else if (argc == 1) {
+ mrb_value v;
+
+ va_start(ap, argc);
+ v = va_arg(ap, mrb_value);
+ va_end(ap);
+ return mrb_funcall_argv(mrb, self, mid, 1, &v);
}
else {
+ mrb_value argv[MRB_FUNCALL_ARGC_MAX];
+
+ if (argc > MRB_FUNCALL_ARGC_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%d)", MRB_FUNCALL_ARGC_MAX);
+ }
+
va_start(ap, argc);
- // assert(argc < 16);
- for (i=0; i<argc; i++) {
- args[i] = va_arg(ap, mrb_value);
+ for (i = 0; i < argc; i++) {
+ argv[i] = va_arg(ap, mrb_value);
}
va_end(ap);
+ return mrb_funcall_argv(mrb, self, mid, argc, argv);
}
- return mrb_funcall_argv(mrb, self, name, argc, args);
}
-
void
mrb_obj_call_init(mrb_state *mrb, mrb_value obj, int argc, mrb_value *argv)
{
- mrb_funcall_argv(mrb, obj, "initialize", argc, argv);
+ mrb_funcall_argv(mrb, obj, mrb_intern(mrb, "initialize"), argc, argv);
}
/*
@@ -782,7 +960,7 @@ mrb_class_new_instance_m(mrb_state *mrb, mrb_value klass)
c = (struct RClass*)mrb_obj_alloc(mrb, k->tt, k);
c->super = k;
obj = mrb_obj_value(c);
- mrb_funcall_with_block(mrb, obj, "initialize", argc, argv, blk);
+ mrb_funcall_with_block(mrb, obj, mrb_intern(mrb, "initialize"), argc, argv, blk);
return obj;
}
@@ -801,11 +979,39 @@ mrb_instance_new(mrb_state *mrb, mrb_value cv)
o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
obj = mrb_obj_value(o);
mrb_get_args(mrb, "*&", &argv, &argc, &blk);
- mrb_funcall_with_block(mrb, obj, "initialize", argc, argv, blk);
+ mrb_funcall_with_block(mrb, obj, mrb_intern(mrb, "initialize"), argc, argv, blk);
return obj;
}
+mrb_value
+mrb_class_new_class(mrb_state *mrb, mrb_value cv)
+{
+ mrb_value super;
+ struct RClass *new_class;
+
+ if (mrb_get_args(mrb, "|o", &super) == 0) {
+ super = mrb_obj_value(mrb->object_class);
+ }
+ new_class = mrb_class_new(mrb, mrb_class_ptr(super));
+ return mrb_obj_value(new_class);
+}
+
+mrb_value
+mrb_class_superclass(mrb_state *mrb, mrb_value klass)
+{
+ struct RClass *c;
+ mrb_value superclass;
+
+ c = mrb_class_ptr(klass);
+ if (c->super)
+ superclass = mrb_obj_value(mrb_class_real(c->super));
+ else
+ superclass = mrb_nil_value();
+
+ return superclass;
+}
+
static mrb_value
mrb_bob_init(mrb_state *mrb, mrb_value cv)
{
@@ -878,8 +1084,14 @@ mrb_obj_respond_to(struct RClass* c, mrb_sym mid)
if (h) {
k = kh_get(mt, h, mid);
- if (k != kh_end(h))
- return 1; /* exist method */
+ if (k != kh_end(h)) {
+ if (kh_value(h, k)) {
+ return 1; /* exist method */
+ }
+ else {
+ return 0;
+ }
+ }
}
c = c->super;
}
@@ -896,6 +1108,8 @@ mrb_value
mrb_class_path(mrb_state *mrb, struct RClass *c)
{
mrb_value path;
+ const char *name;
+ int len;
path = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__"));
if (mrb_nil_p(path)) {
@@ -903,14 +1117,16 @@ mrb_class_path(mrb_state *mrb, struct RClass *c)
mrb_sym sym = class_sym(mrb, c, outer);
if (outer && outer != mrb->object_class) {
mrb_value base = mrb_class_path(mrb, outer);
- path = mrb_str_plus(mrb, base, mrb_str_new_cstr(mrb, "::"));
- mrb_str_concat(mrb, path, mrb_str_new_cstr(mrb, mrb_sym2name(mrb, sym)));
+ path = mrb_str_plus(mrb, base, mrb_str_new(mrb, "::", 2));
+ name = mrb_sym2name_len(mrb, sym, &len);
+ mrb_str_concat(mrb, path, mrb_str_new(mrb, name, len));
}
else if (sym == 0) {
return mrb_nil_value();
}
else {
- path = mrb_str_new_cstr(mrb, mrb_sym2name(mrb, sym));
+ 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);
}
@@ -931,7 +1147,7 @@ mrb_class_name(mrb_state *mrb, struct RClass* c)
{
mrb_value path = mrb_class_path(mrb, c);
if (mrb_nil_p(path)) return 0;
- return mrb_str_ptr(path)->buf;
+ return mrb_str_ptr(path)->ptr;
}
const char*
@@ -976,6 +1192,9 @@ mrb_class_new(mrb_state *mrb, struct RClass *super)
mrb_check_inheritable(mrb, super);
}
c = boot_defclass(mrb, super);
+ if (super){
+ MRB_SET_INSTANCE_TT(c, MRB_INSTANCE_TT(super));
+ }
make_metaclass(mrb, c);
return c;
@@ -988,6 +1207,7 @@ struct RClass *
mrb_module_new(mrb_state *mrb)
{
struct RClass *m = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_MODULE, mrb->module_class);
+ m->mt = kh_init(mt, mrb);
return m;
}
@@ -1044,9 +1264,8 @@ 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)
{
- //if (FL_TEST(klass, FL_SINGLETON)) {
if (mrb_type(klass) == MRB_TT_SCLASS) {
- mrb_value s = mrb_str_new_cstr(mrb, "#<");
+ mrb_value s = mrb_str_new(mrb, "#<", 2);
mrb_value v = mrb_iv_get(mrb, klass, mrb_intern(mrb, "__attached__"));
mrb_str_cat2(mrb, s, "Class:");
@@ -1065,25 +1284,25 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
}
else {
struct RClass *c = mrb_class_ptr(klass);
- const char *cn = mrb_class_name(mrb, c);
+ const char *cn = mrb_class_name(mrb, c);
if (!cn) {
char buf[256];
-
+ int n = 0;
switch (mrb_type(klass)) {
case MRB_TT_CLASS:
- snprintf(buf, 256, "#<Class:%p>", c);
+ n = snprintf(buf, sizeof(buf), "#<Class:%p>", c);
break;
case MRB_TT_MODULE:
- snprintf(buf, 256, "#<Module:%p>", c);
+ n = snprintf(buf, sizeof(buf), "#<Module:%p>", c);
break;
default:
break;
}
- return mrb_str_dup(mrb, mrb_str_new_cstr(mrb, buf));
+ return mrb_str_dup(mrb, mrb_str_new(mrb, buf, n));
}
else {
return mrb_str_dup(mrb, mrb_str_new_cstr(mrb, cn));
@@ -1119,6 +1338,12 @@ mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name)
undef_method(mrb, c, mrb_intern(mrb, name));
}
+void
+mrb_undef_class_method(mrb_state *mrb, struct RClass *c, const char *name)
+{
+ mrb_undef_method(mrb, mrb_class_ptr(mrb_singleton_class(mrb, mrb_obj_value(c))), name);
+}
+
mrb_value
mrb_mod_undef(mrb_state *mrb, mrb_value mod)
{
@@ -1134,11 +1359,29 @@ mrb_mod_undef(mrb_state *mrb, mrb_value mod)
return mrb_nil_value();
}
+static mrb_value
+mod_define_method(mrb_state *mrb, mrb_value self)
+{
+ struct RClass *c = mrb_class_ptr(self);
+ struct RProc *p;
+ mrb_sym mid;
+ mrb_value blk;
+
+ mrb_get_args(mrb, "n&", &mid, &blk);
+ if (mrb_nil_p(blk)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
+ }
+ p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
+ mrb_proc_copy(p, mrb_proc_ptr(blk));
+ mrb_define_method_raw(mrb, c, mid, p);
+ return blk;
+}
+
static mrb_sym
mrb_sym_value(mrb_state *mrb, mrb_value val)
{
if(val.tt == MRB_TT_STRING) {
- return mrb_intern(mrb, RSTRING_PTR(val));
+ return mrb_intern_str(mrb, val);
}
else if(val.tt != MRB_TT_SYMBOL) {
mrb_value obj = mrb_funcall(mrb, val, "inspect", 0);
@@ -1225,17 +1468,28 @@ mrb_init_class(mrb_state *mrb)
MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS);
mrb_define_method(mrb, bob, "initialize", mrb_bob_init, ARGS_NONE());
mrb_define_method(mrb, bob, "!", mrb_bob_not, ARGS_NONE());
- mrb_define_method(mrb, bob, "method_missing", mrb_bob_missing, ARGS_ANY()); /* 15.3.1.3.30 */
- mrb_define_method(mrb, cls, "new", mrb_instance_new, ARGS_ANY());
+ mrb_define_method(mrb, bob, "method_missing", mrb_bob_missing, ARGS_ANY()); /* 15.3.1.3.30 */
+ mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, ARGS_ANY());
+ mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, ARGS_NONE()); /* 15.2.3.3.4 */
+ 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_define_method(mrb, mod, "include", mrb_mod_include, ARGS_REQ(1));
+ mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, ARGS_REQ(1)); /* 15.2.2.4.25 */
+ mrb_define_method(mrb, mod, "extended", mrb_bob_init, ARGS_REQ(1)); /* 15.2.2.4.26 */
+ mrb_define_method(mrb, mod, "include", mrb_mod_include, ARGS_ANY()); /* 15.2.2.4.27 */
+ mrb_define_method(mrb, mod, "append_features", mrb_mod_append_features, ARGS_REQ(1)); /* 15.2.2.4.10 */
+ mrb_define_method(mrb, mod, "included", mrb_bob_init, ARGS_REQ(1)); /* 15.2.2.4.29 */
+ mrb_define_method(mrb, mod, "included_modules", mrb_mod_included_modules, ARGS_NONE()); /* 15.2.2.4.30 */
mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, ARGS_NONE());
- mrb_define_method(mrb, mod, "alias_method", mrb_mod_alias, ARGS_ANY());
- mrb_define_method(mrb, mod, "undef_method", mrb_mod_undef, ARGS_ANY());
- mrb_define_method(mrb, mod, "const_defined?", mrb_mod_const_defined, ARGS_REQ(1));
- mrb_define_method(mrb, mod, "const_get", mrb_mod_const_get, ARGS_REQ(1));
- mrb_define_method(mrb, mod, "const_set", mrb_mod_const_set, ARGS_REQ(2));
+ mrb_define_method(mrb, mod, "alias_method", mrb_mod_alias, ARGS_ANY()); /* 15.2.2.4.8 */
+ mrb_define_method(mrb, mod, "ancestors", mrb_mod_ancestors, ARGS_NONE()); /* 15.2.2.4.9 */
+ mrb_define_method(mrb, mod, "undef_method", mrb_mod_undef, ARGS_ANY()); /* 15.2.2.4.41 */
+ mrb_define_method(mrb, mod, "const_defined?", mrb_mod_const_defined, ARGS_REQ(1)); /* 15.2.2.4.20 */
+ mrb_define_method(mrb, mod, "const_get", mrb_mod_const_get, ARGS_REQ(1)); /* 15.2.2.4.21 */
+ mrb_define_method(mrb, mod, "const_set", mrb_mod_const_set, ARGS_REQ(2)); /* 15.2.2.4.23 */
+ mrb_define_method(mrb, mod, "define_method", mod_define_method, ARGS_REQ(1));
mrb_define_method(mrb, mod, "===", mrb_mod_eqq, ARGS_REQ(1));
+ mrb_undef_method(mrb, cls, "append_features");
+ mrb_undef_method(mrb, cls, "extend_object");
}
diff --git a/src/codegen.c b/src/codegen.c
index 505f0ad5b..bf6fd0b3e 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -10,12 +10,13 @@
#include "mruby.h"
#include "mruby/string.h"
#include "mruby/irep.h"
-#include "mruby/proc.h"
#include "mruby/compile.h"
+#include "mruby/numeric.h"
#include "opcode.h"
#include "node.h"
#include <string.h>
#include <stdlib.h>
+#include <ctype.h>
typedef mrb_ast_node node;
typedef struct mrb_parser_state parser_state;
@@ -47,7 +48,8 @@ typedef struct scope {
int sp;
int pc;
int lastlabel;
- int ainfo;
+ int ainfo:15;
+ int mscope:1;
struct loopinfo *loop;
int ensure_level;
@@ -89,7 +91,9 @@ codegen_error(codegen_scope *s, const char *message)
s = s->prev;
}
mrb_pool_close(s->mpool);
+#ifdef ENABLE_STDIO
fprintf(stderr, "codegen error: %s\n", message);
+#endif
longjmp(s->jmp, 1);
}
@@ -132,7 +136,7 @@ genop(codegen_scope *s, mrb_code i)
{
if (s->pc == s->icapa) {
s->icapa *= 2;
- s->iseq = codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
+ s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
}
s->iseq[s->pc] = i;
s->pc++;
@@ -141,7 +145,7 @@ genop(codegen_scope *s, mrb_code i)
static void
genop_peep(codegen_scope *s, mrb_code i, int val)
{
- // peephole optimization
+ /* peephole optimization */
if (!val && s->lastlabel != s->pc && s->pc > 0) {
mrb_code i0 = s->iseq[s->pc-1];
int c1 = GET_OPCODE(i);
@@ -152,9 +156,13 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
switch (c0) {
case OP_MOVE:
if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0) && GETARG_A(i) >= s->nlocals) {
- // skip swapping OP_MOVE
+ /* skip swapping OP_MOVE */
return;
}
+ if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
+ s->iseq[s->pc-1] = MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0));
+ return;
+ }
break;
case OP_LOADI:
if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
@@ -180,7 +188,6 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
case OP_GETSPECIAL:
case OP_LOADL:
case OP_STRING:
- case OP_GETMCNST:
if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
s->iseq[s->pc-1] = MKOP_ABx(c0, GETARG_A(i), GETARG_Bx(i0));
return;
@@ -202,29 +209,27 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
return;
}
break;
+ default:
+ break;
}
break;
case OP_SETIV:
case OP_SETCV:
case OP_SETCONST:
case OP_SETMCNST:
- switch (c0) {
- case OP_MOVE:
+ if (c0 == OP_MOVE) {
if (GETARG_A(i) == GETARG_A(i0)) {
s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i));
return;
}
- break;
}
break;
case OP_SETUPVAR:
- switch (c0) {
- case OP_MOVE:
+ if (c0 == OP_MOVE) {
if (GETARG_A(i) == GETARG_A(i0)) {
s->iseq[s->pc-1] = MKOP_ABC(c1, GETARG_B(i0), GETARG_B(i), GETARG_C(i));
return;
}
- break;
}
break;
case OP_EPOP:
@@ -239,6 +244,52 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
return;
}
break;
+ case OP_RETURN:
+ switch (c0) {
+ case OP_MOVE:
+ s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL);
+ return;
+ case OP_LOADI:
+ s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, 0, GETARG_sBx(i0));
+ genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
+ return;
+ case OP_ARRAY:
+ case OP_HASH:
+ case OP_RANGE:
+ case OP_AREF:
+ case OP_GETUPVAR:
+ s->iseq[s->pc-1] = MKOP_ABC(c0, 0, GETARG_B(i0), GETARG_C(i0));
+ genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
+ return;
+ case OP_LOADSYM:
+ case OP_GETGLOBAL:
+ case OP_GETIV:
+ case OP_GETCV:
+ case OP_GETCONST:
+ case OP_GETSPECIAL:
+ case OP_LOADL:
+ case OP_STRING:
+ s->iseq[s->pc-1] = MKOP_ABx(c0, 0, GETARG_Bx(i0));
+ genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
+ return;
+ case OP_SCLASS:
+ s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0));
+ genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
+ return;
+ case OP_LOADNIL:
+ case OP_LOADSELF:
+ case OP_LOADT:
+ case OP_LOADF:
+ case OP_OCLASS:
+ s->iseq[s->pc-1] = MKOP_A(c0, 0);
+ genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
+ return;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
}
}
genop(s, i);
@@ -265,7 +316,9 @@ dispatch(codegen_scope *s, int pc)
case OP_ONERR:
break;
default:
+#ifdef ENABLE_STDIO
fprintf(stderr, "bug: dispatch on non JMP op\n");
+#endif
scope_error(s);
}
s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
@@ -297,21 +350,10 @@ push_(codegen_scope *s)
s->sp++;
nregs_update;
}
-#if 0
-static void
-push_n_(codegen_scope *s, int n)
-{
- if (s->sp + n > 511) {
- codegen_error(s, "too complex expression");
- }
- s->sp += n;
- nregs_update;
-}
-#endif
#define push() push_(s)
-#define push_n(n) push_n_(s, n)
-#define pop() (s->sp--)
+#define pop_(s) ((s)->sp--)
+#define pop() pop_(s)
#define pop_n(n) (s->sp-=(n))
#define cursp() (s->sp)
@@ -321,11 +363,11 @@ new_lit(codegen_scope *s, mrb_value val)
int i;
for (i=0; i<s->plen; i++) {
- if (memcmp(&s->pool[i], &val, sizeof(mrb_value)) == 0) return i;
+ if (mrb_obj_equal(s->mrb, s->pool[i], val)) return i;
}
if (s->plen == s->pcapa) {
s->pcapa *= 2;
- s->pool = codegen_realloc(s, s->pool, sizeof(mrb_value)*s->pcapa);
+ s->pool = (mrb_value *)codegen_realloc(s, s->pool, sizeof(mrb_value)*s->pcapa);
}
s->pool[s->plen] = val;
return s->plen++;
@@ -359,7 +401,7 @@ new_sym(codegen_scope *s, mrb_sym sym)
if (s->syms[i] == sym) return i;
}
if (s->slen > 125 && s->slen < 256) {
- s->syms = codegen_realloc(s, s->syms, sizeof(mrb_sym)*65536);
+ s->syms = (mrb_sym *)codegen_realloc(s, s->syms, sizeof(mrb_sym)*65536);
memset(s->syms+s->slen, 0, sizeof(mrb_sym)*(256-s->slen));
s->slen = 256;
}
@@ -429,7 +471,7 @@ for_body(codegen_scope *s, node *tree)
pop();
c = s->iseq[s->pc-1];
if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) {
- genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL));
+ genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
}
loop_pop(s, NOVAL);
scope_finish(s, idx);
@@ -448,6 +490,7 @@ lambda_body(codegen_scope *s, node *tree, int blk)
s = scope_new(s->mrb, s, tree->car);
idx = s->idx;
+ s->mscope = !blk;
if (blk) {
struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
@@ -484,10 +527,10 @@ lambda_body(codegen_scope *s, node *tree, int blk)
pos = new_label(s);
for (i=0; i<oa; i++) {
new_label(s);
- genop(s, MKOP_Ax(OP_JMP, 0));
+ genop(s, MKOP_sBx(OP_JMP, 0));
}
if (oa > 0) {
- genop(s, MKOP_Ax(OP_JMP, 0));
+ genop(s, MKOP_sBx(OP_JMP, 0));
}
opt = tree->car->cdr->car;
i = 0;
@@ -510,7 +553,13 @@ lambda_body(codegen_scope *s, node *tree, int blk)
pop();
c = s->iseq[s->pc-1];
if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) {
- genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL));
+ if (s->nregs == 0) {
+ genop(s, MKOP_A(OP_LOADNIL, 0));
+ genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
+ }
+ else {
+ genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
+ }
}
if (blk) {
loop_pop(s, NOVAL);
@@ -526,13 +575,19 @@ scope_body(codegen_scope *s, node *tree)
codegen_scope *scope = scope_new(s->mrb, s, tree->car);
int idx = scope->idx;
+ codegen(scope, tree->cdr, VAL);
if (!s->iseq) {
- codegen(scope, tree->cdr, VAL);
genop(scope, MKOP_A(OP_STOP, 0));
}
else {
- codegen(scope, tree->cdr, VAL);
- genop(scope, MKOP_AB(OP_RETURN, scope->sp, OP_R_NORMAL));
+ pop_(scope);
+ if (scope->nregs == 0) {
+ genop(scope, MKOP_A(OP_LOADNIL, 0));
+ genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
+ }
+ else {
+ genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp, OP_R_NORMAL), NOVAL);
+ }
}
scope_finish(scope, idx);
@@ -552,16 +607,17 @@ nosplat(node *t)
static mrb_sym
attrsym(codegen_scope *s, mrb_sym a)
{
- const char *name = mrb_sym2name(s->mrb, a);
+ const char *name;
+ int len;
char *name2;
- size_t len = strlen(name);
- name2 = codegen_palloc(s, len+1);
- strcpy(name2, name);
+ name = mrb_sym2name_len(s->mrb, a, &len);
+ name2 = (char *)codegen_palloc(s, len+1);
+ memcpy(name2, name, len);
name2[len] = '=';
name2[len+1] = '\0';
- return mrb_intern(s->mrb, name2);
+ return mrb_intern2(s->mrb, name2, len+1);
}
static int
@@ -607,7 +663,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val)
{
mrb_sym sym = name ? name : (mrb_sym)tree->cdr->car;
int idx;
- int n = 0, noop = 0, sendv = 0;
+ int n = 0, noop = 0, sendv = 0, blk = 0;
codegen(s, tree->car, VAL); /* receiver */
idx = new_msym(s, sym);
@@ -637,31 +693,44 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val)
pop();
}
else {
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ blk = cursp();
}
pop_n(n+1);
{
- const char *name = mrb_sym2name(s->mrb, sym);
+ int len;
+ const char *name = mrb_sym2name_len(s->mrb, sym, &len);
- if (!noop && name[0] == '+' && strlen(name) == 1) {
+ if (!noop && len == 1 && name[0] == '+') {
genop(s, MKOP_ABC(OP_ADD, cursp(), idx, n));
}
- else if (!noop && name[0] == '-' && strlen(name) == 1) {
+ else if (!noop && len == 1 && name[0] == '-') {
genop(s, MKOP_ABC(OP_SUB, cursp(), idx, n));
}
- else if (!noop && name[0] == '<' && strlen(name) == 1) {
+ else if (!noop && len == 1 && name[0] == '*') {
+ genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n));
+ }
+ else if (!noop && len == 1 && name[0] == '/') {
+ genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n));
+ }
+ else if (!noop && len == 1 && name[0] == '<') {
genop(s, MKOP_ABC(OP_LT, cursp(), idx, n));
}
- else if (!noop && name[0] == '<' && strlen(name) == 2 && name[1] == '=') {
+ else if (!noop && len == 2 && name[0] == '<' && name[1] == '=') {
genop(s, MKOP_ABC(OP_LE, cursp(), idx, n));
}
- else if (!noop && name[0] == '>' && strlen(name) == 1) {
+ else if (!noop && len == 1 && name[0] == '>') {
genop(s, MKOP_ABC(OP_GT, cursp(), idx, n));
}
- else if (!noop && name[0] == '>' && strlen(name) == 2 && name[1] == '=') {
+ else if (!noop && len == 2 && name[0] == '>' && name[1] == '=') {
genop(s, MKOP_ABC(OP_GE, cursp(), idx, n));
}
+ else if (!noop && len == 2 && name[0] == '=' && name[1] == '=') {
+ genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n));
+ }
else {
+ if (blk > 0) { /* no block */
+ genop(s, MKOP_A(OP_LOADNIL, blk));
+ }
if (sendv) n = CALL_MAXARGS;
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n));
}
@@ -735,7 +804,9 @@ gen_assignment(codegen_scope *s, node *node, int sp, int val)
break;
default:
+#ifdef ENABLE_STDIO
printf("unknown lhs %d\n", type);
+#endif
break;
}
if (val) push();
@@ -795,6 +866,32 @@ raise_error(codegen_scope *s, const char *msg)
genop(s, MKOP_ABx(OP_ERR, 0, idx));
}
+static double
+readint_float(codegen_scope *s, const char *p, int base)
+{
+ const char *e = p + strlen(p);
+ double f = 0;
+ int n;
+
+ if (*p == '+') p++;
+ while (p < e) {
+ char c = *p;
+ c = tolower((unsigned char)c);
+ for (n=0; n<base; n++) {
+ if (mrb_digitmap[n] == c) {
+ f *= base;
+ f += n;
+ break;
+ }
+ }
+ if (n == base) {
+ codegen_error(s, "malformed readint input");
+ }
+ p++;
+ }
+ return f;
+}
+
static void
codegen(codegen_scope *s, node *tree, int val)
{
@@ -838,28 +935,34 @@ codegen(codegen_scope *s, node *tree, int val)
push();
while (n2) {
node *n3 = n2->car;
+ node *n4 = n3->car;
if (pos1) dispatch(s, pos1);
- if (n3->car) {
- node *n4 = n3->car;
-
- pos2 = 0;
- while (n4) {
+ pos2 = 0;
+ do {
+ if (n4) {
codegen(s, n4->car, VAL);
- genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
+ }
+ else {
+ genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern(s->mrb, "StandardError"))));
push();
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
- pop(); pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1));
- tmp = new_label(s);
- genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
- pos2 = tmp;
+ }
+ genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
+ push();
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ pop(); pop();
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1));
+ tmp = new_label(s);
+ genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
+ pos2 = tmp;
+ if (n4) {
n4 = n4->cdr;
}
- pos1 = new_label(s);
- genop(s, MKOP_Bx(OP_JMP, 0));
- dispatch_linked(s, pos2);
- }
+ } while (n4);
+ pos1 = new_label(s);
+ genop(s, MKOP_sBx(OP_JMP, 0));
+ dispatch_linked(s, pos2);
+
pop();
if (n3->cdr->car) {
gen_assignment(s, n3->cdr->car, exc, NOVAL);
@@ -868,7 +971,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, n3->cdr->cdr->car, val);
}
tmp = new_label(s);
- genop(s, MKOP_AsBx(OP_JMP, cursp(), exend));
+ genop(s, MKOP_sBx(OP_JMP, exend));
exend = tmp;
n2 = n2->cdr;
push();
@@ -878,6 +981,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_A(OP_RAISE, exc));
}
}
+ pop();
tree = tree->cdr;
dispatch(s, noexc);
genop(s, MKOP_A(OP_POPERR, 1));
@@ -983,13 +1087,14 @@ codegen(codegen_scope *s, node *tree, int val)
struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
lp->pc1 = new_label(s);
- codegen(s, tree->car, VAL);
- pop();
+ genop(s, MKOP_sBx(OP_JMP, 0));
lp->pc2 = new_label(s);
- genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0));
codegen(s, tree->cdr, NOVAL);
- genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
- dispatch(s, lp->pc2);
+ dispatch(s, lp->pc1);
+ codegen(s, tree->car, VAL);
+ pop();
+ genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc));
+
loop_pop(s, val);
}
break;
@@ -999,13 +1104,14 @@ codegen(codegen_scope *s, node *tree, int val)
struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
lp->pc1 = new_label(s);
- codegen(s, tree->car, VAL);
- pop();
+ genop(s, MKOP_sBx(OP_JMP, 0));
lp->pc2 = new_label(s);
- genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
codegen(s, tree->cdr, NOVAL);
- genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
- dispatch(s, lp->pc2);
+ dispatch(s, lp->pc1);
+ codegen(s, tree->car, VAL);
+ pop();
+ genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc));
+
loop_pop(s, val);
}
break;
@@ -1046,21 +1152,23 @@ codegen(codegen_scope *s, node *tree, int val)
}
if (tree->car->car) {
pos1 = new_label(s);
- genop(s, MKOP_AsBx(OP_JMP, cursp(), 0));
+ genop(s, MKOP_sBx(OP_JMP, 0));
dispatch_linked(s, pos2);
}
- pop(); pop();
+ pop();
codegen(s, tree->car->cdr, val);
+ pop();
tmp = new_label(s);
- genop(s, MKOP_AsBx(OP_JMP, cursp(), pos3));
+ genop(s, MKOP_sBx(OP_JMP, pos3));
pos3 = tmp;
if (pos1) dispatch(s, pos1);
tree = tree->cdr;
- push(); push();
+ push();
}
pop();
- if (pos3) dispatch_linked(s, pos3);
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
if (val) push();
+ if (pos3) dispatch_linked(s, pos3);
}
break;
@@ -1227,12 +1335,14 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_OP_ASGN:
{
mrb_sym sym = (mrb_sym)tree->cdr->car;
- const char *name = mrb_sym2name(s->mrb, sym);
- int idx;
+ int len;
+ const char *name = mrb_sym2name_len(s->mrb, sym, &len);
+ int idx, blk = 0;
codegen(s, tree->car, VAL);
- if ((name[0] == '|' && strlen(name) == 2 && name[1] == '|') ||
- (name[0] == '&' && strlen(name) == 2 && name[1] == '&')) {
+ if (len == 2 &&
+ ((name[0] == '|' && name[1] == '|') ||
+ (name[0] == '&' && name[1] == '&'))) {
int pos;
pop();
@@ -1245,29 +1355,32 @@ codegen(codegen_scope *s, node *tree, int val)
break;
}
codegen(s, tree->cdr->cdr->car, VAL);
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ blk = cursp();
pop(); pop();
idx = new_msym(s, sym);
- if (name[0] == '+' && strlen(name) == 1) {
+ if (len == 1 && name[0] == '+') {
genop(s, MKOP_ABC(OP_ADD, cursp(), idx, 1));
}
- else if (name[0] == '-' && strlen(name) == 1) {
+ else if (len == 1 && name[0] == '-') {
genop(s, MKOP_ABC(OP_SUB, cursp(), idx, 1));
}
- else if (name[0] == '<' && strlen(name) == 1) {
+ else if (len == 1 && name[0] == '<') {
genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1));
}
- else if (name[0] == '<' && strlen(name) == 2 && name[1] == '=') {
+ else if (len == 2 && name[0] == '<' && name[1] == '=') {
genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1));
}
- else if (name[0] == '>' && strlen(name) == 1) {
+ else if (len == 1 && name[0] == '>') {
genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1));
}
- else if (name[0] == '>' && strlen(name) == 2 && name[1] == '=') {
+ else if (len == 2 && name[0] == '>' && name[1] == '=') {
genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1));
}
else {
+ if (blk > 0) {
+ genop(s, MKOP_A(OP_LOADNIL, blk));
+ }
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1));
}
}
@@ -1276,16 +1389,18 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_SUPER:
{
- int n = 0;
+ int n = 0, noop = 0, sendv = 0;
- push();
+ push(); /* room for receiver */
if (tree) {
node *args = tree->car;
- while (args) {
- codegen(s, args->car, VAL);
- n++;
- args = args->cdr;
- }
+ if (args) {
+ n = gen_values(s, args);
+ if (n < 0) {
+ n = noop = sendv = 1;
+ push();
+ }
+ }
}
if (tree && tree->cdr) {
codegen(s, tree->cdr, VAL);
@@ -1295,6 +1410,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_A(OP_LOADNIL, cursp()));
}
pop_n(n+1);
+ if (sendv) n = CALL_MAXARGS;
genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n));
if (val) push();
}
@@ -1305,14 +1421,19 @@ codegen(codegen_scope *s, node *tree, int val)
codegen_scope *s2 = s;
int lv = 0, ainfo = 0;
- while (s2->ainfo < 0) {
+ push(); /* room for receiver */
+ while (!s2->mscope) {
lv++;
s2 = s2->prev;
if (!s2) break;
}
if (s2) ainfo = s2->ainfo;
- push();
genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf)));
+ if (tree && tree->cdr) {
+ push();
+ codegen(s, tree->cdr, VAL);
+ pop_n(2);
+ }
pop();
genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS));
if (val) push();
@@ -1326,7 +1447,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN));
}
else {
- genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL));
+ genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
}
break;
@@ -1336,7 +1457,7 @@ codegen(codegen_scope *s, node *tree, int val)
int lv = 0, ainfo = 0;
int n = 0, sendv = 0;
- while (s2->ainfo < 0) {
+ while (!s2->mscope) {
lv++;
s2 = s2->prev;
if (!s2) break;
@@ -1378,7 +1499,7 @@ codegen(codegen_scope *s, node *tree, int val)
else {
codegen(s, tree, VAL);
pop();
- genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL));
+ genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
}
if (val) push();
break;
@@ -1498,10 +1619,11 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_BACK_REF:
{
char buf[4];
+ int len;
int sym;
- snprintf(buf, 3, "$%c", (int)(intptr_t)tree);
- sym = new_sym(s, mrb_intern(s->mrb, buf));
+ len = snprintf(buf, sizeof(buf), "$%c", (int)(intptr_t)tree);
+ sym = new_sym(s, mrb_intern2(s->mrb, buf, len));
genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
push();
}
@@ -1510,10 +1632,11 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_NTH_REF:
{
char buf[4];
+ int len;
int sym;
- snprintf(buf, 3, "$%d", (int)(intptr_t)tree);
- sym = new_sym(s, mrb_intern(s->mrb, buf));
+ len = snprintf(buf, sizeof(buf), "$%d", (int)(intptr_t)tree);
+ sym = new_sym(s, mrb_intern2(s->mrb, buf, len));
genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
push();
}
@@ -1531,17 +1654,27 @@ codegen(codegen_scope *s, node *tree, int val)
if (val) {
char *p = (char*)tree->car;
int base = (intptr_t)tree->cdr->car;
- int i = readint(p, base);
+ double f;
+ mrb_int i;
mrb_code co;
- if (i < MAXARG_sBx && i > -MAXARG_sBx) {
- co = MKOP_AsBx(OP_LOADI, cursp(), i);
+ f = readint_float(s, p, base);
+ if (!FIXABLE(f)) {
+ int off = new_lit(s, mrb_float_value(f));
+
+ genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
}
else {
- int off = new_lit(s, mrb_fixnum_value(i));
- co = MKOP_ABx(OP_LOADL, cursp(), off);
+ i = (mrb_int)f;
+ if (i < MAXARG_sBx && i > -MAXARG_sBx) {
+ co = MKOP_AsBx(OP_LOADI, cursp(), i);
+ }
+ else {
+ int off = new_lit(s, mrb_fixnum_value(i));
+ co = MKOP_ABx(OP_LOADL, cursp(), off);
+ }
+ genop(s, co);
}
- genop(s, co);
push();
}
break;
@@ -1577,18 +1710,27 @@ codegen(codegen_scope *s, node *tree, int val)
{
char *p = (char*)tree->car;
int base = (intptr_t)tree->cdr->car;
- int i = readint(p, base);
+ mrb_float f;
+ mrb_int i;
mrb_code co;
- i = -i;
- if (i < MAXARG_sBx && i > -MAXARG_sBx) {
- co = MKOP_AsBx(OP_LOADI, cursp(), i);
- }
- else {
- int off = new_lit(s, mrb_fixnum_value(i));
- co = MKOP_ABx(OP_LOADL, cursp(), off);
- }
- genop(s, co);
+ f = readint_float(s, p, base);
+ if (!FIXABLE(f)) {
+ int off = new_lit(s, mrb_float_value(-f));
+
+ genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
+ }
+ else {
+ i = (mrb_int)-f;
+ if (i < MAXARG_sBx && i > -MAXARG_sBx) {
+ co = MKOP_AsBx(OP_LOADI, cursp(), i);
+ }
+ else {
+ int off = new_lit(s, mrb_fixnum_value(i));
+ co = MKOP_ABx(OP_LOADL, cursp(), off);
+ }
+ genop(s, co);
+ }
push();
}
break;
@@ -1654,6 +1796,15 @@ codegen(codegen_scope *s, node *tree, int val)
}
break;
+ 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();
+ }
+ break;
+
case NODE_SELF:
if (val) {
genop(s, MKOP_A(OP_LOADSELF, cursp()));
@@ -1843,7 +1994,7 @@ static codegen_scope*
scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
{
mrb_pool *pool = mrb_pool_open(mrb);
- codegen_scope *p = mrb_pool_alloc(pool, sizeof(codegen_scope));
+ codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
if (!p) return 0;
memset(p, 0, sizeof(codegen_scope));
@@ -1852,15 +2003,16 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
if (!prev) return p;
p->prev = prev;
p->ainfo = -1;
+ p->mscope = 0;
p->mrb = prev->mrb;
p->icapa = 1024;
- p->iseq = mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
+ p->iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
p->pcapa = 32;
- p->pool = mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
+ p->pool = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
- p->syms = mrb_malloc(mrb, sizeof(mrb_sym)*256);
+ p->syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym)*256);
p->lv = lv;
p->sp += node_len(lv)+2;
@@ -1879,20 +2031,20 @@ scope_finish(codegen_scope *s, int idx)
mrb_irep *irep;
mrb_add_irep(mrb, idx);
- irep = mrb->irep[idx] = mrb_malloc(mrb, sizeof(mrb_irep));
+ irep = mrb->irep[idx] = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
irep->idx = idx;
irep->flags = 0;
if (s->iseq) {
- irep->iseq = codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
+ irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
irep->ilen = s->pc;
}
if (s->pool) {
- irep->pool = codegen_realloc(s, s->pool, sizeof(mrb_value)*s->plen);
+ irep->pool = (mrb_value *)codegen_realloc(s, s->pool, sizeof(mrb_value)*s->plen);
irep->plen = s->plen;
}
if (s->syms) {
- irep->syms = codegen_realloc(s, s->syms, sizeof(mrb_sym)*s->slen);
+ irep->syms = (mrb_sym *)codegen_realloc(s, s->syms, sizeof(mrb_sym)*s->slen);
irep->slen = s->slen;
}
@@ -1906,7 +2058,7 @@ scope_finish(codegen_scope *s, int idx)
static struct loopinfo*
loop_push(codegen_scope *s, enum looptype t)
{
- struct loopinfo *p = codegen_palloc(s, sizeof(struct loopinfo));
+ struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo));
p->type = t;
p->pc1 = p->pc2 = p->pc3 = 0;
@@ -1971,6 +2123,7 @@ loop_pop(codegen_scope *s, int val)
static void
codedump(mrb_state *mrb, int n)
{
+#ifdef ENABLE_STDIO
mrb_irep *irep = mrb->irep[n];
int i;
mrb_code c;
@@ -1995,7 +2148,7 @@ codedump(mrb_state *mrb, int n)
printf("OP_LOADI\tR%d\t%d\n", GETARG_A(c), GETARG_sBx(c));
break;
case OP_LOADSYM:
- printf("OP_LOADSYM\tR%d\t'%s'\n", GETARG_A(c),
+ printf("OP_LOADSYM\tR%d\t:%s\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
break;
case OP_LOADNIL:
@@ -2011,20 +2164,20 @@ codedump(mrb_state *mrb, int n)
printf("OP_LOADF\tR%d\n", GETARG_A(c));
break;
case OP_GETGLOBAL:
- printf("OP_GETGLOBAL\tR%d\t'%s'\n", GETARG_A(c),
+ printf("OP_GETGLOBAL\tR%d\t:%s\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
break;
case OP_SETGLOBAL:
- printf("OP_SETGLOBAL\t'%s'\tR%d\n",
+ printf("OP_SETGLOBAL\t:%s\tR%d\n",
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
GETARG_A(c));
break;
case OP_GETCONST:
- printf("OP_GETCONST\tR%d\t'%s'\n", GETARG_A(c),
+ printf("OP_GETCONST\tR%d\t:%s\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
break;
case OP_SETCONST:
- printf("OP_SETCONST\t'%s'\tR%d\n",
+ printf("OP_SETCONST\t:%s\tR%d\n",
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
GETARG_A(c));
break;
@@ -2073,7 +2226,12 @@ codedump(mrb_state *mrb, int n)
printf("OP_JMPNOT\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c));
break;
case OP_SEND:
- printf("OP_SEND\tR%d\t'%s'\t%d\n", GETARG_A(c),
+ printf("OP_SEND\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_TAILCALL:
+ printf("OP_TAILCALL\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
break;
@@ -2128,37 +2286,52 @@ codedump(mrb_state *mrb, int n)
printf("OP_RANGE\tR%d\tR%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
break;
case OP_METHOD:
- printf("OP_METHOD\tR%d\t'%s'\n", GETARG_A(c),
+ printf("OP_METHOD\tR%d\t:%s\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
break;
case OP_ADD:
- printf("OP_ADD\tR%d\t'%s'\t%d\n", GETARG_A(c),
+ printf("OP_ADD\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
break;
case OP_SUB:
- printf("OP_SUB\tR%d\t'%s'\t%d\n", GETARG_A(c),
+ printf("OP_SUB\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_MUL:
+ printf("OP_MUL\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_DIV:
+ printf("OP_DIV\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
break;
case OP_LT:
- printf("OP_LT\tR%d\t'%s'\t%d\n", GETARG_A(c),
+ printf("OP_LT\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
break;
case OP_LE:
- printf("OP_LE\tR%d\t'%s'\t%d\n", GETARG_A(c),
+ printf("OP_LE\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
break;
case OP_GT:
- printf("OP_GT\tR%d\t'%s'\t%d\n", GETARG_A(c),
+ printf("OP_GT\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
break;
case OP_GE:
- printf("OP_GE\tR%d\t'%s'\t%d\n", GETARG_A(c),
+ printf("OP_GE\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_EQ:
+ printf("OP_EQ\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
break;
@@ -2183,7 +2356,12 @@ codedump(mrb_state *mrb, int n)
printf("OP_APOST\tR%d\t%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
break;
case OP_STRING:
- printf("OP_STRING\tR%d\t'%s'\n", GETARG_A(c), RSTRING_PTR(irep->pool[GETARG_Bx(c)]));
+ {
+ mrb_value s = irep->pool[GETARG_Bx(c)];
+
+ s = mrb_str_dump(mrb, s);
+ printf("OP_STRING\tR%d\t%s\n", GETARG_A(c), RSTRING_PTR(s));
+ }
break;
case OP_STRCAT:
printf("OP_STRCAT\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c));
@@ -2196,11 +2374,11 @@ codedump(mrb_state *mrb, int n)
printf("OP_OCLASS\tR%d\n", GETARG_A(c));
break;
case OP_CLASS:
- printf("OP_CLASS\tR%d\t'%s'\n", GETARG_A(c),
+ printf("OP_CLASS\tR%d\t:%s\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
break;
case OP_MODULE:
- printf("OP_MODULE\tR%d\t'%s'\n", GETARG_A(c),
+ printf("OP_MODULE\tR%d\t:%s\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
break;
case OP_EXEC:
@@ -2213,7 +2391,7 @@ codedump(mrb_state *mrb, int n)
printf("OP_TCLASS\tR%d\n", GETARG_A(c));
break;
case OP_ERR:
- printf("OP_ERR\t:L(%d)\n", GETARG_Bx(c));
+ printf("OP_ERR\tL(%d)\n", GETARG_Bx(c));
break;
case OP_EPUSH:
printf("OP_EPUSH\t:I(%d)\n", n+GETARG_Bx(c));
@@ -2241,6 +2419,7 @@ codedump(mrb_state *mrb, int n)
}
}
printf("\n");
+#endif
}
void
diff --git a/src/compar.c b/src/compar.c
index 1502d450b..1614d2393 100644
--- a/src/compar.c
+++ b/src/compar.c
@@ -5,41 +5,6 @@
*/
#include "mruby.h"
-#include "mruby/string.h"
-#include "mruby/numeric.h"
-
-void
-mrb_cmperr(mrb_state *mrb, mrb_value x, mrb_value y)
-{
- const char *classname;
-
- if (SPECIAL_CONST_P(y)) {
- y = mrb_inspect(mrb, y);
- classname = mrb_string_value_ptr(mrb, y);
- }
- else {
- classname = mrb_obj_classname(mrb, y);
- }
- mrb_raise(mrb, E_ARGUMENT_ERROR, "comparison of %s with %s failed",
- mrb_obj_classname(mrb, x), classname);
-}
-
-int
-mrb_cmpint(mrb_state *mrb, mrb_value val, mrb_value a, mrb_value b)
-{
- if (mrb_nil_p(val)) {
- mrb_cmperr(mrb, a, b);
- }
- if (FIXNUM_P(val)) {
- long l = mrb_fixnum(val);
- if (l > 0) return 1;
- if (l < 0) return -1;
- return 0;
- }
- if (mrb_test(mrb_funcall(mrb, val, ">", 1, mrb_fixnum_value(0)))) return 1;
- if (mrb_test(mrb_funcall(mrb, val, "<", 1, mrb_fixnum_value(0)))) return -1;
- return 0;
-}
void
mrb_init_comparable(mrb_state *mrb)
diff --git a/src/dump.c b/src/dump.c
index f3cbef3a0..230ba9bba 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -8,7 +8,7 @@
#include "mruby/dump.h"
#include "mruby/string.h"
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
#include "re.h"
#endif
#include "mruby/irep.h"
@@ -222,22 +222,23 @@ get_pool_block_size(mrb_state *mrb, mrb_irep *irep, int type)
for (pool_no = 0; pool_no < irep->plen; pool_no++) {
uint16_t nlen =0;
+ int len;
switch (irep->pool[pool_no].tt) {
case MRB_TT_FIXNUM:
- sprintf( buf, "%d", irep->pool[pool_no].value.i);
- size += strlen(buf);
+ len = sprintf( buf, "%d", irep->pool[pool_no].value.i);
+ size += (uint32_t)len;
break;
case MRB_TT_FLOAT:
- sprintf( buf, "%.16e", irep->pool[pool_no].value.f);
- size += strlen(buf);
+ len = sprintf( buf, "%.16e", irep->pool[pool_no].value.f);
+ size += (uint32_t)len;
break;
case MRB_TT_STRING:
str = mrb_string_value( mrb, &irep->pool[pool_no]);
nlen = str_dump_len(RSTRING_PTR(str), RSTRING_LEN(str), type);
size += nlen;
break;
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
case MRB_TT_REGEX:
str = mrb_reg_to_s(mrb, irep->pool[pool_no]);
nlen = str_dump_len(RSTRING_PTR(str), RSTRING_LEN(str), type);
@@ -268,8 +269,10 @@ 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) {
- name = mrb_sym2name(mrb, irep->syms[sym_no]);
- nlen = str_dump_len((char*)name, strlen(name), type);
+ int len;
+
+ name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len);
+ nlen = str_dump_len((char*)name, len, type);
size += nlen; /* sn(n) */
}
}
@@ -329,9 +332,10 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type)
char *buf_top = buf;
char *char_buf;
uint16_t buf_size =0;
+ int len;
buf_size = MRB_DUMP_DEFAULT_STR_LEN;
- if ((char_buf = mrb_malloc(mrb, buf_size)) == 0)
+ if ((char_buf = (char *)mrb_malloc(mrb, buf_size)) == 0)
goto error_exit;
buf += uint32_dump((uint32_t)irep->plen, buf, type); /* number of pool */
@@ -356,14 +360,14 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type)
nlen = str_dump_len(RSTRING_PTR(str), RSTRING_LEN(str), type);
if ( nlen > buf_size - 1) {
buf_size = nlen + 1;
- if ((char_buf = mrb_realloc(mrb, char_buf, buf_size)) == 0)
+ if ((char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size)) == 0)
goto error_exit;
memset(char_buf, 0, buf_size);
}
str_dump(RSTRING_PTR(str), char_buf, RSTRING_LEN(str), type);
break;
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
case MRB_TT_REGEX:
str = mrb_reg_to_s(mrb, irep->pool[pool_no]);
nlen = str_dump_len(RSTRING_PTR(str), RSTRING_LEN(str), type);
@@ -382,10 +386,12 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type)
continue;
}
- buf += uint16_dump((uint16_t)strlen(char_buf), buf, type); /* data length */
+ len = strlen(char_buf);
- memcpy(buf, char_buf, strlen(char_buf));
- buf += strlen(char_buf);
+ buf += uint16_dump((uint16_t)len, buf, type); /* data length */
+
+ memcpy(buf, char_buf, len);
+ buf += len;
}
error_exit:
@@ -403,7 +409,7 @@ write_syms_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type)
uint16_t buf_size =0;
buf_size = MRB_DUMP_DEFAULT_STR_LEN;
- if ((char_buf = mrb_malloc(mrb, buf_size)) == 0)
+ if ((char_buf = (char *)mrb_malloc(mrb, buf_size)) == 0)
goto error_exit;
buf += uint32_dump((uint32_t)irep->slen, buf, type); /* number of symbol */
@@ -413,15 +419,17 @@ write_syms_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type)
uint16_t nlen =0;
if (irep->syms[sym_no] != 0) {
- name = mrb_sym2name(mrb, irep->syms[sym_no]);
- nlen = str_dump_len((char*)name, strlen(name), type);
+ int len;
+
+ name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len);
+ nlen = str_dump_len((char*)name, len, type);
if ( nlen > buf_size - 1) {
buf_size = nlen + 1;
- if ((char_buf = mrb_realloc(mrb, char_buf, buf_size)) == 0)
+ if ((char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size)) == 0)
goto error_exit;
}
memset(char_buf, 0, buf_size);
- str_dump((char*)name, char_buf, strlen(name), type);
+ str_dump((char*)name, char_buf, len, type);
buf += uint16_dump(nlen, buf, type); /* length of symbol name */
memcpy(buf, char_buf, nlen); /* symbol name */
@@ -453,11 +461,10 @@ calc_crc_section(mrb_state *mrb, mrb_irep *irep, uint16_t *crc, int section)
default: return MRB_DUMP_GENERAL_FAILURE;
}
- if ((buf = mrb_malloc(mrb, buf_size)) == 0)
+ if ((buf = (char *)mrb_calloc(mrb, 1, buf_size)) == 0)
return MRB_DUMP_GENERAL_FAILURE;
buf_top = buf;
- memset(buf, 0, buf_size);
switch (section) {
case DUMP_IREP_HEADER: buf += write_irep_header(mrb, irep, buf, type); break;
@@ -591,13 +598,13 @@ dump_irep_record(mrb_state *mrb, int irep_no, FILE* fp, uint32_t *rlen)
if (irep_record_size == 0)
return MRB_DUMP_GENERAL_FAILURE;
- if ((buf = mrb_malloc(mrb, irep_record_size)) == 0)
+ if ((buf = (char *)mrb_calloc(mrb, 1, irep_record_size)) == 0)
return MRB_DUMP_GENERAL_FAILURE;
- memset( buf, 0, irep_record_size);
-
- if ((rc = write_irep_record(mrb, irep_no, buf, rlen, DUMP_TYPE_HEX)) != MRB_DUMP_OK)
+ if ((rc = write_irep_record(mrb, irep_no, buf, rlen, DUMP_TYPE_HEX)) != MRB_DUMP_OK) {
+ rc = MRB_DUMP_GENERAL_FAILURE;
goto error_exit;
+ }
if (fwrite(buf, irep_record_size, 1, fp) != 1)
@@ -683,7 +690,7 @@ mrb_bdump_irep(mrb_state *mrb, int n, FILE *f,const char *initname)
buf_size += get_irep_record_size(mrb, irep_no, DUMP_TYPE_BIN);
buf_size += MRB_DUMP_SIZE_OF_LONG; /* end of file */
- if ((buf = mrb_malloc(mrb, buf_size)) == 0)
+ if ((buf = (char *)mrb_malloc(mrb, buf_size)) == 0)
return MRB_DUMP_GENERAL_FAILURE;
rc = mrb_write_irep(mrb, n, buf);
diff --git a/src/error.c b/src/error.c
index ae89541c1..6fe839cb2 100644
--- a/src/error.c
+++ b/src/error.c
@@ -6,28 +6,15 @@
#include "mruby.h"
#include <stdarg.h>
-#include <string.h>
#include <stdio.h>
#include <setjmp.h>
#include "error.h"
-#include "opcode.h"
-#include "mruby/irep.h"
-#include "mruby/proc.h"
-#include "mruby/numeric.h"
#include "mruby/variable.h"
#include "mruby/string.h"
#include "mruby/class.h"
#define warn_printf printf
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
mrb_value
mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len)
{
@@ -42,7 +29,6 @@ mrb_exc_new3(mrb_state *mrb, struct RClass* c, mrb_value str)
return mrb_funcall(mrb, mrb_obj_value(c), "new", 1, str);
}
-//mrb_value make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr);
/*
* call-seq:
* Exception.new(msg = nil) -> exception
@@ -79,14 +65,14 @@ static mrb_value
exc_exception(mrb_state *mrb, mrb_value self)
{
mrb_value exc;
- mrb_value *argv;
+ mrb_value a;
int argc;
- mrb_get_args(mrb, "*", &argv, &argc);
+ argc = mrb_get_args(mrb, "|o", &a);
if (argc == 0) return self;
- if (argc == 1 && mrb_obj_equal(mrb, self, argv[0])) return self;
+ if (mrb_obj_equal(mrb, self, a)) return self;
exc = mrb_obj_clone(mrb, self);
- exc_initialize(mrb, exc);
+ mrb_iv_set(mrb, exc, mrb_intern(mrb, "mesg"), a);
return exc;
}
@@ -134,20 +120,15 @@ exc_message(mrb_state *mrb, mrb_value exc)
static mrb_value
exc_inspect(mrb_state *mrb, mrb_value exc)
{
- mrb_value str, klass;
+ mrb_value str;
- klass = mrb_str_new2(mrb, mrb_obj_classname(mrb, exc));
+ str = mrb_str_new2(mrb, mrb_obj_classname(mrb, exc));
exc = mrb_obj_as_string(mrb, exc);
- if (RSTRING_LEN(exc) == 0) {
- return klass;
- }
-
- str = mrb_str_new2(mrb, "#<");
- mrb_str_append(mrb, str, klass);
- mrb_str_cat2(mrb, str, ": ");
- mrb_str_append(mrb, str, exc);
- mrb_str_cat2(mrb, str, ">");
+ if (RSTRING_LEN(exc) > 0) {
+ mrb_str_cat2(mrb, str, ": ");
+ mrb_str_append(mrb, str, exc);
+ }
return str;
}
@@ -163,7 +144,7 @@ exc_equal(mrb_state *mrb, mrb_value exc)
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")) ) {
+ if (mrb_respond_to(mrb, obj, mrb_intern(mrb, "message"))) {
mesg = mrb_funcall(mrb, obj, "message", 0);
}
else
@@ -186,24 +167,19 @@ mrb_exc_raise(mrb_state *mrb, mrb_value exc)
}
void
-mrb_raise_va(mrb_state *mrb, struct RClass *c, const char *fmt, va_list args)
-{
- char buf[256];
-
- vsnprintf(buf, 256, fmt, args);
- mrb_exc_raise(mrb, mrb_exc_new(mrb, c, buf, strlen(buf)));
-}
-
-void
mrb_raise(mrb_state *mrb, struct RClass *c, const char *fmt, ...)
{
va_list args;
char buf[256];
+ int n;
va_start(args, fmt);
- vsnprintf(buf, 256, fmt, args);
+ n = vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
- mrb_exc_raise(mrb, mrb_exc_new(mrb, c, buf, strlen(buf)));
+ if (n < 0) {
+ n = 0;
+ }
+ mrb_exc_raise(mrb, mrb_exc_new(mrb, c, buf, n));
}
void
@@ -212,51 +188,44 @@ mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...)
mrb_value exc, argv[2];
va_list args;
char buf[256];
+ int n;
va_start(args, fmt);
- //argv[0] = mrb_vsprintf(fmt, args);
- vsnprintf(buf, 256, fmt, args);
- argv[0] = mrb_str_new(mrb, buf, strlen(buf));
+ n = vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
-
- argv[1] = mrb_str_new_cstr(mrb, mrb_sym2name(mrb, id));
- exc = mrb_class_new_instance(mrb, 2, argv, E_NAME_ERROR);
+ if (n < 0) {
+ n = 0;
+ }
+ argv[0] = mrb_str_new(mrb, buf, n);
+ argv[1] = mrb_symbol_value(id); /* ignore now */
+ exc = mrb_class_new_instance(mrb, 1, argv, E_NAME_ERROR);
mrb_exc_raise(mrb, exc);
}
+
mrb_value
mrb_sprintf(mrb_state *mrb, const char *fmt, ...)
{
va_list args;
char buf[256];
+ int n;
va_start(args, fmt);
- vsnprintf(buf, 256, fmt, args);
+ n = vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
- return mrb_str_new(mrb, buf, strlen(buf));
+ if (n < 0) {
+ n = 0;
+ }
+ return mrb_str_new(mrb, buf, n);
}
void
mrb_warn(const char *fmt, ...)
{
va_list args;
- char buf[256];
va_start(args, fmt);
- snprintf(buf, 256, "warning: %s", fmt);
- printf(buf, args);
- va_end(args);
-}
-
-
-void
-mrb_warning(const char *fmt, ...)
-{
- va_list args;
- char buf[256];
-
- va_start(args, fmt);
- snprintf(buf, 256, "warning: %s", fmt);
- printf(buf, args);
+ printf("warning: ");
+ vprintf(fmt, args);
va_end(args);
}
@@ -264,12 +233,12 @@ void
mrb_bug(const char *fmt, ...)
{
va_list args;
- char buf[256];
va_start(args, fmt);
- snprintf(buf, 256, "bug: %s", fmt);
- printf(buf, args);
+ printf("bug: ");
+ vprintf(fmt, args);
va_end(args);
+ exit(EXIT_FAILURE);
}
static const char *
@@ -304,28 +273,6 @@ sysexit_status(mrb_state *mrb, mrb_value err)
return mrb_fixnum(st);
}
-void
-error_pos(void)
-{
-#if 0
- const char *sourcefile = mrb_sourcefile();
- int sourceline = mrb_sourceline();
-
- if (sourcefile) {
- if (sourceline == 0) {
- warn_printf("%s", sourcefile);
- }
- else if (mrb_frame_callee()) {
- warn_printf("%s:%d:in `%s'", sourcefile, sourceline,
- mrb_sym2name(mrb, mrb_frame_callee()));
- }
- else {
- warn_printf("%s:%d", sourcefile, sourceline);
- }
- }
-#endif
-}
-
static void
set_backtrace(mrb_state *mrb, mrb_value info, mrb_value bt)
{
@@ -348,7 +295,7 @@ make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr)
if (isstr) {
mesg = mrb_check_string_type(mrb, argv[0]);
if (!mrb_nil_p(mesg)) {
- mesg = mrb_exc_new3(mrb, mrb->eRuntimeError_class, mesg);
+ mesg = mrb_exc_new3(mrb, E_RUNTIME_ERROR, mesg);
break;
}
}
@@ -359,20 +306,15 @@ make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr)
case 3:
n = 1;
exception_call:
- //if (argv[0] == sysstack_error) return argv[0];
-
- //CONST_ID(mrb, exception, "exception");
- //mesg = mrb_check_funcall(mrb, argv[0], exception, n, argv+1);
- //if (mrb_nil_p(mesg)) {
- // /* undef */
- // mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected");
- //}
- if (mrb_respond_to(mrb, argv[0], mrb_intern(mrb, "exception"))) {
- mesg = mrb_funcall(mrb, argv[0], "exception", n, argv+1);
- }
- else {
- /* undef */
- mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected");
+ {
+ mrb_sym exc = mrb_intern(mrb, "exception");
+ if (mrb_respond_to(mrb, argv[0], exc)) {
+ mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1);
+ }
+ else {
+ /* undef */
+ mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected");
+ }
}
break;
@@ -399,16 +341,13 @@ mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv)
void
mrb_sys_fail(mrb_state *mrb, const char *mesg)
{
- mrb_raise(mrb, mrb->eRuntimeError_class, "%s", mesg);
+ mrb_raise(mrb, E_RUNTIME_ERROR, "%s", mesg);
}
void
mrb_init_exception(mrb_state *mrb)
{
struct RClass *e;
- struct RClass *eIndexError;
- struct RClass *eRangeError;
- struct RClass *eNameError;
mrb->eException_class = e = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */
mrb_define_class_method(mrb, e, "exception", mrb_instance_new, ARGS_ANY());
@@ -419,32 +358,6 @@ mrb_init_exception(mrb_state *mrb)
mrb_define_method(mrb, e, "message", exc_message, ARGS_NONE());
mrb_define_method(mrb, e, "inspect", exc_inspect, ARGS_NONE());
- mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */
- mrb->eRuntimeError_class = mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */
-
- mrb_define_class(mrb, "TypeError", mrb->eStandardError_class); /* 15.2.29 */
- mrb_define_class(mrb, "ArgumentError", mrb->eStandardError_class); /* 15.2.24 */
- eIndexError = mrb_define_class(mrb, "IndexError", mrb->eStandardError_class); /* 15.2.33 */
- eRangeError = mrb_define_class(mrb, "RangeError", mrb->eStandardError_class); /* 15.2.26 */
- eNameError = mrb_define_class(mrb, "NameError", mrb->eStandardError_class); /* 15.2.31 */
-
- mrb_define_class(mrb, "NoMethodError", eNameError); /* 15.2.32 */
- // eScriptError = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */
- // mrb_define_class(mrb, "SyntaxError", eScriptError); /* 15.2.38 */
- // mrb_define_class(mrb, "LoadError", eScriptError); /* 15.2.39 */
- // mrb_define_class(mrb, "NotImplementedError", eScriptError_class);
- // mrb_define_class(mrb, "SystemCallError", mrb->eStandardError_class); /* 15.2.36 */
- mrb_define_class(mrb, "LocalJumpError", mrb->eStandardError_class); /* 15.2.25 */
-
-#ifdef INCLUDE_REGEX
- mrb_define_class(mrb, "RegexpError", mrb->eStandardError_class); /* 15.2.27 */
-#endif
-
-#ifdef INCLUDE_ENCODING
- mrb_define_class(mrb, "EncodingError", mrb->eStandardError_class);
-#endif
- // mrb_define_class(mrb, "ZeroDivisionError", mrb->eStandardError_class); /* 15.2.30 */
-
- mrb_define_class(mrb, "FloatDomainError", eRangeError);
- mrb_define_class(mrb, "KeyError", eIndexError);
+ mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */
+ mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */
}
diff --git a/src/error.h b/src/error.h
index babf93a7d..e4d6acb6c 100644
--- a/src/error.h
+++ b/src/error.h
@@ -12,13 +12,10 @@ struct RException {
};
void mrb_sys_fail(mrb_state *mrb, const char *mesg);
-void mrb_exc_raise(mrb_state *mrb, mrb_value mesg);
void mrb_bug_errno(const char*, int);
int sysexit_status(mrb_state *mrb, mrb_value err);
-void error_pos(void);
mrb_value mrb_exc_new3(mrb_state *mrb, struct RClass* c, mrb_value str);
mrb_value make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr);
-mrb_value mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len);
mrb_value mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv);
mrb_value mrb_sprintf(mrb_state *mrb, const char *fmt, ...);
void mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...);
diff --git a/src/etc.c b/src/etc.c
index 90ec47fb9..d14498d9c 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -10,14 +10,6 @@
#include "mruby/numeric.h"
#include "mruby/data.h"
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
struct RData*
mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const struct mrb_data_type *type)
{
@@ -60,11 +52,6 @@ mrb_check_datatype(mrb_state *mrb, mrb_value obj, const struct mrb_data_type *ty
mrb_value
mrb_lastline_get(mrb_state *mrb)
{
- //mrb_value *var = mrb_svar(0);
- //if (var) {
- // return *var;
- //}
- //return mrb_nil_value();
mrb_value *argv;
int argc;
@@ -78,21 +65,6 @@ mrb_lastline_get(mrb_state *mrb)
}
}
-mrb_value
-mrb_rescue2(mrb_state *mrb, mrb_value (* b_proc) (ANYARGS), mrb_value *data1,
- mrb_value (* r_proc) (ANYARGS), mrb_value *data2, ...)
-{
- mrb_value result = (*b_proc) (mrb, data1);
- return result;
-}
-
-mrb_value
-mrb_rescue(mrb_state *mrb, mrb_value (* b_proc)(ANYARGS), mrb_value *data1,
- mrb_value (* r_proc)(ANYARGS), mrb_value *data2)
-{
- return mrb_rescue2(mrb, b_proc, data1, r_proc, data2, mrb->eStandardError_class,
- mrb_fixnum_value(0));
-}
/* ------------------------------------------------ */
/*
* Calls func(obj, arg, recursive), where recursive is non-zero if the
@@ -111,14 +83,6 @@ mrb_exec_recursive(mrb_state *mrb, mrb_value (*func) (mrb_state *, mrb_value, mr
* current method is called recursively on the ordered pair <obj, paired_obj>
*/
-mrb_value
-mrb_exec_recursive_paired(mrb_state *mrb, mrb_value (*func) (mrb_state *, mrb_value, mrb_value, int),
- mrb_value obj, mrb_value paired_obj, void* arg)
-{
- // return mrb_exec_recursive_paired(mrb, recursive_eql, hash1, hash2, mrb_fixnum_value((int)&data));
- return func(mrb, obj, paired_obj, 0);
-}
-
mrb_sym
mrb_to_id(mrb_state *mrb, mrb_value name)
{
@@ -157,136 +121,64 @@ mrb_block_proc(void)
return mrb_nil_value();//proc_new(mrb_cProc, FALSE);
}
-/*
- * Document-method: __id__
- * Document-method: object_id
- *
- * call-seq:
- * obj.__id__ -> fixnum
- * obj.object_id -> fixnum
- *
- * Returns an integer identifier for <i>obj</i>. The same number will
- * be returned on all calls to <code>id</code> for a given object, and
- * no two active objects will share an id.
- * <code>Object#object_id</code> is a different concept from the
- * <code>:name</code> notation, which returns the symbol id of
- * <code>name</code>. Replaces the deprecated <code>Object#id</code>.
- */
+static mrb_int
+float_id(mrb_float f)
+{
+ const char *p = (const char*)&f;
+ int len = sizeof(f);
+ mrb_int id = 0;
-/*
- * call-seq:
- * obj.hash -> fixnum
- *
- * Generates a <code>Fixnum</code> hash value for this object. This
- * function must have the property that <code>a.eql?(b)</code> implies
- * <code>a.hash == b.hash</code>. The hash value is used by class
- * <code>Hash</code>. Any hash value that exceeds the capacity of a
- * <code>Fixnum</code> will be truncated before being used.
- */
+ while (len--) {
+ id = id*65599 + *p;
+ p++;
+ }
+ id = id + (id>>5);
+
+ return id;
+}
-int
+mrb_int
mrb_obj_id(mrb_value obj)
{
- /*
- * 32-bit mrb_value space
- * MSB ------------------------ LSB
- * false 00000000000000000000000000000000
- * true 00000000000000000000000000000010
- * nil 00000000000000000000000000000100
- * undef 00000000000000000000000000000110
- * symbol ssssssssssssssssssssssss00001110
- * object oooooooooooooooooooooooooooooo00 = 0 (mod sizeof(RVALUE))
- * fixnum fffffffffffffffffffffffffffffff1
- *
- * object_id space
- * LSB
- * false 00000000000000000000000000000000
- * true 00000000000000000000000000000010
- * nil 00000000000000000000000000000100
- * undef 00000000000000000000000000000110
- * symbol 000SSSSSSSSSSSSSSSSSSSSSSSSSSS0 S...S % A = 4 (S...S = s...s * A + 4)
- * object oooooooooooooooooooooooooooooo0 o...o % A = 0
- * fixnum fffffffffffffffffffffffffffffff1 bignum if required
- *
- * where A = sizeof(RVALUE)/4
- *
- * sizeof(RVALUE) is
- * 20 if 32-bit, double is 4-byte aligned
- * 24 if 32-bit, double is 8-byte aligned
- * 40 if 64-bit
- */
- /*
- * 128-bit mrb_value space
- * MSB -------- LSB
- * x86 [0,1] [2,3] [4,5] [6,7] [8,9] [A,B] [C,D] [E,F]
- * 7 6 5 4 3 2 1 0
- * 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF
- * FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210
- * false 0000000000000000 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000001 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- * true 0000000000000001 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000010 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- * nil 0000000000000001 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000001 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- * undef 0000000000000000 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000101 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- * symbol ssssssssssssssss ssssssssssssssss xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000100 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- * object oooooooooooooooo oooooooooooooo00 = 0 (mod sizeof(RVALUE))
- (1)fixnum 0000000000000001 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000011 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- * float 0000000000000001 0000000000000000 0000000000000000 0000000000000000 xxxxxxxx00000011 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- * <-- mrb_float --> xxxxxxxx00001101 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- *
- * object_id space
- * LSB
- * false 0000000000000000 0000000000000000
- * true 0000000000000000 0000000000000010
- * nil 0000000000000000 0000000000000100
- * undef 0000000000000000 0000000000000110
- * symbol 000SSSSSSSSSSSS SSSSSSSSSSSSSSS0 S...S % A = 4 (S...S = s...s * A + 4)
- * object ooooooooooooooo ooooooooooooooo0 o...o % A = 0
- * fixnum ffffffffffffffff fffffffffffffff1 bignum if required
- *
- * where A = sizeof(RVALUE)/4
- *
- * sizeof(RVALUE) is
- * 20 if 32-bit, double is 4-byte aligned
- * 24 if 32-bit, double is 8-byte aligned
- * 40 if 64-bit
- */
- /* tt:0_27 */
- switch (mrb_type(obj)) {
- case MRB_TT_FREE:
- return 0; /* not define */
- case MRB_TT_FALSE:
- if (mrb_nil_p(obj))
- return 4;
- return 0;
- case MRB_TT_TRUE:
- return 2;
- case MRB_TT_FIXNUM:
- return mrb_fixnum(obj)*2+1; /* odd number */
- case MRB_TT_SYMBOL:
- return SYM2ID(obj) * 2;
- case MRB_TT_UNDEF:
- return 0; /* not define */
- case MRB_TT_FLOAT:
- return (int)mrb_float(obj)*2; /* even number */
- case MRB_TT_OBJECT:
- case MRB_TT_CLASS:
- case MRB_TT_MODULE:
- case MRB_TT_ICLASS:
- case MRB_TT_SCLASS:
- case MRB_TT_PROC:
- case MRB_TT_ARRAY:
- case MRB_TT_HASH:
- case MRB_TT_STRING:
- case MRB_TT_RANGE:
- case MRB_TT_REGEX:
- case MRB_TT_STRUCT:
- case MRB_TT_EXCEPTION:
- case MRB_TT_MATCH:
- case MRB_TT_FILE:
- case MRB_TT_DATA:
- case MRB_TT_THREAD:
- case MRB_TT_THREADGRP:
- default:
- return mrb_fixnum(obj); /* even number */
+ mrb_int tt = obj.tt;
+
+#define MakeID2(p,t) (((intptr_t)(p))^(t))
+#define MakeID(p) MakeID2(p,tt)
+
+ switch (tt) {
+ case MRB_TT_FREE:
+ case MRB_TT_UNDEF:
+ return MakeID(0); /* not define */
+ case MRB_TT_FALSE:
+ if (mrb_nil_p(obj))
+ return MakeID(1);
+ return MakeID(0);
+ case MRB_TT_TRUE:
+ return MakeID(1);
+ case MRB_TT_SYMBOL:
+ return MakeID(SYM2ID(obj));
+ case MRB_TT_FIXNUM:
+ return MakeID2(float_id((mrb_float)mrb_fixnum(obj)), MRB_TT_FLOAT);
+ case MRB_TT_FLOAT:
+ return MakeID(float_id(mrb_float(obj)));
+ case MRB_TT_STRING:
+ case MRB_TT_OBJECT:
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ case MRB_TT_ICLASS:
+ case MRB_TT_SCLASS:
+ case MRB_TT_PROC:
+ case MRB_TT_ARRAY:
+ case MRB_TT_HASH:
+ case MRB_TT_RANGE:
+ case MRB_TT_REGEX:
+ case MRB_TT_STRUCT:
+ case MRB_TT_EXCEPTION:
+ case MRB_TT_MATCH:
+ case MRB_TT_FILE:
+ case MRB_TT_DATA:
+ default:
+ return MakeID(obj.value.p);
}
}
diff --git a/src/gc.c b/src/gc.c
index 04be437c1..9a630f626 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -11,13 +11,15 @@
#include "mruby/string.h"
#include "mruby/hash.h"
#include "mruby/range.h"
-#include "mruby/khash.h"
#include <string.h>
-#include <stdio.h>
#include "mruby/struct.h"
#include "mruby/proc.h"
#include "mruby/data.h"
-#include "mruby/numeric.h"
+#include "mruby/variable.h"
+
+#ifndef SIZE_MAX
+#include <limits.h> // for SIZE_MAX
+#endif
/*
= Tri-color Incremental Garbage Collection
@@ -70,13 +72,38 @@
*/
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
#include "re.h"
#endif
-#include "gc.h"
+struct free_obj {
+ MRUBY_OBJECT_HEADER;
+ struct RBasic *next;
+};
+
+typedef struct {
+ union {
+ struct free_obj free;
+ struct RBasic basic;
+ struct RObject object;
+ struct RClass klass;
+ struct RString string;
+ struct RArray array;
+ struct RHash hash;
+ struct RRange range;
+#ifdef ENABLE_STRUCT
+ struct RStruct structdata;
+#endif
+ struct RProc procdata;
+#ifdef ENABLE_REGEXP
+ struct RMatch match;
+ struct RRegexp regexp;
+#endif
+ } as;
+} RVALUE;
#ifdef GC_PROFILE
+#include <stdio.h>
#include <sys/time.h>
static double program_invoke_time = 0;
@@ -121,25 +148,40 @@ gettimeofday_time(void)
#define GC_STEP_SIZE 1024
-
void*
mrb_realloc(mrb_state *mrb, void *p, size_t len)
{
- return (mrb->allocf)(mrb, p, len);
+ void *p2;
+
+ p2 = (mrb->allocf)(mrb, p, len);
+
+ if (!p2 && len > 0 && mrb->heaps) {
+ mrb_garbage_collect(mrb);
+ p2 = (mrb->allocf)(mrb, p, len);
+ }
+ return p2;
}
void*
mrb_malloc(mrb_state *mrb, size_t len)
{
- return (mrb->allocf)(mrb, 0, len);
+ return mrb_realloc(mrb, 0, len);
}
void*
mrb_calloc(mrb_state *mrb, size_t nelem, size_t len)
{
- void *p = (mrb->allocf)(mrb, 0, nelem*len);
+ void *p = NULL;
+ size_t size;
+
+ if (nelem <= SIZE_MAX / len) {
+ size = nelem * len;
+ p = mrb_realloc(mrb, 0, size);
+
+ if (p && size > 0)
+ memset(p, 0, size);
+ }
- memset(p, 0, nelem*len);
return p;
}
@@ -149,7 +191,9 @@ mrb_free(mrb_state *mrb, void *p)
return (mrb->allocf)(mrb, p, 0);
}
-#define HEAP_PAGE_SIZE 1024
+#ifndef MRB_HEAP_PAGE_SIZE
+#define MRB_HEAP_PAGE_SIZE 1024
+#endif
struct heap_page {
struct RBasic *freelist;
@@ -157,7 +201,7 @@ struct heap_page {
struct heap_page *next;
struct heap_page *free_next;
struct heap_page *free_prev;
- RVALUE objects[HEAP_PAGE_SIZE];
+ RVALUE objects[MRB_HEAP_PAGE_SIZE];
};
static void
@@ -208,13 +252,11 @@ unlink_free_heap_page(mrb_state *mrb, struct heap_page *page)
static void
add_heap(mrb_state *mrb)
{
- struct heap_page *page = mrb_malloc(mrb, sizeof(struct heap_page));
+ struct heap_page *page = (struct heap_page *)mrb_calloc(mrb, 1, sizeof(struct heap_page));
RVALUE *p, *e;
struct RBasic *prev = NULL;
- memset(page, 0, sizeof(struct heap_page));
-
- for (p = page->objects, e=p+HEAP_PAGE_SIZE; p<e; p++) {
+ for (p = page->objects, e=p+MRB_HEAP_PAGE_SIZE; p<e; p++) {
p->as.free.tt = MRB_TT_FREE;
p->as.free.next = prev;
prev = &p->as.basic;
@@ -248,7 +290,7 @@ gc_protect(mrb_state *mrb, struct RBasic *p)
if (mrb->arena_idx > MRB_ARENA_SIZE) {
/* arena overflow error */
mrb->arena_idx = MRB_ARENA_SIZE - 4; /* force room in arena */
- mrb_raise(mrb, mrb->eRuntimeError_class, "arena overflow error");
+ mrb_raise(mrb, E_RUNTIME_ERROR, "arena overflow error");
}
mrb->arena[mrb->arena_idx++] = p;
}
@@ -316,8 +358,8 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj)
break;
case MRB_TT_CLASS:
- case MRB_TT_SCLASS:
case MRB_TT_MODULE:
+ case MRB_TT_SCLASS:
{
struct RClass *c = (struct RClass*)obj;
@@ -361,7 +403,7 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj)
size_t i, e;
for (i=0,e=a->len; i<e; i++) {
- mrb_gc_mark_value(mrb, a->buf[i]);
+ mrb_gc_mark_value(mrb, a->ptr[i]);
}
}
break;
@@ -372,13 +414,6 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj)
break;
case MRB_TT_STRING:
- {
- struct RString *s = (struct RString*)obj;
-
- if (s->flags & MRB_STR_SHARED) {
- mrb_gc_mark(mrb, (struct RBasic*)s->aux.shared);
- }
- }
break;
case MRB_TT_RANGE:
@@ -390,7 +425,7 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj)
}
break;
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
case MRB_TT_MATCH:
{
struct RMatch *m = (struct RMatch*)obj;
@@ -408,6 +443,18 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj)
break;
#endif
+#ifdef ENABLE_STRUCT
+ case MRB_TT_STRUCT:
+ {
+ struct RStruct *s = (struct RStruct*)obj;
+ long i;
+ for (i=0; i<s->len; i++){
+ mrb_gc_mark_value(mrb, s->ptr[i]);
+ }
+ }
+ break;
+#endif
+
default:
break;
}
@@ -458,7 +505,10 @@ obj_free(mrb_state *mrb, struct RBasic *obj)
break;
case MRB_TT_ARRAY:
- mrb_free(mrb, ((struct RArray*)obj)->buf);
+ if (obj->flags & MRB_ARY_SHARED)
+ mrb_ary_decref(mrb, ((struct RArray*)obj)->aux.shared);
+ else
+ mrb_free(mrb, ((struct RArray*)obj)->ptr);
break;
case MRB_TT_HASH:
@@ -467,20 +517,29 @@ obj_free(mrb_state *mrb, struct RBasic *obj)
break;
case MRB_TT_STRING:
- if (!(obj->flags & MRB_STR_SHARED))
- mrb_free(mrb, ((struct RString*)obj)->buf);
+ if (obj->flags & MRB_STR_SHARED)
+ mrb_str_decref(mrb, ((struct RString*)obj)->aux.shared);
+ else
+ mrb_free(mrb, ((struct RString*)obj)->ptr);
break;
case MRB_TT_RANGE:
mrb_free(mrb, ((struct RRange*)obj)->edges);
break;
+#ifdef ENABLE_STRUCT
+ case MRB_TT_STRUCT:
+ mrb_free(mrb, ((struct RStruct*)obj)->ptr);
+ break;
+#endif
+
case MRB_TT_DATA:
{
struct RData *d = (struct RData*)obj;
if (d->type->dfree) {
d->type->dfree(mrb, d->data);
}
+ mrb_gc_free_iv(mrb, (struct RObject*)obj);
}
break;
@@ -504,10 +563,14 @@ root_scan_phase(mrb_state *mrb)
for (i=0,e=mrb->arena_idx; i<e; i++) {
mrb_gc_mark(mrb, mrb->arena[i]);
}
+ /* mark class hierarchy */
mrb_gc_mark(mrb, (struct RBasic*)mrb->object_class);
+ /* mark exception */
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->exc);
/* mark stack */
e = mrb->stack - mrb->stbase;
if (mrb->ci) e += mrb->ci->nregs;
+ if (mrb->stbase + e > mrb->stend) e = mrb->stend - mrb->stbase;
for (i=0; i<e; i++) {
mrb_gc_mark_value(mrb, mrb->stbase[i]);
}
@@ -560,6 +623,7 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj)
break;
case MRB_TT_OBJECT:
+ case MRB_TT_DATA:
children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
break;
@@ -584,7 +648,7 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj)
children+=2;
break;
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
case MRB_TT_MATCH:
children+=2;
break;
@@ -593,6 +657,15 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj)
break;
#endif
+#ifdef ENABLE_STRUCT
+ case MRB_TT_STRUCT:
+ {
+ struct RStruct *s = (struct RStruct*)obj;
+ children += s->len;
+ }
+ break;
+#endif
+
default:
break;
}
@@ -642,7 +715,7 @@ incremental_sweep_phase(mrb_state *mrb, size_t limit)
while (page && (tried_sweep < limit)) {
RVALUE *p = page->objects;
- RVALUE *e = p + HEAP_PAGE_SIZE;
+ RVALUE *e = p + MRB_HEAP_PAGE_SIZE;
size_t freed = 0;
int dead_slot = 1;
int full = (page->freelist == NULL);
@@ -664,7 +737,7 @@ incremental_sweep_phase(mrb_state *mrb, size_t limit)
}
/* free dead slot */
- if (dead_slot && freed < HEAP_PAGE_SIZE) {
+ if (dead_slot && freed < MRB_HEAP_PAGE_SIZE) {
struct heap_page *next = page->next;
unlink_heap_page(mrb, page);
@@ -678,7 +751,7 @@ incremental_sweep_phase(mrb_state *mrb, size_t limit)
}
page = page->next;
}
- tried_sweep += HEAP_PAGE_SIZE;
+ tried_sweep += MRB_HEAP_PAGE_SIZE;
mrb->live -= freed;
mrb->gc_live_after_mark -= freed;
}
@@ -1092,7 +1165,7 @@ test_incremental_gc(void)
page = mrb->heaps;
while (page) {
RVALUE *p = page->objects;
- RVALUE *e = p + HEAP_PAGE_SIZE;
+ RVALUE *e = p + MRB_HEAP_PAGE_SIZE;
while (p<e) {
if (is_black(&p->as.basic)) {
live++;
@@ -1103,7 +1176,7 @@ test_incremental_gc(void)
p++;
}
page = page->next;
- total += HEAP_PAGE_SIZE;
+ total += MRB_HEAP_PAGE_SIZE;
}
gc_assert(mrb->gray_list == NULL);
@@ -1138,7 +1211,7 @@ test_incremental_sweep_phase(void)
gc_assert(mrb->heaps->next->next == NULL);
gc_assert(mrb->free_heaps->next->next == NULL);
- incremental_sweep_phase(mrb, HEAP_PAGE_SIZE*3);
+ incremental_sweep_phase(mrb, MRB_HEAP_PAGE_SIZE*3);
gc_assert(mrb->heaps->next == NULL);
gc_assert(mrb->heaps == mrb->free_heaps);
diff --git a/src/gc.h b/src/gc.h
deleted file mode 100644
index fea761d1b..000000000
--- a/src/gc.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-** gc.h - garbage collector for RiteVM
-**
-** See Copyright Notice in mruby.h
-*/
-
-#ifndef MRUBY_GC_H
-#define MRUBY_GC_H
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-struct free_obj {
- MRUBY_OBJECT_HEADER;
- struct RBasic *next;
-};
-
-typedef struct {
- union {
- struct free_obj free;
- struct RBasic basic;
- struct RObject object;
- struct RClass klass;
- struct RString string;
- struct RArray array;
- struct RHash hash;
- struct RRange range;
- struct RStruct structdata;
- struct RProc procdata;
-#ifdef INCLUDE_REGEXP
- struct RMatch match;
- struct RRegexp regexp;
-#endif
- } as;
-} RVALUE;
-
-void mrb_gc_mark_gv(mrb_state*);
-void mrb_gc_free_gv(mrb_state*);
-void mrb_gc_mark_iv(mrb_state*, struct RObject*);
-size_t mrb_gc_mark_iv_size(mrb_state*, struct RObject*);
-void mrb_gc_free_iv(mrb_state*, struct RObject*);
-void mrb_gc_mark_mt(mrb_state*, struct RClass*);
-size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
-void mrb_gc_free_mt(mrb_state*, struct RClass*);
-void mrb_gc_mark_ht(mrb_state*, struct RHash*);
-size_t mrb_gc_mark_ht_size(mrb_state*, struct RHash*);
-void mrb_gc_free_ht(mrb_state*, struct RHash*);
-
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
-
-#endif /* MRUBY_GC_H */
diff --git a/src/hash.c b/src/hash.c
index a06becd91..927e40e66 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -11,8 +11,6 @@
#include "mruby/array.h"
#include "mruby/string.h"
#include "mruby/variable.h"
-#include <string.h>
-#include <stdio.h>
static inline khint_t
mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key)
@@ -31,15 +29,8 @@ mrb_hash_ht_hash_equal(mrb_state *mrb, mrb_value a, mrb_value b)
return mrb_eql(mrb, a, b);
}
-KHASH_INIT(ht, mrb_value, mrb_value, 1, mrb_hash_ht_hash_func, mrb_hash_ht_hash_equal);
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
+KHASH_DECLARE(ht, mrb_value, mrb_value, 1);
+KHASH_DEFINE (ht, mrb_value, mrb_value, 1, mrb_hash_ht_hash_func, mrb_hash_ht_hash_equal);
static void mrb_hash_modify(mrb_state *mrb, mrb_value hash);
@@ -60,6 +51,7 @@ mrb_gc_mark_ht(mrb_state *mrb, struct RHash *hash)
khiter_t k;
khash_t(ht) *h = hash->ht;
+ if (!h) return;
for (k = kh_begin(h); k != kh_end(h); k++)
if (kh_exist(h, k)) {
mrb_gc_mark_value(mrb, kh_key(h, k));
@@ -70,43 +62,48 @@ mrb_gc_mark_ht(mrb_state *mrb, struct RHash *hash)
size_t
mrb_gc_mark_ht_size(mrb_state *mrb, struct RHash *hash)
{
+ if (!hash->ht) return 0;
return kh_size(hash->ht)*2;
}
void
mrb_gc_free_ht(mrb_state *mrb, struct RHash *hash)
{
- kh_destroy(ht, hash->ht);
+ if (hash->ht) kh_destroy(ht, hash->ht);
}
mrb_value
-mrb_hash_new_capa(mrb_state *mrb, size_t capa)
+mrb_hash_new_capa(mrb_state *mrb, int capa)
{
struct RHash *h;
h = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
h->ht = kh_init(ht, mrb);
- kh_resize(ht, h->ht, capa);
+ if (capa > 0) {
+ kh_resize(ht, h->ht, capa);
+ }
h->iv = 0;
return mrb_obj_value(h);
}
mrb_value
-mrb_hash_new(mrb_state *mrb, int capa)
+mrb_hash_new(mrb_state *mrb)
{
- return mrb_hash_new_capa(mrb, capa);
+ return mrb_hash_new_capa(mrb, 0);
}
mrb_value
-mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) /* mrb_hash_aref */ /* mrb_hash_lookup */
+mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key)
{
khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k;
- k = kh_get(ht, h, key);
- if (k != kh_end(h))
- return kh_value(h, k);
+ if (h) {
+ k = kh_get(ht, h, key);
+ if (k != kh_end(h))
+ return kh_value(h, k);
+ }
/* not found */
if (MRB_RHASH_PROCDEFAULT_P(hash)) {
@@ -116,13 +113,13 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) /* mrb_hash_aref */
}
mrb_value
-mrb_hash_getWithDef(mrb_state *mrb, mrb_value hash, mrb_value vkey, mrb_value def) /* mrb_hash_lookup2 */
+mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def)
{
khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k;
if (h) {
- k = kh_get(ht, h, vkey);
+ k = kh_get(ht, h, key);
if (k != kh_end(h))
return kh_value(h, k);
}
@@ -140,6 +137,7 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val) /* mr
mrb_hash_modify(mrb, hash);
h = RHASH_TBL(hash);
+ if (!h) h = RHASH_TBL(hash) = kh_init(ht, mrb);
k = kh_get(ht, h, key);
if (k == kh_end(h)) {
/* expand */
@@ -165,11 +163,11 @@ mrb_hash_dup(mrb_state *mrb, mrb_value hash)
khash_t(ht) *h, *ret_h;
khiter_t k, ret_k;
+ h = RHASH_TBL(hash);
ret = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
ret->ht = kh_init(ht, mrb);
- if (!RHASH_EMPTY_P(hash)) {
- h = RHASH_TBL(hash);
+ if (kh_size(h) > 0) {
ret_h = ret->ht;
for (k = kh_begin(h); k != kh_end(h); k++) {
@@ -194,7 +192,7 @@ mrb_hash_tbl(mrb_state *mrb, mrb_value hash)
{
khash_t(ht) *h = RHASH_TBL(hash);
- if (!RHASH_TBL(hash)) {
+ if (!h) {
RHASH_TBL(hash) = kh_init(ht, mrb);
}
return h;
@@ -331,15 +329,9 @@ mrb_hash_aget(mrb_state *mrb, mrb_value self)
}
mrb_value
-mrb_hash_lookup2(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def)
-{
- return mrb_hash_getWithDef(mrb, hash, key, def);
-}
-
-mrb_value
mrb_hash_lookup(mrb_state *mrb, mrb_value hash, mrb_value key)
{
- return mrb_hash_lookup2(mrb, hash, key, mrb_nil_value());
+ return mrb_hash_get(mrb, hash, key);
}
/*
@@ -496,7 +488,7 @@ mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash)
return ifnone;
}
-mrb_value
+static mrb_value
mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key)
{
khash_t(ht) *h = RHASH_TBL(hash);
@@ -576,7 +568,9 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash)
if (!kh_exist(h,k)) continue;
delKey = kh_key(h,k);
+ mrb_gc_protect(mrb, delKey);
delVal = mrb_hash_delete_key(mrb, hash, delKey);
+ mrb_gc_protect(mrb, delVal);
return mrb_assoc_new(mrb, delKey, delVal);
}
@@ -700,7 +694,7 @@ mrb_hash_clear(mrb_state *mrb, mrb_value hash)
{
khash_t(ht) *h = RHASH_TBL(hash);
- kh_clear(ht, h);
+ if (h) kh_clear(ht, h);
return hash;
}
@@ -817,13 +811,12 @@ static mrb_value
mrb_hash_empty_p(mrb_state *mrb, mrb_value self)
{
khash_t(ht) *h = RHASH_TBL(self);
- khiter_t k;
+
if (h) {
- for (k = kh_begin(h); k != kh_end(h); k++)
- if (kh_exist(h, k))
- return mrb_false_value();
+ if (kh_size(h) == 0)
+ return mrb_true_value();
}
- return mrb_true_value();
+ return mrb_false_value();
}
/* 15.2.13.4.11 */
@@ -896,9 +889,9 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur)
khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k;
- if (recur) return mrb_str_new_cstr(mrb, "{...}");
+ if (recur) return mrb_str_new(mrb, "{...}", 5);
- str = mrb_str_new_cstr(mrb, "{");
+ str = mrb_str_new(mrb, "{", 1);
if (h && kh_size(h) > 0) {
for (k = kh_begin(h); k != kh_end(h); k++) {
int ai;
@@ -911,14 +904,14 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur)
str2 = mrb_inspect(mrb, kh_key(h,k));
mrb_str_append(mrb, str, str2);
- mrb_str_buf_cat(mrb, str, "=>", strlen("=>"));
+ mrb_str_buf_cat(mrb, str, "=>", 2);
str2 = mrb_inspect(mrb, kh_value(h,k));
mrb_str_append(mrb, str, str2);
mrb_gc_arena_restore(mrb, ai);
}
}
- mrb_str_buf_cat(mrb, str, "}", strlen("}"));//mrb_str_buf_cat2(str, "}");
+ mrb_str_buf_cat(mrb, str, "}", 1);
return str;
}
@@ -938,8 +931,10 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur)
static mrb_value
mrb_hash_inspect(mrb_state *mrb, mrb_value hash)
{
- if (RHASH_EMPTY_P(hash))
- return mrb_str_new_cstr(mrb, "{}");
+ khash_t(ht) *h = RHASH_TBL(hash);
+
+ if (!h || kh_size(h) == 0)
+ return mrb_str_new(mrb, "{}", 2);
return inspect_hash(mrb, hash, 0);
}
@@ -1106,6 +1101,8 @@ mrb_hash_has_value(mrb_state *mrb, mrb_value hash)
static mrb_value
hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql)
{
+ khash_t(ht) *h1, *h2;
+
if (mrb_obj_equal(mrb, hash1, hash2)) return mrb_true_value();
if (mrb_type(hash2) != MRB_TT_HASH) {
if (!mrb_respond_to(mrb, hash2, mrb_intern(mrb, "to_hash"))) {
@@ -1116,10 +1113,15 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql)
else
return mrb_fixnum_value(mrb_equal(mrb, hash2, hash1));
}
- if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2)) return mrb_false_value();
+ h1 = RHASH_TBL(hash1);
+ h2 = RHASH_TBL(hash2);
+ if (!h2) {
+ if (!h2) return mrb_true_value();
+ return mrb_false_value();
+ }
+ if (!h2) return mrb_false_value();
+ if (kh_size(h1) != kh_size(h2)) return mrb_false_value();
else {
- khash_t(ht) *h1 = RHASH_TBL(hash1);
- khash_t(ht) *h2 = RHASH_TBL(hash2);
khiter_t k1, k2;
mrb_value key;
@@ -1337,9 +1339,9 @@ mrb_init_hash(mrb_state *mrb)
mrb_define_method(mrb, h, "default_proc", mrb_hash_default_proc,ARGS_NONE()); /* 15.2.13.4.7 */
mrb_define_method(mrb, h, "default_proc=", mrb_hash_set_default_proc,ARGS_REQ(1)); /* 15.2.13.4.7 */
mrb_define_method(mrb, h, "__delete", mrb_hash_delete, ARGS_REQ(1)); /* core of 15.2.13.4.8 */
-//mrb_define_method(mrb, h, "each", mrb_hash_each_pair, ARGS_NONE()); /* 15.2.13.4.9 */ /* move to mrblib\hash.rb */
-//mrb_define_method(mrb, h, "each_key", mrb_hash_each_key, ARGS_NONE()); /* 15.2.13.4.10 */ /* move to mrblib\hash.rb */
-//mrb_define_method(mrb, h, "each_value", mrb_hash_each_value, ARGS_NONE()); /* 15.2.13.4.11 */ /* move to mrblib\hash.rb */
+// "each" 15.2.13.4.9 move to mrblib/hash.rb
+// "each_key" 15.2.13.4.10 move to mrblib/hash.rb
+// "each_value" 15.2.13.4.11 move to mrblib/hash.rb
mrb_define_method(mrb, h, "empty?", mrb_hash_empty_p, ARGS_NONE()); /* 15.2.13.4.12 */
mrb_define_method(mrb, h, "has_key?", mrb_hash_has_key, ARGS_REQ(1)); /* 15.2.13.4.13 */
mrb_define_method(mrb, h, "has_value?", mrb_hash_has_value, ARGS_REQ(1)); /* 15.2.13.4.14 */
@@ -1350,7 +1352,7 @@ mrb_init_hash(mrb_state *mrb)
mrb_define_method(mrb, h, "keys", mrb_hash_keys, ARGS_NONE()); /* 15.2.13.4.19 */
mrb_define_method(mrb, h, "length", mrb_hash_size_m, ARGS_NONE()); /* 15.2.13.4.20 */
mrb_define_method(mrb, h, "member?", mrb_hash_has_key, ARGS_REQ(1)); /* 15.2.13.4.21 */
-//mrb_define_method(mrb, h, "merge", mrb_hash_merge, ARGS_REQ(1)); /* 15.2.13.4.22 */ /* move to mrblib\hash.rb */
+// "merge" 15.2.13.4.22 move to mrblib/hash.rb
mrb_define_method(mrb, h, "replace", mrb_hash_replace, ARGS_REQ(1)); /* 15.2.13.4.23 */
mrb_define_method(mrb, h, "shift", mrb_hash_shift, ARGS_NONE()); /* 15.2.13.4.24 */
mrb_define_method(mrb, h, "size", mrb_hash_size_m, ARGS_NONE()); /* 15.2.13.4.25 */
diff --git a/src/init.c b/src/init.c
index 17ce24313..e6af6989b 100644
--- a/src/init.c
+++ b/src/init.c
@@ -8,7 +8,7 @@
void mrb_init_class(mrb_state*);
void mrb_init_symtbl(mrb_state*);
-void mrb_init_symbols(mrb_state*);
+void mrb_init_symbol(mrb_state*);
void mrb_init_object(mrb_state*);
void mrb_init_kernel(mrb_state*);
void mrb_init_enumerable(mrb_state*);
@@ -42,22 +42,30 @@ mrb_init_core(mrb_state *mrb)
mrb_init_comparable(mrb);
mrb_init_enumerable(mrb);
- mrb_init_symbols(mrb);
+ mrb_init_symbol(mrb);
+ mrb_init_exception(mrb);
mrb_init_proc(mrb);
mrb_init_string(mrb);
mrb_init_array(mrb);
mrb_init_hash(mrb);
mrb_init_numeric(mrb);
mrb_init_range(mrb);
+#ifdef ENABLE_STRUCT
mrb_init_struct(mrb);
+#endif
mrb_init_gc(mrb);
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
mrb_init_regexp(mrb);
#endif
- mrb_init_exception(mrb);
+#ifdef ENABLE_STDIO
mrb_init_print(mrb);
+#endif
+#ifdef ENABLE_TIME
mrb_init_time(mrb);
+#endif
+#ifdef ENABLE_MATH
mrb_init_math(mrb);
+#endif
mrb_init_mrblib(mrb);
diff --git a/src/kernel.c b/src/kernel.c
index 9092d239d..6327f967d 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -6,18 +6,10 @@
#include "mruby.h"
#include "mruby/string.h"
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
#include "mruby/proc.h"
-
-#include "mruby/range.h"
#include "mruby/array.h"
-#include "mruby/hash.h"
#include "mruby/class.h"
-#include "mruby/struct.h"
#include "mruby/variable.h"
-#include "mruby/khash.h"
#include "error.h"
typedef enum {
@@ -34,22 +26,6 @@ typedef enum {
NOEX_RESPONDS = 0x80
} mrb_method_flag_t;
-#ifdef INCLUDE_REGEXP
-#include "re.h"
-#include "regint.h"
-#endif
-
-KHASH_MAP_INIT_INT(mt, struct RProc*);
-KHASH_MAP_INIT_INT(iv, mrb_value);
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
struct obj_ivar_tag {
mrb_value obj;
int (*func)(mrb_sym key, mrb_value val, void * arg);
@@ -96,9 +72,6 @@ inspect_obj(mrb_state *mrb, mrb_value obj, mrb_value str, int recur)
int
mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj)
{
- //const mrb_method_entry_t *me = mrb_method_entry(CLASS_OF(obj), mrb_intern("to_s"));
- //if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC &&
- //me->def->body.cfunc.func == mrb_any_to_s)
struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern(mrb, "to_s"));
if (me && MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s))
return 1;
@@ -135,7 +108,7 @@ mrb_obj_inspect(mrb_state *mrb, mrb_value obj)
return mrb_any_to_s(mrb, obj);
}
else if (mrb_nil_p(obj)) {
- return mrb_str_new_cstr(mrb, "nil");
+ return mrb_str_new(mrb, "nil", 3);
}
return mrb_funcall(mrb, obj, "to_s", 0, 0);
}
@@ -191,7 +164,7 @@ mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self)
mrb_value arg;
mrb_get_args(mrb, "o", &arg);
- if (mrb_obj_equal(mrb, self, arg)) {
+ if (mrb_equal(mrb, self, arg)) {
return mrb_false_value();
}
else {
@@ -225,14 +198,19 @@ mrb_equal_m(mrb_state *mrb, mrb_value self)
/* 15.3.1.3.3 */
/* 15.3.1.3.33 */
/*
- * call-seq:
- * obj.hash -> fixnum
+ * Document-method: __id__
+ * Document-method: object_id
*
- * Generates a <code>Fixnum</code> hash value for this object. This
- * function must have the property that <code>a.eql?(b)</code> implies
- * <code>a.hash == b.hash</code>. The hash value is used by class
- * <code>Hash</code>. Any hash value that exceeds the capacity of a
- * <code>Fixnum</code> will be truncated before being used.
+ * call-seq:
+ * obj.__id__ -> fixnum
+ * obj.object_id -> fixnum
+ *
+ * Returns an integer identifier for <i>obj</i>. The same number will
+ * be returned on all calls to <code>id</code> for a given object, and
+ * no two active objects will share an id.
+ * <code>Object#object_id</code> is a different concept from the
+ * <code>:name</code> notation, which returns the symbol id of
+ * <code>name</code>. Replaces the deprecated <code>Object#id</code>.
*/
static mrb_value
mrb_obj_id_m(mrb_state *mrb, mrb_value self)
@@ -262,17 +240,12 @@ mrb_obj_id_m(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_f_send(mrb_state *mrb, mrb_value self)
{
- mrb_value name, block, *argv;
+ mrb_sym name;
+ mrb_value block, *argv;
int argc;
- mrb_get_args(mrb, "o*&", &name, &argv, &argc, &block);
- return mrb_funcall_with_block(mrb,self, mrb_string_value_ptr(mrb, name), argc, argv, block);
-}
-
-static mrb_value
-mrb_f_block_given_p(void)
-{
- return mrb_false_value(); /* dummy */
+ mrb_get_args(mrb, "n*&", &name, &argv, &argc, &block);
+ return mrb_funcall_with_block(mrb,self, name, argc, argv, block);
}
/* 15.3.1.2.2 */
@@ -302,7 +275,17 @@ mrb_f_block_given_p(void)
static mrb_value
mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
{
- return mrb_f_block_given_p();
+ mrb_callinfo *ci = mrb->ci;
+ mrb_value *bp;
+
+ bp = mrb->stbase + ci->stackidx + 1;
+ ci--;
+ if (ci <= mrb->cibase) return mrb_false_value();
+ if (ci->argc > 0) {
+ bp += ci->argc;
+ }
+ if (mrb_nil_p(*bp)) return mrb_false_value();
+ return mrb_true_value();
}
/* 15.3.1.3.7 */
@@ -328,56 +311,48 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
{
struct RClass *klass = RBASIC(obj)->c;
- //if (!FL_TEST(klass, FL_SINGLETON))
- //return klass;
if (klass->tt != MRB_TT_SCLASS)
return klass;
else {
- //struct clone_method_data data;
- /* copy singleton(unnamed) class */
- //VALUE clone = class_alloc(RBASIC(klass)->flags, 0);
+ /* copy singleton(unnamed) class */
struct RClass *clone = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, mrb->class_class);
- //clone->super = objklass->super;
- if ((mrb_type(obj) == MRB_TT_CLASS) ||
- (mrb_type(obj) == MRB_TT_SCLASS)) { /* BUILTIN_TYPE(obj) == T_CLASS */
- clone->c = clone;
- }
- else {
- clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass));
- }
+ if ((mrb_type(obj) == MRB_TT_CLASS) ||
+ (mrb_type(obj) == MRB_TT_SCLASS)) { /* BUILTIN_TYPE(obj) == T_CLASS */
+ clone->c = clone;
+ }
+ else {
+ clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass));
+ }
- clone->super = klass->super;
- if (klass->iv) {
- clone->iv = klass->iv;
- }
- clone->mt = kh_init(mt, mrb);
- clone->tt = MRB_TT_SCLASS;
- return clone;
+ clone->super = klass->super;
+ if (klass->iv) {
+ clone->iv = klass->iv;
+ }
+ if (klass->mt) {
+ clone->mt = kh_copy(mt, mrb, klass->mt);
+ }
+ else {
+ clone->mt = kh_init(mt, mrb);
+ }
+ clone->tt = MRB_TT_SCLASS;
+ return clone;
}
}
static void
init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj)
{
- //if (OBJ_FROZEN(dest)) {
- // rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest));
- //}
- //RBASIC(dest)->flags &= ~(T_MASK|FL_EXIVAR);
- //RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR|FL_TAINT);
- //if (FL_TEST(obj, FL_EXIVAR)) {
- // mrb_copy_generic_ivar(dest, obj);
- //}
- //mrb_gc_copy_finalizer(dest, obj);
switch (mrb_type(obj)) {
case MRB_TT_OBJECT:
case MRB_TT_CLASS:
case MRB_TT_MODULE:
if (ROBJECT(dest)->iv) {
+ kh_destroy(iv, ROBJECT(dest)->iv);
ROBJECT(dest)->iv = 0;
}
if (ROBJECT(obj)->iv) {
- ROBJECT(dest)->iv = ROBJECT(obj)->iv;
+ ROBJECT(dest)->iv = kh_copy(iv, mrb, ROBJECT(obj)->iv);
}
break;
@@ -424,8 +399,6 @@ mrb_obj_clone(mrb_state *mrb, mrb_value self)
clone = (struct RObject*)mrb_obj_alloc(mrb, self.tt, mrb_obj_class(mrb, self));
clone->c = mrb_singleton_class_clone(mrb, self);
init_copy(mrb, mrb_obj_value(clone), self);
- //1-9-2 no bug mrb_funcall(mrb, clone, "initialize_clone", 1, self);
- //RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
return mrb_obj_value(clone);
}
@@ -459,47 +432,12 @@ mrb_obj_dup(mrb_state *mrb, mrb_value obj)
mrb_raise(mrb, E_TYPE_ERROR, "can't dup %s", mrb_obj_classname(mrb, obj));
}
p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj));
- //init_copy(dup, obj);
dup = mrb_obj_value(p);
- mrb_funcall(mrb, dup, "initialize_copy", 1, obj);
+ init_copy(mrb, dup, obj);
return dup;
}
-/* 15.3.1.2.3 */
-/* 15.3.1.3.12 */
-/*
- * call-seq:
- * eval(string [, binding [, filename [,lineno]]]) -> obj
- *
- * Evaluates the Ruby expression(s) in <em>string</em>. If
- * <em>binding</em> is given, which must be a <code>Binding</code>
- * object, the evaluation is performed in its context. If the
- * optional <em>filename</em> and <em>lineno</em> parameters are
- * present, they will be used when reporting syntax errors.
- *
- * def getBinding(str)
- * return binding
- * end
- * str = "hello"
- * eval "str + ' Fred'" #=> "hello Fred"
- * eval "str + ' Fred'", getBinding("bye") #=> "bye Fred"
- */
-mrb_value
-mrb_f_eval(int argc, mrb_value *argv, mrb_value self)
-{
- return mrb_false_value(); /* dummy */
-}
-mrb_value
-mrb_f_eval_m(mrb_state *mrb, mrb_value self)
-{
- mrb_value *argv;
- int argc;
-
- mrb_get_args(mrb, "*", &argv, &argc);
- return mrb_f_eval(argc, argv, self);
-}
-
static mrb_value
mrb_obj_extend(mrb_state *mrb, int argc, mrb_value *argv, mrb_value obj)
{
@@ -509,7 +447,6 @@ mrb_obj_extend(mrb_state *mrb, int argc, mrb_value *argv, mrb_value obj)
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (at least 1)");
}
for (i = 0; i < argc; i++) {
- //Check_Type(argv[i], T_MODULE);
mrb_check_type(mrb, argv[i], MRB_TT_MODULE);
}
while (argc--) {
@@ -554,20 +491,17 @@ mrb_obj_extend_m(mrb_state *mrb, mrb_value self)
return mrb_obj_extend(mrb, argc, argv, self);
}
-/* 15.3.1.2.4 */
-/* 15.3.1.3.14 */
+/* 15.3.1.3.15 */
/*
* call-seq:
- * global_variables -> array
- *
- * Returns an array of the names of global variables.
+ * obj.hash -> fixnum
*
- * global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr]
+ * Generates a <code>Fixnum</code> hash value for this object. This
+ * function must have the property that <code>a.eql?(b)</code> implies
+ * <code>a.hash == b.hash</code>. The hash value is used by class
+ * <code>Hash</code>. Any hash value that exceeds the capacity of a
+ * <code>Fixnum</code> will be truncated before being used.
*/
-//mrb_value
-//mrb_f_global_variables(mrb_state *mrb, mrb_value self)
-
-/* 15.3.1.3.15 */
mrb_value
mrb_obj_hash(mrb_state *mrb, mrb_value self)
{
@@ -588,15 +522,15 @@ mrb_obj_init_copy(mrb_state *mrb, mrb_value self)
return self;
}
+mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c);
+
/* 15.3.1.3.18 */
/*
* call-seq:
- * obj.instance_eval(string [, filename [, lineno]] ) -> obj
* obj.instance_eval {| | block } -> obj
*
- * Evaluates a string containing Ruby source code, or the given block,
- * within the context of the receiver (_obj_). In order to set the
- * context, the variable +self+ is set to _obj_ while
+ * Evaluates the given block,within the context of the receiver (_obj_).
+ * In order to set the context, the variable +self+ is set to _obj_ while
* the code is executing, giving the code access to _obj_'s
* instance variables. In the version of <code>instance_eval</code>
* that takes a +String+, the optional second and third
@@ -614,10 +548,24 @@ mrb_obj_init_copy(mrb_state *mrb, mrb_value self)
mrb_value
mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
{
- mrb_value b;
+ mrb_value a, b;
+ mrb_value cv;
+ struct RClass *c;
- mrb_get_args(mrb, "&", &b);
- return mrb_yield_with_self(mrb, b, 0, 0, self);
+ if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
+ mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented");
+ }
+ switch (mrb_type(self)) {
+ case MRB_TT_SYMBOL:
+ case MRB_TT_FIXNUM:
+ case MRB_TT_FLOAT:
+ c = 0;
+ break;
+ default:
+ cv = mrb_singleton_class(mrb, self);
+ c = mrb_class_ptr(cv);
+ }
+ return mrb_yield_internal(mrb, b, 0, 0, self, c);
}
int
@@ -755,46 +703,6 @@ mrb_obj_ivar_set(mrb_state *mrb, mrb_value self)
return val;
}
-/* 15.3.1.3.23 */
-/*
- * call-seq:
- * obj.instance_variables -> array
- *
- * Returns an array of instance variable names for the receiver. Note
- * that simply defining an accessor does not create the corresponding
- * instance variable.
- *
- * class Fred
- * attr_accessor :a1
- * def initialize
- * @iv = 3
- * end
- * end
- * Fred.new.instance_variables #=> [:@iv]
- */
-mrb_value
-mrb_obj_instance_variables(mrb_state *mrb, mrb_value self)
-{
- mrb_value ary;
- kh_iv_t *h = RCLASS_IV_TBL(self);
- khint_t i;
- const char* p;
-
- ary = mrb_ary_new(mrb);
- if (h) {
- for (i=0;i<kh_end(h);i++) {
- if (kh_exist(h, i)) {
- p = mrb_sym2name(mrb, kh_key(h,i));
- if (*p == '@') {
- if (mrb_type(kh_value(h, i)) != MRB_TT_UNDEF)
- mrb_ary_push(mrb, ary, mrb_str_new_cstr(mrb, p));
- }
- }
- }
- }
- return ary;
-}
-
/* 15.3.1.3.24 */
/* 15.3.1.3.26 */
/*
@@ -836,71 +744,6 @@ mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self)
}
}
-/* 15.3.1.2.6 */
-/* 15.3.1.3.27 */
-/*
- * call-seq:
- * lambda { |...| block } -> a_proc
- *
- * Equivalent to <code>Proc.new</code>, except the resulting Proc objects
- * check the number of parameters passed when called.
- */
-mrb_value
-proc_lambda(mrb_state *mrb, mrb_value self)
-{
- //return mrb_block_lambda();
- return mrb_nil_value(); /* dummy */
-}
-
-/* 15.3.1.2.7 */
-/* 15.3.1.3.28 */
-/*
- * call-seq:
- * local_variables -> array
- *
- * Returns the names of the current local variables.
- *
- * fred = 1
- * for i in 1..10
- * # ...
- * end
- * local_variables #=> [:fred, :i]
- */
-mrb_value
-mrb_f_local_variables(mrb_state *mrb, mrb_value self)
-{
- mrb_value ary;
-
- ary = mrb_ary_new(mrb);
- return ary; /* dummy */
-}
-
-/* 15.3.1.2.8 */
-/* 15.3.1.3.29 */
-/*
- * call-seq:
- * loop { block }
- * loop -> an_enumerator
- *
- * Repeatedly executes the block.
- *
- * If no block is given, an enumerator is returned instead.
- *
- * loop do
- * print "Input: "
- * line = gets
- * break if !line or line =~ /^qQ/
- * # ...
- * end
- *
- * StopIteration raised in the block breaks the loop.
- */
-mrb_value
-mrb_f_loop(mrb_state *mrb, mrb_value self)
-{
- return mrb_nil_value(); /* dummy */
-}
-
static void
method_entry_loop(mrb_state *mrb, struct RClass* klass, mrb_value ary)
{
@@ -958,7 +801,6 @@ mrb_obj_singleton_methods(mrb_state *mrb, int argc, mrb_value *argv, mrb_value o
recur = mrb_true_value();
}
else {
- //mrb_scan_args(argc, argv, "01", &recur);
recur = argv[0];
}
klass = mrb_class(mrb, obj);
@@ -987,7 +829,6 @@ retry:
else {
mrb_value recur;
- //mrb_scan_args(argc, argv, "1", &recur);
recur = argv[0];
if (mrb_test(recur)) {
argc = 0;
@@ -1022,7 +863,7 @@ mrb_obj_methods_m(mrb_state *mrb, mrb_value self)
int argc;
mrb_get_args(mrb, "*", &argv, &argc);
- return mrb_obj_methods(mrb, argc, argv, self, 0); /* everything but private */
+ return mrb_obj_methods(mrb, argc, argv, self, (mrb_method_flag_t)0); /* everything but private */
}
/* 15.3.1.3.32 */
@@ -1039,31 +880,6 @@ mrb_false(mrb_state *mrb, mrb_value self)
return mrb_false_value();
}
-/* 15.3.1.2.10 */
-/* 15.3.1.3.35 */
-/*
- * call-seq:
- * print(obj, ...) -> nil
- *
- * Prints each object in turn to <code>$stdout</code>. If the output
- * field separator (<code>$,</code>) is not +nil+, its
- * contents will appear between each field. If the output record
- * separator (<code>$\\</code>) is not +nil+, it will be
- * appended to the output. If no arguments are given, prints
- * <code>$_</code>. Objects that aren't strings will be converted by
- * calling their <code>to_s</code> method.
- *
- * print "cat", [1,2,3], 99, "\n"
- * $, = ", "
- * $\ = "\n"
- * print "cat", [1,2,3], 99
- *
- * <em>produces:</em>
- *
- * cat12399
- * cat, 1, 2, 3, 99
- */
-
/* 15.3.1.3.36 */
/*
* call-seq:
@@ -1121,37 +937,15 @@ mrb_obj_public_methods(mrb_state *mrb, mrb_value self)
return mrb_obj_methods(mrb, argc, argv, self, NOEX_PUBLIC); /* public attribute not define */
}
-/* 15.3.1.2.11 */
-/* 15.3.1.3.39 */
-/*
- * call-seq:
- * puts(obj, ...) -> nil
- *
- * Equivalent to
- *
- * $stdout.puts(obj, ...)
- */
-
-static mrb_value
-get_errinfo(mrb_state *mrb)
-{
- //return get_thread_errinfo(GET_THREAD());
- return mrb_str_new_cstr(mrb, "error!!"); /* dummy */
-}
-
/* 15.3.1.2.12 */
/* 15.3.1.3.40 */
/*
* call-seq:
* raise
* raise(string)
- * raise(exception [, string [, array]])
- * fail
- * fail(string)
- * fail(exception [, string [, array]])
+ * raise(exception [, string])
*
- * With no arguments, raises the exception in <code>$!</code> or raises
- * a <code>RuntimeError</code> if <code>$!</code> is +nil+.
+ * With no arguments, raises a <code>RuntimeError</code>
* With a single +String+ argument, raises a
* +RuntimeError+ with the string as a message. Otherwise,
* the first parameter should be the name of an +Exception+
@@ -1167,19 +961,24 @@ get_errinfo(mrb_state *mrb)
mrb_value
mrb_f_raise(mrb_state *mrb, mrb_value self)
{
- mrb_value err;
- mrb_value *argv;
+ mrb_value a[2];
int argc;
- mrb_get_args(mrb, "*", &argv, &argc);
- if (argc == 0) {
- err = get_errinfo(mrb);
- if (!mrb_nil_p(err)) {
- argc = 1;
- argv[0] = err;
- }
+ argc = mrb_get_args(mrb, "|oo", &a[0], &a[1]);
+ switch (argc) {
+ case 0:
+ mrb_raise(mrb, E_RUNTIME_ERROR, "");
+ break;
+ case 1:
+ a[1] = mrb_check_string_type(mrb, a[0]);
+ if (!mrb_nil_p(a[1])) {
+ argc = 2;
+ a[0] = mrb_obj_value(E_RUNTIME_ERROR);
+ }
+ /* fall through */
+ default:
+ mrb_exc_raise(mrb, mrb_make_exception(mrb, argc, a));
}
- mrb_exc_raise(mrb, mrb_make_exception(mrb, argc, argv));
return mrb_nil_value(); /* not reached */
}
@@ -1209,79 +1008,20 @@ mrb_value
mrb_obj_remove_instance_variable(mrb_state *mrb, mrb_value self)
{
mrb_sym sym;
- mrb_value name;
- khash_t(iv) *h;
- khiter_t k;
mrb_value val;
- mrb_value Qundef = mrb_undef_value();
- mrb_get_args(mrb, "o", &name);
- sym = mrb_to_id(mrb, name);
- //if (OBJ_FROZEN(obj)) mrb_error_frozen("object");
- //if (!mrb_is_instance_id(id)) {
- // mrb_name_error(mrb, id, "`%s' is not allowed as an instance variable name", mrb_sym2name(mrb, id));
- //}
- switch (mrb_type(self)) {
- case MRB_TT_OBJECT:
- case MRB_TT_CLASS:
- case MRB_TT_MODULE:
- if (!mrb_obj_ptr(self)->iv) break;
- h = mrb_obj_ptr(self)->iv;
- if (!h) break;
- k = kh_get(iv, h, sym);
- if (k != kh_end(h)) {
- val = kh_value(h, k);
- if (!mrb_obj_equal(mrb, val, Qundef)) {
- kh_value(h, k) = Qundef;
- return val;
- }
- }
- break;
- default:
- break;
+ mrb_get_args(mrb, "n", &sym);
+ val = mrb_iv_remove(mrb, self, sym);
+ if (mrb_undef_p(val)) {
+ mrb_name_error(mrb, sym, "instance variable %s not defined", mrb_sym2name(mrb, sym));
}
- mrb_name_error(mrb, sym, "instance variable %s not defined", mrb_sym2name(mrb, sym));
- return mrb_nil_value(); /* not reached */
-}
-
-/* 15.3.1.2.13 */
-/* 15.3.1.3.42 */
-/*
- * call-seq:
- * require(string) -> true or false
- *
- * Ruby tries to load the library named _string_, returning
- * +true+ if successful. If the filename does not resolve to
- * an absolute path, it will be searched for in the directories listed
- * in <code>$:</code>. If the file has the extension ``.rb'', it is
- * loaded as a source file; if the extension is ``.so'', ``.o'', or
- * ``.dll'', or whatever the default shared library extension is on
- * the current platform, Ruby loads the shared library as a Ruby
- * extension. Otherwise, Ruby tries adding ``.rb'', ``.so'', and so on
- * to the name. The name of the loaded feature is added to the array in
- * <code>$"</code>. A feature will not be loaded if its name already
- * appears in <code>$"</code>. The file name is converted to an absolute
- * path, so ``<code>require 'a'; require './a'</code>'' will not load
- * <code>a.rb</code> twice.
- *
- * require "my-library.rb"
- * require "db-driver"
- */
-mrb_value
-mrb_f_require(mrb_state *mrb, mrb_value self)
-{
- mrb_value fname;
-
- mrb_get_args(mrb, "o", &fname);
- return mrb_nil_value(); /* dummy */
+ return val;
}
-
static inline int
basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub)
{
return mrb_respond_to(mrb, obj, id);
- //return TRUE;
}
/* 15.3.1.3.43 */
/*
@@ -1308,7 +1048,6 @@ obj_respond_to(mrb_state *mrb, mrb_value self)
mrb_sym id;
mrb_get_args(mrb, "*", &argv, &argc);
- //mrb_scan_args(argc, argv, "11", &mid, &priv);
mid = argv[0];
if (argc > 1) priv = argv[1];
else priv = mrb_nil_value();
@@ -1370,15 +1109,10 @@ mrb_init_kernel(mrb_state *mrb)
krn = mrb->kernel_module = mrb_define_module(mrb, "Kernel");
mrb_define_class_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, ARGS_NONE()); /* 15.3.1.2.2 */
- mrb_define_class_method(mrb, krn, "eval", mrb_f_eval_m, ARGS_ANY()); /* 15.3.1.2.3 */
mrb_define_class_method(mrb, krn, "global_variables", mrb_f_global_variables, ARGS_NONE()); /* 15.3.1.2.4 */
mrb_define_class_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, ARGS_NONE()); /* 15.3.1.2.5 */
- mrb_define_class_method(mrb, krn, "lambda", proc_lambda, ARGS_NONE()); /* 15.3.1.2.6 */
- mrb_define_class_method(mrb, krn, "local_variables", mrb_f_local_variables, ARGS_NONE()); /* 15.3.1.2.7 */
- mrb_define_class_method(mrb, krn, "loop", mrb_f_loop, ARGS_NONE()); /* 15.3.1.2.8 */
; /* 15.3.1.2.11 */
mrb_define_class_method(mrb, krn, "raise", mrb_f_raise, ARGS_ANY()); /* 15.3.1.2.12 */
- mrb_define_class_method(mrb, krn, "require", mrb_f_require, ARGS_REQ(1)); /* 15.3.1.2.13 */
mrb_define_method(mrb, krn, "singleton_class", mrb_singleton_class, ARGS_NONE());
@@ -1393,7 +1127,6 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method(mrb, krn, "dup", mrb_obj_dup, ARGS_NONE()); /* 15.3.1.3.9 */
mrb_define_method(mrb, krn, "eql?", mrb_obj_equal_m, ARGS_REQ(1)); /* 15.3.1.3.10 */
mrb_define_method(mrb, krn, "equal?", mrb_obj_equal_m, ARGS_REQ(1)); /* 15.3.1.3.11 */
- mrb_define_method(mrb, krn, "eval", mrb_f_eval_m, ARGS_ANY()); /* 15.3.1.3.12 */
mrb_define_method(mrb, krn, "extend", mrb_obj_extend_m, ARGS_ANY()); /* 15.3.1.3.13 */
mrb_define_method(mrb, krn, "global_variables", mrb_f_global_variables, ARGS_NONE()); /* 15.3.1.3.14 */
mrb_define_method(mrb, krn, "hash", mrb_obj_hash, ARGS_NONE()); /* 15.3.1.3.15 */
@@ -1408,9 +1141,6 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method(mrb, krn, "is_a?", mrb_obj_is_kind_of_m, ARGS_REQ(1)); /* 15.3.1.3.24 */
mrb_define_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, ARGS_NONE()); /* 15.3.1.3.25 */
mrb_define_method(mrb, krn, "kind_of?", mrb_obj_is_kind_of_m, ARGS_REQ(1)); /* 15.3.1.3.26 */
- mrb_define_method(mrb, krn, "lambda", proc_lambda, ARGS_NONE()); /* 15.3.1.3.27 */
- mrb_define_method(mrb, krn, "local_variables", mrb_f_local_variables, ARGS_NONE()); /* 15.3.1.3.28 */
- mrb_define_method(mrb, krn, "loop", mrb_f_loop, ARGS_NONE()); /* 15.3.1.3.29 */
mrb_define_method(mrb, krn, "methods", mrb_obj_methods_m, ARGS_ANY()); /* 15.3.1.3.31 */
mrb_define_method(mrb, krn, "nil?", mrb_false, ARGS_NONE()); /* 15.3.1.3.32 */
mrb_define_method(mrb, krn, "object_id", mrb_obj_id_m, ARGS_NONE()); /* 15.3.1.3.33 */
@@ -1419,14 +1149,16 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method(mrb, krn, "public_methods", mrb_obj_public_methods, ARGS_ANY()); /* 15.3.1.3.38 */
mrb_define_method(mrb, krn, "raise", mrb_f_raise, ARGS_ANY()); /* 15.3.1.3.40 */
mrb_define_method(mrb, krn, "remove_instance_variable", mrb_obj_remove_instance_variable,ARGS_REQ(1)); /* 15.3.1.3.41 */
- mrb_define_method(mrb, krn, "require", mrb_f_require, ARGS_REQ(1)); /* 15.3.1.3.42 */
mrb_define_method(mrb, krn, "respond_to?", obj_respond_to, ARGS_ANY()); /* 15.3.1.3.43 */
mrb_define_method(mrb, krn, "send", mrb_f_send, ARGS_ANY()); /* 15.3.1.3.44 */
+ mrb_define_method(mrb, krn, "__send__", mrb_f_send, ARGS_ANY()); /* 15.3.1.3.4 */
mrb_define_method(mrb, krn, "singleton_methods", mrb_obj_singleton_methods_m, ARGS_ANY()); /* 15.3.1.3.45 */
mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, ARGS_NONE()); /* 15.3.1.3.46 */
+#ifdef ENABLE_SPRINTF
mrb_define_method(mrb, krn, "sprintf", mrb_f_sprintf, ARGS_ANY()); /* in sprintf.c */
mrb_define_method(mrb, krn, "format", mrb_f_sprintf, ARGS_ANY()); /* in sprintf.c */
+#endif
mrb_include_module(mrb, mrb->object_class, mrb->kernel_module);
}
diff --git a/src/load.c b/src/load.c
index c0684f1aa..cee985f43 100644
--- a/src/load.c
+++ b/src/load.c
@@ -8,19 +8,11 @@
#include "mruby/dump.h"
#include "mruby/string.h"
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
#include "re.h"
#endif
#include "mruby/irep.h"
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
typedef struct _RiteFILE
{
FILE* fp;
@@ -151,7 +143,7 @@ load_rite_irep_record(mrb_state *mrb, RiteFILE* rfp, unsigned char* dst, uint32_
uint16_t buf_size =0;
buf_size = MRB_DUMP_DEFAULT_STR_LEN;
- if ((char_buf = mrb_malloc(mrb, buf_size)) == 0)
+ if ((char_buf = (char *)mrb_malloc(mrb, buf_size)) == 0)
goto error_exit;
pStart = dst;
@@ -200,7 +192,7 @@ load_rite_irep_record(mrb_state *mrb, RiteFILE* rfp, unsigned char* dst, uint32_
if ( pdl > buf_size - 1) {
buf_size = pdl + 1;
- if ((char_buf = mrb_realloc(mrb, char_buf, buf_size)) == 0)
+ if ((char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size)) == 0)
goto error_exit;
}
memset(char_buf, '\0', buf_size);
@@ -227,7 +219,7 @@ load_rite_irep_record(mrb_state *mrb, RiteFILE* rfp, unsigned char* dst, uint32_
if ( snl > buf_size - 1) {
buf_size = snl + 1;
- if ((char_buf = mrb_realloc(mrb, char_buf, buf_size)) == 0)
+ if ((char_buf = (char *)mrb_realloc(mrb, char_buf, buf_size)) == 0)
goto error_exit;
}
memset(char_buf, '\0', buf_size);
@@ -256,12 +248,12 @@ mrb_load_irep(mrb_state *mrb, FILE* fp)
unsigned char hex8[8], hcrc[4];
unsigned char *dst, *rite_dst = NULL;
rite_binary_header bin_header;
- RiteFILE ritefp, *rfp;
+ RiteFILE ritefp = { 0 };
+ RiteFILE *rfp;
if ((mrb == NULL) || (fp == NULL)) {
return MRB_DUMP_INVALID_ARGUMENT;
}
- memset(&ritefp, 0, sizeof(ritefp));
ritefp.fp = fp;
rfp = &ritefp;
@@ -270,7 +262,7 @@ mrb_load_irep(mrb_state *mrb, FILE* fp)
return ret;
len = sizeof(rite_binary_header) + bin_to_uint32(bin_header.rbds);
- if ((rite_dst = mrb_malloc(mrb, len)) == NULL)
+ if ((rite_dst = (unsigned char *)mrb_malloc(mrb, len)) == NULL)
return MRB_DUMP_GENERAL_FAILURE;
dst = rite_dst;
@@ -339,7 +331,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32
int ai = mrb_gc_arena_save(mrb);
recordStart = src;
- buf = mrb_malloc(mrb, bufsize);
+ buf = (char *)mrb_malloc(mrb, bufsize);
if (buf == NULL) {
ret = MRB_DUMP_INVALID_IREP;
goto error_exit;
@@ -367,7 +359,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32
irep->ilen = bin_to_uint32(src); //iseq length
src += MRB_DUMP_SIZE_OF_LONG;
if (irep->ilen > 0) {
- if ((irep->iseq = mrb_malloc(mrb, sizeof(mrb_code) * irep->ilen)) == NULL) {
+ if ((irep->iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code) * irep->ilen)) == NULL) {
ret = MRB_DUMP_GENERAL_FAILURE;
goto error_exit;
}
@@ -388,7 +380,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32
irep->plen = bin_to_uint32(src); //pool length
src += MRB_DUMP_SIZE_OF_LONG;
if (irep->plen > 0) {
- irep->pool = mrb_malloc(mrb, sizeof(mrb_value) * irep->plen);
+ irep->pool = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value) * irep->plen);
if (irep->pool == NULL) {
ret = MRB_DUMP_INVALID_IREP;
goto error_exit;
@@ -402,7 +394,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32
if (pdl > bufsize - 1) {
mrb_free(mrb, buf);
bufsize = pdl + 1;
- if ((buf = mrb_malloc(mrb, bufsize)) == NULL) {
+ if ((buf = (char *)mrb_malloc(mrb, bufsize)) == NULL) {
ret = MRB_DUMP_GENERAL_FAILURE;
goto error_exit;
}
@@ -413,7 +405,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32
switch (tt) { //pool data
case MRB_TT_FIXNUM:
- fix_num = readint(buf, 10);
+ fix_num = strtol(buf, NULL, 10);
irep->pool[i] = mrb_fixnum_value(fix_num);
break;
@@ -426,7 +418,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32
irep->pool[i] = mrb_str_new(mrb, buf, pdl);
break;
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
case MRB_TT_REGEX:
str = mrb_str_new(mrb, buf, pdl);
irep->pool[i] = mrb_reg_quote(mrb, str);
@@ -451,7 +443,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32
irep->slen = bin_to_uint32(src); //syms length
src += MRB_DUMP_SIZE_OF_LONG;
if (irep->slen > 0) {
- if ((irep->syms = mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen)) == NULL) {
+ if ((irep->syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen)) == NULL) {
ret = MRB_DUMP_INVALID_IREP;
goto error_exit;
}
@@ -469,7 +461,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32
if (snl > bufsize - 1) {
mrb_free(mrb, buf);
bufsize = snl + 1;
- if ((buf = mrb_malloc(mrb, bufsize)) == NULL) {
+ if ((buf = (char *)mrb_malloc(mrb, bufsize)) == NULL) {
ret = MRB_DUMP_GENERAL_FAILURE;
goto error_exit;
}
@@ -477,7 +469,7 @@ read_rite_irep_record(mrb_state *mrb, unsigned char *src, mrb_irep *irep, uint32
memcpy(buf, src, snl); //symbol name
src += snl;
buf[snl] = '\0';
- irep->syms[i] = mrb_intern(mrb, buf);
+ irep->syms[i] = mrb_intern2(mrb, buf, snl);
}
}
crc = calc_crc_16_ccitt((unsigned char*)pStart, src - pStart); //Calculate CRC
@@ -517,7 +509,7 @@ mrb_read_irep(mrb_state *mrb, const char *bin)
mrb_add_irep(mrb, sirep + nirep);
for (n=0,i=sirep; n<nirep; n++,i++) {
- if ((mrb->irep[i] = mrb_malloc(mrb, sizeof(mrb_irep))) == NULL) {
+ if ((mrb->irep[i] = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep))) == NULL) {
ret = MRB_DUMP_GENERAL_FAILURE;
goto error_exit;
}
@@ -616,13 +608,11 @@ static char*
hex_to_str(char *hex, char *str, uint16_t *str_len)
{
char *src, *dst;
- uint16_t hex_len = strlen(hex);
+ int escape = 0;
*str_len = 0;
-
- for (src = hex, dst = str; hex_len > 0; (*str_len)++, hex_len--) {
- if (*src == '\\' && hex_len > 1) {
- src++; hex_len--;
+ for (src = hex, dst = str; *src != '\0'; src++) {
+ if (escape) {
switch(*src) {
case 'a': *dst++ = '\a'/* BEL */; break;
case 'b': *dst++ = '\b'/* BS */; break;
@@ -637,12 +627,18 @@ hex_to_str(char *hex, char *str, uint16_t *str_len)
case '\\': *dst++ = *src; break;
default:break;
}
- src++;
+ escape = 0;
} else {
- *dst++ = *src++;
+ if (*src == '\\') {
+ escape = 1;
+ } else {
+ escape = 0;
+ *dst++ = *src;
+ }
+ }
+ if (!escape) {
+ (*str_len)++;
}
}
-
return str;
}
-
diff --git a/src/math.c b/src/math.c
index b0d911573..9aae87acd 100644
--- a/src/math.c
+++ b/src/math.c
@@ -5,15 +5,19 @@
*/
#include "mruby.h"
+#include "mruby/array.h"
+
+#ifdef ENABLE_MATH
#include <math.h>
#define domain_error(msg) \
mrb_raise(mrb, E_RANGE_ERROR, "Numerical argument is out of domain - " #msg);
-#define MATH_TOLERANCE 1E-12
-
/* math functions not provided under Microsoft Visual C++ */
#ifdef _MSC_VER
+
+#define MATH_TOLERANCE 1E-12
+
#define asinh(x) log(x + sqrt(pow(x,2.0) + 1))
#define acosh(x) log(x + sqrt(pow(x,2.0) - 1))
#define atanh(x) (log(1+x) - log(1-x))/2.0
@@ -85,10 +89,6 @@ erfc(double x)
#endif
-
-mrb_value
-mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr);
-
/*
TRIGONOMETRIC FUNCTIONS
*/
@@ -410,11 +410,14 @@ math_exp(mrb_state *mrb, mrb_value obj)
static mrb_value
math_log(mrb_state *mrb, mrb_value obj)
{
- mrb_float x;
+ mrb_float x, base;
+ int argc;
- mrb_get_args(mrb, "f", &x);
+ argc = mrb_get_args(mrb, "f|f", &x, &base);
x = log(x);
-
+ if (argc == 2) {
+ x /= log(base);
+ }
return mrb_float_value(x);
}
@@ -465,6 +468,25 @@ math_log10(mrb_state *mrb, mrb_value obj)
/*
* call-seq:
+ * Math.sqrt(numeric) -> float
+ *
+ * Returns the square root of <i>numeric</i>.
+ *
+ */
+static mrb_value
+math_sqrt(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ x = sqrt(x);
+
+ return mrb_float_value(x);
+}
+
+
+/*
+ * call-seq:
* Math.cbrt(numeric) -> float
*
* Returns the cube root of <i>numeric</i>.
@@ -612,47 +634,54 @@ mrb_init_math(mrb_state *mrb)
struct RClass *mrb_math;
mrb_math = mrb_define_module(mrb, "Math");
- mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(MATH_TOLERANCE));
- #ifdef M_PI
- mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(M_PI));
- #else
- mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(atan(1.0)*4.0));
- #endif
-
- #ifdef M_E
- mrb_define_const(mrb, mrb_math, "E", mrb_float_value(M_E));
- #else
- mrb_define_const(mrb, mrb_math, "E", mrb_float_value(exp(1.0)));
- #endif
+#ifdef M_PI
+ mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(M_PI));
+#else
+ mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(atan(1.0)*4.0));
+#endif
- mrb_define_module_function(mrb, mrb_math, "sin", math_sin, 1);
- mrb_define_module_function(mrb, mrb_math, "cos", math_cos, 1);
- mrb_define_module_function(mrb, mrb_math, "tan", math_tan, 1);
-
- mrb_define_module_function(mrb, mrb_math, "asin", math_asin, 1);
- mrb_define_module_function(mrb, mrb_math, "acos", math_acos, 1);
- mrb_define_module_function(mrb, mrb_math, "atan", math_atan, 1);
- mrb_define_module_function(mrb, mrb_math, "atan2", math_atan2, 2);
+#ifdef M_E
+ mrb_define_const(mrb, mrb_math, "E", mrb_float_value(M_E));
+#else
+ mrb_define_const(mrb, mrb_math, "E", mrb_float_value(exp(1.0)));
+#endif
+
+#ifdef MRB_USE_FLOAT
+ mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(1e-5));
+#else
+ mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(1e-12));
+#endif
+
+ mrb_define_module_function(mrb, mrb_math, "sin", math_sin, ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "cos", math_cos, ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "tan", math_tan, ARGS_REQ(1));
+
+ mrb_define_module_function(mrb, mrb_math, "asin", math_asin, ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "acos", math_acos, ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "atan", math_atan, ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "atan2", math_atan2, ARGS_REQ(2));
- mrb_define_module_function(mrb, mrb_math, "sinh", math_sinh, 1);
- mrb_define_module_function(mrb, mrb_math, "cosh", math_cosh, 1);
- mrb_define_module_function(mrb, mrb_math, "tanh", math_tanh, 1);
+ mrb_define_module_function(mrb, mrb_math, "sinh", math_sinh, ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "cosh", math_cosh, ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "tanh", math_tanh, ARGS_REQ(1));
- mrb_define_module_function(mrb, mrb_math, "asinh", math_asinh, 1);
- mrb_define_module_function(mrb, mrb_math, "acosh", math_acosh, 1);
- mrb_define_module_function(mrb, mrb_math, "atanh", math_atanh, 1);
+ mrb_define_module_function(mrb, mrb_math, "asinh", math_asinh, ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "acosh", math_acosh, ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "atanh", math_atanh, ARGS_REQ(1));
- mrb_define_module_function(mrb, mrb_math, "exp", math_exp, 1);
- mrb_define_module_function(mrb, mrb_math, "log", math_log, -1);
- mrb_define_module_function(mrb, mrb_math, "log2", math_log2, 1);
- mrb_define_module_function(mrb, mrb_math, "log10", math_log10, 1);
- mrb_define_module_function(mrb, mrb_math, "cbrt", math_cbrt, 1);
+ mrb_define_module_function(mrb, mrb_math, "exp", math_exp, ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "log", math_log, ARGS_REQ(1)|ARGS_OPT(1));
+ mrb_define_module_function(mrb, mrb_math, "log2", math_log2, ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "log10", math_log10, ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "sqrt", math_sqrt, ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "cbrt", math_cbrt, ARGS_REQ(1));
- mrb_define_module_function(mrb, mrb_math, "frexp", math_frexp, 1);
- mrb_define_module_function(mrb, mrb_math, "ldexp", math_ldexp, 2);
+ mrb_define_module_function(mrb, mrb_math, "frexp", math_frexp, ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "ldexp", math_ldexp, ARGS_REQ(2));
- mrb_define_module_function(mrb, mrb_math, "hypot", math_hypot, 2);
+ mrb_define_module_function(mrb, mrb_math, "hypot", math_hypot, ARGS_REQ(2));
- mrb_define_module_function(mrb, mrb_math, "erf", math_erf, 1);
- mrb_define_module_function(mrb, mrb_math, "erfc", math_erfc, 1);
+ mrb_define_module_function(mrb, mrb_math, "erf", math_erf, ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "erfc", math_erfc, ARGS_REQ(1));
}
+#endif /* ENABLE_MATH */
diff --git a/src/node.h b/src/node.h
index 8ae0301ba..29edd6cc5 100644
--- a/src/node.h
+++ b/src/node.h
@@ -103,29 +103,3 @@ enum node_type {
NODE_ATTRASGN,
NODE_LAST
};
-
-typedef struct RNode {
- unsigned long flags;
- char *nd_file;
- union {
- struct RNode *node;
- mrb_sym id;
- mrb_value value;
- //mrb_value (*cfunc)((ARGS_ANY()));
- mrb_sym *tbl;
- } u1;
- union {
- struct RNode *node;
- mrb_sym id;
- long argc;
- mrb_value value;
- } u2;
- union {
- struct RNode *node;
- mrb_sym id;
- long state;
- struct global_entry *entry;
- long cnt;
- mrb_value value;
- } u3;
-} NODE;
diff --git a/src/numeric.c b/src/numeric.c
index e1f711478..8280921c7 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -8,13 +8,10 @@
#include "mruby/numeric.h"
#include "mruby/string.h"
#include "mruby/array.h"
-#include <string.h>
-#include "mruby/class.h"
-#include "mruby/variable.h"
-#include <ctype.h>
#include <math.h>
#include <stdio.h>
+#include <assert.h>
#if defined(__FreeBSD__) && __FreeBSD__ < 4
#include <floatingpoint.h>
@@ -28,7 +25,7 @@
#include <ieeefp.h>
#endif
-#define SIGNED_VALUE intptr_t
+#define RSHIFT(x,y) ((x)>>(int)(y))
#ifdef MRB_USE_FLOAT
#define floor(f) floorf(f)
@@ -118,6 +115,12 @@ num_pow(mrb_state *mrb, mrb_value x)
* result.
*/
+mrb_value
+mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y)
+{
+ return mrb_float_value(mrb_to_flo(mrb, x) / mrb_to_flo(mrb, y));
+}
+
/* 15.2.9.3.19(x) */
/*
* call-seq:
@@ -180,29 +183,25 @@ static mrb_value
flo_to_s(mrb_state *mrb, mrb_value flt)
{
char buf[32];
+ int n;
mrb_float value = mrb_float(flt);
- char *p, *e;
- if (isinf(value))
- return mrb_str_new2(mrb, value < 0 ? "-Infinity" : "Infinity");
- else if(isnan(value))
- return mrb_str_new2(mrb, "NaN");
+ 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);
- sprintf(buf, "%#.15g", value); /* ensure to print decimal point */
- if (!(e = strchr(buf, 'e'))) {
- e = buf + strlen(buf);
- }
- if (!ISDIGIT(e[-1])) { /* reformat if ended with decimal point (ex 111111111111111.) */
- sprintf(buf, "%#.14e", value);
- if (!(e = strchr(buf, 'e'))) {
- e = buf + strlen(buf);
- }
- }
- p = e;
- while (p[-1]=='0' && ISDIGIT(p[-2]))
- p--;
- memmove(p, e, strlen(e)+1);
- return mrb_str_new2(mrb, buf);
+#ifdef MRB_USE_FLOAT
+ n = sprintf(buf, "%.7g", value);
+#else
+ n = sprintf(buf, "%.14g", value);
+#endif
+ assert(n >= 0);
+ return mrb_str_new(mrb, buf, n);
}
/* 15.2.9.3.2 */
@@ -404,7 +403,7 @@ flo_to_f(mrb_state *mrb, mrb_value num)
*/
static mrb_value
-flo_is_infinite_p(mrb_state *mrb, mrb_value num)
+flo_infinite_p(mrb_state *mrb, mrb_value num)
{
mrb_float value = mrb_float(num);
@@ -426,7 +425,7 @@ flo_is_infinite_p(mrb_state *mrb, mrb_value num)
*/
static mrb_value
-flo_is_finite_p(mrb_state *mrb, mrb_value num)
+flo_finite_p(mrb_state *mrb, mrb_value num)
{
mrb_float value = mrb_float(num);
@@ -516,21 +515,13 @@ flo_ceil(mrb_state *mrb, mrb_value num)
*/
static mrb_value
-flo_round(mrb_state *mrb, /*int argc, mrb_value *argv,*/ mrb_value num)
+flo_round(mrb_state *mrb, mrb_value num)
{
- mrb_value nd;
- mrb_float number, f;
+ double number, f;
int ndigits = 0, i;
- mrb_value *argv;
- int argc;
-
- mrb_get_args(mrb, "*", &argv, &argc);
- if (argc == 1) {
- nd = argv[0];
- ndigits = mrb_fixnum(nd);
- }
- number = mrb_float(num);
+ mrb_get_args(mrb, "|i", &ndigits);
+ number = mrb_float(num);
f = 1.0;
i = abs(ndigits);
while (--i >= 0)
@@ -540,7 +531,7 @@ flo_round(mrb_state *mrb, /*int argc, mrb_value *argv,*/ mrb_value num)
if (ndigits < 0) number = 0;
}
else {
- mrb_float d;
+ double d;
if (ndigits < 0) number /= f;
else number *= f;
@@ -558,7 +549,6 @@ flo_round(mrb_state *mrb, /*int argc, mrb_value *argv,*/ mrb_value num)
if (ndigits < 0) number *= f;
else number /= f;
}
-
if (ndigits > 0) return mrb_float_value(number);
return mrb_fixnum_value((mrb_int)number);
}
@@ -691,9 +681,31 @@ int_succ(mrb_state *mrb, mrb_value num)
return mrb_funcall(mrb, num, "+", 1, mrb_fixnum_value(1));
}
-#define SQRT_LONG_MAX ((SIGNED_VALUE)1<<((sizeof(mrb_int)*CHAR_BIT-1)/2))
+#define SQRT_INT_MAX ((mrb_int)1<<((sizeof(mrb_int)*CHAR_BIT-1)/2))
/*tests if N*N would overflow*/
-#define FIT_SQRT_LONG(n) (((n)<SQRT_LONG_MAX)&&((n)>=-SQRT_LONG_MAX))
+#define FIT_SQRT_INT(n) (((n)<SQRT_INT_MAX)&&((n)>=-SQRT_INT_MAX))
+
+mrb_value
+mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y)
+{
+ mrb_int a;
+
+ a = mrb_fixnum(x);
+ if (a == 0) return x;
+ if (FIXNUM_P(y)) {
+ mrb_int b, c;
+
+ b = mrb_fixnum(y);
+ if (FIT_SQRT_INT(a) && FIT_SQRT_INT(b))
+ return mrb_fixnum_value(a*b);
+ c = a * b;
+ if (c/a != b) {
+ return mrb_float_value((mrb_float)a*(mrb_float)b);
+ }
+ return mrb_fixnum_value(c);;
+ }
+ return mrb_float_value((mrb_float)a * mrb_to_flo(mrb, y));
+}
/* 15.2.8.3.3 */
/*
@@ -709,27 +721,8 @@ static mrb_value
fix_mul(mrb_state *mrb, mrb_value x)
{
mrb_value y;
- mrb_int a;
mrb_get_args(mrb, "o", &y);
-
- a = mrb_fixnum(x);
- if (FIXNUM_P(y)) {
- mrb_int b, c;
- mrb_value r;
-
- b = mrb_fixnum(y);
- if (FIT_SQRT_LONG(a) && FIT_SQRT_LONG(b))
- return mrb_fixnum_value(a*b);
- c = a * b;
- r = mrb_fixnum_value(c);
-
- if (a == 0) return x;
- if (mrb_fixnum(r) != c || c/a != b) {
- r = mrb_float_value((mrb_float)a*(mrb_float)b);
- }
- return r;
- }
- return mrb_float_value((mrb_float)a * mrb_to_flo(mrb, y));
+ return mrb_fixnum_mul(mrb, x, y);
}
static void
@@ -772,12 +765,11 @@ static mrb_value
fix_mod(mrb_state *mrb, mrb_value x)
{
mrb_value y;
- mrb_int a;
+ mrb_int a, b;
mrb_get_args(mrb, "o", &y);
-
a = mrb_fixnum(x);
- if (FIXNUM_P(y)) {
+ if (FIXNUM_P(y) && (b=mrb_fixnum(y)) != 0) {
mrb_int mod;
fixdivmod(mrb, a, mrb_fixnum(y), 0, &mod);
@@ -942,8 +934,28 @@ fix_xor(mrb_state *mrb, mrb_value x)
return mrb_fixnum_value(val);
}
-static mrb_value fix_lshift(mrb_state *mrb, mrb_int, unsigned long);
-static mrb_value fix_rshift(mrb_int, unsigned long);
+static mrb_value
+lshift(mrb_state *mrb, mrb_int val, unsigned long width)
+{
+ if (width > (sizeof(mrb_int)*CHAR_BIT-1)
+ || ((unsigned long)abs(val))>>(sizeof(mrb_int)*CHAR_BIT-1-width) > 0) {
+ mrb_raise(mrb, E_RANGE_ERROR, "width(%d) > (%d:sizeof(mrb_int)*CHAR_BIT-1)", width,
+ sizeof(mrb_int)*CHAR_BIT-1);
+ }
+ val = val << width;
+ return mrb_fixnum_value(val);
+}
+
+static mrb_value
+rshift(mrb_int val, unsigned long i)
+{
+ if (i >= sizeof(mrb_int)*CHAR_BIT-1) {
+ if (val < 0) return mrb_fixnum_value(-1);
+ return mrb_fixnum_value(0);
+ }
+ val = RSHIFT(val, i);
+ return mrb_fixnum_value(val);
+}
/* 15.2.8.3.12 */
/*
@@ -954,7 +966,7 @@ static mrb_value fix_rshift(mrb_int, unsigned long);
*/
static mrb_value
-mrb_fix_lshift(mrb_state *mrb, mrb_value x)
+fix_lshift(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_int val, width;
@@ -964,20 +976,8 @@ mrb_fix_lshift(mrb_state *mrb, mrb_value x)
y = bit_coerce(mrb, y);
width = mrb_fixnum(y);
if (width < 0)
- return fix_rshift(val, (unsigned long)-width);
- return fix_lshift(mrb, val, width);
-}
-
-static mrb_value
-fix_lshift(mrb_state *mrb, mrb_int val, unsigned long width)
-{
- if (width > (sizeof(mrb_int)*CHAR_BIT-1)
- || ((unsigned long)abs(val))>>(sizeof(mrb_int)*CHAR_BIT-1-width) > 0) {
- mrb_raise(mrb, E_RANGE_ERROR, "width(%d) > (%d:sizeof(mrb_int)*CHAR_BIT-1)", width,
- sizeof(mrb_int)*CHAR_BIT-1);
- }
- val = val << width;
- return mrb_fixnum_value(val);
+ return rshift(val, (unsigned long)-width);
+ return lshift(mrb, val, width);
}
/* 15.2.8.3.13 */
@@ -989,7 +989,7 @@ fix_lshift(mrb_state *mrb, mrb_int val, unsigned long width)
*/
static mrb_value
-mrb_fix_rshift(mrb_state *mrb, mrb_value x)
+fix_rshift(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_int i, val;
@@ -1000,19 +1000,8 @@ mrb_fix_rshift(mrb_state *mrb, mrb_value x)
i = mrb_fixnum(y);
if (i == 0) return x;
if (i < 0)
- return fix_lshift(mrb, val, (unsigned long)-i);
- return fix_rshift(val, i);
-}
-
-static mrb_value
-fix_rshift(mrb_int val, unsigned long i)
-{
- if (i >= sizeof(mrb_int)*CHAR_BIT-1) {
- if (val < 0) return mrb_fixnum_value(-1);
- return mrb_fixnum_value(0);
- }
- val = RSHIFT(val, i);
- return mrb_fixnum_value(val);
+ return lshift(mrb, val, (unsigned long)-i);
+ return rshift(val, i);
}
/* 15.2.8.3.23 */
@@ -1066,7 +1055,28 @@ flt2big(mrb_state *mrb, mrb_float d)
mrb_value
mrb_flt2big(mrb_state *mrb, mrb_float d)
{
- return mrb_fixnum_value(flt2big(mrb, d));
+ return mrb_fixnum_value(flt2big(mrb, d));
+}
+
+mrb_value
+mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y)
+{
+ mrb_int a;
+
+ a = mrb_fixnum(x);
+ if (a == 0) return y;
+ if (FIXNUM_P(y)) {
+ mrb_int b, c;
+
+ b = mrb_fixnum(y);
+ c = a + b;
+ if (((a < 0) ^ (b < 0)) == 0 && (a < 0) != (c < 0)) {
+ /* integer overflow */
+ return mrb_float_value((mrb_float)a + (mrb_float)b);
+ }
+ return mrb_fixnum_value(c);
+ }
+ return mrb_float_value((mrb_float)a + mrb_to_flo(mrb, y));
}
/* 15.2.8.3.1 */
@@ -1079,15 +1089,32 @@ mrb_flt2big(mrb_state *mrb, mrb_float d)
* result.
*/
static mrb_value
-mrb_fixnum_plus(mrb_state *mrb, mrb_value self)
+fix_plus(mrb_state *mrb, mrb_value self)
{
- mrb_int x, y;
+ mrb_value other;
+
+ mrb_get_args(mrb, "o", &other);
+ return mrb_fixnum_plus(mrb, self, other);
+}
- x = mrb_fixnum(self);
- mrb_get_args(mrb, "i", &y);
+mrb_value
+mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y)
+{
+ mrb_int a;
+
+ a = mrb_fixnum(x);
+ if (FIXNUM_P(y)) {
+ mrb_int b, c;
- DEBUG(printf("%d + %d = %d\n", x, y, x+y));
- return mrb_fixnum_value(x + y);
+ b = mrb_fixnum(y);
+ c = a - b;
+ if (((a < 0) ^ (b < 0)) != 0 && (a < 0) != (c < 0)) {
+ /* integer overflow */
+ return mrb_float_value((mrb_float)a - (mrb_float)b);
+ }
+ return mrb_fixnum_value(c);
+ }
+ return mrb_float_value((mrb_float)a - mrb_to_flo(mrb, y));
}
/* 15.2.8.3.2 */
@@ -1101,15 +1128,12 @@ mrb_fixnum_plus(mrb_state *mrb, mrb_value self)
* result.
*/
static mrb_value
-mrb_fixnum_minus(mrb_state *mrb, mrb_value self)
+fix_minus(mrb_state *mrb, mrb_value self)
{
- mrb_int x, y;
-
- x = mrb_fixnum(self);
- mrb_get_args(mrb, "i", &y);
+ mrb_value other;
- DEBUG(printf("%d - %d = %d\n", x, y, x-y));
- return mrb_fixnum_value(x - y);
+ mrb_get_args(mrb, "o", &other);
+ return mrb_fixnum_minus(mrb, self, other);
}
/* 15.2.8.3.29 (x) */
@@ -1132,16 +1156,23 @@ mrb_fix2str(mrb_state *mrb, mrb_value x, int base)
mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid radix %d", base);
}
if (val == 0) {
- return mrb_str_new2(mrb, "0");
+ return mrb_str_new(mrb, "0", 1);
}
if (val < 0) {
val = -val;
neg = 1;
}
*--b = '\0';
- do {
- *--b = mrb_digitmap[(int)(val % base)];
- } while (val /= base);
+ if (neg && val < 0) {
+ do {
+ *--b = mrb_digitmap[abs(val % base)];
+ } while (val /= base);
+ }
+ else {
+ do {
+ *--b = mrb_digitmap[(int)(val % base)];
+ } while (val /= base);
+ }
if (neg) {
*--b = '-';
}
@@ -1149,19 +1180,6 @@ mrb_fix2str(mrb_state *mrb, mrb_value x, int base)
return mrb_str_new2(mrb, b);
}
-mrb_value
-mrb_fix_to_s(mrb_state *mrb, mrb_value self, int argc, mrb_value *argv)
-{
- int base;
-
- if (argc == 0) base = 10;
- else {
- mrb_get_args(mrb, "i", &base);
- }
-
- return mrb_fix2str(mrb, self, base);
-}
-
/* 15.2.8.3.25 */
/*
* call-seq:
@@ -1179,13 +1197,12 @@ mrb_fix_to_s(mrb_state *mrb, mrb_value self, int argc, mrb_value *argv)
*
*/
static mrb_value
-mrb_fixnum_to_s(mrb_state *mrb, mrb_value self) /* fix_to_s */
+fix_to_s(mrb_state *mrb, mrb_value self)
{
- mrb_value *argv;
- int argc;
+ mrb_int base = 10;
- mrb_get_args(mrb, "*", &argv, &argc);
- return mrb_fix_to_s(mrb, self, argc, argv);
+ mrb_get_args(mrb, "|i", &base);
+ return mrb_fix2str(mrb, self, base);
}
/* 15.2.9.3.6 */
@@ -1236,7 +1253,7 @@ num_cmp(mrb_state *mrb, mrb_value self)
* and <code>other</code>.
*/
static mrb_value
-mrb_float_plus(mrb_state *mrb, mrb_value self)
+flo_plus(mrb_state *mrb, mrb_value self)
{
mrb_float x, y;
@@ -1266,9 +1283,9 @@ mrb_init_numeric(mrb_state *mrb)
integer = mrb_define_class(mrb, "Integer", numeric);
fixnum = mrb->fixnum_class = mrb_define_class(mrb, "Fixnum", integer);
- mrb_undef_method(mrb, fixnum, "new");
- mrb_define_method(mrb, fixnum, "+", mrb_fixnum_plus, ARGS_REQ(1)); /* 15.2.8.3.1 */
- mrb_define_method(mrb, fixnum, "-", mrb_fixnum_minus, ARGS_REQ(1)); /* 15.2.8.3.2 */
+ mrb_undef_class_method(mrb, fixnum, "new");
+ mrb_define_method(mrb, fixnum, "+", fix_plus, ARGS_REQ(1)); /* 15.2.8.3.1 */
+ mrb_define_method(mrb, fixnum, "-", fix_minus, ARGS_REQ(1)); /* 15.2.8.3.2 */
mrb_define_method(mrb, fixnum, "-@", fix_uminus, ARGS_REQ(1)); /* 15.2.7.4.2 */
mrb_define_method(mrb, fixnum, "*", fix_mul, ARGS_REQ(1)); /* 15.2.8.3.3 */
mrb_define_method(mrb, fixnum, "%", fix_mod, ARGS_REQ(1)); /* 15.2.8.3.5 */
@@ -1277,8 +1294,8 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method(mrb, fixnum, "&", fix_and, ARGS_REQ(1)); /* 15.2.8.3.9 */
mrb_define_method(mrb, fixnum, "|", fix_or, ARGS_REQ(1)); /* 15.2.8.3.10 */
mrb_define_method(mrb, fixnum, "^", fix_xor, ARGS_REQ(1)); /* 15.2.8.3.11 */
- mrb_define_method(mrb, fixnum, "<<", mrb_fix_lshift, ARGS_REQ(1)); /* 15.2.8.3.12 */
- mrb_define_method(mrb, fixnum, ">>", mrb_fix_rshift, ARGS_REQ(1)); /* 15.2.8.3.13 */
+ mrb_define_method(mrb, fixnum, "<<", fix_lshift, ARGS_REQ(1)); /* 15.2.8.3.12 */
+ mrb_define_method(mrb, fixnum, ">>", fix_rshift, ARGS_REQ(1)); /* 15.2.8.3.13 */
mrb_define_method(mrb, fixnum, "ceil", int_to_i, ARGS_NONE()); /* 15.2.8.3.14 */
mrb_define_method(mrb, fixnum, "eql?", num_eql, ARGS_REQ(1)); /* 15.2.8.3.16 */
mrb_define_method(mrb, fixnum, "floor", num_floor, ARGS_NONE()); /* 15.2.8.3.17 */
@@ -1288,22 +1305,22 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method(mrb, fixnum, "succ", fix_succ, ARGS_NONE()); /* 15.2.8.3.21 */
mrb_define_method(mrb, fixnum, "to_f", fix_to_f, ARGS_NONE()); /* 15.2.8.3.23 */
mrb_define_method(mrb, fixnum, "to_i", int_to_i, ARGS_NONE()); /* 15.2.8.3.24 */
- mrb_define_method(mrb, fixnum, "to_s", mrb_fixnum_to_s, ARGS_NONE()); /* 15.2.8.3.25 */
+ mrb_define_method(mrb, fixnum, "to_s", fix_to_s, ARGS_NONE()); /* 15.2.8.3.25 */
mrb_define_method(mrb, fixnum, "truncate", int_to_i, ARGS_NONE()); /* 15.2.8.3.26 */
mrb_define_method(mrb, fixnum, "divmod", fix_divmod, ARGS_REQ(1)); /* 15.2.8.3.30 (x) */
/* Float Class */
fl = mrb->float_class = mrb_define_class(mrb, "Float", numeric);
- mrb_undef_method(mrb, fl, "new");
- mrb_define_method(mrb, fl, "+", mrb_float_plus, ARGS_REQ(1)); /* 15.2.9.3.1 */
+ mrb_undef_class_method(mrb, fl, "new");
+ mrb_define_method(mrb, fl, "+", flo_plus, ARGS_REQ(1)); /* 15.2.9.3.1 */
mrb_define_method(mrb, fl, "-", flo_minus, ARGS_REQ(1)); /* 15.2.9.3.2 */
mrb_define_method(mrb, fl, "*", flo_mul, ARGS_REQ(1)); /* 15.2.9.3.3 */
mrb_define_method(mrb, fl, "%", flo_mod, ARGS_REQ(1)); /* 15.2.9.3.5 */
mrb_define_method(mrb, fl, "==", flo_eq, ARGS_REQ(1)); /* 15.2.9.3.7 */
mrb_define_method(mrb, fl, "ceil", flo_ceil, ARGS_NONE()); /* 15.2.9.3.8 */
- mrb_define_method(mrb, fl, "finite?", flo_is_finite_p, ARGS_NONE()); /* 15.2.9.3.9 */
+ mrb_define_method(mrb, fl, "finite?", flo_finite_p, ARGS_NONE()); /* 15.2.9.3.9 */
mrb_define_method(mrb, fl, "floor", flo_floor, ARGS_NONE()); /* 15.2.9.3.10 */
- mrb_define_method(mrb, fl, "infinite?", flo_is_infinite_p,ARGS_NONE()); /* 15.2.9.3.11 */
+ mrb_define_method(mrb, fl, "infinite?", flo_infinite_p, ARGS_NONE()); /* 15.2.9.3.11 */
mrb_define_method(mrb, fl, "round", flo_round, ARGS_ANY()); /* 15.2.9.3.12 */
mrb_define_method(mrb, fl, "to_f", flo_to_f, ARGS_NONE()); /* 15.2.9.3.13 */
mrb_define_method(mrb, fl, "to_i", flo_truncate, ARGS_NONE()); /* 15.2.9.3.14 */
diff --git a/src/object.c b/src/object.c
index 81e3867a7..26df48afd 100644
--- a/src/object.c
+++ b/src/object.c
@@ -11,14 +11,6 @@
#include "mruby/class.h"
#include "mruby/numeric.h"
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
int
mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2)
{
@@ -159,7 +151,7 @@ true_xor(mrb_state *mrb, mrb_value obj)
static mrb_value
true_to_s(mrb_state *mrb, mrb_value obj)
{
- return mrb_str_new_cstr(mrb, "true");
+ return mrb_str_new(mrb, "true", 4);
}
/* 15.2.5.3.4 */
@@ -272,7 +264,7 @@ false_or(mrb_state *mrb, mrb_value obj)
static mrb_value
false_to_s(mrb_state *mrb, mrb_value obj)
{
- return mrb_str_new_cstr(mrb, "false");
+ return mrb_str_new(mrb, "false", 5);
}
void
@@ -283,7 +275,7 @@ mrb_init_object(mrb_state *mrb)
struct RClass *f;
n = mrb->nil_class = mrb_define_class(mrb, "NilClass", mrb->object_class);
- mrb_undef_method(mrb, n, "new");
+ mrb_undef_class_method(mrb, n, "new");
mrb_define_method(mrb, n, "&", false_and, ARGS_REQ(1)); /* 15.2.4.3.1 */
mrb_define_method(mrb, n, "^", false_xor, ARGS_REQ(1)); /* 15.2.4.3.2 */
mrb_define_method(mrb, n, "|", false_or, ARGS_REQ(1)); /* 15.2.4.3.3 */
@@ -291,14 +283,14 @@ mrb_init_object(mrb_state *mrb)
mrb_define_method(mrb, n, "to_s", nil_to_s, ARGS_NONE()); /* 15.2.4.3.5 */
t = mrb->true_class = mrb_define_class(mrb, "TrueClass", mrb->object_class);
- mrb_undef_method(mrb, n, "new");
+ mrb_undef_class_method(mrb, t, "new");
mrb_define_method(mrb, t, "&", true_and, ARGS_REQ(1)); /* 15.2.5.3.1 */
mrb_define_method(mrb, t, "^", true_xor, ARGS_REQ(1)); /* 15.2.5.3.2 */
mrb_define_method(mrb, t, "to_s", true_to_s, ARGS_NONE()); /* 15.2.5.3.3 */
mrb_define_method(mrb, t, "|", true_or, ARGS_REQ(1)); /* 15.2.5.3.4 */
f = mrb->false_class = mrb_define_class(mrb, "FalseClass", mrb->object_class);
- mrb_undef_method(mrb, n, "new");
+ mrb_undef_class_method(mrb, f, "new");
mrb_define_method(mrb, f, "&", false_and, ARGS_REQ(1)); /* 15.2.6.3.1 */
mrb_define_method(mrb, f, "^", false_xor, ARGS_REQ(1)); /* 15.2.6.3.2 */
mrb_define_method(mrb, f, "to_s", false_to_s, ARGS_NONE()); /* 15.2.6.3.3 */
@@ -325,7 +317,7 @@ convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *metho
return mrb_nil_value();
}
}
- return mrb_funcall(mrb, val, method, 0);
+ return mrb_funcall_argv(mrb, val, m, 0, 0);
}
mrb_value
@@ -335,8 +327,7 @@ mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method)
if (mrb_type(val) == MRB_TT_FIXNUM) return val;
v = convert_type(mrb, val, "Integer", method, FALSE);
- if (mrb_nil_p(v)) return (v);
- if (!mrb_obj_is_kind_of(mrb, v, mrb_obj_class(mrb, v))) {
+ if (mrb_nil_p(v) || mrb_type(v) != MRB_TT_FIXNUM) {
return mrb_nil_value();
}
return v;
@@ -350,8 +341,8 @@ mrb_convert_type(mrb_state *mrb, mrb_value val, mrb_int type, const char *tname,
if (mrb_type(val) == type) return val;
v = convert_type(mrb, val, tname, method, 1/*Qtrue*/);
if (mrb_type(v) != type) {
- mrb_raise(mrb, E_TYPE_ERROR, "%s#%s should return %s",
- mrb_obj_classname(mrb, val), method, tname);
+ mrb_raise(mrb, E_TYPE_ERROR, "%s cannot be converted to %s by #%s",
+ mrb_obj_classname(mrb, val), tname, method);
}
return v;
}
@@ -361,14 +352,9 @@ mrb_check_convert_type(mrb_state *mrb, mrb_value val, mrb_int type, const char *
{
mrb_value v;
- /* always convert T_DATA */
if (mrb_type(val) == type && type != MRB_TT_DATA) return val;
v = convert_type(mrb, val, tname, method, 0/*Qfalse*/);
- if (mrb_nil_p(v)) return mrb_nil_value();
- if (mrb_type(v) != type) {
- mrb_raise(mrb, E_TYPE_ERROR, "%s#%s should return %s",
- mrb_obj_classname(mrb, val), method, tname);
- }
+ if (mrb_nil_p(v) || mrb_type(v) != type) return mrb_nil_value();
return v;
}
@@ -411,11 +397,6 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t)
struct RString *s;
int xt;
- /*if (x == Qundef) {
- //mrb_bug("undef leaked to the Ruby space");
- printf ("undef leaked to the Ruby space\n");
- }*/
-
xt = mrb_type(x);
if ((xt != t) || (xt == MRB_TT_DATA)) {
while (type->type < MRB_TT_MAXDEFINE) {
@@ -433,18 +414,17 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t)
}
else if (mrb_special_const_p(x)) {
s = mrb_str_ptr(mrb_obj_as_string(mrb, x));
- etype = s->buf;
+ etype = s->ptr;
}
else {
etype = mrb_obj_classname(mrb, x);
}
mrb_raise(mrb, E_TYPE_ERROR, "wrong argument type %s (expected %s)",
- etype, type->name);
+ etype, type->name);
}
type++;
}
- /*mrb_bug("unknown type 0x%x", t);*/
- printf ("unknown type 0x%x (0x%x given)", t, mrb_type(x));
+ mrb_raise(mrb, E_TYPE_ERROR, "unknown type 0x%x (0x%x given)", t, mrb_type(x));
}
}
@@ -470,9 +450,7 @@ mrb_any_to_s(mrb_state *mrb, mrb_value obj)
len = strlen(cname)+6+16;
str = mrb_str_new(mrb, 0, len); /* 6:tags 16:addr */
s = mrb_str_ptr(str);
- // snprintf(RSTRING(str)->ptr, len+1, "#<%s:0x%lx>", cname, obj);
- sprintf(s->buf, "#<%s:0x%lx>", cname, (unsigned long)(obj.value.p));
- s->len = strlen(s->buf);
+ s->len = sprintf(s->ptr, "#<%s:0x%lx>", cname, (unsigned long)(obj.value.p));
return str;
}
@@ -532,7 +510,6 @@ mrb_to_integer(mrb_state *mrb, mrb_value val, const char *method)
mrb_value v;
if (FIXNUM_P(val)) return val;
- //if (TYPE(val) == T_BIGNUM) return val;
v = convert_type(mrb, val, "Integer", method, TRUE);
if (!mrb_obj_is_kind_of(mrb, v, mrb->fixnum_class)) {
const char *cname = mrb_obj_classname(mrb, val);
diff --git a/src/opcode.h b/src/opcode.h
index 9e7cf7f34..40ba9d126 100644
--- a/src/opcode.h
+++ b/src/opcode.h
@@ -14,15 +14,15 @@
/* OP:A:Bx = 7:9:16 */
/* OP:Ax = 7:25 */
-#define GET_OPCODE(i) (((mrb_code)(i)) & 0x7f)
-#define GETARG_A(i) ((((mrb_code)(i)) >> 23) & 0x1ff)
-#define GETARG_B(i) ((((mrb_code)(i)) >> 14) & 0x1ff)
-#define GETARG_C(i) ((((mrb_code)(i)) >> 7) & 0x7f)
-#define GETARG_Bx(i) ((((mrb_code)(i)) >> 7) & 0xffff)
-#define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx)
-#define GETARG_Ax(i) ((((mrb_code)(i)) >> 7) & 0x1ffffff)
-#define GETARG_UNPACK_b(i,n1,n2) ((((mrb_code)(i)) >> (7+n2)) & (((1<<n1)-1)))
-#define GETARG_UNPACK_c(i,n1,n2) ((((mrb_code)(i)) >> 7) & (((1<<n2)-1)))
+#define GET_OPCODE(i) ((int)(((mrb_code)(i)) & 0x7f))
+#define GETARG_A(i) ((int)((((mrb_code)(i)) >> 23) & 0x1ff))
+#define GETARG_B(i) ((int)((((mrb_code)(i)) >> 14) & 0x1ff))
+#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_b(i) GETARG_UNPACK_b(i,14,2)
#define GETARG_c(i) GETARG_UNPACK_c(i,14,2)
diff --git a/src/parse.y b/src/parse.y
index eae9fb373..50f55bf7b 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -20,8 +20,8 @@
#include "mruby.h"
#include "mruby/compile.h"
+#include "mruby/proc.h"
#include "node.h"
-#include "st.h"
#include <stdio.h>
#include <errno.h>
@@ -41,30 +41,22 @@ static void backref_error(parser_state *p, node *n);
#define identchar(c) (isalnum(c) || (c) == '_' || !isascii(c))
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
typedef unsigned int stack_type;
-#define BITSTACK_PUSH(stack, n) ((stack) = ((stack)<<1)|((n)&1))
-#define BITSTACK_POP(stack) ((stack) = (stack) >> 1)
-#define BITSTACK_LEXPOP(stack) ((stack) = ((stack) >> 1) | ((stack) & 1))
-#define BITSTACK_SET_P(stack) ((stack)&1)
+#define BITSTACK_PUSH(stack, n) ((stack) = ((stack)<<1)|((n)&1))
+#define BITSTACK_POP(stack) ((stack) = (stack) >> 1)
+#define BITSTACK_LEXPOP(stack) ((stack) = ((stack) >> 1) | ((stack) & 1))
+#define BITSTACK_SET_P(stack) ((stack)&1)
-#define COND_PUSH(n) BITSTACK_PUSH(p->cond_stack, (n))
-#define COND_POP() BITSTACK_POP(p->cond_stack)
-#define COND_LEXPOP() BITSTACK_LEXPOP(p->cond_stack)
-#define COND_P() BITSTACK_SET_P(p->cond_stack)
+#define COND_PUSH(n) BITSTACK_PUSH(p->cond_stack, (n))
+#define COND_POP() BITSTACK_POP(p->cond_stack)
+#define COND_LEXPOP() BITSTACK_LEXPOP(p->cond_stack)
+#define COND_P() BITSTACK_SET_P(p->cond_stack)
-#define CMDARG_PUSH(n) BITSTACK_PUSH(p->cmdarg_stack, (n))
-#define CMDARG_POP() BITSTACK_POP(p->cmdarg_stack)
-#define CMDARG_LEXPOP() BITSTACK_LEXPOP(p->cmdarg_stack)
-#define CMDARG_P() BITSTACK_SET_P(p->cmdarg_stack)
+#define CMDARG_PUSH(n) BITSTACK_PUSH(p->cmdarg_stack, (n))
+#define CMDARG_POP() BITSTACK_POP(p->cmdarg_stack)
+#define CMDARG_LEXPOP() BITSTACK_LEXPOP(p->cmdarg_stack)
+#define CMDARG_P() BITSTACK_SET_P(p->cmdarg_stack)
static mrb_sym
intern_gen(parser_state *p, const char *s)
@@ -102,7 +94,7 @@ cons_gen(parser_state *p, node *car, node *cdr)
p->cells = p->cells->cdr;
}
else {
- c = parser_palloc(p, sizeof(mrb_ast_node));
+ c = (node *)parser_palloc(p, sizeof(mrb_ast_node));
}
c->car = car;
@@ -173,7 +165,7 @@ append_gen(parser_state *p, node *a, node *b)
static char*
parser_strndup(parser_state *p, const char *s, size_t len)
{
- char *b = parser_palloc(p, len+1);
+ char *b = (char *)parser_palloc(p, len+1);
memcpy(b, s, len);
b[len] = '\0';
@@ -526,6 +518,15 @@ new_sym(parser_state *p, mrb_sym sym)
return cons((node*)NODE_SYM, (node*)sym);
}
+static mrb_sym
+new_strsym(parser_state *p, node* str)
+{
+ const char *s = (const char*)str->cdr->car;
+ size_t len = (size_t)str->cdr->cdr;
+
+ return mrb_intern2(p->mrb, s, len);
+}
+
// (:lvar . a)
static node*
new_lvar(parser_state *p, mrb_sym sym)
@@ -685,9 +686,9 @@ new_float(parser_state *p, const char *s)
// (:str . (s . len))
static node*
-new_str(parser_state *p, const char *s, size_t len)
+new_str(parser_state *p, const char *s, int len)
{
- return cons((node*)NODE_STR, cons((node*)strndup(s, len), (node*)len));
+ return cons((node*)NODE_STR, cons((node*)strndup(s, len), (node*)(intptr_t)len));
}
// (:dstr . a)
@@ -697,6 +698,13 @@ new_dstr(parser_state *p, node *a)
return cons((node*)NODE_DSTR, a);
}
+// (:dsym . a)
+static node*
+new_dsym(parser_state *p, node *a)
+{
+ return cons((node*)NODE_DSYM, new_dstr(p, a));
+}
+
// (:backref . n)
static node*
new_back_ref(parser_state *p, int n)
@@ -754,11 +762,21 @@ args_with_block(parser_state *p, node *a, node *b)
static void
call_with_block(parser_state *p, node *a, node *b)
{
- node *n = a->cdr->cdr->cdr;
+ node *n;
- if (!n->car) n->car = cons(0, b);
+ if (a->car == (node*)NODE_SUPER ||
+ a->car == (node*)NODE_ZSUPER) {
+ if (!a->cdr) a->cdr = cons(0, b);
+ else {
+ args_with_block(p, a->cdr, b);
+ }
+ }
else {
- args_with_block(p, n->car, b);
+ n = a->cdr->cdr->cdr;
+ if (!n->car) n->car = cons(0, b);
+ else {
+ args_with_block(p, n->car, b);
+ }
}
}
@@ -787,12 +805,8 @@ ret_args(parser_state *p, node *n)
static void
assignable(parser_state *p, node *lhs)
{
- switch ((int)(intptr_t)lhs->car) {
- case NODE_LVAR:
+ if ((int)(intptr_t)lhs->car == NODE_LVAR) {
local_add(p, (mrb_sym)lhs->cdr);
- break;
- default:
- break;
}
}
@@ -801,17 +815,14 @@ var_reference(parser_state *p, node *lhs)
{
node *n;
- switch ((int)(intptr_t)lhs->car) {
- case NODE_LVAR:
+ if ((int)(intptr_t)lhs->car == NODE_LVAR) {
if (!local_var_p(p, (mrb_sym)lhs->cdr)) {
n = new_fcall(p, (mrb_sym)lhs->cdr, 0);
cons_free(lhs);
return n;
}
- break;
- default:
- break;
}
+
return lhs;
}
@@ -888,7 +899,7 @@ var_reference(parser_state *p, node *lhs)
%token <num> tREGEXP_END
%type <nd> singleton string string_interp regexp
-%type <nd> literal numeric cpath
+%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
%type <nd> expr_value arg_value primary_value
@@ -904,8 +915,8 @@ var_reference(parser_state *p, node *lhs)
%type <nd> bv_decls opt_bv_decl bvar f_larglist lambda_body
%type <nd> brace_block cmd_brace_block do_block lhs none fitem f_bad_arg
%type <nd> mlhs mlhs_list mlhs_post mlhs_basic mlhs_item mlhs_node mlhs_inner
-%type <id> fsym sym symbol operation operation2 operation3
-%type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg
+%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
%token tUPLUS /* unary+ */
%token tUMINUS /* unary- */
@@ -1472,7 +1483,7 @@ fname : tIDENTIFIER
;
fsym : fname
- | symbol
+ | basic_symbol
;
fitem : fsym
@@ -1502,7 +1513,7 @@ op : '|' { $$ = intern("|"); }
| '>' { $$ = intern(">"); }
| tGEQ { $$ = intern(">="); }
| '<' { $$ = intern("<"); }
- | tLEQ { $$ = intern(">="); }
+ | tLEQ { $$ = intern("<="); }
| tNEQ { $$ = intern("!="); }
| tLSHFT { $$ = intern("<<"); }
| tRSHFT { $$ = intern(">>"); }
@@ -2456,9 +2467,6 @@ opt_ensure : keyword_ensure compstmt
literal : numeric
| symbol
- {
- $$ = new_sym(p, $1);
- }
;
string : tCHAR
@@ -2501,7 +2509,18 @@ string_interp : tSTRING_PART
regexp : tREGEXP
;
-symbol : tSYMBEG sym
+symbol : basic_symbol
+ {
+ $$ = new_sym(p, $1);
+ }
+ | tSYMBEG tSTRING_BEG string_interp tSTRING
+ {
+ p->lstate = EXPR_END;
+ $$ = new_dsym(p, push($3, $4));
+ }
+ ;
+
+basic_symbol : tSYMBEG sym
{
p->lstate = EXPR_END;
$$ = $2;
@@ -2512,6 +2531,14 @@ sym : fname
| tIVAR
| tGVAR
| tCVAR
+ | tSTRING
+ {
+ $$ = new_strsym(p, $1);
+ }
+ | tSTRING_BEG tSTRING
+ {
+ $$ = new_strsym(p, $2);
+ }
;
numeric : tINTEGER
@@ -2585,7 +2612,7 @@ var_ref : variable
{
char buf[16];
- snprintf(buf, 16, "%d", p->lineno);
+ snprintf(buf, sizeof(buf), "%d", p->lineno);
$$ = new_int(p, buf, 10);
}
;
@@ -2787,7 +2814,8 @@ f_rest_arg : restarg_mark tIDENTIFIER
}
| restarg_mark
{
- $$ = 0;
+ local_add_f(p, 0);
+ $$ = -1;
}
;
@@ -2824,7 +2852,7 @@ singleton : var_ref
yyerror(p, "can't define singleton method for ().");
}
else {
- switch ((enum node_type)$3->car) {
+ switch ((enum node_type)(int)(intptr_t)$3->car) {
case NODE_STR:
case NODE_DSTR:
case NODE_DREGX:
@@ -2926,19 +2954,21 @@ static void
yyerror(parser_state *p, const char *s)
{
char* c;
- size_t n;
+ int n;
if (! p->capture_errors) {
+#ifdef ENABLE_STDIO
if (p->filename) {
fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
}
else {
fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s);
}
+#endif
}
else if (p->nerr < sizeof(p->error_buffer) / sizeof(p->error_buffer[0])) {
n = strlen(s);
- c = parser_palloc(p, n + 1);
+ c = (char *)parser_palloc(p, n + 1);
memcpy(c, s, n + 1);
p->error_buffer[p->nerr].message = c;
p->error_buffer[p->nerr].lineno = p->lineno;
@@ -2952,7 +2982,7 @@ yyerror_i(parser_state *p, const char *fmt, int i)
{
char buf[256];
- snprintf(buf, 256, fmt, i);
+ snprintf(buf, sizeof(buf), fmt, i);
yyerror(p, buf);
}
@@ -2960,19 +2990,21 @@ static void
yywarn(parser_state *p, const char *s)
{
char* c;
- size_t n;
+ int n;
if (! p->capture_errors) {
+#ifdef ENABLE_STDIO
if (p->filename) {
fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
}
else {
fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s);
}
+#endif
}
else if (p->nerr < sizeof(p->warn_buffer) / sizeof(p->warn_buffer[0])) {
n = strlen(s);
- c = parser_palloc(p, n + 1);
+ c = (char *)parser_palloc(p, n + 1);
memcpy(c, s, n + 1);
p->warn_buffer[p->nwarn].message = c;
p->warn_buffer[p->nwarn].lineno = p->lineno;
@@ -2992,20 +3024,23 @@ yywarning_s(parser_state *p, const char *fmt, const char *s)
{
char buf[256];
- snprintf(buf, 256, fmt, s);
+ snprintf(buf, sizeof(buf), fmt, s);
yywarning(p, buf);
}
static void
backref_error(parser_state *p, node *n)
{
- switch ((int)(intptr_t)n->car) {
- case NODE_NTH_REF:
+ int c;
+
+ c = (int)(intptr_t)n->car;
+
+ if (c == NODE_NTH_REF) {
yyerror_i(p, "can't set variable $%d", (int)(intptr_t)n->cdr);
- break;
- case NODE_BACK_REF:
+ } else if (c == NODE_BACK_REF) {
yyerror_i(p, "can't set variable $%c", (int)(intptr_t)n->cdr);
- break;
+ } else {
+ mrb_bug("Internal error in backref_error() : n=>car == %d", c);
}
}
@@ -3198,9 +3233,9 @@ toklen(parser_state *p)
#define IS_LABEL_SUFFIX(n) (peek_n(p, ':',(n)) && !peek_n(p, ':', (n)+1))
static unsigned long
-scan_oct(const char *start, int len, int *retlen)
+scan_oct(const int *start, int len, int *retlen)
{
- const char *s = start;
+ const int *s = start;
unsigned long retval = 0;
while (len-- && *s >= '0' && *s <= '7') {
@@ -3212,14 +3247,14 @@ scan_oct(const char *start, int len, int *retlen)
}
static unsigned long
-scan_hex(const char *start, int len, int *retlen)
+scan_hex(const int *start, int len, int *retlen)
{
static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
- register const char *s = start;
+ register const int *s = start;
register unsigned long retval = 0;
char *tmp;
- while (len-- && *s && (tmp = strchr(hexdigit, *s))) {
+ while (len-- && *s && (tmp = (char *)strchr(hexdigit, *s))) {
retval <<= 4;
retval |= (tmp - hexdigit) & 15;
s++;
@@ -3261,7 +3296,7 @@ read_escape(parser_state *p)
case '0': case '1': case '2': case '3': /* octal constant */
case '4': case '5': case '6': case '7':
{
- char buf[3];
+ int buf[3];
int i;
for (i=0; i<3; i++) {
@@ -3278,7 +3313,7 @@ read_escape(parser_state *p)
case 'x': /* hex constant */
{
- char buf[2];
+ int buf[2];
int i;
for (i=0; i<2; i++) {
@@ -3389,8 +3424,8 @@ parse_string(parser_state *p, int term)
return tSTRING;
}
-static int
-parse_qstring(parser_state *p, int term)
+static node*
+qstring_node(parser_state *p, int term)
{
int c;
@@ -3426,9 +3461,20 @@ parse_qstring(parser_state *p, int term)
}
tokfix(p);
- yylval.nd = new_str(p, tok(p), toklen(p));
p->lstate = EXPR_END;
- return tSTRING;
+ return new_str(p, tok(p), toklen(p));
+}
+
+static int
+parse_qstring(parser_state *p, int term)
+{
+ node *nd = qstring_node(p, term);
+
+ if (nd) {
+ yylval.nd = new_str(p, tok(p), toklen(p));
+ return tSTRING;
+ }
+ return 0;
}
static int
@@ -3537,11 +3583,10 @@ parser_yylex(parser_state *p)
c = '*';
}
}
- switch (p->lstate) {
- case EXPR_FNAME: case EXPR_DOT:
- p->lstate = EXPR_ARG; break;
- default:
- p->lstate = EXPR_BEG; break;
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ } else {
+ p->lstate = EXPR_BEG;
}
return c;
@@ -3572,11 +3617,10 @@ parser_yylex(parser_state *p)
goto retry;
}
}
- switch (p->lstate) {
- case EXPR_FNAME: case EXPR_DOT:
- p->lstate = EXPR_ARG; break;
- default:
- p->lstate = EXPR_BEG; break;
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ } else {
+ p->lstate = EXPR_BEG;
}
if ((c = nextc(p)) == '=') {
if ((c = nextc(p)) == '=') {
@@ -3608,13 +3652,13 @@ parser_yylex(parser_state *p)
if (token) return token;
}
#endif
- switch (p->lstate) {
- case EXPR_FNAME: case EXPR_DOT:
- p->lstate = EXPR_ARG; break;
- case EXPR_CLASS:
- p->cmd_start = TRUE;
- default:
- p->lstate = EXPR_BEG; break;
+ 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;
+ }
}
if (c == '=') {
if ((c = nextc(p)) == '>') {
@@ -3636,11 +3680,10 @@ parser_yylex(parser_state *p)
return '<';
case '>':
- switch (p->lstate) {
- case EXPR_FNAME: case EXPR_DOT:
- p->lstate = EXPR_ARG; break;
- default:
- p->lstate = EXPR_BEG; break;
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ } else {
+ p->lstate = EXPR_BEG;
}
if ((c = nextc(p)) == '=') {
return tGEQ;
@@ -3676,7 +3719,7 @@ parser_yylex(parser_state *p)
}
if (isspace(c)) {
if (!IS_ARG()) {
- int c2 = 0;
+ int c2;
switch (c) {
case ' ':
c2 = 's';
@@ -3696,10 +3739,13 @@ parser_yylex(parser_state *p)
case '\f':
c2 = 'f';
break;
+ default:
+ c2 = 0;
+ break;
}
if (c2) {
char buf[256];
- snprintf(buf, 256, "invalid character syntax; use ?\\%c", c2);
+ snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2);
yyerror(p, buf);
}
}
@@ -3765,10 +3811,9 @@ parser_yylex(parser_state *p)
else {
c = '&';
}
- switch (p->lstate) {
- case EXPR_FNAME: case EXPR_DOT:
- p->lstate = EXPR_ARG; break;
- default:
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ } else {
p->lstate = EXPR_BEG;
}
return c;
@@ -3902,7 +3947,7 @@ parser_yylex(parser_state *p)
}
if (!ISXDIGIT(c)) break;
nondigit = 0;
- tokadd(p, c);
+ tokadd(p, tolower(c));
} while ((c = nextc(p)) != -1);
}
pushback(p, c);
@@ -4081,8 +4126,15 @@ parser_yylex(parser_state *p)
}
tokfix(p);
if (is_float) {
- (void)strtod(tok(p), 0); /* just check if float is within range */
- if (errno == ERANGE) {
+ 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;
}
@@ -4120,21 +4172,7 @@ parser_yylex(parser_state *p)
p->lstate = EXPR_BEG;
return ':';
}
- switch (c) {
- case '\'':
-#if 0
- p->lex_strterm = new_strterm(p, str_ssym, c, 0);
-#endif
- break;
- case '"':
-#if 0
- p->lex_strterm = new_strterm(p, str_dsym, c, 0);
-#endif
- break;
- default:
- pushback(p, c);
- break;
- }
+ pushback(p, c);
p->lstate = EXPR_FNAME;
return tSYMBEG;
@@ -4158,11 +4196,10 @@ parser_yylex(parser_state *p)
#endif
return tREGEXP_BEG;
}
- switch (p->lstate) {
- case EXPR_FNAME: case EXPR_DOT:
- p->lstate = EXPR_ARG; break;
- default:
- p->lstate = EXPR_BEG; break;
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ } else {
+ p->lstate = EXPR_BEG;
}
return '/';
@@ -4172,11 +4209,10 @@ parser_yylex(parser_state *p)
p->lstate = EXPR_BEG;
return tOP_ASGN;
}
- switch (p->lstate) {
- case EXPR_FNAME: case EXPR_DOT:
- p->lstate = EXPR_ARG; break;
- default:
- p->lstate = EXPR_BEG; break;
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ } else {
+ p->lstate = EXPR_BEG;
}
pushback(p, c);
return '^';
@@ -4361,11 +4397,10 @@ parser_yylex(parser_state *p)
if (IS_SPCARG(c)) {
goto quotation;
}
- switch (p->lstate) {
- case EXPR_FNAME: case EXPR_DOT:
- p->lstate = EXPR_ARG; break;
- default:
- p->lstate = EXPR_BEG; break;
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ } else {
+ p->lstate = EXPR_BEG;
}
pushback(p, c);
return '%';
@@ -4539,7 +4574,7 @@ parser_yylex(parser_state *p)
pushback(p, c);
}
}
- if (result == 0 && isupper(tok(p)[0])) {
+ if (result == 0 && isupper((int)tok(p)[0])) {
result = tCONSTANT;
}
else {
@@ -4636,8 +4671,48 @@ yylex(void *lval, parser_state *p)
return t;
}
+static void
+parser_init_cxt(parser_state *p, mrbc_context *cxt)
+{
+ if (!cxt) return;
+ if (cxt->lineno) p->lineno = cxt->lineno;
+ if (cxt->filename) p->filename = cxt->filename;
+ if (cxt->syms) {
+ int i;
+
+ p->locals = cons(0,0);
+ for (i=0; i<cxt->slen; i++) {
+ local_add_f(p, cxt->syms[i]);
+ }
+ }
+ p->capture_errors = cxt->capture_errors;
+}
+
+static void
+parser_update_cxt(parser_state *p, mrbc_context *cxt)
+{
+ node *n, *n0;
+ int i = 0;
+
+ if (!cxt) return;
+ if ((int)(intptr_t)p->tree->car != NODE_SCOPE) return;
+ n0 = n = p->tree->cdr->car;
+ while (n) {
+ i++;
+ n = n->cdr;
+ }
+ cxt->syms = (mrb_sym *)mrb_realloc(p->mrb, cxt->syms, i*sizeof(mrb_sym));
+ cxt->slen = i;
+ for (i=0, n=n0; n; i++,n=n->cdr) {
+ cxt->syms[i] = (mrb_sym)n->car;
+ }
+}
+
+void codedump_all(mrb_state*, int);
+void parser_dump(mrb_state *mrb, node *tree, int offset);
+
void
-mrb_parser_parse(parser_state *p)
+mrb_parser_parse(parser_state *p, mrbc_context *c)
{
node *tree;
@@ -4653,6 +4728,7 @@ mrb_parser_parse(parser_state *p)
p->nerr = p->nwarn = 0;
p->sterm = 0;
+ parser_init_cxt(p, c);
yyparse(p);
tree = p->tree;
if (!tree) {
@@ -4664,14 +4740,15 @@ mrb_parser_parse(parser_state *p)
}
}
else {
- if ((intptr_t)tree->car == NODE_SCOPE) {
- p->locals = cons(tree->cdr->car, 0);
- }
+ parser_update_cxt(p, c);
if (p->begin_tree) {
tree = new_begin(p, p->begin_tree);
append(tree, p->tree);
}
}
+ if (c && c->dump_result) {
+ parser_dump(p->mrb, p->tree, 0);
+ }
}
parser_state*
@@ -4682,7 +4759,7 @@ mrb_parser_new(mrb_state *mrb)
pool = mrb_pool_open(mrb);
if (!pool) return 0;
- p = mrb_pool_alloc(pool, sizeof(parser_state));
+ p = (parser_state *)mrb_pool_alloc(pool, sizeof(parser_state));
if (!p) return 0;
memset(p, 0, sizeof(parser_state));
@@ -4697,7 +4774,6 @@ mrb_parser_new(mrb_state *mrb)
p->in_def = p->in_single = FALSE;
p->capture_errors = 0;
-
p->lineno = 1;
p->column = 0;
#if defined(PARSER_TEST) || defined(PARSER_DEBUG)
@@ -4707,28 +4783,45 @@ mrb_parser_new(mrb_state *mrb)
return p;
}
-const char*
-mrb_parser_filename(parser_state *p, const char *s)
+void
+mrb_parser_free(parser_state *p) {
+ mrb_pool_close(p->pool);
+}
+
+mrbc_context*
+mrbc_context_new(mrb_state *mrb)
{
- if (s) {
- p->filename = strdup(s);
- }
- return p->filename;
+ mrbc_context *c;
+
+ c = (mrbc_context *)mrb_calloc(mrb, 1, sizeof(mrbc_context));
+ return c;
}
-int
-mrb_parser_lineno(struct mrb_parser_state *p, int n)
+void
+mrbc_context_free(mrb_state *mrb, mrbc_context *cxt)
+{
+ mrb_free(mrb, cxt->syms);
+ mrb_free(mrb, cxt->filename);
+ mrb_free(mrb, cxt);
+}
+
+const char*
+mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s)
{
- if (n <= 0) {
- return p->lineno;
+ if (s) {
+ int len = strlen(s);
+ char *p = (char *)mrb_malloc(mrb, len);
+
+ memcpy(p, s, len);
+ if (c->filename) mrb_free(mrb, c->filename);
+ c->filename = p;
+ c->lineno = 1;
}
- p->column = 0;
- p->lineno = n;
- return n;
+ return c->filename;
}
parser_state*
-mrb_parse_file(mrb_state *mrb, FILE *f)
+mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
{
parser_state *p;
@@ -4737,12 +4830,12 @@ mrb_parse_file(mrb_state *mrb, FILE *f)
p->s = p->send = NULL;
p->f = f;
- mrb_parser_parse(p);
+ mrb_parser_parse(p, c);
return p;
}
parser_state*
-mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len)
+mrb_parse_nstring(mrb_state *mrb, const char *s, int len, mrbc_context *c)
{
parser_state *p;
@@ -4751,64 +4844,97 @@ mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len)
p->s = s;
p->send = s + len;
- mrb_parser_parse(p);
+ mrb_parser_parse(p, c);
return p;
}
parser_state*
-mrb_parse_string(mrb_state *mrb, const char *s)
+mrb_parse_string(mrb_state *mrb, const char *s, mrbc_context *c)
{
- return mrb_parse_nstring(mrb, s, strlen(s));
+ return mrb_parse_nstring(mrb, s, strlen(s), c);
}
-#define PARSER_DUMP
-
-void parser_dump(mrb_state *mrb, node *tree, int offset);
-
-int
-mrb_compile_file(mrb_state * mrb, FILE *f)
+static mrb_value
+load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c)
{
- parser_state *p;
int n;
+ mrb_value v;
- p = mrb_parse_file(mrb, f);
- if (!p) return -1;
- if (!p->tree) return -1;
- if (p->nerr) return -1;
-#ifdef PARSER_DUMP
- parser_dump(mrb, p->tree, 0);
-#endif
+ if (!p) {
+ mrb_parser_free(p);
+ return mrb_undef_value();
+ }
+ if (!p->tree || p->nerr) {
+ if (p->capture_errors) {
+ char buf[256];
+
+ 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_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_parser_free(p);
+ return mrb_nil_value();
+ }
+ }
n = mrb_generate_code(mrb, p->tree);
- mrb_pool_close(p->pool);
+ 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));
+ return mrb_nil_value();
+ }
+ if (c) {
+ if (c->dump_result) codedump_all(mrb, n);
+ if (c->no_exec) return mrb_fixnum_value(n);
+ }
+ v = mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));
+ if (mrb->exc) return mrb_nil_value();
+ return v;
+}
- return n;
+mrb_value
+mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c)
+{
+ return load_exec(mrb, mrb_parse_file(mrb, f, c), c);
}
-int
-mrb_compile_nstring(mrb_state *mrb, char *s, size_t len)
+mrb_value
+mrb_load_file(mrb_state *mrb, FILE *f)
{
- parser_state *p;
- int n;
+ return mrb_load_file_cxt(mrb, f, NULL);
+}
- p = mrb_parse_nstring(mrb, s, len);
- if (!p) return -1;
- if (!p->tree) return -1;
- if (p->nerr) return -1;
-#ifdef PARSER_DUMP
- parser_dump(mrb, p->tree, 0);
-#endif
- n = mrb_generate_code(mrb, p->tree);
- mrb_pool_close(p->pool);
+mrb_value
+mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *c)
+{
+ return load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c);
+}
- return n;
+mrb_value
+mrb_load_nstring(mrb_state *mrb, const char *s, int len)
+{
+ return mrb_load_nstring_cxt(mrb, s, len, NULL);
}
-int
-mrb_compile_string(mrb_state *mrb, char *s)
+mrb_value
+mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *c)
+{
+ return mrb_load_nstring_cxt(mrb, s, strlen(s), c);
+}
+
+mrb_value
+mrb_load_string(mrb_state *mrb, const char *s)
{
- return mrb_compile_nstring(mrb, s, strlen(s));
+ return mrb_load_string_cxt(mrb, s, NULL);
}
+#ifdef ENABLE_STDIO
+
static void
dump_prefix(int offset)
{
@@ -4827,9 +4953,12 @@ dump_recur(mrb_state *mrb, node *tree, int offset)
}
}
+#endif
+
void
parser_dump(mrb_state *mrb, node *tree, int offset)
{
+#ifdef ENABLE_STDIO
int n;
if (!tree) return;
@@ -4891,7 +5020,7 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
parser_dump(mrb, tree->car, offset+2);
dump_prefix(offset+1);
printf("ensure:\n");
- parser_dump(mrb, tree->cdr, offset+2);
+ parser_dump(mrb, tree->cdr->cdr, offset+2);
break;
case NODE_LAMBDA:
@@ -5052,15 +5181,20 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
case NODE_SCOPE:
printf("NODE_SCOPE:\n");
- dump_prefix(offset+1);
- printf("local variables:\n");
{
node *n2 = tree->car;
- while (n2) {
- dump_prefix(offset+2);
- printf("%s\n", mrb_sym2name(mrb, (mrb_sym)n2->car));
- n2 = n2->cdr;
+ if (n2 && (n2->car || n2->cdr)) {
+ dump_prefix(offset+1);
+ printf("local variables:\n");
+ while (n2) {
+ if (n2->car) {
+ dump_prefix(offset+2);
+ printf("%s ", mrb_sym2name(mrb, (mrb_sym)n2->car));
+ }
+ n2 = n2->cdr;
+ }
+ printf("\n");
}
}
tree = tree->cdr;
@@ -5392,16 +5526,21 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
dump_prefix(offset+1);
printf("%s\n", mrb_sym2name(mrb, (mrb_sym)tree->car));
tree = tree->cdr;
- dump_prefix(offset+1);
- printf("local variables:\n");
{
node *n2 = tree->car;
- while (n2) {
- dump_prefix(offset+2);
- if (n2->car)
- printf("%s\n", mrb_sym2name(mrb, (mrb_sym)n2->car));
- n2 = n2->cdr;
+ if (n2 && (n2->car || n2->cdr)) {
+ dump_prefix(offset+1);
+ printf("local variables:\n");
+
+ while (n2) {
+ if (n2->car) {
+ dump_prefix(offset+2);
+ printf("%s ", mrb_sym2name(mrb, (mrb_sym)n2->car));
+ }
+ n2 = n2->cdr;
+ }
+ printf("\n");
}
}
tree = tree->cdr;
@@ -5508,7 +5647,7 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
printf("node type: %d (0x%x)\n", (int)n, (int)n);
break;
}
- return;
+#endif
}
#ifdef PARSER_TEST
diff --git a/src/pool.c b/src/pool.c
index 3cbb2b163..daa6d0f69 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -8,6 +8,18 @@
#include <stddef.h>
#include <string.h>
+/* configuration section */
+/* allocated memory address should be multiple of POOL_ALIGNMENT */
+/* or undef it if alignment does not matter */
+#ifndef POOL_ALIGNMENT
+#define POOL_ALIGNMENT 4
+#endif
+/* page size of memory pool */
+#ifndef POOL_PAGE_SIZE
+#define POOL_PAGE_SIZE 16000
+#endif
+/* end of configuration section */
+
struct mrb_pool_page {
struct mrb_pool_page *next;
size_t offset;
@@ -23,16 +35,13 @@ struct mrb_pool {
#undef TEST_POOL
#ifdef TEST_POOL
-#include <stdio.h>
#define mrb_malloc(m,s) malloc(s)
#define mrb_free(m,p) free(p)
#endif
-#define POOL_PAGE_SIZE 16000
-
-#ifdef ALLOC_ALIGN
-# define ALIGN_PADDING(x) ((x % ALLOC_ALIGN) ? ALLOC_ALIGN - (x % ALLOC_ALIGN) : 0)
+#ifdef POOL_ALIGNMENT
+# define ALIGN_PADDING(x) ((-x) & (POOL_ALIGNMENT - 1))
#else
# define ALIGN_PADDING(x) (0)
#endif
@@ -40,7 +49,7 @@ struct mrb_pool {
mrb_pool*
mrb_pool_open(mrb_state *mrb)
{
- mrb_pool *pool = mrb_malloc(mrb, sizeof(mrb_pool));
+ mrb_pool *pool = (mrb_pool *)mrb_malloc(mrb, sizeof(mrb_pool));
if (pool) {
pool->mrb = mrb;
@@ -72,7 +81,7 @@ page_alloc(mrb_pool *pool, size_t len)
if (len < POOL_PAGE_SIZE)
len = POOL_PAGE_SIZE;
- page = mrb_malloc(pool->mrb, sizeof(struct mrb_pool_page)+len-1);
+ page = (struct mrb_pool_page *)mrb_malloc(pool->mrb, sizeof(struct mrb_pool_page)+len-1);
if (page) {
page->offset = 0;
page->len = len;
diff --git a/src/print.c b/src/print.c
index 505597935..e6805edbf 100644
--- a/src/print.c
+++ b/src/print.c
@@ -5,35 +5,31 @@
*/
#include "mruby.h"
+#ifdef ENABLE_STDIO
#include "mruby/string.h"
#include <stdio.h>
-mrb_value
+static void
printstr(mrb_state *mrb, mrb_value obj)
{
struct RString *str;
char *s;
- size_t len;
+ int len;
if (mrb_type(obj) == MRB_TT_STRING) {
str = mrb_str_ptr(obj);
- s = str->buf;
+ s = str->ptr;
len = str->len;
- while (len--) {
- putc(*s, stdout);
- s++;
- }
+ fwrite(s, len, 1, stdout);
}
- return obj;
}
-mrb_value
+void
mrb_p(mrb_state *mrb, mrb_value obj)
{
obj = mrb_funcall(mrb, obj, "inspect", 0);
printstr(mrb, obj);
putc('\n', stdout);
- return obj;
}
/* 15.3.1.2.9 */
@@ -71,3 +67,19 @@ mrb_show_copyright(mrb_state *mrb)
{
printf("mruby - Copyright (c) 2010-2012 mruby developers\n");
}
+#else
+void
+mrb_p(mrb_state *mrb, mrb_value obj)
+{
+}
+
+void
+mrb_show_version(mrb_state *mrb)
+{
+}
+
+void
+mrb_show_copyright(mrb_state *mrb)
+{
+}
+#endif
diff --git a/src/proc.c b/src/proc.c
index 21c462493..e5c233e1b 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -6,7 +6,6 @@
#include "mruby.h"
#include "mruby/proc.h"
-#include "mruby/array.h"
#include "mruby/class.h"
#include "opcode.h"
@@ -16,8 +15,8 @@ mrb_proc_new(mrb_state *mrb, mrb_irep *irep)
struct RProc *p;
p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
- p->body.irep = irep;
p->target_class = (mrb->ci) ? mrb->ci->target_class : 0;
+ p->body.irep = irep;
p->env = 0;
return p;
@@ -56,20 +55,41 @@ mrb_proc_new_cfunc(mrb_state *mrb, mrb_func_t func)
return p;
}
+void
+mrb_proc_copy(struct RProc *a, struct RProc *b)
+{
+ a->flags = b->flags;
+ a->body = b->body;
+ a->target_class = b->target_class;
+ a->env = b->env;
+}
+
static mrb_value
mrb_proc_initialize(mrb_state *mrb, mrb_value self)
{
mrb_value blk;
mrb_get_args(mrb, "&", &blk);
- if (!mrb_nil_p(blk)) {
- *mrb_proc_ptr(self) = *mrb_proc_ptr(blk);
- }
- else {
+ if (mrb_nil_p(blk)) {
/* Calling Proc.new without a block is not implemented yet */
mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
}
+ else {
+ mrb_proc_copy(mrb_proc_ptr(self), mrb_proc_ptr(blk));
+ }
+ return self;
+}
+
+static mrb_value
+mrb_proc_init_copy(mrb_state *mrb, mrb_value self)
+{
+ mrb_value proc;
+ mrb_get_args(mrb, "o", &proc);
+ if (mrb_type(proc) != MRB_TT_PROC) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc");
+ }
+ mrb_proc_copy(mrb_proc_ptr(self), mrb_proc_ptr(proc));
return self;
}
@@ -91,12 +111,41 @@ mrb_proc_iseq(mrb_state *mrb, struct RProc *p)
return p->body.irep->iseq;
}
+/* 15.3.1.2.6 */
+/* 15.3.1.3.27 */
+/*
+ * call-seq:
+ * lambda { |...| block } -> a_proc
+ *
+ * Equivalent to <code>Proc.new</code>, except the resulting Proc objects
+ * check the number of parameters passed when called.
+ */
+static mrb_value
+proc_lambda(mrb_state *mrb, mrb_value self)
+{
+ mrb_value blk;
+ struct RProc *p;
+
+ mrb_get_args(mrb, "&", &blk);
+ if (mrb_nil_p(blk)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
+ }
+ p = mrb_proc_ptr(blk);
+ if (!MRB_PROC_STRICT_P(p)) {
+ struct RProc *p2 = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, p->c);
+ mrb_proc_copy(p2, p);
+ p2->flags |= MRB_PROC_STRICT;
+ return mrb_obj_value(p2);
+ }
+ return blk;
+}
+
void
mrb_init_proc(mrb_state *mrb)
{
struct RProc *m;
- mrb_code *call_iseq = mrb_malloc(mrb, sizeof(mrb_code));
- mrb_irep *call_irep = mrb_calloc(mrb, sizeof(mrb_irep), 1);
+ mrb_code *call_iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code));
+ mrb_irep *call_irep = (mrb_irep *)mrb_calloc(mrb, sizeof(mrb_irep), 1);
if ( call_iseq == NULL || call_irep == NULL )
return;
@@ -108,10 +157,15 @@ mrb_init_proc(mrb_state *mrb)
call_irep->ilen = 1;
mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class);
+ MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC);
mrb_define_method(mrb, mrb->proc_class, "initialize", mrb_proc_initialize, ARGS_NONE());
+ mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, ARGS_REQ(1));
m = mrb_proc_new(mrb, call_irep);
mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern(mrb, "call"), m);
mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern(mrb, "[]"), m);
+
+ mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, ARGS_NONE()); /* 15.3.1.2.6 */
+ mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, ARGS_NONE()); /* 15.3.1.3.27 */
}
diff --git a/src/range.c b/src/range.c
index c1fb580b5..db17c7d40 100644
--- a/src/range.c
+++ b/src/range.c
@@ -7,30 +7,35 @@
#include "mruby.h"
#include "mruby/class.h"
#include "mruby/range.h"
-#include "mruby/variable.h"
-#include "error.h"
-#include "mruby/numeric.h"
#include "mruby/string.h"
-
-#include <stdio.h>
#include <string.h>
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
#ifndef OTHER
#define OTHER 2
#endif
#define RANGE_CLASS (mrb_class_obj_get(mrb, "Range"))
-mrb_value mrb_exec_recursive_paired(mrb_state *mrb, mrb_value (*func) (mrb_state *, mrb_value, mrb_value, int),
- mrb_value obj, mrb_value paired_obj, void* arg);
+static void
+range_check(mrb_state *mrb, mrb_value a, mrb_value b)
+{
+ mrb_value ans;
+ int ta;
+ int tb;
+
+ ta = mrb_type(a);
+ tb = mrb_type(b);
+ if ((ta == MRB_TT_FIXNUM || ta == MRB_TT_FLOAT) &&
+ (tb == MRB_TT_FIXNUM || tb == MRB_TT_FLOAT)) {
+ return;
+ }
+
+ ans = mrb_funcall(mrb, a, "<=>", 1, b);
+ if (mrb_nil_p(ans)) {
+ /* can not be compared */
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "bad value for range");
+ }
+}
mrb_value
mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, int excl)
@@ -38,7 +43,8 @@ mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, int excl)
struct RRange *r;
r = (struct RRange*)mrb_obj_alloc(mrb, MRB_TT_RANGE, RANGE_CLASS);
- r->edges = mrb_malloc(mrb, sizeof(struct mrb_range_edges));
+ r->edges = (struct mrb_range_edges *)mrb_malloc(mrb, sizeof(struct mrb_range_edges));
+ range_check(mrb, beg, end);
r->edges->beg = beg;
r->edges->end = end;
r->excl = excl;
@@ -93,41 +99,12 @@ mrb_range_excl(mrb_state *mrb, mrb_value range)
return r->excl ? mrb_true_value() : mrb_false_value();
}
-/*
- * call-seq:
- * beg end
- * args[0] <= args[1] => true
- * args[0] > args[1] => false
- */
-static int
-range_check(mrb_state *mrb, mrb_value *args)
-{
- mrb_value ans = mrb_funcall(mrb, args[0], "<=>", 1, args[1]);
- /* beg end
- ans :args[0] < args[1] => -1
- args[0] = args[1] => 0
- args[0] > args[1] => +1 */
- if (mrb_nil_p(ans)) return FALSE;
- //if (mrb_obj_equal(mrb, ans, mrb_fixnum_value(1))) return FALSE;
- if (mrb_fixnum(ans) == 1) return FALSE;
- return TRUE;
-}
-
static void
range_init(mrb_state *mrb, mrb_value range, mrb_value beg, mrb_value end, mrb_int exclude_end)
{
- mrb_value args[2];
struct RRange *r = mrb_range_ptr(range);
- if ((mrb_type(beg) != MRB_TT_FIXNUM) || (mrb_type(end) != MRB_TT_FIXNUM)) {
- args[0] = beg;
- args[1] = end;
- /* eroor.c v = mrb_rescue(range_check, (mrb_value)args, range_failed, 0);
- if (mrb_nil_p(v)) range_failed(); */
- if (!range_check(mrb, args)) {
- printf("range_failed()\n");
- }
- }
+ range_check(mrb, beg, end);
r->excl = exclude_end;
r->edges->beg = beg;
r->edges->end = end;
@@ -179,7 +156,6 @@ mrb_range_eq(mrb_state *mrb, mrb_value range)
if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
/* same class? */
- // if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range)))
return mrb_false_value();
@@ -198,55 +174,41 @@ mrb_range_eq(mrb_state *mrb, mrb_value range)
static int
r_le(mrb_state *mrb, mrb_value a, mrb_value b)
{
- //int c;
mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
/* output :a < b => -1, a = b => 0, a > b => +1 */
- if (mrb_nil_p(r)) return FALSE;
+ if (mrb_type(r) == MRB_TT_FIXNUM) {
+ int c = mrb_fixnum(r);
+ if (c == 0 || c == -1) return TRUE;
+ }
- /* mrb_value -> int */
- //c = mrb_cmpint(mrb, r, a, b);
- //if (c == 0) return TRUE;
- //if (c < 0) return TRUE;
- //return FALSE;
- if (mrb_obj_equal(mrb, r, mrb_fixnum_value(0))) return TRUE;
- if (mrb_obj_equal(mrb, r, mrb_fixnum_value(-1))) return TRUE;
return FALSE;
}
static int
r_gt(mrb_state *mrb, mrb_value a, mrb_value b)
{
- //int c;
mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b);
/* output :a < b => -1, a = b => 0, a > b => +1 */
- if (mrb_nil_p(r)) return FALSE;
+ if (mrb_type(r) == MRB_TT_FIXNUM) {
+ if (mrb_fixnum(r) == 1) return TRUE;
+ }
- /* mrb_value -> int */
- //c = mrb_cmpint(mrb, r);
- //if (c > 0) return TRUE;
- //return FALSE;
- if (mrb_obj_equal(mrb, r, mrb_fixnum_value(1))) return TRUE;
return FALSE;
}
static int
r_ge(mrb_state *mrb, mrb_value a, mrb_value b)
{
- //int c;
mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
/* output :a < b => -1, a = b => 0, a > b => +1 */
- if (mrb_nil_p(r)) return FALSE;
+ if (mrb_type(r) == MRB_TT_FIXNUM) {
+ int c = mrb_fixnum(r);
+ if (c == 0 || c == 1) return TRUE;
+ }
- /* mrb_value -> int */
- //c = mrb_cmpint(mrb, r);
- //if (c == 0) return TRUE;
- //if (c > 0) return TRUE;
- //return FALSE;
- if (mrb_obj_equal(mrb, r, mrb_fixnum_value(0))) return TRUE;
- if (mrb_obj_equal(mrb, r, mrb_fixnum_value(1))) return TRUE;
return FALSE;
}
@@ -370,7 +332,12 @@ inspect_range(mrb_state *mrb, mrb_value range, mrb_value dummy, int recur)
struct RRange *r = mrb_range_ptr(range);
if (recur) {
- return mrb_str_new2(mrb, r->excl ? "(... ... ...)" : "(... .. ...)");
+ static const char s[2][14] = { "(... ... ...)", "(... .. ...)" };
+ static const int n[] = { 13, 12 };
+ int idx;
+
+ idx = (r->excl) ? 0 : 1;
+ return mrb_str_new(mrb, s[idx], n[idx]);
}
str = mrb_inspect(mrb, r->edges->beg);
str2 = mrb_inspect(mrb, r->edges->end);
@@ -397,23 +364,6 @@ range_inspect(mrb_state *mrb, mrb_value range)
return inspect_range(mrb, range, range, 0);
}
-static mrb_value
-recursive_eql(mrb_state *mrb, mrb_value range, mrb_value obj, int recur)
-{
- struct RRange *r = mrb_range_ptr(range);
- struct RRange *o = mrb_range_ptr(obj);
-
- if (recur) return mrb_true_value(); /* Subtle! */
- 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();
-}
-
/* 15.2.14.4.14(x) */
/*
* call-seq:
@@ -433,13 +383,24 @@ static mrb_value
range_eql(mrb_state *mrb, mrb_value range)
{
mrb_value obj;
+ struct RRange *r, *o;
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();
- return mrb_exec_recursive_paired(mrb, recursive_eql, range, obj, &obj);
+
+ r = mrb_range_ptr(range);
+ if (obj.tt != 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();
}
/* 15.2.14.4.15(x) */
@@ -451,7 +412,6 @@ range_initialize_copy(mrb_state *mrb, mrb_value copy)
mrb_get_args(mrb, "o", &src);
if (mrb_obj_equal(mrb, copy, src)) return copy;
- //mrb_check_frozen(copy);
if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) {
mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
}
diff --git a/src/re.c b/src/re.c
index b4134c81c..0022f9a9c 100644
--- a/src/re.c
+++ b/src/re.c
@@ -13,7 +13,7 @@
#include "regint.h"
#include "mruby/class.h"
#include "error.h"
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
#define REGEX_CLASS (mrb_class_obj_get(mrb, "Regexp"))
#define MATCH_CLASS (mrb_class_obj_get(mrb, "MatchData"))
@@ -26,14 +26,6 @@
#define MKARG_B(c) (((c) & 0xff) << 16)
#define MKARG_C(c) (((c) & 0xff) << 8)
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
#define ARG_REG_OPTION_MASK \
(ONIG_OPTION_IGNORECASE|ONIG_OPTION_MULTILINE|ONIG_OPTION_EXTEND)
#define ARG_ENCODING_FIXED 16
@@ -84,7 +76,7 @@ mrb_reg_s_new_instance(mrb_state *mrb, /*int argc, mrb_value *argv, */mrb_value
re->ptr = 0;
re->src = 0;
re->usecnt = 0;
- return mrb_funcall_argv(mrb, mrb_obj_value(re), "initialize", argc, argv);
+ return mrb_funcall_argv(mrb, mrb_obj_value(re), mrb_intern(mrb, "initialize"), argc, argv);
}
mrb_value
@@ -362,17 +354,17 @@ mrb_reg_options(mrb_state *mrb, mrb_value re)
static mrb_value
mrb_reg_desc(mrb_state *mrb, const char *s, long len, mrb_value re)
{
- mrb_value str = mrb_str_new_cstr(mrb, "/");//mrb_str_buf_new2("/");
+ mrb_value str = mrb_str_new(mrb, "/", 1);
mrb_reg_expr_str(mrb, str, s, len);
- mrb_str_buf_cat(mrb, str, "/", strlen("/"));
+ mrb_str_buf_cat(mrb, str, "/", 1);
if (re.tt) {
char opts[4];
mrb_reg_check(mrb, re);
if (*option_to_str(opts, RREGEXP(re)->ptr->options))
mrb_str_buf_cat(mrb, str, opts, strlen(opts));//mrb_str_buf_cat2(str, opts);
if (RBASIC(re)->flags & REG_ENCODING_NONE)
- mrb_str_buf_cat(mrb, str, "n", strlen("n"));//mrb_str_buf_cat2(str, "n");
+ mrb_str_buf_cat(mrb, str, "n", 1);
}
return str;
@@ -1696,9 +1688,10 @@ mrb_reg_expr_str(mrb_state *mrb, mrb_value str, const char *s, long len)
}
else if (!ISSPACE(c)) {
char b[8];
+ int n;
- snprintf(b, sizeof(b), "\\x%02X", c);
- mrb_str_buf_cat(mrb, str, b, 4);
+ n = snprintf(b, sizeof(b), "\\x%02X", c);
+ mrb_str_buf_cat(mrb, str, b, n);
}
else {
mrb_str_buf_cat(mrb, str, p, 1);
@@ -1736,7 +1729,7 @@ mrb_reg_to_s(mrb_state *mrb, mrb_value re)
const int embeddable = ONIG_OPTION_MULTILINE|ONIG_OPTION_IGNORECASE|ONIG_OPTION_EXTEND;
long len;
const UChar* ptr;
- mrb_value str = mrb_str_new_cstr(mrb, "(?");
+ mrb_value str = mrb_str_new(mrb, "(?", 2);
char optbuf[5];
mrb_encoding *enc = mrb_enc_get(mrb, re);
@@ -1804,9 +1797,9 @@ again:
mrb_str_buf_cat(mrb, str, optbuf, strlen(optbuf));
}
- mrb_str_buf_cat(mrb, str, ":", strlen(":"));
+ mrb_str_buf_cat(mrb, str, ":", 1);
mrb_reg_expr_str(mrb, str, (char*)ptr, len);
- mrb_str_buf_cat(mrb, str, ")", strlen(")"));
+ mrb_str_buf_cat(mrb, str, ")", 1);
return str;
}
@@ -1926,30 +1919,29 @@ mrb_match_inspect(mrb_state *mrb, mrb_value match)
onig_foreach_name(regexp->ptr,
match_inspect_name_iter, names);
- str = mrb_str_new_cstr(mrb, "#<");//mrb_str_buf_new2("#<");
- mrb_str_buf_cat(mrb, str, cname, strlen(cname));//mrb_str_buf_cat2(str, cname);
+ str = mrb_str_new(mrb, "#<", 2);
+ mrb_str_buf_cat(mrb, str, cname, strlen(cname));
for (i = 0; i < num_regs; i++) {
char buf[sizeof(num_regs)*3+1];
mrb_value v;
- mrb_str_buf_cat(mrb, str, " ", strlen(" "));//mrb_str_buf_cat2(str, " ");
+ mrb_str_buf_cat(mrb, str, " ", 1);
if (0 < i) {
if (names[i].name)
mrb_str_buf_cat(mrb, str, (const char*)names[i].name, names[i].len);
else {
- //mrb_str_catf(mrb, str, "%d", i);
- sprintf(buf, "%d", i);
- mrb_str_buf_cat(mrb, str, (const char*)buf, strlen(buf));
+ int n = sprintf(buf, "%d", i);
+ mrb_str_buf_cat(mrb, str, (const char*)buf, n);
}
- mrb_str_buf_cat(mrb, str, ":", strlen(":"));//mrb_str_buf_cat2(str, ":");
+ mrb_str_buf_cat(mrb, str, ":", 1);
}
v = mrb_reg_nth_match(mrb, i, match);
if (mrb_nil_p(v))
- mrb_str_buf_cat(mrb, str, "nil", strlen("nil"));//mrb_str_buf_cat2(str, "nil");
+ mrb_str_buf_cat(mrb, str, "nil", 3);
else
mrb_str_buf_append(mrb, str, mrb_str_inspect(mrb, v));
}
- mrb_str_buf_cat(mrb, str, ">", strlen(">"));//mrb_str_buf_cat2(str, ">");
+ mrb_str_buf_cat(mrb, str, ">", 1);
return str;
}
@@ -2049,7 +2041,7 @@ mrb_init_regexp(mrb_state *mrb)
mrb_define_const(mrb, s, "FIXEDENCODING", mrb_fixnum_value(ARG_ENCODING_FIXED));
s = mrb_define_class(mrb, "MatchData", mrb->object_class);
- //mrb_undef_method(CLASS_OF(rb_cMatch), "new");
+ //mrb_undef_class_method(CLASS_OF(rb_cMatch), "new");
mrb_define_method(mrb, s, "[]", mrb_match_aref, ARGS_ANY()); /* 15.2.16.3.1 */
mrb_define_method(mrb, s, "begin", mrb_match_begin, ARGS_REQ(1)); /* 15.2.16.3.2 */
@@ -2151,7 +2143,7 @@ mrb_reg_regsub(mrb_state *mrb, mrb_value str, mrb_value src, struct re_registers
break;
}
else {
- mrb_raise(mrb, mrb->eRuntimeError_class, "invalid group name reference format");
+ mrb_raise(mrb, E_RUNTIME_ERROR, "invalid group name reference format");
}
}
@@ -2318,7 +2310,7 @@ mrb_backref_set(mrb_state *mrb, mrb_value val)
{
vm_svar_set(mrb, 1, val);
}
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
#ifdef INCLUDE_ENCODING
static inline long
@@ -2421,7 +2413,7 @@ mrb_memsearch(mrb_state *mrb, const void *x0, int m, const void *y0, int n, mrb_
}
#endif //INCLUDE_ENCODING
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
mrb_value
mrb_reg_init_str(mrb_state *mrb, mrb_value re, mrb_value s, int options)
{
@@ -2469,7 +2461,7 @@ re_adjust_startpos(struct re_pattern_buffer *bufp, const char *string, int size,
}*/
return startpos;
}
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
#ifdef INCLUDE_ENCODING
static const unsigned char mbctab_ascii[] = {
diff --git a/src/re.h b/src/re.h
index 238b4e408..91bd1abc1 100644
--- a/src/re.h
+++ b/src/re.h
@@ -13,6 +13,7 @@
#include "node.h"
#include "regex.h"
#include "encoding.h"
+#include "st.h"
#define BEG(no) regs->beg[no]
#define END(no) regs->end[no]
diff --git a/src/regcomp.c b/src/regcomp.c
index 523124b26..b8c652999 100644
--- a/src/regcomp.c
+++ b/src/regcomp.c
@@ -30,7 +30,7 @@
#include "mruby.h"
#include <string.h>
#include "regparse.h"
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
OnigCaseFoldType OnigDefaultCaseFoldFlag = ONIGENC_CASE_FOLD_MIN;
@@ -5628,7 +5628,7 @@ onig_end(void)
THREAD_SYSTEM_END;
return 0;
}
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
#ifdef INCLUDE_ENCODING
extern int
@@ -5653,7 +5653,7 @@ onig_is_in_code_range(const UChar* p, OnigCodePoint code)
}
#endif //INCLUDE_ENCODING
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
extern int
onig_is_code_in_cc_len(int elen, OnigCodePoint code, CClassNode* cc)
{
@@ -6285,4 +6285,4 @@ print_tree(FILE* f, Node* node)
print_indent_tree(f, node, 0);
}
#endif
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
diff --git a/src/regenc.c b/src/regenc.c
index 3764a694f..4cc496782 100644
--- a/src/regenc.c
+++ b/src/regenc.c
@@ -32,14 +32,6 @@
#include <string.h>
#include "regint.h"
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
OnigEncoding OnigEncDefaultCharEncoding = ONIG_ENCODING_INIT_DEFAULT;
extern int
diff --git a/src/regerror.c b/src/regerror.c
index 2ba879f78..df60b49cc 100644
--- a/src/regerror.c
+++ b/src/regerror.c
@@ -28,7 +28,7 @@
*/
#include "mruby.h"
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
#include <string.h>
#include "regint.h"
#include <stdio.h> /* for vsnprintf() */
@@ -372,4 +372,4 @@ onig_snprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc,
pat, pat_end, fmt, args);
va_end(args);
}
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
diff --git a/src/regexec.c b/src/regexec.c
index 4d8950b73..d265cc803 100644
--- a/src/regexec.c
+++ b/src/regexec.c
@@ -28,7 +28,7 @@
*/
#include "mruby.h"
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
#include <string.h>
#include "regint.h"
@@ -3754,4 +3754,4 @@ onig_copy_encoding(OnigEncoding to, OnigEncoding from)
{
*to = *from;
}
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
diff --git a/src/regparse.c b/src/regparse.c
index 509740ac3..f7bb23306 100644
--- a/src/regparse.c
+++ b/src/regparse.c
@@ -32,7 +32,7 @@
#include <string.h>
#include "regparse.h"
#include <stdarg.h>
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
#define WARN_BUFSIZE 256
@@ -298,7 +298,7 @@ strcat_capa_from_static(UChar* dest, UChar* dest_end,
onig_strcpy(r + (dest_end - dest), src, src_end);
return r;
}
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
#ifdef INCLUDE_ENCODING
#ifdef USE_ST_LIBRARY
@@ -393,7 +393,7 @@ onig_st_insert_strend(hash_table_type* table, const UChar* str_key,
#endif /* USE_ST_LIBRARY */
#endif //INCLUDE_ENCODING
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
#ifdef USE_NAMED_GROUP
#define INIT_NAME_BACKREFS_ALLOC_NUM 8
@@ -5597,4 +5597,4 @@ onig_scan_env_set_error_string(ScanEnv* env, int ecode ARG_UNUSED,
env->error = arg;
env->error_end = arg_end;
}
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
diff --git a/src/sprintf.c b/src/sprintf.c
index 79bd101ad..519e40b4b 100644
--- a/src/sprintf.c
+++ b/src/sprintf.c
@@ -5,6 +5,9 @@
*/
#include "mruby.h"
+
+#ifdef ENABLE_SPRINTF
+
#include <stdio.h>
#include <string.h>
#include "encoding.h"
@@ -12,7 +15,6 @@
#include "mruby/hash.h"
#include "mruby/numeric.h"
#include <math.h>
-#include <stdarg.h>
#include <ctype.h>
#ifdef HAVE_IEEEFP_H
@@ -86,7 +88,7 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base)
val &= 0x3ff;
if (val == 0) {
- return mrb_str_new2(mrb, "0");
+ return mrb_str_new(mrb, "0", 1);
}
*--b = '\0';
do {
@@ -142,7 +144,7 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base)
blen += (l);\
} while (0)
-#define GETARG() (!UNDEF_P(nextvalue) ? nextvalue : \
+#define GETARG() (!mrb_undef_p(nextvalue) ? nextvalue : \
posarg == -1 ? \
(mrb_raise(mrb, E_ARGUMENT_ERROR, "unnumbered(%d) mixed with numbered", nextarg), mrb_undef_value()) : \
posarg == -2 ? \
@@ -165,7 +167,7 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base)
(mrb_raise(mrb, E_ARGUMENT_ERROR, "named%.*s after unnumbered(%d)", (len), (name), posarg), mrb_undef_value()) : \
posarg == -1 ? \
(mrb_raise(mrb, E_ARGUMENT_ERROR, "named%.*s after numbered", (len), (name)), mrb_undef_value()) : \
- (posarg = -2, mrb_hash_getWithDef(mrb, get_hash(mrb, &hash, argc, argv), id, mrb_undef_value())))
+ (posarg = -2, mrb_hash_fetch(mrb, get_hash(mrb, &hash, argc, argv), id, mrb_undef_value())))
#define GETNUM(n, val) \
for (; p < end && ISDIGIT(*p); p++) {\
@@ -198,7 +200,7 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv)
{
mrb_value tmp;
- if (!UNDEF_P(*hash)) return *hash;
+ if (!mrb_undef_p(*hash)) return *hash;
if (argc != 2) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "one hash required");
}
@@ -493,7 +495,7 @@ mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt)
char *buf;
long blen, bsiz;
mrb_value result;
-
+ int n;
int width, prec, flags = FNONE;
int nextarg = 1;
int posarg = 0;
@@ -530,7 +532,6 @@ mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt)
for (; p < end; p++) {
const char *t;
- int n;
mrb_sym id = 0;
for (t = p; t < end && *t != '%'; t++) ;
@@ -584,7 +585,7 @@ retry:
n = 0;
GETNUM(n, width);
if (*p == '$') {
- if (!UNDEF_P(nextvalue)) {
+ if (!mrb_undef_p(nextvalue)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "value given twice - %d$", n);
}
nextvalue = GETPOSARG(n);
@@ -610,9 +611,9 @@ retry:
(int)(p - start + 1), start, mrb_sym2name(mrb, id));
}
symname = mrb_str_new(mrb, start + 1, p - start - 1);
- id = mrb_intern(mrb, RSTRING_PTR(symname));
+ id = mrb_intern_str(mrb, symname);
nextvalue = GETNAMEARG(mrb_symbol_value(id), start, (int)(p - start + 1));
- if (UNDEF_P(nextvalue)) {
+ if (mrb_undef_p(nextvalue)) {
mrb_raise(mrb, E_KEY_ERROR, "key%.*s not found", (int)(p - start + 1), start);
}
if (term == '}') goto format_s;
@@ -666,7 +667,6 @@ retry:
mrb_value val = GETARG();
mrb_value tmp;
unsigned int c;
- int n;
tmp = mrb_check_string_type(mrb, val);
if (!mrb_nil_p(tmp)) {
@@ -981,6 +981,7 @@ bin_retry:
fval = mrb_float(mrb_Float(mrb, val));
if (isnan(fval) || isinf(fval)) {
const char *expr;
+ const int elen = 3;
if (isnan(fval)) {
expr = "NaN";
@@ -988,14 +989,14 @@ bin_retry:
else {
expr = "Inf";
}
- need = (int)strlen(expr);
+ need = elen;
if ((!isnan(fval) && fval < 0.0) || (flags & FPLUS))
need++;
if ((flags & FWIDTH) && need < width)
need = width;
CHECK(need + 1);
- snprintf(&buf[blen], need + 1, "%*s", need, "");
+ n = snprintf(&buf[blen], need + 1, "%*s", need, "");
if (flags & FMINUS) {
if (!isnan(fval) && fval < 0.0)
buf[blen++] = '-';
@@ -1003,17 +1004,16 @@ bin_retry:
buf[blen++] = '+';
else if (flags & FSPACE)
blen++;
- memcpy(&buf[blen], expr, strlen(expr));
+ memcpy(&buf[blen], expr, elen);
}
else {
if (!isnan(fval) && fval < 0.0)
- buf[blen + need - strlen(expr) - 1] = '-';
+ buf[blen + need - elen - 1] = '-';
else if (flags & FPLUS)
- buf[blen + need - strlen(expr) - 1] = '+';
+ buf[blen + need - elen - 1] = '+';
else if ((flags & FSPACE) && need > width)
blen++;
- memcpy(&buf[blen + need - strlen(expr)], expr,
- strlen(expr));
+ memcpy(&buf[blen + need - elen], expr, elen);
}
blen += strlen(&buf[blen]);
break;
@@ -1033,8 +1033,8 @@ bin_retry:
need += 20;
CHECK(need);
- snprintf(&buf[blen], need, fbuf, fval);
- blen += strlen(&buf[blen]);
+ n = snprintf(&buf[blen], need, fbuf, fval);
+ blen += n;
}
break;
}
@@ -1058,6 +1058,8 @@ static void
fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec)
{
char *end = buf + size;
+ int n;
+
*buf++ = '%';
if (flags & FSHARP) *buf++ = '#';
if (flags & FPLUS) *buf++ = '+';
@@ -1066,15 +1068,17 @@ fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec)
if (flags & FSPACE) *buf++ = ' ';
if (flags & FWIDTH) {
- snprintf(buf, end - buf, "%d", width);
- buf += strlen(buf);
+ n = snprintf(buf, end - buf, "%d", width);
+ buf += n;
}
if (flags & FPREC) {
- snprintf(buf, end - buf, ".%d", prec);
- buf += strlen(buf);
+ n = snprintf(buf, end - buf, ".%d", prec);
+ buf += n;
}
*buf++ = c;
*buf = '\0';
}
+
+#endif /* ENABLE_SPRINTF */
diff --git a/src/st.c b/src/st.c
index 257da7e2b..c3c20c80a 100644
--- a/src/st.c
+++ b/src/st.c
@@ -24,21 +24,21 @@
static int numcmp(long, long);
static st_index_t numhash(long);
static struct st_hash_type type_numhash = {
- numcmp,
- numhash,
+ (int (*)(ANYARGS))numcmp,
+ (st_index_t (*)(ANYARGS))numhash,
};
/* extern int strcmp(const char *, const char *); */
static st_index_t strhash(const char*);
static struct st_hash_type type_strhash = {
- strcmp,
- strhash,
+ (int (*)(ANYARGS))strcmp,
+ (st_index_t (*)(ANYARGS))strhash,
};
static st_index_t strcasehash(st_data_t);
static const struct st_hash_type type_strcasehash = {
- st_strcasecmp,
- strcasehash,
+ (int (*)(ANYARGS))st_strcasecmp,
+ (st_index_t (*)(ANYARGS))strcasehash,
};
static void rehash(st_table*);
diff --git a/src/state.c b/src/state.c
index b3946bad9..26e7dff4a 100644
--- a/src/state.c
+++ b/src/state.c
@@ -15,7 +15,8 @@ void mrb_init_ext(mrb_state*);
mrb_state*
mrb_open_allocf(mrb_allocf f)
{
- mrb_state *mrb = (f)(NULL, NULL, sizeof(mrb_state));
+ mrb_state *mrb = (mrb_state *)(f)(NULL, NULL, sizeof(mrb_state));
+ if (mrb == NULL) return NULL;
memset(mrb, 0, sizeof(mrb_state));
mrb->allocf = f;
@@ -75,14 +76,14 @@ mrb_add_irep(mrb_state *mrb, int idx)
int max = 256;
if (idx > max) max = idx+1;
- mrb->irep = mrb_malloc(mrb, sizeof(mrb_irep*)*max);
+ mrb->irep = (mrb_irep **)mrb_calloc(mrb, max, sizeof(mrb_irep*));
mrb->irep_capa = max;
}
else if (mrb->irep_capa <= idx) {
while (mrb->irep_capa <= idx) {
mrb->irep_capa *= 2;
}
- mrb->irep = mrb_realloc(mrb, mrb->irep, sizeof(mrb_irep)*mrb->irep_capa);
+ mrb->irep = (mrb_irep **)mrb_realloc(mrb, mrb->irep, sizeof(mrb_irep*)*mrb->irep_capa);
}
}
diff --git a/src/string.c b/src/string.c
index 26ed7b052..aef0ac88f 100644
--- a/src/string.c
+++ b/src/string.c
@@ -10,56 +10,65 @@
#include <string.h>
#include "mruby/string.h"
#include <ctype.h>
-#include "mruby/numeric.h"
+#include <limits.h>
#include "mruby/range.h"
#include "mruby/array.h"
#include "mruby/class.h"
-#include "mruby/variable.h"
#include <stdio.h>
+#ifdef ENABLE_REGEXP
#include "re.h"
-#ifdef INCLUDE_REGEXP
#include "regex.h"
-#include "st.h"
-#endif //INCLUDE_REGEXP
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
+#endif //ENABLE_REGEXP
const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
static mrb_value get_pat(mrb_state *mrb, mrb_value pat, mrb_int quote);
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
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, long beg, long len);
+static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len);
#define RESIZE_CAPA(s,capacity) do {\
- s->buf = mrb_realloc(mrb, s->buf, (capacity)+1);\
+ s->ptr = (char *)mrb_realloc(mrb, s->ptr, (capacity)+1);\
s->aux.capa = capacity;\
} while (0)
+void
+mrb_str_decref(mrb_state *mrb, struct mrb_shared_string *shared)
+{
+ shared->refcnt--;
+ if (shared->refcnt == 0) {
+ mrb_free(mrb, shared->ptr);
+ mrb_free(mrb, shared);
+ }
+}
+
static void
str_modify(mrb_state *mrb, struct RString *s)
{
if (s->flags & MRB_STR_SHARED) {
- char *ptr, *p;
- long len;
+ struct mrb_shared_string *shared = s->aux.shared;
- p = s->buf;
- len = s->len;
- ptr = mrb_malloc(mrb, sizeof(char)*(len+1));
- if (p) {
- memcpy(ptr, p, len);
+ if (shared->refcnt == 1 && s->ptr == shared->ptr) {
+ s->ptr = shared->ptr;
+ s->aux.capa = shared->len;
+ mrb_free(mrb, shared);
+ }
+ else {
+ char *ptr, *p;
+ long len;
+
+ p = s->ptr;
+ len = s->len;
+ ptr = (char *)mrb_malloc(mrb, len+1);
+ if (p) {
+ memcpy(ptr, p, len);
+ }
+ ptr[len] = 0;
+ s->ptr = ptr;
+ s->aux.capa = len;
+ mrb_str_decref(mrb, shared);
}
- ptr[len] = 0;
- s->buf = ptr;
- s->len = len;
- s->aux.capa = len;
s->flags &= ~MRB_STR_SHARED;
}
}
@@ -74,13 +83,11 @@ mrb_str_resize(mrb_state *mrb, mrb_value str, int len)
slen = s->len;
if (len != slen) {
if (slen < len || slen -len > 1024) {
- s->buf = mrb_realloc(mrb, s->buf, len+1);
- }
- if (!(s->flags & MRB_STR_SHARED)) {
- s->aux.capa = len;
+ s->ptr = (char *)mrb_realloc(mrb, s->ptr, len+1);
}
+ s->aux.capa = len;
s->len = len;
- s->buf[len] = '\0'; /* sentinel */
+ s->ptr[len] = '\0'; /* sentinel */
}
return str;
}
@@ -90,8 +97,8 @@ str_mod_check(mrb_state *mrb, mrb_value str, char *p, mrb_int len)
{
struct RString *s = mrb_str_ptr(str);
- if (s->buf != p || s->len != len) {
- mrb_raise(mrb, mrb->eRuntimeError_class, "string modified");
+ if (s->ptr != p || s->len != len) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "string modified");
}
}
@@ -105,7 +112,7 @@ str_alloc(mrb_state *mrb, struct RClass *c)
s = mrb_obj_alloc_string(mrb);
s->c = c;
- s->buf = 0;
+ s->ptr = 0;
s->len = 0;
s->aux.capa = 0;
@@ -126,11 +133,11 @@ str_new(mrb_state *mrb, const char *p, int len)
s->len = len;
s->aux.capa = len;
- s->buf = mrb_malloc(mrb, len+1);
+ s->ptr = (char *)mrb_malloc(mrb, len+1);
if (p) {
- memcpy(s->buf, p, len);
+ memcpy(s->ptr, p, len);
}
- s->buf[len] = '\0';
+ s->ptr[len] = '\0';
return s;
}
@@ -161,8 +168,8 @@ mrb_str_buf_new(mrb_state *mrb, int capa)
}
s->len = 0;
s->aux.capa = capa;
- s->buf = mrb_malloc(mrb, capa+1);
- s->buf[0] = '\0';
+ s->ptr = (char *)mrb_malloc(mrb, capa+1);
+ s->ptr[0] = '\0';
return mrb_obj_value(s);
}
@@ -173,18 +180,18 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len)
long capa, total, off = -1;
str_modify(mrb, s);
- if (ptr >= s->buf && ptr <= s->buf + s->len) {
- off = ptr - s->buf;
+ if (ptr >= s->ptr && ptr <= s->ptr + s->len) {
+ off = ptr - s->ptr;
}
if (len == 0) return;
capa = s->aux.capa;
- if (s->len >= LONG_MAX - len) {
+ if (s->len >= 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 >= LONG_MAX / 2) {
+ if (capa + 1 >= INT_MAX / 2) {
capa = (total + 4095) / 4096;
break;
}
@@ -193,11 +200,11 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len)
RESIZE_CAPA(s, capa);
}
if (off != -1) {
- ptr = s->buf + off;
+ ptr = s->ptr + off;
}
- memcpy(s->buf + s->len, ptr, len);
+ memcpy(s->ptr + s->len, ptr, len);
s->len = total;
- s->buf[total] = '\0'; /* sentinel */
+ s->ptr[total] = '\0'; /* sentinel */
}
mrb_value
@@ -211,7 +218,9 @@ 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)
{
- struct RString *s = str_new(mrb, p, len);
+ struct RString *s;
+
+ s = str_new(mrb, p, len);
return mrb_obj_value(s);
}
@@ -240,39 +249,32 @@ mrb_str_new_cstr(mrb_state *mrb, const char *p)
int len = strlen(p);
s = mrb_obj_alloc_string(mrb);
- s->buf = mrb_malloc(mrb, len+1);
- memcpy(s->buf, p, len);
- s->buf[len] = 0;
+ s->ptr = (char *)mrb_malloc(mrb, len+1);
+ memcpy(s->ptr, p, len);
+ s->ptr[len] = 0;
s->len = len;
s->aux.capa = len;
return mrb_obj_value(s);
}
-static struct RString*
-str_make_shared(mrb_state *mrb, mrb_value str)
+static void
+str_make_shared(mrb_state *mrb, struct RString *s)
{
- struct RString *orig, *s;
+ if (!(s->flags & MRB_STR_SHARED)) {
+ struct mrb_shared_string *shared = (struct mrb_shared_string *)mrb_malloc(mrb, sizeof(struct mrb_shared_string));
- s = str_new(mrb, 0, 0);
- str_with_class(mrb, s, str);
- orig = mrb_str_ptr(str);
- if (!(orig->flags & MRB_STR_SHARED)) {
- struct RString *shared = mrb_obj_alloc_string(mrb);
-
- shared->buf = orig->buf;
- shared->len = orig->len;
- shared->aux.capa = orig->aux.capa;
-
- orig->aux.shared = shared;
- orig->flags |= MRB_STR_SHARED;
+ shared->refcnt = 1;
+ if (s->aux.capa > s->len) {
+ s->ptr = shared->ptr = (char *)mrb_realloc(mrb, s->ptr, s->len+1);
+ }
+ else {
+ shared->ptr = s->ptr;
+ }
+ shared->len = s->len;
+ s->aux.shared = shared;
+ s->flags |= MRB_STR_SHARED;
}
- s->buf = orig->buf;
- s->len = orig->len;
- s->aux.shared = orig->aux.shared;
- s->flags |= MRB_STR_SHARED;
-
- return s;
}
/*
@@ -285,16 +287,19 @@ str_make_shared(mrb_state *mrb, mrb_value str)
mrb_value
mrb_str_literal(mrb_state *mrb, mrb_value str)
{
- struct RString *orig, *s;
+ struct RString *s, *orig;
+ struct mrb_shared_string *shared;
- s = str_new(mrb, 0, 0);
+ s = str_alloc(mrb, mrb->string_class);
orig = mrb_str_ptr(str);
- while (orig->flags & MRB_STR_SHARED) {
- orig = orig->aux.shared;
+ if (!(orig->flags & MRB_STR_SHARED)) {
+ str_make_shared(mrb, mrb_str_ptr(str));
}
- s->buf = orig->buf;
- s->len = orig->len;
- s->aux.shared = orig;
+ shared = orig->aux.shared;
+ shared->refcnt++;
+ s->ptr = shared->ptr;
+ s->len = shared->len;
+ s->aux.shared = shared;
s->flags |= MRB_STR_SHARED;
return mrb_obj_value(s);
@@ -312,7 +317,7 @@ mrb_str_body(mrb_value str, int *len_p)
struct RString *s = mrb_str_ptr(str);
*len_p = s->len;
- return s->buf;
+ return s->ptr;
}
/*
@@ -336,11 +341,11 @@ mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other)
if (s1->aux.capa < len) {
s1->aux.capa = len;
- s1->buf = mrb_realloc(mrb, s1->buf, len+1);
+ s1->ptr = (char *)mrb_realloc(mrb, s1->ptr, len+1);
}
- memcpy(s1->buf+s1->len, s2->buf, s2->len);
+ memcpy(s1->ptr+s1->len, s2->ptr, s2->len);
s1->len = len;
- s1->buf[len] = 0;
+ s1->ptr[len] = 0;
}
/*
@@ -357,8 +362,8 @@ mrb_str_plus(mrb_state *mrb, mrb_value a, mrb_value b)
struct RString *t;
t = str_new(mrb, 0, s->len + s2->len);
- memcpy(t->buf, s->buf, s->len);
- memcpy(t->buf + s->len, s2->buf, s2->len);
+ memcpy(t->ptr, s->ptr, s->len);
+ memcpy(t->ptr + s->len, s2->ptr, s2->len);
return mrb_obj_value(t);
}
@@ -426,14 +431,14 @@ mrb_str_times(mrb_state *mrb, mrb_value self)
if (times < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument");
}
- if (times && INT32_MAX/times < RSTRING_LEN(self)) {
+ if (times && INT_MAX/times < RSTRING_LEN(self)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "argument too big");
}
len = RSTRING_LEN(self)*times;
str2 = str_new(mrb, 0, len);
str_with_class(mrb, str2, self);
- p = str2->buf;
+ p = str2->ptr;
if (len > 0) {
n = RSTRING_LEN(self);
memcpy(p, RSTRING_PTR(self), n);
@@ -468,7 +473,7 @@ mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2)
struct RString *s2 = mrb_str_ptr(str2);
len = lesser(s1->len, s2->len);
- retval = memcmp(s1->buf, s2->buf, len);
+ retval = memcmp(s1->ptr, s2->ptr, len);
if (retval == 0) {
if (s1->len == s2->len) return 0;
if (s1->len > s2->len) return 1;
@@ -659,7 +664,7 @@ mrb_memsearch_qs(const unsigned char *xs, long m, const unsigned char *ys, long
static int
mrb_memsearch(const void *x0, int m, const void *y0, int n)
{
- const unsigned char *x = x0, *y = y0;
+ const unsigned char *x = (const unsigned char *)x0, *y = (const unsigned char *)y0;
if (m > n) return -1;
else if (m == n) {
@@ -676,7 +681,7 @@ mrb_memsearch(const void *x0, int m, const void *y0, int n)
}
return -1;
}
- return mrb_memsearch_qs(x0, m, y0, n);
+ return mrb_memsearch_qs((const unsigned char *)x0, m, (const unsigned char *)y0, n);
}
static mrb_int
@@ -712,7 +717,7 @@ mrb_str_dup(mrb_state *mrb, mrb_value str)
/* should return shared string */
struct RString *s = mrb_str_ptr(str);
- return mrb_str_new(mrb, s->buf, s->len);
+ return mrb_str_new(mrb, s->ptr, s->len);
}
static mrb_value
@@ -730,12 +735,12 @@ num_index:
return str;
case MRB_TT_REGEX:
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
return mrb_str_subpat(mrb, str, indx, 0); //mrb_str_subpat(str, indx, INT2FIX(0));
#else
mrb_raise(mrb, E_TYPE_ERROR, "Regexp Class not supported");
return mrb_nil_value();
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
case MRB_TT_STRING:
if (mrb_str_index(mrb, str, indx, 0) != -1)
@@ -750,7 +755,7 @@ num_index:
len = RSTRING_LEN(str);
switch (mrb_range_beg_len(mrb, indx, &beg, &len, len, 0)) {
- case 0/*FLASE*/:
+ case FALSE:
break;
case 2/*OTHER*/:
return mrb_nil_value();
@@ -822,12 +827,12 @@ mrb_str_aref_m(mrb_state *mrb, mrb_value str)
argc = mrb_get_args(mrb, "o|o", &a1, &a2);
if (argc == 2) {
if (mrb_type(a1) == MRB_TT_REGEX) {
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
return mrb_str_subpat(mrb, str, argv[0], mrb_fixnum(argv[1]));
#else
mrb_raise(mrb, E_TYPE_ERROR, "Regexp Class not supported");
return mrb_nil_value();
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
}
return mrb_str_substr(mrb, str, mrb_fixnum(a1), mrb_fixnum(a2));
}
@@ -858,8 +863,8 @@ mrb_str_capitalize_bang(mrb_state *mrb, mrb_value str)
struct RString *s = mrb_str_ptr(str);
str_modify(mrb, s);
- if (s->len == 0 || !s->buf) return mrb_nil_value();
- p = s->buf; pend = s->buf + s->len;
+ if (s->len == 0 || !s->ptr) return mrb_nil_value();
+ p = s->ptr; pend = s->ptr + s->len;
if (ISLOWER(*p)) {
*p = toupper(*p);
modify = 1;
@@ -918,14 +923,14 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str)
if (mrb_get_args(mrb, "|S", &rs) == 0) {
if (len == 0) return mrb_nil_value();
smart_chomp:
- if (s->buf[len-1] == '\n') {
+ if (s->ptr[len-1] == '\n') {
s->len--;
if (s->len > 0 &&
- s->buf[s->len-1] == '\r') {
+ s->ptr[s->len-1] == '\r') {
s->len--;
}
}
- else if (s->buf[len-1] == '\r') {
+ else if (s->ptr[len-1] == '\r') {
s->len--;
}
else {
@@ -935,7 +940,7 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str)
}
if (len == 0 || mrb_nil_p(rs)) return mrb_nil_value();
- p = s->buf;
+ p = s->ptr;
rslen = RSTRING_LEN(rs);
if (rslen == 0) {
while (len>0 && p[len-1] == '\n') {
@@ -1015,14 +1020,14 @@ mrb_str_chop_bang(mrb_state *mrb, mrb_value str)
if (s->len > 0) {
int len;
len = s->len - 1;
- if (s->buf[len] == '\n') {
+ if (s->ptr[len] == '\n') {
if (len > 0 &&
- s->buf[len-1] == '\r') {
+ s->ptr[len-1] == '\r') {
len--;
}
}
s->len = len;
- s->buf[len] = '\0';
+ s->ptr[len] = '\0';
return str;
}
return mrb_nil_value();
@@ -1070,8 +1075,8 @@ mrb_str_downcase_bang(mrb_state *mrb, mrb_value str)
struct RString *s = mrb_str_ptr(str);
str_modify(mrb, s);
- p = s->buf;
- pend = s->buf + s->len;
+ p = s->ptr;
+ pend = s->ptr + s->len;
while (p < pend) {
if (ISUPPER(*p)) {
*p = tolower(*p);
@@ -1184,13 +1189,20 @@ mrb_str_eql(mrb_state *mrb, mrb_value self)
}
static mrb_value
-mrb_str_subseq(mrb_state *mrb, mrb_value str, long beg, long len)
+mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len)
{
- struct RString *s;
+ struct RString *orig, *s;
+ struct mrb_shared_string *shared;
- s = str_make_shared(mrb, str);
- s->buf += beg;
+ orig = mrb_str_ptr(str);
+ str_make_shared(mrb, orig);
+ shared = orig->aux.shared;
+ s = mrb_obj_alloc_string(mrb);
+ s->ptr = orig->ptr + beg;
s->len = len;
+ s->aux.shared = shared;
+ s->flags |= MRB_STR_SHARED;
+ shared->refcnt++;
return mrb_obj_value(s);
}
@@ -1226,7 +1238,7 @@ mrb_str_buf_append(mrb_state *mrb, mrb_value str, mrb_value str2)
return str;
}
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
static mrb_value
str_gsub(mrb_state *mrb, mrb_value str, mrb_int bang)
{
@@ -1342,7 +1354,6 @@ str_gsub(mrb_state *mrb, mrb_value str, mrb_int bang)
static mrb_value
mrb_str_gsub(mrb_state *mrb, mrb_value self)
{
- //return str_gsub(argc, argv, self, 0);
return str_gsub(mrb, self, 0);
}
@@ -1363,7 +1374,7 @@ mrb_str_gsub_bang(mrb_state *mrb, mrb_value self)
str_modify(mrb, s);
return str_gsub(mrb, s, 1);
}
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
mrb_int
mrb_str_hash(mrb_state *mrb, mrb_value str)
@@ -1371,7 +1382,7 @@ mrb_str_hash(mrb_state *mrb, mrb_value str)
/* 1-8-7 */
struct RString *s = mrb_str_ptr(str);
long len = s->len;
- char *p = s->buf;
+ char *p = s->ptr;
mrb_int key = 0;
while (len--) {
@@ -1457,10 +1468,8 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
int argc;
mrb_value sub;
- //mrb_value initpos;
mrb_int pos;
- //if (mrb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
mrb_get_args(mrb, "*", &argv, &argc);
if (argc == 2) {
pos = mrb_fixnum(argv[1]);
@@ -1486,7 +1495,7 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
switch (mrb_type(sub)) {
case MRB_TT_REGEX:
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
if (pos > RSTRING_LEN(str))
return mrb_nil_value();
pos = mrb_str_offset(mrb, str, pos);
@@ -1494,7 +1503,7 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
pos = mrb_str_sublen(mrb, str, pos);
#else
mrb_raise(mrb, E_TYPE_ERROR, "Regexp Class not supported");
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
break;
case MRB_TT_FIXNUM: {
@@ -1528,16 +1537,43 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
return mrb_fixnum_value(pos);
}
+#define STR_REPLACE_SHARED_MIN 10
+
static mrb_value
str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
{
- int len = s2->len;
-
- str_modify(mrb, s1);
- s1->buf = mrb_realloc(mrb, s1->buf, len);
- memcpy(s1->buf, s2->buf, len);
- s1->len = s2->len;
- s2->aux.capa = s2->len;
+ if (s2->flags & MRB_STR_SHARED) {
+ L_SHARE:
+ if (s1->flags & MRB_STR_SHARED){
+ mrb_str_decref(mrb, s1->aux.shared);
+ }
+ else {
+ mrb_free(mrb, s1->ptr);
+ }
+ s1->ptr = s2->ptr;
+ s1->len = s2->len;
+ s1->aux.shared = s2->aux.shared;
+ s1->flags |= MRB_STR_SHARED;
+ s1->aux.shared->refcnt++;
+ }
+ else if (s2->len > STR_REPLACE_SHARED_MIN) {
+ str_make_shared(mrb, s2);
+ goto L_SHARE;
+ }
+ else {
+ if (s1->flags & MRB_STR_SHARED) {
+ mrb_str_decref(mrb, s1->aux.shared);
+ s1->flags &= ~MRB_STR_SHARED;
+ s1->ptr = (char *)mrb_malloc(mrb, s2->len+1);
+ }
+ else {
+ s1->ptr = (char *)mrb_realloc(mrb, s1->ptr, s2->len+1);
+ }
+ memcpy(s1->ptr, s2->ptr, s2->len);
+ s1->ptr[s2->len] = 0;
+ s1->len = s2->len;
+ s1->aux.capa = s2->len;
+ }
return mrb_obj_value(s1);
}
@@ -1577,12 +1613,6 @@ mrb_str_init(mrb_state *mrb, mrb_value self)
return self;
}
-mrb_sym
-mrb_intern_str(mrb_state *mrb, mrb_value str)
-{
- return mrb_intern(mrb, RSTRING_PTR(str));
-}
-
/* 15.2.10.5.25 */
/* 15.2.10.5.41 */
/*
@@ -1635,7 +1665,7 @@ mrb_check_string_type(mrb_state *mrb, mrb_value str)
return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
}
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
static mrb_value
get_pat(mrb_state *mrb, mrb_value pat, mrb_int quote)
{
@@ -1663,7 +1693,7 @@ get_pat(mrb_state *mrb, mrb_value pat, mrb_int quote)
return mrb_reg_regcomp(mrb, pat);
}
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
/* 15.2.10.5.27 */
/*
@@ -1678,7 +1708,7 @@ get_pat(mrb_state *mrb, mrb_value pat, mrb_int quote)
* 'hello'.match(/(.)\1/)[0] #=> "ll"
* 'hello'.match('xx') #=> nil
*/
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
static mrb_value
mrb_str_match_m(mrb_state *mrb, mrb_value self)
{
@@ -1698,7 +1728,7 @@ mrb_str_match_m(mrb_state *mrb, mrb_value self)
}
return result;
}
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
/* ---------------------------------- */
/* 15.2.10.5.29 */
@@ -1721,7 +1751,7 @@ mrb_str_reverse(mrb_state *mrb, mrb_value str)
s2 = str_new(mrb, 0, RSTRING(str)->len);
str_with_class(mrb, s2, str);
s = RSTRING_PTR(str); e = RSTRING_END(str) - 1;
- p = s2->buf;
+ p = s2->ptr;
while (e >= s) {
*p++ = *e--;
@@ -1745,7 +1775,7 @@ mrb_str_reverse_bang(mrb_state *mrb, mrb_value str)
str_modify(mrb, s);
if (s->len > 1) {
- p = s->buf;
+ p = s->ptr;
e = p + s->len - 1;
while (p < e) {
c = *p;
@@ -1787,13 +1817,13 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
if (ps->len - pos < len) {
pos = ps->len - len;
}
- sbeg = ps->buf;
- s = ps->buf + pos;
- t = psub->buf;
+ sbeg = ps->ptr;
+ s = ps->ptr + pos;
+ t = psub->ptr;
if (len) {
while (sbeg <= s) {
if (memcmp(s, t, len) == 0) {
- return s - ps->buf;
+ return s - ps->ptr;
}
s--;
}
@@ -1850,11 +1880,11 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
pos += len;
if (pos < 0) {
if (mrb_type(sub) == MRB_TT_REGEX) {
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
mrb_backref_set(mrb, mrb_nil_value());
#else
mrb_raise(mrb, E_TYPE_ERROR, "Regexp Class not supported");
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
}
return mrb_nil_value();
}
@@ -1871,7 +1901,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
switch (mrb_type(sub)) {
case MRB_TT_REGEX:
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
pos = mrb_str_offset(mrb, str, pos);
if (!RREGEXP(sub)->ptr || RREGEXP_SRC_LEN(sub)) {
pos = mrb_reg_search(mrb, sub, str, pos, 1);
@@ -1880,7 +1910,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
if (pos >= 0) return mrb_fixnum_value(pos);
#else
mrb_raise(mrb, E_TYPE_ERROR, "Regexp Class not supported");
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
break;
case MRB_TT_FIXNUM: {
@@ -1914,7 +1944,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
return mrb_nil_value();
}
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
static mrb_value
scan_once(mrb_state *mrb, mrb_value str, mrb_value pat, mrb_int *start)
{
@@ -1926,7 +1956,6 @@ scan_once(mrb_state *mrb, mrb_value str, mrb_value pat, mrb_int *start)
if (mrb_reg_search(mrb, pat, str, *start, 0) >= 0) {
match = mrb_backref_get(mrb);
- //regs = RMATCH(match)->regs;
pmatch = mrb_match_ptr(match);
regs = &pmatch->rmatch->regs;
if (regs->beg[0] == regs->end[0]) {
@@ -1944,7 +1973,7 @@ scan_once(mrb_state *mrb, mrb_value str, mrb_value pat, mrb_int *start)
if (regs->num_regs == 1) {
return mrb_reg_nth_match(mrb, 0, match);
}
- result = mrb_ary_new_capa(mrb, regs->num_regs);//mrb_ary_new2(regs->num_regs);
+ result = mrb_ary_new_capa(mrb, regs->num_regs);
for (i=1; i < regs->num_regs; i++) {
mrb_ary_push(mrb, result, mrb_reg_nth_match(mrb, i, match));
}
@@ -1953,7 +1982,7 @@ scan_once(mrb_state *mrb, mrb_value str, mrb_value pat, mrb_int *start)
}
return mrb_nil_value();
}
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
/* 15.2.10.5.32 */
/*
@@ -1986,7 +2015,7 @@ scan_once(mrb_state *mrb, mrb_value str, mrb_value pat, mrb_int *start)
* <<cruel>> <<world>>
* rceu lowlr
*/
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
static mrb_value
mrb_str_scan(mrb_state *mrb, mrb_value str)
{
@@ -1995,7 +2024,7 @@ mrb_str_scan(mrb_state *mrb, mrb_value str)
mrb_int start = 0;
mrb_value match = mrb_nil_value();
struct RString *ps = mrb_str_ptr(str);
- char *p = ps->buf;
+ char *p = ps->ptr;
long len = ps->len;
mrb_get_args(mrb, "o&", &pat, &b);
@@ -2020,7 +2049,7 @@ mrb_str_scan(mrb_state *mrb, mrb_value str)
mrb_backref_set(mrb, match);
return str;
}
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
static const char isspacetable[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
@@ -2089,27 +2118,16 @@ static const char isspacetable[256] = {
static mrb_value
mrb_str_split_m(mrb_state *mrb, mrb_value str)
{
- mrb_value *argv;
int argc;
mrb_value spat = mrb_nil_value();
- mrb_value limit;
enum {awk, string, regexp} split_type = string;
long beg, end, i = 0;
- int lim = 0;
+ int lim = -1;
mrb_value result, tmp;
- mrb_get_args(mrb, "*", &argv, &argc);
- if (argc > 0)
- spat = argv[0];
- if (argc > 1)
- limit = argv[1];
- else
- limit = mrb_nil_value();
-
+ argc = mrb_get_args(mrb, "|oi", &spat, &lim);
if (argc == 2) {
- lim = mrb_fixnum(limit);
- if (lim <= 0) limit = mrb_nil_value();
- else if (lim == 1) {
+ if (lim == 1) {
if (RSTRING_LEN(str) == 0)
return mrb_ary_new_capa(mrb, 0);
return mrb_ary_new_from_values(mrb, 1, &str);
@@ -2117,35 +2135,34 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
i = 1;
}
- if (argc == 0) {
+ if (argc == 0 || mrb_nil_p(spat)) {
split_type = awk;
}
else {
-//fs_set:
if (mrb_type(spat) == MRB_TT_STRING) {
split_type = string;
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
if (RSTRING_LEN(spat) == 0) {
/* Special case - split into chars */
spat = mrb_reg_regcomp(mrb, spat);
split_type = regexp;
}
else {
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' '){
split_type = awk;
}
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
}
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
}
else {
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
spat = get_pat(mrb, spat, 1);
split_type = regexp;
#else
mrb_raise(mrb, E_TYPE_ERROR, "Regexp Class not supported");
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
}
}
@@ -2168,22 +2185,47 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
else {
end = ptr - bptr;
skip = 0;
- if (!mrb_nil_p(limit) && lim <= i) break;
+ if (lim >= 0 && lim <= i) break;
}
}
else if (ascii_isspace(c)) {
mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, beg, end-beg));
skip = 1;
beg = ptr - bptr;
- if (!mrb_nil_p(limit)) ++i;
+ if (lim >= 0) ++i;
}
else {
end = ptr - bptr;
}
}
}
+ else if (split_type == string) {
+ char *ptr = RSTRING_PTR(str);
+ char *temp = ptr;
+ char *eptr = RSTRING_END(str);
+ long slen = RSTRING_LEN(spat);
+
+ if (slen == 0) {
+ while (ptr < eptr) {
+ mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, ptr-temp, 1));
+ ptr++;
+ if (lim >= 0 && lim <= ++i) break;
+ }
+ }
+ else {
+ char *sptr = RSTRING_PTR(spat);
+
+ while (ptr < eptr &&
+ (end = mrb_memsearch(sptr, slen, ptr, eptr - ptr)) >= 0) {
+ mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, ptr - temp, end));
+ ptr += end + slen;
+ if (lim >= 0 && lim <= ++i) break;
+ }
+ }
+ beg = ptr - temp;
+ }
else {
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
char *ptr = RSTRING_PTR(str);
long len = RSTRING_LEN(str);
long start = beg;
@@ -2225,20 +2267,20 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
tmp = mrb_str_subseq(mrb, str, BEG(idx), END(idx)-BEG(idx));
mrb_ary_push(mrb, result, tmp);
}
- if (!mrb_nil_p(limit) && lim <= ++i) break;
+ if (lim >= 0 && lim <= ++i) break;
}
#else
mrb_raise(mrb, E_TYPE_ERROR, "Regexp Class not supported");
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
}
- if (RSTRING_LEN(str) > 0 && (!mrb_nil_p(limit) || RSTRING_LEN(str) > beg || lim < 0)) {
+ if (RSTRING_LEN(str) > 0 && (lim >= 0 || RSTRING_LEN(str) > beg || lim < 0)) {
if (RSTRING_LEN(str) == beg)
tmp = mrb_str_new_empty(mrb, str);
else
tmp = mrb_str_subseq(mrb, str, beg, RSTRING_LEN(str)-beg);
mrb_ary_push(mrb, result, tmp);
}
- if (mrb_nil_p(limit) && lim == 0) {
+ if (lim < 0) {
long len;
while ((len = RARRAY_LEN(result)) > 0 &&
(tmp = RARRAY_PTR(result)[len-1], RSTRING_LEN(tmp) == 0))
@@ -2267,14 +2309,14 @@ mrb_block_given_p()
* returning <i>str</i>, or <code>nil</code> if no substitutions were
* performed.
*/
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
static mrb_value
mrb_str_sub_bang(mrb_state *mrb, mrb_value str)
{
str_modify(mrb, str);
return mrb_nil_value();
}
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
/* 15.2.10.5.36 */
@@ -2315,7 +2357,7 @@ mrb_str_sub_bang(mrb_state *mrb, mrb_value str)
* #=> "Is /bin/bash your preferred shell?"
*/
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
static mrb_value
mrb_str_sub(mrb_state *mrb, mrb_value self)
{
@@ -2324,7 +2366,7 @@ mrb_str_sub(mrb_state *mrb, mrb_value self)
mrb_str_sub_bang(mrb, str);
return str;
}
-#endif //INCLUDE_REGEXP
+#endif //ENABLE_REGEXP
mrb_value
mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
@@ -2332,17 +2374,10 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
#define BDIGIT unsigned int
#define BDIGIT_DBL unsigned long
-// const char *s = str;
char *end;
char sign = 1;
-// char nondigit = 0;
int c;
-// BDIGIT_DBL num;
long len;
-// long blen = 1;
-// long i;
-// mrb_value z;
-// BDIGIT *zds;
unsigned long val;
#undef ISDIGIT
@@ -2459,28 +2494,30 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
}
len *= strlen(str)*sizeof(char);
- val = strtoul((char*)str, &end, base);
+ val = strtoul((char*)str, &end, base);
- if (badcheck) {
- if (end == str) goto bad; /* no number */
- while (*end && ISSPACE(*end)) end++;
- if (*end) goto bad; /* trailing garbage */
- }
+ 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);
- }
+ if (sign) return mrb_fixnum_value(val);
+ else {
+ long result = -(long)val;
+ return mrb_fixnum_value(result);
+ }
bad:
- printf("Integer");
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "invalide string for number(%s)", str);
+ /* not reached */
return mrb_fixnum_value(0);
}
+
char *
mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr)
{
struct RString *ps = mrb_str_ptr(*ptr);
- char *s = ps->buf;
+ char *s = ps->ptr;
if (!s || ps->len != strlen(s)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
@@ -2494,10 +2531,8 @@ mrb_str_to_inum(mrb_state *mrb, mrb_value str, int base, int badcheck)
char *s;
int len;
- //StringValue(str);
mrb_string_value(mrb, &str);
if (badcheck) {
- //s = StringValueCStr(str);
s = mrb_string_value_cstr(mrb, &str);
}
else {
@@ -2506,8 +2541,7 @@ mrb_str_to_inum(mrb_state *mrb, mrb_value str, int base, int badcheck)
if (s) {
len = RSTRING_LEN(str);
if (s[len]) { /* no sentinel somehow */
- //char *p = ALLOCA_N(char, len+1);
- char *p = mrb_malloc(mrb, len+1);
+ char *p = (char *)mrb_malloc(mrb, len+1);
//MEMCPY(p, s, char, len);
memcpy(p, s, sizeof(char)*len);
@@ -2544,10 +2578,8 @@ mrb_str_to_i(mrb_state *mrb, mrb_value self)
{
mrb_value *argv;
int argc;
- //mrb_value b;
int base;
- //mrb_scan_args(argc, *argv, "01", &b);
mrb_get_args(mrb, "*", &argv, &argc);
if (argc == 0)
base = 10;
@@ -2583,8 +2615,8 @@ mrb_cstr_to_dbl(mrb_state *mrb, const char * p, int badcheck)
if (p == end) {
if (badcheck) {
bad:
- //mrb_invalid_str(q, "Float()");
- printf("Float()\n");
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "invalide string for float(%s)", p);
+ /* not reached */
}
return d;
}
@@ -2643,7 +2675,7 @@ mrb_str_to_dbl(mrb_state *mrb, mrb_value str, int badcheck)
mrb_raise(mrb, E_ARGUMENT_ERROR, "string for Float contains null byte");
}
if (s[len]) { /* no sentinel somehow */
- char *p = mrb_malloc(mrb, len+1);
+ char *p = (char *)mrb_malloc(mrb, len+1);
memcpy(p, s, sizeof(char)*len);
p[len] = '\0';
@@ -2670,7 +2702,6 @@ mrb_str_to_dbl(mrb_state *mrb, mrb_value str, int badcheck)
static mrb_value
mrb_str_to_f(mrb_state *mrb, mrb_value self)
{
- //return mrb_float_new(mrb_str_to_dbl(self, 0/*Qfalse*/));
return mrb_float_value(mrb_str_to_dbl(mrb, self, 0/*Qfalse*/));
}
@@ -2778,7 +2809,7 @@ mrb_str_dump(mrb_state *mrb, mrb_value str)
len++;
}
else {
- len += 4; /* \xNN */
+ len += 4; /* \NNN */
}
break;
}
@@ -2787,7 +2818,7 @@ mrb_str_dump(mrb_state *mrb, mrb_value str)
result = str_new(mrb, 0, len);
str_with_class(mrb, result, str);
p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
- q = result->buf;
+ q = result->ptr;
*q++ = '"';
while (p < pend) {
@@ -2849,19 +2880,10 @@ 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)
{
- struct RString *s = mrb_str_ptr(str);
-
if (len < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "negative string size (or size too big)");
}
- if (0/*STR_ASSOC_P(str)*/) {
- mrb_realloc(mrb, s->buf, s->len+len+1);
- memcpy(s->buf + s->len, ptr, len);
- s->len += len;
- s->buf[s->len] = '\0'; /* sentinel */
- return str;
- }
- str_buf_cat(mrb, s, ptr, len);
+ str_buf_cat(mrb, mrb_str_ptr(str), ptr, len);
return str;
}
@@ -2915,18 +2937,15 @@ mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2)
mrb_value
mrb_str_inspect(mrb_state *mrb, mrb_value str)
{
- const char *p, *pend, *prev;
+ const char *p, *pend;
char buf[CHAR_ESC_LEN + 1];
- mrb_value result = mrb_str_new_cstr(mrb, "\"");
+ mrb_value result = mrb_str_new(mrb, "\"", 1);
p = RSTRING_PTR(str); pend = RSTRING_END(str);
- prev = p;
- while (p < pend) {
+ for (;p < pend; p++) {
unsigned int c, cc;
- int n;
- c = *p++;
- n = 1;
+ c = *p;
if (c == '"'|| c == '\\' || (c == '#' && IS_EVSTR(p, pend))) {
buf[0] = '\\'; buf[1] = c;
mrb_str_buf_cat(mrb, result, buf, 2);
@@ -2949,25 +2968,18 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str)
default: cc = 0; break;
}
if (cc) {
- if (p - n > prev) mrb_str_buf_cat(mrb, result, prev, p - n - prev);
buf[0] = '\\';
buf[1] = (char)cc;
mrb_str_buf_cat(mrb, result, buf, 2);
- prev = p;
continue;
}
else {
- if (p - n > prev) mrb_str_buf_cat(mrb, result, prev, p - n - prev);
- sprintf(buf, "\\%03o", c & 0377);
- mrb_str_buf_cat(mrb, result, buf, strlen(buf));
- prev = p;
+ int n = sprintf(buf, "\\%03o", c & 0377);
+ mrb_str_buf_cat(mrb, result, buf, n);
continue;
}
}
-#ifdef INCLUDE_ENCODING
- if (p > prev) mrb_str_buf_cat(mrb, result, prev, p - prev);
-#endif
- mrb_str_buf_cat(mrb, result, "\"", strlen("\""));
+ mrb_str_buf_cat(mrb, result, "\"", 1);
return result;
}
@@ -3002,7 +3014,7 @@ mrb_init_string(mrb_state *mrb)
mrb_define_method(mrb, s, "each_line", mrb_str_each_line, ARGS_REQ(1)); /* 15.2.10.5.15 */
mrb_define_method(mrb, s, "empty?", mrb_str_empty_p, ARGS_NONE()); /* 15.2.10.5.16 */
mrb_define_method(mrb, s, "eql?", mrb_str_eql, ARGS_REQ(1)); /* 15.2.10.5.17 */
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
mrb_define_method(mrb, s, "gsub", mrb_str_gsub, ARGS_REQ(1)); /* 15.2.10.5.18 */
mrb_define_method(mrb, s, "gsub!", mrb_str_gsub_bang, ARGS_REQ(1)); /* 15.2.10.5.19 */
#endif
@@ -3012,19 +3024,19 @@ mrb_init_string(mrb_state *mrb)
mrb_define_method(mrb, s, "initialize", mrb_str_init, ARGS_REQ(1)); /* 15.2.10.5.23 */
mrb_define_method(mrb, s, "initialize_copy", mrb_str_replace, ARGS_REQ(1)); /* 15.2.10.5.24 */
mrb_define_method(mrb, s, "intern", mrb_str_intern, ARGS_NONE()); /* 15.2.10.5.25 */
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
mrb_define_method(mrb, s, "match", mrb_str_match_m, ARGS_REQ(1)); /* 15.2.10.5.27 */
#endif
mrb_define_method(mrb, s, "replace", mrb_str_replace, ARGS_REQ(1)); /* 15.2.10.5.28 */
mrb_define_method(mrb, s, "reverse", mrb_str_reverse, ARGS_NONE()); /* 15.2.10.5.29 */
mrb_define_method(mrb, s, "reverse!", mrb_str_reverse_bang, ARGS_NONE()); /* 15.2.10.5.30 */
mrb_define_method(mrb, s, "rindex", mrb_str_rindex_m, ARGS_ANY()); /* 15.2.10.5.31 */
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
mrb_define_method(mrb, s, "scan", mrb_str_scan, ARGS_REQ(1)); /* 15.2.10.5.32 */
#endif
mrb_define_method(mrb, s, "slice", mrb_str_aref_m, ARGS_ANY()); /* 15.2.10.5.34 */
mrb_define_method(mrb, s, "split", mrb_str_split_m, ARGS_ANY()); /* 15.2.10.5.35 */
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
mrb_define_method(mrb, s, "sub", mrb_str_sub, ARGS_REQ(1)); /* 15.2.10.5.36 */
mrb_define_method(mrb, s, "sub!", mrb_str_sub_bang, ARGS_REQ(1)); /* 15.2.10.5.37 */
#endif
diff --git a/src/struct.c b/src/struct.c
index d06124b50..beb7c2f46 100644
--- a/src/struct.c
+++ b/src/struct.c
@@ -5,6 +5,7 @@
*/
#include "mruby.h"
+#ifdef ENABLE_STRUCT
#include <string.h>
#include "error.h"
#include "mruby/struct.h"
@@ -12,21 +13,13 @@
#include <stdarg.h>
//#include "defines.h"
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
#include "encoding.h"
#endif
-mrb_sym rb_frame_this_func(mrb_state *mrb);
-mrb_sym mrb_frame_callee(mrb_state *mrb);
-mrb_value mrb_exec_recursive_paired(mrb_state *mrb, mrb_value (*func) (mrb_state *, mrb_value, mrb_value, int),
- mrb_value obj, mrb_value paired_obj, void* arg);
-#include "mruby/numeric.h"
-#include "mruby/hash.h"
#include "mruby/string.h"
#include "mruby/class.h"
#include "mruby/variable.h"
-#include "mruby/range.h"
-#include "error.h"
//#include "defines.h"
#define mrb_long2int(n) ((int)(n))
@@ -45,8 +38,6 @@ struct_ivar_get(mrb_state *mrb, mrb_value c, mrb_sym id)
mrb_value ans;
for (;;) {
- //if (mrb_ivar_defined(c, id))
- // return mrb_iv_get(mrb, c, id);
ans = mrb_iv_get(mrb, c, id);
if (!mrb_nil_p(ans)) return ans;
kclass = RCLASS_SUPER(c);
@@ -96,7 +87,7 @@ mrb_struct_s_members_m(mrb_state *mrb, mrb_value klass)
mrb_value *p, *pend;
members = mrb_struct_s_members(mrb, klass);
- ary = mrb_ary_new_capa(mrb, RARRAY_LEN(members));//mrb_ary_new2(RARRAY_LEN(members));
+ ary = mrb_ary_new_capa(mrb, RARRAY_LEN(members));
p = RARRAY_PTR(members); pend = p + RARRAY_LEN(members);
while (p < pend) {
mrb_ary_push(mrb, ary, *p);
@@ -134,7 +125,7 @@ mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id)
ptr = RSTRUCT_PTR(obj);
members = mrb_struct_members(mrb, obj);
ptr_members = RARRAY_PTR(members);
- slot = mrb_str_new_cstr(mrb, mrb_sym2name(mrb, id));
+ slot = mrb_symbol_value(id);
len = RARRAY_LEN(members);
for (i=0; i<len; i++) {
if (mrb_obj_equal(mrb, ptr_members[i], slot)) {
@@ -148,8 +139,7 @@ mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id)
static mrb_value
mrb_struct_ref(mrb_state *mrb, mrb_value obj)
{
- //return mrb_struct_getmember(mrb, obj, rb_frame_this_func(mrb));
- return mrb_nil_value();
+ return mrb_struct_getmember(mrb, obj, mrb->ci->mid);
}
static mrb_value mrb_struct_ref0(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[0];}
@@ -186,33 +176,60 @@ mrb_struct_modify(mrb_value s)
}
mrb_sym
-mrb_id_attrset(mrb_sym id)
+mrb_id_attrset(mrb_state *mrb, mrb_sym id)
{
- //id &= ~ID_SCOPE_MASK;
- //id |= ID_ATTRSET;
- return id;
+ const char *name;
+ char *buf;
+ int len;
+ mrb_sym mid;
+
+ name = mrb_sym2name_len(mrb, id, &len);
+ buf = (char *)mrb_malloc(mrb, len+2);
+ memcpy(buf, name, len);
+ buf[len] = '=';
+ buf[len+1] = '\0';
+
+ mid = mrb_intern2(mrb, buf, len+1);
+ mrb_free(mrb, buf);
+ return mid;
}
static mrb_value
mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val)
{
- mrb_value members, slot, *ptr, *ptr_members;
- long i, len;
-
- members = mrb_struct_members(mrb, obj);
- ptr_members = RARRAY_PTR(members);
- len = RARRAY_LEN(members);
- mrb_struct_modify(obj);
- ptr = RSTRUCT_PTR(obj);
- for (i=0; i<len; i++) {
- slot = ptr_members[i];
- if (mrb_id_attrset(SYM2ID(slot)) == 0/*rb_frame_this_func(mrb)*/) {
- return ptr[i] = val;
- }
+ const char *name;
+ int i, len;
+ mrb_sym mid;
+ mrb_value members, slot, *ptr, *ptr_members;
+
+ /* get base id */
+ name = mrb_sym2name_len(mrb, mrb->ci->mid, &len);
+ mid = mrb_intern2(mrb, name, len-1); /* omit last "=" */
+
+ members = mrb_struct_members(mrb, obj);
+ ptr_members = RARRAY_PTR(members);
+ len = RARRAY_LEN(members);
+ mrb_struct_modify(obj);
+ ptr = RSTRUCT_PTR(obj);
+ for (i=0; i<len; i++) {
+ slot = ptr_members[i];
+ if (SYM2ID(slot) == mid) {
+ return ptr[i] = val;
}
- mrb_name_error(mrb, 0/*rb_frame_this_func(mrb)*/, "`%s' is not a struct member",
- mrb_sym2name(mrb, 0/*rb_frame_this_func(mrb)*/));
- return mrb_nil_value(); /* not reached */
+ }
+
+ mrb_name_error(mrb, mid, "`%s' is not a struct member",
+ mrb_sym2name(mrb, mid));
+ return mrb_nil_value(); /* not reached */
+}
+
+static mrb_value
+mrb_struct_set_m(mrb_state *mrb, mrb_value obj)
+{
+ mrb_value val;
+
+ mrb_get_args(mrb, "o", &val);
+ return mrb_struct_set(mrb, obj, val);
}
#define is_notop_id(id) (id)//((id)>tLAST_TOKEN)
@@ -241,19 +258,15 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k
//OBJ_FREEZE(members);
if (mrb_nil_p(name)) {
c = mrb_class_new(mrb, klass);
- //mrb_make_metaclass(nstr, RBASIC(klass)->c);
- //mrb_class_inherited(klass, nstr);
}
else {
/* old style: should we warn? */
name = mrb_str_to_str(mrb, name);
id = mrb_to_id(mrb, name);
if (!mrb_is_const_id(id)) {
- //mrb_name_error(id, "identifier %s needs to be constant", StringValuePtr(name));
mrb_name_error(mrb, id, "identifier %s needs to be constant", mrb_string_value_ptr(mrb, name));
}
if (mrb_const_defined_at(mrb, klass, id)) {
- //mrb_warn("redefining constant Struct::%s", StringValuePtr(name));
mrb_warn("redefining constant Struct::%s", mrb_string_value_ptr(mrb, name));
//?rb_mod_remove_const(klass, mrb_sym2name(mrb, id));
}
@@ -263,8 +276,8 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k
nstr = mrb_obj_value(c);
mrb_iv_set(mrb, nstr, mrb_intern(mrb, "__members__"), members);
- mrb_define_class_method(mrb, c, "new", mrb_class_new_instance_m, ARGS_ANY());
- mrb_define_class_method(mrb, c, "[]", mrb_class_new_instance_m, ARGS_ANY());
+ mrb_define_class_method(mrb, c, "new", mrb_instance_new, ARGS_ANY());
+ mrb_define_class_method(mrb, c, "[]", mrb_instance_new, ARGS_ANY());
mrb_define_class_method(mrb, c, "members", mrb_struct_s_members_m, ARGS_NONE());
//RSTRUCT(nstr)->basic.c->super = c->c;
ptr_members = RARRAY_PTR(members);
@@ -273,12 +286,12 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k
mrb_sym id = SYM2ID(ptr_members[i]);
if (mrb_is_local_id(id) || mrb_is_const_id(id)) {
if (i < N_REF_FUNC) {
- mrb_define_method_id(mrb, c, id, (mrb_func_t)ref_func[i], 0);
+ mrb_define_method_id(mrb, c, id, ref_func[i], ARGS_NONE());
}
else {
- mrb_define_method_id(mrb, c, id, mrb_struct_ref, 0);
+ mrb_define_method_id(mrb, c, id, mrb_struct_ref, ARGS_NONE());
}
- mrb_define_method_id(mrb, c, mrb_id_attrset(id), (mrb_func_t)mrb_struct_set, 1);
+ mrb_define_method_id(mrb, c, mrb_id_attrset(mrb, id), mrb_struct_set_m, ARGS_REQ(1));
}
}
@@ -299,7 +312,7 @@ mrb_struct_define(mrb_state *mrb, const char *name, ...)
va_start(ar, name);
while ((mem = va_arg(ar, char*)) != 0) {
mrb_sym slot = mrb_intern(mrb, mem);
- mrb_ary_push(mrb, ary, mrb_str_new_cstr(mrb, mrb_sym2name(mrb, slot)));
+ mrb_ary_push(mrb, ary, mrb_symbol_value(slot));
}
va_end(ar);
@@ -354,33 +367,31 @@ mrb_struct_s_def(mrb_state *mrb, mrb_value klass)
name = mrb_nil_value();
rest = mrb_nil_value();
- mrb_get_args(mrb, "&*", &b, &argv, &argc);
+ mrb_get_args(mrb, "*&", &argv, &argc, &b);
if (argc > 0) name = argv[0];
if (argc > 1) rest = argv[1];
- //mrb_scan_args(argc, argv, "1*", &name, &rest);
if (mrb_type(rest) == MRB_TT_ARRAY) {
if (!mrb_nil_p(name) && SYMBOL_P(name)) {
/* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */
mrb_ary_unshift(mrb, rest, name);
name = mrb_nil_value();
}
- for (i=0; i<RARRAY_LEN(rest); i++) {
- id = mrb_to_id(mrb, RARRAY_PTR(rest)[i]);
- RARRAY_PTR(rest)[i] = mrb_str_new_cstr(mrb, mrb_sym2name(mrb, id));
- }
}
else {
pargv = &argv[1];
argcnt = argc-1;
if (!mrb_nil_p(name) && SYMBOL_P(name)) {
/* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */
- //mrb_ary_unshift(mrb, rest, name);
name = mrb_nil_value();
pargv = &argv[0];
argcnt++;
}
rest = mrb_ary_new_from_values(mrb, argcnt, pargv);
}
+ for (i=0; i<RARRAY_LEN(rest); i++) {
+ id = mrb_to_id(mrb, RARRAY_PTR(rest)[i]);
+ RARRAY_PTR(rest)[i] = mrb_symbol_value(id);
+ }
st = make_struct(mrb, name, rest, struct_class(mrb));
if (!mrb_nil_p(b)) {
mrb_funcall(mrb, b, "call", 1, &st);
@@ -389,7 +400,7 @@ mrb_struct_s_def(mrb_state *mrb, mrb_value klass)
return st;
}
-static long
+static int
num_members(mrb_state *mrb, struct RClass *klass)
{
mrb_value members;
@@ -407,7 +418,7 @@ static mrb_value
mrb_struct_initialize_withArg(mrb_state *mrb, int argc, mrb_value *argv, mrb_value self)
{
struct RClass *klass = mrb_obj_class(mrb, self);
- long n;
+ int n;
struct RStruct *st;
mrb_struct_modify(self);
@@ -416,12 +427,10 @@ mrb_struct_initialize_withArg(mrb_state *mrb, int argc, mrb_value *argv, mrb_val
mrb_raise(mrb, E_ARGUMENT_ERROR, "struct size differs");
}
st = RSTRUCT(self);
- st->ptr = malloc(sizeof(mrb_value)*argc);
+ st->ptr = (mrb_value *)mrb_calloc(mrb, sizeof(mrb_value), n);
st->len = n;
memcpy(st->ptr, argv, sizeof(mrb_value)*argc);
- //if (n > argc) {
- // mrb_mem_clear(RSTRUCT_PTR(self)+argc, n-argc);
- //}
+
return self;
}
@@ -438,41 +447,14 @@ mrb_struct_initialize_m(mrb_state *mrb, /*int argc, mrb_value *argv,*/ mrb_value
mrb_value
mrb_struct_initialize(mrb_state *mrb, mrb_value self, mrb_value values)
{
- return mrb_struct_initialize_withArg(mrb, RARRAY_LEN/*INT*/(values), RARRAY_PTR(values), self);
-}
-
-mrb_value
-mrb_struct_alloc(mrb_state *mrb, mrb_value klass, mrb_value values)
-{
- return mrb_class_new_instance(mrb, RARRAY_LEN(values), RARRAY_PTR(values), mrb_class(mrb, klass));
-}
-
-mrb_value
-mrb_struct_new(mrb_state *mrb, struct RClass *klass, ...)
-{
- mrb_value tmpargs[N_REF_FUNC], *mem = tmpargs;
- int size, i;
- va_list args;
-
- size = mrb_long2int(num_members(mrb, klass));
- if (size > numberof(tmpargs)) {
- tmpargs[0] = mrb_ary_tmp_new(mrb, size);
- mem = RARRAY_PTR(tmpargs[0]);
- }
- va_start(args, klass);
- for (i=0; i<size; i++) {
- mem[i] = va_arg(args, mrb_value);
- }
- va_end(args);
-
- return mrb_class_new_instance(mrb, size, mem, klass);
+ return mrb_struct_initialize_withArg(mrb, RARRAY_LEN(values), RARRAY_PTR(values), self);
}
static mrb_value
inspect_struct(mrb_state *mrb, mrb_value s, mrb_value dummy, int recur)
{
const char *cn = mrb_class_name(mrb, mrb_obj_class(mrb, s));
- mrb_value members, str = mrb_str_new2(mrb, "#<struct ");
+ mrb_value members, str = mrb_str_new(mrb, "#<struct ", 9);
mrb_value *ptr, *ptr_members;
long i, len;
@@ -500,8 +482,11 @@ inspect_struct(mrb_state *mrb, mrb_value s, mrb_value dummy, int recur)
slot = ptr_members[i];
id = SYM2ID(slot);
if (mrb_is_local_id(id) || mrb_is_const_id(id)) {
- //mrb_str_append(str, mrb_id2str(id));
- mrb_str_append(mrb, str, mrb_str_new_cstr(mrb, mrb_sym2name(mrb, id)));
+ const char *name;
+ int len;
+
+ name = mrb_sym2name_len(mrb, id, &len);
+ mrb_str_append(mrb, str, mrb_str_new(mrb, name, len));
}
else {
mrb_str_append(mrb, str, mrb_inspect(mrb, slot));
@@ -537,7 +522,6 @@ mrb_struct_init_copy(mrb_state *mrb, mrb_value copy)
mrb_get_args(mrb, "o", &s);
if (mrb_obj_equal(mrb, copy, s)) return copy;
- //mrb_check_frozen(copy);
if (!mrb_obj_is_instance_of(mrb, s, mrb_obj_class(mrb, copy))) {
mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
}
@@ -690,22 +674,6 @@ mrb_struct_aset(mrb_state *mrb, mrb_value s)
return RSTRUCT_PTR(s)[i] = val;
}
-static mrb_value
-recursive_equal(mrb_state *mrb, mrb_value s, mrb_value s2, int recur)
-{
- mrb_value *ptr, *ptr2;
- long i, len;
-
- if (recur) return mrb_true_value(); /* Subtle! */
- 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();
- }
- return mrb_true_value();
-}
-
/* 15.2.18.4.1 */
/*
* call-seq:
@@ -728,6 +696,8 @@ static mrb_value
mrb_struct_equal(mrb_state *mrb, mrb_value s)
{
mrb_value s2;
+ mrb_value *ptr, *ptr2;
+ long i, len;
mrb_get_args(mrb, "o", &s2);
if (mrb_obj_equal(mrb, s, s2)) return mrb_true_value();
@@ -736,24 +706,13 @@ mrb_struct_equal(mrb_state *mrb, mrb_value s)
if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
mrb_bug("inconsistent struct"); /* should never happen */
}
-
- return mrb_exec_recursive_paired(mrb, recursive_equal, s, s2, (void*)0);
-}
-
-static mrb_value
-recursive_eql(mrb_state *mrb, mrb_value s, mrb_value s2, int recur)
-{
- mrb_value *ptr, *ptr2;
- long i, len;
-
- if (recur) return mrb_true_value(); /* Subtle! */
- 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();
- }
- return mrb_true_value();
+ 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();
+ }
+ return mrb_true_value();
}
/* 15.2.18.4.12(x) */
@@ -768,6 +727,8 @@ static mrb_value
mrb_struct_eql(mrb_state *mrb, mrb_value s)
{
mrb_value s2;
+ mrb_value *ptr, *ptr2;
+ long i, len;
mrb_get_args(mrb, "o", &s2);
if (mrb_obj_equal(mrb, s, s2)) return mrb_true_value();
@@ -777,7 +738,13 @@ mrb_struct_eql(mrb_state *mrb, mrb_value s)
mrb_bug("inconsistent struct"); /* should never happen */
}
- return mrb_exec_recursive_paired(mrb, recursive_eql, s, s2, (void*)0);
+ 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();
+ }
+ return mrb_true_value();
}
/*
@@ -800,9 +767,7 @@ mrb_init_struct(mrb_state *mrb)
{
struct RClass *st;
st = mrb_define_class(mrb, "Struct", mrb->object_class);
- //mrb_include_module(mrb_cStruct, rb_mEnumerable);
- //mrb_undef_alloc_func(mrb_cStruct);
mrb_define_class_method(mrb, st, "new", mrb_struct_s_def, ARGS_ANY()); /* 15.2.18.3.1 */
mrb_define_method(mrb, st, "==", mrb_struct_equal, ARGS_REQ(1)); /* 15.2.18.4.1 */
@@ -816,3 +781,4 @@ mrb_init_struct(mrb_state *mrb)
mrb_define_method(mrb, st, "eql?", mrb_struct_eql, ARGS_REQ(1)); /* 15.2.18.4.12(x) */
}
+#endif /* ENABLE_STRUCT */
diff --git a/src/symbol.c b/src/symbol.c
index aa5b659fa..b81296929 100644
--- a/src/symbol.c
+++ b/src/symbol.c
@@ -8,68 +8,99 @@
#include "mruby/khash.h"
#include <string.h>
-#include <stdarg.h>
-#include <string.h>
#include "mruby/string.h"
#include <ctype.h>
-#include "mruby/class.h"
-#include "mruby/variable.h"
-#include <stdio.h>
/* ------------------------------------------------------ */
-KHASH_INIT(s2n, mrb_sym, const char*, 1, kh_int_hash_func, kh_int_hash_equal)
-KHASH_MAP_INIT_STR(n2s, mrb_sym);
+typedef struct symbol_name {
+ int len;
+ const char *name;
+} symbol_name;
+
+static inline khint_t
+sym_hash_func(mrb_state *mrb, const symbol_name s)
+{
+ khint_t h = 0;
+ size_t i;
+ const char *p = s.name;
+
+ for (i=0; i<s.len; i++) {
+ h = (h << 5) - h + *p++;
+ }
+ return h;
+}
+#define sym_hash_equal(mrb,a, b) (a.len == b.len && memcmp(a.name, b.name, a.len) == 0)
+
+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_intern(mrb_state *mrb, const char *name)
+mrb_intern2(mrb_state *mrb, const char *name, int len)
{
khash_t(n2s) *h = mrb->name2sym;
- khash_t(s2n) *rh = mrb->sym2name;
+ symbol_name sname;
khiter_t k;
- size_t len;
- char *p;
mrb_sym sym;
+ char *p;
- k = kh_get(n2s, h, name);
+ sname.len = len;
+ sname.name = name;
+ k = kh_get(n2s, h, sname);
if (k != kh_end(h))
return kh_value(h, k);
sym = ++mrb->symidx;
- len = strlen(name);
- p = mrb_malloc(mrb, len+1);
+ p = (char *)mrb_malloc(mrb, len+1);
memcpy(p, name, len);
p[len] = 0;
- k = kh_put(n2s, h, p);
+ sname.name = (const char*)p;
+ k = kh_put(n2s, h, sname);
kh_value(h, k) = sym;
- k = kh_put(s2n, rh, sym);
- kh_value(rh, k) = p;
-
return sym;
}
+mrb_sym
+mrb_intern(mrb_state *mrb, const char *name)
+{
+ return mrb_intern2(mrb, name, strlen(name));
+}
+
+mrb_sym
+mrb_intern_str(mrb_state *mrb, mrb_value str)
+{
+ return mrb_intern2(mrb, RSTRING_PTR(str), RSTRING_LEN(str));
+}
+
const char*
-mrb_sym2name(mrb_state *mrb, mrb_sym sym)
+mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, int *lenp)
{
- khash_t(s2n) *h = mrb->sym2name;
+ khash_t(n2s) *h = mrb->name2sym;
khiter_t k;
+ symbol_name sname;
- k = kh_get(s2n, h, sym);
+ for (k = kh_begin(h); k != kh_end(h); k++) {
+ if (kh_exist(h, k)) {
+ if (kh_value(h, k) == sym) break;
+ }
+ }
if (k == kh_end(h)) {
- return NULL; /* missing */
+ *lenp = 0;
+ return NULL; /* missing */
}
- return kh_value(h, k);
+ sname = kh_key(h, k);
+ *lenp = sname.len;
+ return sname.name;
}
void
mrb_free_symtbls(mrb_state *mrb)
{
- khash_t(s2n) *h = mrb->sym2name;
+ khash_t(n2s) *h = mrb->name2sym;
khiter_t k;
- for (k = kh_begin(h); k != kh_end(h); ++k)
- if (kh_exist(h, k)) mrb_free(mrb, (char*)kh_value(h, k));
- kh_destroy(s2n,mrb->sym2name);
+ for (k = kh_begin(h); k != kh_end(h); k++)
+ if (kh_exist(h, k)) mrb_free(mrb, (char*)kh_key(h, k).name);
kh_destroy(n2s,mrb->name2sym);
}
@@ -77,7 +108,6 @@ void
mrb_init_symtbl(mrb_state *mrb)
{
mrb->name2sym = kh_init(n2s, mrb);
- mrb->sym2name = kh_init(s2n, mrb);
}
/**********************************************************************
@@ -148,8 +178,11 @@ mrb_value
mrb_sym_to_s(mrb_state *mrb, mrb_value sym)
{
mrb_sym id = SYM2ID(sym);
+ const char *p;
+ int len;
- return mrb_str_new_cstr(mrb, mrb_sym2name(mrb, id));
+ p = mrb_sym2name_len(mrb, id, &len);
+ return mrb_str_new(mrb, p, len);
}
/* 15.2.11.3.4 */
@@ -188,8 +221,7 @@ sym_to_sym(mrb_state *mrb, mrb_value sym)
#define is_identchar(c) (SIGN_EXTEND_CHAR(c)!=-1&&(ISALNUM(c) || (c) == '_'))
static int
-is_special_global_name(m)
- const char *m;
+is_special_global_name(const char* m)
{
switch (*m) {
case '~': case '*': case '$': case '?': case '!': case '@':
@@ -240,6 +272,7 @@ symname_p(const char *name)
case '>':
switch (*++m) {
case '>': case '=': ++m; break;
+ default: break;
}
break;
@@ -254,12 +287,20 @@ symname_p(const char *name)
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 '%': case '~': case '`':
+ case '^': case '/': case '%': case '~': case '`':
++m;
break;
@@ -275,7 +316,8 @@ id:
while (is_identchar(*m)) m += 1;
if (localid) {
switch (*m) {
- case '!': case '?': case '=': ++m;
+ case '!': case '?': case '=': ++m;
+ default: break;
}
}
break;
@@ -288,22 +330,69 @@ sym_inspect(mrb_state *mrb, mrb_value sym)
{
mrb_value str;
const char *name;
+ int len;
mrb_sym id = SYM2ID(sym);
- name = mrb_sym2name(mrb, id); //mrb_id2name(id);
- str = mrb_str_new(mrb, 0, strlen(name)+1);
- RSTRING(str)->buf[0] = ':';
- strcpy(RSTRING(str)->buf+1, name);
- if (!symname_p(name)) {
+ name = mrb_sym2name_len(mrb, id, &len);
+ str = mrb_str_new(mrb, 0, len+1);
+ RSTRING(str)->ptr[0] = ':';
+ memcpy(RSTRING(str)->ptr+1, name, len);
+ if (!symname_p(name) || strlen(name) != len) {
str = mrb_str_dump(mrb, str);
- strncpy(RSTRING(str)->buf, ":\"", 2);
+ memcpy(RSTRING(str)->ptr, ":\"", 2);
}
return str;
}
+const char*
+mrb_sym2name(mrb_state *mrb, mrb_sym sym)
+{
+ int len;
+ const char *name = mrb_sym2name_len(mrb, sym, &len);
+
+ if (!name) return NULL;
+ if (symname_p(name) && strlen(name) == len) {
+ return name;
+ }
+ else {
+ mrb_value str = mrb_str_dump(mrb, mrb_str_new(mrb, name, len));
+ return RSTRING(str)->ptr;
+ }
+}
+
+#define lesser(a,b) (((a)>(b))?(b):(a))
+
+static mrb_value
+sym_cmp(mrb_state *mrb, mrb_value s1)
+{
+ mrb_value s2;
+ mrb_sym sym1, sym2;
+
+ mrb_get_args(mrb, "o", &s2);
+ if (mrb_type(s2) != MRB_TT_SYMBOL) return mrb_nil_value();
+ sym1 = mrb_symbol(s1);
+ sym2 = mrb_symbol(s2);
+ if (sym1 == sym2) return mrb_fixnum_value(0);
+ else {
+ const char *p1, *p2;
+ int len, len1, len2, retval;
+
+ p1 = mrb_sym2name_len(mrb, sym1, &len1);
+ p2 = mrb_sym2name_len(mrb, sym2, &len2);
+ len = lesser(len1, len2);
+ retval = memcmp(p1, p2, len);
+ if (retval == 0) {
+ if (len1 == len2) return mrb_fixnum_value(0);
+ if (len1 > len2) return mrb_fixnum_value(1);
+ return mrb_fixnum_value(-1);
+ }
+ if (retval > 0) return mrb_fixnum_value(1);
+ return mrb_fixnum_value(-1);
+ }
+}
void
-mrb_init_symbols(mrb_state *mrb)
+mrb_init_symbol(mrb_state *mrb)
{
struct RClass *sym;
@@ -313,6 +402,6 @@ mrb_init_symbols(mrb_state *mrb)
mrb_define_method(mrb, sym, "id2name", mrb_sym_to_s, ARGS_NONE()); /* 15.2.11.3.2 */
mrb_define_method(mrb, sym, "to_s", mrb_sym_to_s, ARGS_NONE()); /* 15.2.11.3.3 */
mrb_define_method(mrb, sym, "to_sym", sym_to_sym, ARGS_NONE()); /* 15.2.11.3.4 */
-
mrb_define_method(mrb, sym, "inspect", sym_inspect, ARGS_NONE()); /* 15.2.11.3.5(x) */
+ mrb_define_method(mrb, sym, "<=>", sym_cmp, ARGS_REQ(1));
}
diff --git a/src/time.c b/src/time.c
index 63b763a08..ac04745e5 100644
--- a/src/time.c
+++ b/src/time.c
@@ -6,6 +6,7 @@
#include "mruby.h"
+#ifdef ENABLE_TIME
#include <string.h>
#include <stdio.h>
#include <time.h>
@@ -136,13 +137,13 @@ mrb_time_update_datetime(struct mrb_time *self)
{
struct tm *aid;
- if(self->timezone == MRB_TIMEZONE_UTC) {
+ if (self->timezone == MRB_TIMEZONE_UTC) {
aid = gmtime_r(&self->sec, &self->datetime);
}
else {
aid = localtime_r(&self->sec, &self->datetime);
}
- if(!aid) return NULL;
+ if (!aid) return NULL;
#ifdef NO_GMTIME_R
self->datetime = *aid; // copy data
#endif
@@ -159,13 +160,21 @@ mrb_time_wrap(mrb_state *mrb, struct RClass *tc, struct mrb_time *tm)
/* Allocates a mrb_time object and initializes it. */
static struct mrb_time*
-mrb_time_alloc(mrb_state *mrb, mrb_float seconds, enum mrb_timezone timezone)
+mrb_time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone)
{
struct mrb_time *tm;
- tm = mrb_malloc(mrb, sizeof(struct mrb_time));
- tm->sec = (time_t)seconds;
- tm->usec = (seconds - tm->sec) * 1.0e6;
+ tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(struct mrb_time));
+ tm->sec = (time_t)sec;
+ tm->usec = (sec - tm->sec) * 1.0e6 + usec;
+ while (tm->usec < 0) {
+ tm->sec--;
+ tm->usec += 1.0e6;
+ }
+ while (tm->usec > 1.0e6) {
+ tm->sec++;
+ tm->usec -= 1.0e6;
+ }
tm->timezone = timezone;
mrb_time_update_datetime(tm);
@@ -173,9 +182,9 @@ mrb_time_alloc(mrb_state *mrb, mrb_float seconds, enum mrb_timezone timezone)
}
static mrb_value
-mrb_time_make(mrb_state *mrb, struct RClass *c, mrb_float seconds, enum mrb_timezone timezone)
+mrb_time_make(mrb_state *mrb, struct RClass *c, double sec, double usec, enum mrb_timezone timezone)
{
- return mrb_time_wrap(mrb, c, mrb_time_alloc(mrb, seconds, timezone));
+ return mrb_time_wrap(mrb, c, mrb_time_alloc(mrb, sec, usec, timezone));
}
static struct mrb_time*
@@ -183,7 +192,7 @@ current_mrb_time(mrb_state *mrb)
{
struct mrb_time *tm;
- tm = mrb_malloc(mrb, sizeof(*tm));
+ tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm));
#ifdef NO_GETTIMEOFDAY
{
static time_t last_sec = 0, last_usec = 0;
@@ -226,10 +235,10 @@ mrb_time_now(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_time_at(mrb_state *mrb, mrb_value self)
{
- mrb_float f;
+ mrb_float f, f2 = 0;
- mrb_get_args(mrb, "f", &f);
- return mrb_time_make(mrb, mrb_class_ptr(self), f, MRB_TIMEZONE_LOCAL);
+ mrb_get_args(mrb, "f|f", &f, &f2);
+ return mrb_time_make(mrb, mrb_class_ptr(self), f, f2, MRB_TIMEZONE_LOCAL);
}
static struct mrb_time*
@@ -238,9 +247,8 @@ time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday,
enum mrb_timezone timezone)
{
time_t nowsecs;
- struct tm nowtime;
+ struct tm nowtime = { 0 };
- memset(&nowtime, 0, sizeof(struct tm));
nowtime.tm_year = (int)ayear - 1900;
nowtime.tm_mon = (int)amonth - 1;
nowtime.tm_mday = (int)aday;
@@ -258,7 +266,7 @@ time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday,
mrb_raise(mrb, E_ARGUMENT_ERROR, "Not a valid time.");
}
- return mrb_time_alloc(mrb, nowsecs+ausec/10e6, timezone);
+ return mrb_time_alloc(mrb, nowsecs, ausec, timezone);
}
/* 15.2.19.6.2 */
@@ -296,8 +304,8 @@ mrb_time_eq(mrb_state *mrb, mrb_value self)
struct mrb_time *tm1, *tm2;
mrb_get_args(mrb, "o", &other);
- tm1 = mrb_get_datatype(mrb, self, &mrb_time_type);
- tm2 = mrb_get_datatype(mrb, other, &mrb_time_type);
+ 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();
@@ -312,8 +320,8 @@ mrb_time_cmp(mrb_state *mrb, mrb_value self)
struct mrb_time *tm1, *tm2;
mrb_get_args(mrb, "o", &other);
- tm1 = mrb_get_datatype(mrb, self, &mrb_time_type);
- tm2 = mrb_get_datatype(mrb, other, &mrb_time_type);
+ 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_nil_value();
if (tm1->sec > tm2->sec) {
return mrb_fixnum_value(1);
@@ -338,25 +346,32 @@ mrb_time_plus(mrb_state *mrb, mrb_value self)
struct mrb_time *tm;
mrb_get_args(mrb, "f", &f);
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
- f += tm->sec;
- f += (mrb_float)tm->usec / 1.0e6;
- return mrb_time_make(mrb, mrb_obj_class(mrb, self), f, tm->timezone);
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
+ return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec+f, tm->usec, tm->timezone);
}
static mrb_value
mrb_time_minus(mrb_state *mrb, mrb_value self)
{
mrb_float f;
- struct mrb_time *tm;
+ mrb_value other;
+ struct mrb_time *tm, *tm2;
- mrb_get_args(mrb, "f", &f);
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
- f -= tm->sec;
- f -= (mrb_float)tm->usec / 1.0e6;
- return mrb_time_make(mrb, mrb_obj_class(mrb, self), f, tm->timezone);
+ mrb_get_args(mrb, "o", &other);
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
+
+ tm2 = (struct mrb_time *)mrb_get_datatype(mrb, other, &mrb_time_type);
+ if (tm2) {
+ f = (mrb_float)(tm->sec - tm2->sec)
+ + (mrb_float)(tm->usec - tm2->usec) / 1.0e6;
+ return mrb_float_value(f);
+ }
+ else {
+ mrb_get_args(mrb, "f", &f);
+ return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec-f, tm->usec, tm->timezone);
+ }
}
/* 15.2.19.7.30 */
@@ -366,8 +381,8 @@ mrb_time_wday(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
return mrb_fixnum_value(tm->datetime.tm_wday);
}
@@ -378,8 +393,8 @@ mrb_time_yday(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_check_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_check_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
return mrb_fixnum_value(tm->datetime.tm_yday);
}
@@ -390,8 +405,8 @@ mrb_time_year(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
return mrb_fixnum_value(tm->datetime.tm_year + 1900);
}
@@ -402,10 +417,10 @@ mrb_time_zone(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
- if(tm->timezone <= MRB_TIMEZONE_NONE) return mrb_nil_value();
- if(tm->timezone >= MRB_TIMEZONE_LAST) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
+ if (tm->timezone <= MRB_TIMEZONE_NONE) return mrb_nil_value();
+ if (tm->timezone >= MRB_TIMEZONE_LAST) return mrb_nil_value();
return mrb_str_new_cstr(mrb, timezone_names[tm->timezone]);
}
@@ -417,16 +432,17 @@ mrb_time_asctime(mrb_state *mrb, mrb_value self)
struct mrb_time *tm;
struct tm *d;
char buf[256];
+ int len;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
d = &tm->datetime;
- snprintf(buf, 256, "%s %s %02d %02d:%02d:%02d %s%d",
- wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday,
- d->tm_hour, d->tm_min, d->tm_sec,
- tm->timezone == MRB_TIMEZONE_UTC ? "UTC " : "",
- d->tm_year + 1900);
- return mrb_str_new_cstr(mrb, buf);
+ len = snprintf(buf, sizeof(buf), "%s %s %02d %02d:%02d:%02d %s%d",
+ wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday,
+ d->tm_hour, d->tm_min, d->tm_sec,
+ tm->timezone == MRB_TIMEZONE_UTC ? "UTC " : "",
+ d->tm_year + 1900);
+ return mrb_str_new(mrb, buf, len);
}
/* 15.2.19.7.6 */
@@ -436,8 +452,8 @@ mrb_time_day(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
return mrb_fixnum_value(tm->datetime.tm_mday);
}
@@ -449,11 +465,44 @@ mrb_time_dstp(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
return mrb_bool_value(tm->datetime.tm_isdst);
}
+/* 15.2.19.7.8 */
+/* 15.2.19.7.10 */
+/* Returns the Time object of the UTC(GMT) timezone. */
+static mrb_value
+mrb_time_getutc(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm, *tm2;
+
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return self;
+ tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm));
+ *tm2 = *tm;
+ tm2->timezone = MRB_TIMEZONE_UTC;
+ mrb_time_update_datetime(tm2);
+ return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2);
+}
+
+/* 15.2.19.7.9 */
+/* Returns the Time object of the LOCAL timezone. */
+static mrb_value
+mrb_time_getlocal(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm, *tm2;
+
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return self;
+ tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm));
+ *tm2 = *tm;
+ tm2->timezone = MRB_TIMEZONE_LOCAL;
+ mrb_time_update_datetime(tm2);
+ return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2);
+}
+
/* 15.2.19.7.15 */
/* Returns hour of time. */
static mrb_value
@@ -461,8 +510,8 @@ mrb_time_hour(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
return mrb_fixnum_value(tm->datetime.tm_hour);
}
@@ -473,18 +522,20 @@ mrb_time_initialize(mrb_state *mrb, mrb_value self)
{
mrb_int ayear = 0, amonth = 1, aday = 1, ahour = 0,
amin = 0, asec = 0, ausec = 0;
+ int n;
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
if (tm) {
mrb_time_free(mrb, tm);
}
- if (mrb->ci->argc == 0) {
+
+ n = mrb_get_args(mrb, "|iiiiiii",
+ &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
+ if (n == 0) {
tm = current_mrb_time(mrb);
}
else {
- mrb_get_args(mrb, "iiiiiii",
- &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
tm = time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL);
}
DATA_PTR(self) = tm;
@@ -519,8 +570,8 @@ mrb_time_localtime(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return self;
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return self;
tm->timezone = MRB_TIMEZONE_LOCAL;
mrb_time_update_datetime(tm);
return self;
@@ -533,8 +584,8 @@ mrb_time_mday(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
return mrb_fixnum_value(tm->datetime.tm_mday);
}
@@ -545,8 +596,8 @@ mrb_time_min(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
return mrb_fixnum_value(tm->datetime.tm_min);
}
@@ -557,8 +608,8 @@ mrb_time_mon(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
return mrb_fixnum_value(tm->datetime.tm_mon + 1);
}
@@ -569,8 +620,8 @@ mrb_time_sec(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
return mrb_fixnum_value(tm->datetime.tm_sec);
}
@@ -582,8 +633,8 @@ mrb_time_to_f(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
return mrb_float_value((mrb_float)tm->sec + (mrb_float)tm->usec/1.0e6);
}
@@ -594,8 +645,8 @@ mrb_time_to_i(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
return mrb_fixnum_value(tm->sec);
}
@@ -606,8 +657,8 @@ mrb_time_usec(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
return mrb_fixnum_value(tm->usec);
}
@@ -618,7 +669,7 @@ mrb_time_utc(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
if (tm) {
tm->timezone = MRB_TIMEZONE_UTC;
mrb_time_update_datetime(tm);
@@ -632,8 +683,8 @@ static mrb_value
mrb_time_utcp(mrb_state *mrb, mrb_value self)
{
struct mrb_time *tm;
- tm = mrb_get_datatype(mrb, self, &mrb_time_type);
- if(!tm) return mrb_nil_value();
+ tm = (struct mrb_time *)mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (!tm) return mrb_nil_value();
return mrb_bool_value(tm->timezone == MRB_TIMEZONE_UTC);
}
@@ -647,41 +698,54 @@ mrb_init_time(mrb_state *mrb)
tc = mrb_define_class(mrb, "Time", mrb->object_class);
MRB_SET_INSTANCE_TT(tc, MRB_TT_DATA);
mrb_include_module(mrb, tc, mrb_class_get(mrb, "Comparable"));
- mrb_define_class_method(mrb, tc, "now", mrb_time_now, ARGS_NONE());
- mrb_define_class_method(mrb, tc, "at", mrb_time_at, ARGS_ANY());
- mrb_define_class_method(mrb, tc, "gm", mrb_time_gm, ARGS_REQ(1)|ARGS_OPT(6));
- mrb_define_class_method(mrb, tc, "local", mrb_time_local, ARGS_REQ(1)|ARGS_OPT(6));
+ mrb_define_class_method(mrb, tc, "at", mrb_time_at, ARGS_ANY()); /* 15.2.19.6.1 */
+ mrb_define_class_method(mrb, tc, "gm", mrb_time_gm, ARGS_REQ(1)|ARGS_OPT(6)); /* 15.2.19.6.2 */
+ mrb_define_class_method(mrb, tc, "local", mrb_time_local, ARGS_REQ(1)|ARGS_OPT(6)); /* 15.2.19.6.3 */
+ mrb_define_class_method(mrb, tc, "mktime", mrb_time_local, ARGS_REQ(1)|ARGS_OPT(6));/* 15.2.19.6.4 */
+ mrb_define_class_method(mrb, tc, "now", mrb_time_now, ARGS_NONE()); /* 15.2.19.6.5 */
+ mrb_define_class_method(mrb, tc, "utc", mrb_time_gm, ARGS_REQ(1)|ARGS_OPT(6)); /* 15.2.19.6.6 */
mrb_define_method(mrb, tc, "==" , mrb_time_eq , ARGS_REQ(1));
- mrb_define_method(mrb, tc, "<=>" , mrb_time_cmp , ARGS_REQ(1));
- mrb_define_method(mrb, tc, "+" , mrb_time_plus , ARGS_REQ(1));
- mrb_define_method(mrb, tc, "-" , mrb_time_minus , ARGS_REQ(1));
+ mrb_define_method(mrb, tc, "<=>" , mrb_time_cmp , ARGS_REQ(1)); /* 15.2.19.7.1 */
+ mrb_define_method(mrb, tc, "+" , mrb_time_plus , ARGS_REQ(1)); /* 15.2.19.7.2 */
+ mrb_define_method(mrb, tc, "-" , mrb_time_minus , ARGS_REQ(1)); /* 15.2.19.7.3 */
mrb_define_method(mrb, tc, "to_s" , mrb_time_asctime, ARGS_NONE());
- mrb_define_method(mrb, tc, "asctime", mrb_time_asctime, ARGS_NONE());
- mrb_define_method(mrb, tc, "ctime" , mrb_time_asctime, ARGS_NONE());
- mrb_define_method(mrb, tc, "day" , mrb_time_day , ARGS_NONE());
- mrb_define_method(mrb, tc, "dst?" , mrb_time_dstp , ARGS_NONE());
- mrb_define_method(mrb, tc, "gmt?" , mrb_time_utcp , ARGS_NONE());
- mrb_define_method(mrb, tc, "gmtime" , mrb_time_utc , ARGS_NONE());
- mrb_define_method(mrb, tc, "hour" , mrb_time_hour, ARGS_NONE());
- mrb_define_method(mrb, tc, "localtime", mrb_time_localtime, ARGS_NONE());
- mrb_define_method(mrb, tc, "mday" , mrb_time_mday, ARGS_NONE());
- mrb_define_method(mrb, tc, "min" , mrb_time_min, ARGS_NONE());
+ mrb_define_method(mrb, tc, "asctime", mrb_time_asctime, ARGS_NONE()); /* 15.2.19.7.4 */
+ mrb_define_method(mrb, tc, "ctime" , mrb_time_asctime, ARGS_NONE()); /* 15.2.19.7.5 */
+ mrb_define_method(mrb, tc, "day" , mrb_time_day , ARGS_NONE()); /* 15.2.19.7.6 */
+ mrb_define_method(mrb, tc, "dst?" , mrb_time_dstp , ARGS_NONE()); /* 15.2.19.7.7 */
+ mrb_define_method(mrb, tc, "getgm" , mrb_time_getutc , ARGS_NONE()); /* 15.2.19.7.8 */
+ mrb_define_method(mrb, tc, "getlocal",mrb_time_getlocal,ARGS_NONE()); /* 15.2.19.7.9 */
+ mrb_define_method(mrb, tc, "getutc" , mrb_time_getutc , ARGS_NONE()); /* 15.2.19.7.10 */
+ mrb_define_method(mrb, tc, "gmt?" , mrb_time_utcp , ARGS_NONE()); /* 15.2.19.7.11 */
+ mrb_define_method(mrb, tc, "gmtime" , mrb_time_utc , ARGS_NONE()); /* 15.2.19.7.13 */
+ mrb_define_method(mrb, tc, "hour" , mrb_time_hour, ARGS_NONE()); /* 15.2.19.7.15 */
+ mrb_define_method(mrb, tc, "localtime", mrb_time_localtime, ARGS_NONE()); /* 15.2.19.7.18 */
+ mrb_define_method(mrb, tc, "mday" , mrb_time_mday, ARGS_NONE()); /* 15.2.19.7.19 */
+ mrb_define_method(mrb, tc, "min" , mrb_time_min, ARGS_NONE()); /* 15.2.19.7.20 */
- mrb_define_method(mrb, tc, "mon" , mrb_time_mon, ARGS_NONE());
- mrb_define_method(mrb, tc, "month", mrb_time_mon, ARGS_NONE());
+ mrb_define_method(mrb, tc, "mon" , mrb_time_mon, ARGS_NONE()); /* 15.2.19.7.21 */
+ mrb_define_method(mrb, tc, "month", mrb_time_mon, ARGS_NONE()); /* 15.2.19.7.22 */
- mrb_define_method(mrb, tc, "sec" , mrb_time_sec, ARGS_NONE());
- mrb_define_method(mrb, tc, "to_i", mrb_time_to_i, ARGS_NONE());
- mrb_define_method(mrb, tc, "to_f", mrb_time_to_f, ARGS_NONE());
- mrb_define_method(mrb, tc, "usec", mrb_time_usec, ARGS_NONE());
- mrb_define_method(mrb, tc, "utc" , mrb_time_utc, ARGS_NONE());
- mrb_define_method(mrb, tc, "utc?", mrb_time_utcp, ARGS_NONE());
- mrb_define_method(mrb, tc, "wday", mrb_time_wday, ARGS_NONE());
- mrb_define_method(mrb, tc, "yday", mrb_time_yday, ARGS_NONE());
- mrb_define_method(mrb, tc, "year", mrb_time_year, ARGS_NONE());
- mrb_define_method(mrb, tc, "zone", mrb_time_zone, ARGS_NONE());
+ mrb_define_method(mrb, tc, "sec" , mrb_time_sec, ARGS_NONE()); /* 15.2.19.7.23 */
+ mrb_define_method(mrb, tc, "to_i", mrb_time_to_i, ARGS_NONE()); /* 15.2.19.7.25 */
+ mrb_define_method(mrb, tc, "to_f", mrb_time_to_f, ARGS_NONE()); /* 15.2.19.7.24 */
+ mrb_define_method(mrb, tc, "usec", mrb_time_usec, ARGS_NONE()); /* 15.2.19.7.26 */
+ mrb_define_method(mrb, tc, "utc" , mrb_time_utc, ARGS_NONE()); /* 15.2.19.7.27 */
+ mrb_define_method(mrb, tc, "utc?", mrb_time_utcp, ARGS_NONE()); /* 15.2.19.7.28 */
+ mrb_define_method(mrb, tc, "wday", mrb_time_wday, ARGS_NONE()); /* 15.2.19.7.30 */
+ mrb_define_method(mrb, tc, "yday", mrb_time_yday, ARGS_NONE()); /* 15.2.19.7.31 */
+ mrb_define_method(mrb, tc, "year", mrb_time_year, ARGS_NONE()); /* 15.2.19.7.32 */
+ mrb_define_method(mrb, tc, "zone", mrb_time_zone, ARGS_NONE()); /* 15.2.19.7.33 */
- mrb_define_method(mrb, tc, "initialize", mrb_time_initialize, ARGS_REQ(1));
- mrb_define_method(mrb, tc, "initialize_copy", mrb_time_initialize_copy, ARGS_REQ(1));
+ mrb_define_method(mrb, tc, "initialize", mrb_time_initialize, ARGS_REQ(1)); /* 15.2.19.7.16 */
+ mrb_define_method(mrb, tc, "initialize_copy", mrb_time_initialize_copy, ARGS_REQ(1)); /* 15.2.19.7.17 */
+
+ /*
+ methods not available:
+ gmt_offset(15.2.19.7.12)
+ gmtoff(15.2.19.7.14)
+ utc_offset(15.2.19.7.29)
+ */
}
+#endif
diff --git a/src/variable.c b/src/variable.c
index 82ab7bef3..8b94f5bbb 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -4,29 +4,20 @@
** See Copyright Notice in mruby.h
*/
-#include <stdio.h>
#include "mruby.h"
#include "mruby/class.h"
#include "mruby/khash.h"
#include "mruby/variable.h"
-#include "mruby/string.h"
-#include "mruby/range.h"
#include "error.h"
#include "mruby/array.h"
+#include "mruby/proc.h"
-#ifdef INCLUDE_REGEXP
+#ifdef ENABLE_REGEXP
#include "re.h"
-#include "st.h"
#endif
-KHASH_MAP_INIT_INT(iv, mrb_value);
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
+#ifndef MRB_IV_INITIAL_SIZE
+#define MRB_IV_INITIAL_SIZE 8
#endif
static void
@@ -104,10 +95,28 @@ mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
return ivget(mrb, obj->iv, sym);
}
+static int
+obj_iv_p(mrb_value obj)
+{
+ switch (mrb_type(obj)) {
+ case MRB_TT_OBJECT:
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ case MRB_TT_HASH:
+ case MRB_TT_DATA:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
mrb_value
mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym)
{
- return mrb_obj_iv_get(mrb, mrb_obj_ptr(obj), sym);
+ if (obj_iv_p(obj)) {
+ return mrb_obj_iv_get(mrb, mrb_obj_ptr(obj), sym);
+ }
+ return mrb_nil_value();
}
static void
@@ -125,7 +134,7 @@ mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
khash_t(iv) *h;
if (!obj->iv) {
- h = obj->iv = kh_init(iv, mrb);
+ h = obj->iv = kh_init_size(iv, mrb, MRB_IV_INITIAL_SIZE);
}
else {
h = obj->iv;
@@ -137,7 +146,30 @@ mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
void
mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v) /* mrb_ivar_set */
{
- mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), sym, v);
+ if (obj_iv_p(obj)) {
+ mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), sym, v);
+ }
+}
+
+mrb_value
+mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym)
+{
+ mrb_value val;
+
+ if (obj_iv_p(obj)) {
+ khash_t(iv) *h = mrb_obj_ptr(obj)->iv;
+ khiter_t k;
+
+ if (h) {
+ k = kh_get(iv, h, sym);
+ if (k != kh_end(h)) {
+ val = kh_value(h, k);
+ kh_del(iv, h, k);
+ return val;
+ }
+ }
+ }
+ return mrb_undef_value();
}
mrb_value
@@ -154,11 +186,56 @@ mrb_vm_iv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
mrb_iv_set(mrb, mrb->stack[0], sym, v);
}
+/* 15.3.1.3.23 */
+/*
+ * call-seq:
+ * obj.instance_variables -> array
+ *
+ * Returns an array of instance variable names for the receiver. Note
+ * that simply defining an accessor does not create the corresponding
+ * instance variable.
+ *
+ * class Fred
+ * attr_accessor :a1
+ * def initialize
+ * @iv = 3
+ * end
+ * end
+ * Fred.new.instance_variables #=> [:@iv]
+ */
+mrb_value
+mrb_obj_instance_variables(mrb_state *mrb, mrb_value self)
+{
+ mrb_value ary;
+ kh_iv_t *h;
+ khint_t i;
+ int len;
+ const char* p;
+
+ ary = mrb_ary_new(mrb);
+ if (obj_iv_p(self)) {
+ h = ROBJECT_IVPTR(self);
+ if (h) {
+ for (i=0;i<kh_end(h);i++) {
+ if (kh_exist(h, i)) {
+ p = mrb_sym2name_len(mrb, kh_key(h,i), &len);
+ if (len > 1 && *p == '@') {
+ if (mrb_type(kh_value(h, i)) != MRB_TT_UNDEF)
+ mrb_ary_push(mrb, ary, mrb_str_new(mrb, p, len));
+ }
+ }
+ }
+ }
+ }
+ return ary;
+}
+
mrb_value
mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym)
{
- struct RClass *c = mrb->ci->target_class;
+ struct RClass *c = mrb->ci->proc->target_class;
+ if (!c) c = mrb->ci->target_class;
while (c) {
if (c->iv) {
khash_t(iv) *h = c->iv;
@@ -175,10 +252,11 @@ mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym)
void
mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
{
- struct RClass *c = mrb->ci->target_class;
+ struct RClass *c = mrb->ci->proc->target_class;
khash_t(iv) *h;
khiter_t k;
+ if (!c) c = mrb->ci->target_class;
while (c) {
if (c->iv) {
h = c->iv;
@@ -186,7 +264,7 @@ mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
if (k != kh_end(h)) {
k = kh_put(iv, h, sym);
kh_value(h, k) = v;
- return;
+ return;
}
}
c = c->super;
@@ -194,7 +272,7 @@ mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
c = mrb->ci->target_class;
h = c->iv;
if (!h) {
- c->iv = h = kh_init(iv, mrb);
+ c->iv = h = kh_init_size(iv, mrb, MRB_IV_INITIAL_SIZE);
}
k = kh_put(iv, h, sym);
kh_value(h, k) = v;
@@ -233,26 +311,10 @@ const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym)
struct RClass *c = base;
khash_t(iv) *h;
khiter_t k;
+ int retry = 0;
+ mrb_sym cm;
- if (c->iv) {
- h = c->iv;
- k = kh_get(iv, h, sym);
- if (k != kh_end(h)) {
- return kh_value(h, k);
- }
- }
- for (;;) {
- c = mrb_class_outer_module(mrb, c);
- if (!c) break;
- if (c->iv) {
- h = c->iv;
- k = kh_get(iv, h, sym);
- if (k != kh_end(h)) {
- return kh_value(h, k);
- }
- }
- }
- c = base->super;
+ L_RETRY:
while (c) {
if (c->iv) {
h = c->iv;
@@ -263,16 +325,20 @@ const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym)
}
c = c->super;
}
-
- if (!c) {
+ if (!retry && base->tt == MRB_TT_MODULE) {
c = mrb->object_class;
+ retry = 1;
+ goto L_RETRY;
}
-
- if (mrb_respond_to(mrb, mrb_obj_value(c), mrb_intern(mrb, "const_missing"))) {
- mrb_value argv = mrb_symbol_value(sym);
- return mrb_funcall_argv(mrb, mrb_obj_value(c), "const_missing", 1, &argv);
+ c = base;
+ cm = mrb_intern(mrb, "const_missing");
+ while (c) {
+ if (mrb_respond_to(mrb, mrb_obj_value(c), cm)) {
+ mrb_value name = mrb_symbol_value(sym);
+ return mrb_funcall(mrb, mrb_obj_value(c), "const_missing", 1, name);
+ }
+ c = c->super;
}
-
mrb_raise(mrb, E_NAME_ERROR, "uninitialized constant %s",
mrb_sym2name(mrb, sym));
/* not reached */
@@ -289,7 +355,10 @@ mrb_const_get(mrb_state *mrb, mrb_value mod, mrb_sym sym)
mrb_value
mrb_vm_const_get(mrb_state *mrb, mrb_sym sym)
{
- return const_get(mrb, mrb->ci->target_class, sym);
+ struct RClass *c = mrb->ci->proc->target_class;
+
+ if (!c) c = mrb->ci->target_class;
+ return const_get(mrb, c, sym);
}
void
@@ -302,7 +371,10 @@ mrb_const_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v)
void
mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
{
- mrb_obj_iv_set(mrb, (struct RObject*)mrb->ci->target_class, sym, v);
+ struct RClass *c = mrb->ci->proc->target_class;
+
+ if (!c) c = mrb->ci->target_class;
+ mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v);
}
void
@@ -394,16 +466,12 @@ mrb_st_lookup(struct kh_iv *table, mrb_sym id, khiter_t *value)
}
}
-int
+static int
kiv_lookup(khash_t(iv)* table, mrb_sym key, mrb_value *value)
{
khash_t(iv) *h=table;
khiter_t k;
- // you must check(iv==0), before you call this function.
- //if (!obj->iv) {
- // return 0;
- //}
k = kh_get(iv, h, key);
if (k != kh_end(h)) {
*value = kh_value(h, k);
@@ -442,23 +510,9 @@ mrb_const_defined_at(mrb_state *mrb, struct RClass *klass, mrb_sym id)
return mrb_const_defined_0(mrb, klass, id, TRUE, FALSE);
}
-struct RClass *
-mrb_class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
-{
- mrb_value c = const_get(mrb, klass, id);
- return mrb_class_ptr(c);
-}
-
-struct RClass *
-mrb_class_get(mrb_state *mrb, const char *name)
-{
- return mrb_class_from_sym(mrb, mrb->object_class, mrb_intern(mrb, name));
-}
-
mrb_value
mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id)
{
- //return ivar_get(obj, id, FALSE);
return mrb_iv_get(mrb, obj, id);
}
diff --git a/src/vm.c b/src/vm.c
index be55a0124..cbea3ee77 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -28,25 +28,41 @@ static void
stack_init(mrb_state *mrb)
{
/* assert(mrb->stack == NULL); */
- mrb->stbase = mrb_malloc(mrb, sizeof(mrb_value) * STACK_INIT_SIZE);
- memset(mrb->stbase, 0, sizeof(mrb_value) * STACK_INIT_SIZE);
+ mrb->stbase = (mrb_value *)mrb_calloc(mrb, STACK_INIT_SIZE, sizeof(mrb_value));
mrb->stend = mrb->stbase + STACK_INIT_SIZE;
mrb->stack = mrb->stbase;
/* assert(mrb->ci == NULL); */
- mrb->cibase = mrb_malloc(mrb, sizeof(mrb_callinfo)*CALLINFO_INIT_SIZE);
+ mrb->cibase = (mrb_callinfo *)mrb_calloc(mrb, CALLINFO_INIT_SIZE, sizeof(mrb_callinfo));
mrb->ciend = mrb->cibase + CALLINFO_INIT_SIZE;
mrb->ci = mrb->cibase;
- memset(mrb->ci, 0, sizeof(mrb_callinfo));
mrb->ci->target_class = mrb->object_class;
}
static void
+envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
+{
+ mrb_callinfo *ci = mrb->cibase;
+
+ while (ci <= mrb->ci) {
+ struct REnv *e = ci->env;
+ if (e && e->cioff >= 0) {
+ int off = e->stack - oldbase;
+
+ e->stack = newbase + off;
+ }
+ ci++;
+ }
+}
+
+static void
stack_extend(mrb_state *mrb, int room, int keep)
{
int size, off;
- if (mrb->stack + room > mrb->stend) {
+ if (mrb->stack + room >= mrb->stend) {
+ mrb_value *oldbase = mrb->stbase;
+
size = mrb->stend - mrb->stbase;
off = mrb->stack - mrb->stbase;
@@ -54,9 +70,10 @@ stack_extend(mrb_state *mrb, int room, int keep)
size *= 2;
else
size += room;
- mrb->stbase = mrb_realloc(mrb, mrb->stbase, sizeof(mrb_value) * size);
+ mrb->stbase = (mrb_value *)mrb_realloc(mrb, mrb->stbase, sizeof(mrb_value) * size);
mrb->stack = mrb->stbase + off;
mrb->stend = mrb->stbase + size;
+ envadjust(mrb, oldbase, mrb->stbase);
}
if (room > keep) {
memset(mrb->stack+keep, 0, sizeof(mrb_value) * (room-keep));
@@ -75,8 +92,8 @@ uvenv(mrb_state *mrb, int up)
{
struct REnv *e = mrb->ci->proc->env;
- if (!e) return 0;
while (up--) {
+ if (!e) return 0;
e = (struct REnv*)e->c;
}
return e;
@@ -104,19 +121,18 @@ uvset(mrb_state *mrb, int up, int idx, mrb_value v)
static mrb_callinfo*
cipush(mrb_state *mrb)
{
- size_t nregs = mrb->ci->nregs;
int eidx = mrb->ci->eidx;
int ridx = mrb->ci->ridx;
if (mrb->ci + 1 == mrb->ciend) {
size_t size = mrb->ci - mrb->cibase;
- mrb->cibase = mrb_realloc(mrb, mrb->cibase, sizeof(mrb_callinfo)*size*2);
+ mrb->cibase = (mrb_callinfo *)mrb_realloc(mrb, mrb->cibase, sizeof(mrb_callinfo)*size*2);
mrb->ci = mrb->cibase + size;
mrb->ciend = mrb->cibase + size * 2;
}
mrb->ci++;
- mrb->ci->nregs = nregs;
+ mrb->ci->nregs = 2;
mrb->ci->eidx = eidx;
mrb->ci->ridx = ridx;
mrb->ci->env = 0;
@@ -129,7 +145,7 @@ cipop(mrb_state *mrb)
if (mrb->ci->env) {
struct REnv *e = mrb->ci->env;
int len = (int)e->flags;
- mrb_value *p = mrb_malloc(mrb, sizeof(mrb_value)*len);
+ mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
e->cioff = -1;
memcpy(p, e->stack, sizeof(mrb_value)*len);
@@ -145,6 +161,7 @@ ecall(mrb_state *mrb, int i)
struct RProc *p;
mrb_callinfo *ci;
mrb_value *self = mrb->stack;
+ struct RObject *exc;
p = mrb->ensure[i];
ci = cipush(mrb);
@@ -156,20 +173,24 @@ ecall(mrb_state *mrb, int i)
ci->nregs = p->body.irep->nregs;
ci->target_class = p->target_class;
mrb->stack = mrb->stack + ci[-1].nregs;
+ exc = mrb->exc; mrb->exc = 0;
mrb_run(mrb, p, *self);
+ if (!mrb->exc) mrb->exc = exc;
}
mrb_value
-mrb_funcall_with_block(mrb_state *mrb, mrb_value self, const char *name, int argc, mrb_value *argv, mrb_value blk)
+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 mid = mrb_intern(mrb, name);
mrb_sym undef = 0;
mrb_callinfo *ci;
int n = mrb->ci->nregs;
mrb_value val;
+ if (argc < 0) {
+ mrb_raise(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) {
@@ -200,7 +221,10 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, const char *name, int arg
mrb->stack[argc+1] = blk;
if (MRB_PROC_CFUNC_P(p)) {
+ int ai = mrb->arena_idx;
val = p->body.func(mrb, self);
+ mrb->arena_idx = ai;
+ mrb_gc_protect(mrb, val);
mrb->stack = mrb->stbase + ci->stackidx;
cipop(mrb);
}
@@ -211,13 +235,13 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, const char *name, int arg
}
mrb_value
-mrb_funcall_argv(mrb_state *mrb, mrb_value self, const char *name, int argc, mrb_value *argv)
+mrb_funcall_argv(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mrb_value *argv)
{
- return mrb_funcall_with_block(mrb, self, name, argc, argv, mrb_nil_value());
+ return mrb_funcall_with_block(mrb, self, mid, argc, argv, mrb_nil_value());
}
mrb_value
-mrb_yield_with_self(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self)
+mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c)
{
struct RProc *p;
mrb_sym mid = mrb->ci->mid;
@@ -231,7 +255,7 @@ mrb_yield_with_self(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_
ci->proc = p;
ci->stackidx = mrb->stack - mrb->stbase;
ci->argc = argc;
- ci->target_class = p->target_class;
+ ci->target_class = c;
ci->nregs = argc + 2;
ci->acc = -1;
mrb->stack = mrb->stack + n;
@@ -257,23 +281,28 @@ mrb_yield_with_self(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_
mrb_value
mrb_yield_argv(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv)
{
- return mrb_yield_with_self(mrb, b, argc, argv, mrb->stack[0]);
+ struct RProc *p = mrb_proc_ptr(b);
+
+ return mrb_yield_internal(mrb, b, argc, argv, mrb->stack[0], p->target_class);
}
mrb_value
mrb_yield(mrb_state *mrb, mrb_value b, mrb_value v)
{
- return mrb_yield_with_self(mrb, b, 1, &v, mrb->stack[0]);
+ struct RProc *p = mrb_proc_ptr(b);
+
+ return mrb_yield_internal(mrb, b, 1, &v, mrb->stack[0], p->target_class);
}
static void
localjump_error(mrb_state *mrb, const char *kind)
{
char buf[256];
+ int len;
mrb_value exc;
- snprintf(buf, 256, "unexpected %s", kind);
- exc = mrb_exc_new(mrb, E_LOCALJUMP_ERROR, buf, strlen(buf));
+ len = snprintf(buf, sizeof(buf), "unexpected %s", kind);
+ exc = mrb_exc_new(mrb, E_LOCALJUMP_ERROR, buf, len);
mrb->exc = (struct RObject*)mrb_object(exc);
}
@@ -281,18 +310,19 @@ static void
argnum_error(mrb_state *mrb, int num)
{
char buf[256];
+ int len;
mrb_value exc;
if (mrb->ci->mid) {
- snprintf(buf, 256, "'%s': wrong number of arguments (%d for %d)",
- mrb_sym2name(mrb, mrb->ci->mid),
- mrb->ci->argc, num);
+ len = snprintf(buf, sizeof(buf), "'%s': wrong number of arguments (%d for %d)",
+ mrb_sym2name(mrb, mrb->ci->mid),
+ mrb->ci->argc, num);
}
else {
- snprintf(buf, 256, "wrong number of arguments (%d for %d)",
- mrb->ci->argc, num);
+ len = snprintf(buf, sizeof(buf), "wrong number of arguments (%d for %d)",
+ mrb->ci->argc, num);
}
- exc = mrb_exc_new(mrb, E_ARGUMENT_ERROR, buf, strlen(buf));
+ exc = mrb_exc_new(mrb, E_ARGUMENT_ERROR, buf, len);
mrb->exc = (struct RObject*)mrb_object(exc);
}
@@ -337,20 +367,20 @@ argnum_error(mrb_state *mrb, int num)
#ifndef DIRECT_THREADED
-#define INIT_DISPACTH for (;;) { i = *pc; switch (GET_OPCODE(i)) {
+#define INIT_DISPATCH for (;;) { i = *pc; switch (GET_OPCODE(i)) {
#define CASE(op) case op:
-#define NEXT mrb->arena_idx = ai; pc++; break
+#define NEXT pc++; break
#define JUMP break
-#define END_DISPACTH }}
+#define END_DISPATCH }}
#else
-#define INIT_DISPACTH JUMP; return mrb_nil_value();
+#define INIT_DISPATCH JUMP; return mrb_nil_value();
#define CASE(op) L_ ## op:
-#define NEXT mrb->arena_idx = ai; i=*++pc; goto *optable[GET_OPCODE(i)]
+#define NEXT i=*++pc; goto *optable[GET_OPCODE(i)]
#define JUMP i=*pc; goto *optable[GET_OPCODE(i)]
-#define END_DISPACTH
+#define END_DISPATCH
#endif
@@ -370,8 +400,8 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
mrb_value *regs = NULL;
mrb_code i;
int ai = mrb->arena_idx;
+ jmp_buf *prev_jmp = (jmp_buf *)mrb->jmp;
jmp_buf c_jmp;
- jmp_buf *prev_jmp = NULL;
#ifdef DIRECT_THREADED
static void *optable[] = {
@@ -400,7 +430,6 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
if (setjmp(c_jmp) == 0) {
- prev_jmp = mrb->jmp;
mrb->jmp = &c_jmp;
}
else {
@@ -413,7 +442,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
mrb->ci->nregs = irep->nregs + 2;
regs = mrb->stack;
- INIT_DISPACTH {
+ INIT_DISPATCH {
CASE(OP_NOP) {
/* do nothing */
NEXT;
@@ -453,14 +482,6 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
NEXT;
}
- CASE(OP_LOADNIL) {
- /* A B R(A) := nil */
- int a = GETARG_A(i);
-
- SET_NIL_VALUE(regs[a]);
- NEXT;
- }
-
CASE(OP_LOADSELF) {
/* A R(A) := self */
regs[GETARG_A(i)] = mrb->stack[0];
@@ -596,7 +617,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
if (mrb->rsize <= mrb->ci->ridx) {
if (mrb->rsize == 0) mrb->rsize = 16;
else mrb->rsize *= 2;
- mrb->rescue = mrb_realloc(mrb, mrb->rescue, sizeof(mrb_code*) * mrb->rsize);
+ mrb->rescue = (mrb_code **)mrb_realloc(mrb, mrb->rescue, sizeof(mrb_code*) * mrb->rsize);
}
mrb->rescue[mrb->ci->ridx++] = pc + GETARG_sBx(i);
NEXT;
@@ -633,9 +654,10 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
if (mrb->esize <= mrb->ci->eidx) {
if (mrb->esize == 0) mrb->esize = 16;
else mrb->esize *= 2;
- mrb->ensure = mrb_realloc(mrb, mrb->ensure, sizeof(struct RProc*) * mrb->esize);
+ mrb->ensure = (struct RProc **)mrb_realloc(mrb, mrb->ensure, sizeof(struct RProc*) * mrb->esize);
}
mrb->ensure[mrb->ci->eidx++] = p;
+ mrb->arena_idx = ai;
NEXT;
}
@@ -647,6 +669,15 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
for (n=0; n<a; n++) {
ecall(mrb, --mrb->ci->eidx);
}
+ mrb->arena_idx = ai;
+ NEXT;
+ }
+
+ CASE(OP_LOADNIL) {
+ /* A B R(A) := nil */
+ int a = GETARG_A(i);
+
+ SET_NIL_VALUE(regs[a]);
NEXT;
}
@@ -686,25 +717,29 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci->stackidx = mrb->stack - mrb->stbase;
ci->argc = n;
if (ci->argc == CALL_MAXARGS) ci->argc = -1;
- ci->target_class = m->target_class;
+ ci->target_class = c;
ci->pc = pc + 1;
+ ci->acc = a;
/* prepare stack */
mrb->stack += a;
if (MRB_PROC_CFUNC_P(m)) {
+ if (n == CALL_MAXARGS) {
+ ci->nregs = 3;
+ }
+ else {
+ ci->nregs = n + 2;
+ }
mrb->stack[0] = m->body.func(mrb, recv);
mrb->arena_idx = ai;
if (mrb->exc) goto L_RAISE;
/* pop stackpos */
- mrb->stack = mrb->stbase + ci->stackidx;
+ regs = mrb->stack = mrb->stbase + ci->stackidx;
cipop(mrb);
NEXT;
}
else {
- /* fill callinfo */
- ci->acc = a;
-
/* setup environment for calling method */
proc = mrb->ci->proc = m;
irep = m->body.irep;
@@ -766,6 +801,10 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
/* setup environment for calling method */
proc = m;
irep = m->body.irep;
+ if (!irep) {
+ mrb->stack[0] = mrb_nil_value();
+ goto L_RETURN;
+ }
pool = irep->pool;
syms = irep->syms;
ci->nregs = irep->nregs;
@@ -793,10 +832,9 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
int n = GETARG_C(i);
recv = regs[0];
- c = mrb->ci->proc->target_class->super;
+ c = mrb->ci->target_class->super;
m = mrb_method_search_vm(mrb, &c, mid);
if (!m) {
- c = mrb->ci->proc->target_class;
mid = mrb_intern(mrb, "method_missing");
m = mrb_method_search_vm(mrb, &c, mid);
if (n == CALL_MAXARGS) {
@@ -828,7 +866,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
mrb->arena_idx = ai;
if (mrb->exc) goto L_RAISE;
/* pop stackpos */
- mrb->stack = mrb->stbase + ci->stackidx;
+ regs = mrb->stack = mrb->stbase + ci->stackidx;
cipop(mrb);
NEXT;
}
@@ -867,6 +905,13 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
if (lv == 0) stack = regs + 1;
else {
struct REnv *e = uvenv(mrb, lv-1);
+ if (!e) {
+ 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);
+ goto L_RAISE;
+ }
stack = e->stack + 1;
}
if (r == 0) {
@@ -880,21 +925,22 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
if (stack[m1].tt == MRB_TT_ARRAY) {
struct RArray *ary = mrb_ary_ptr(stack[m1]);
- pp = ary->buf;
+ pp = ary->ptr;
len = ary->len;
}
regs[a] = mrb_ary_new_capa(mrb, m1+len+m2);
rest = mrb_ary_ptr(regs[a]);
- memcpy(rest->buf, stack, sizeof(mrb_value)*m1);
+ memcpy(rest->ptr, stack, sizeof(mrb_value)*m1);
if (len > 0) {
- memcpy(rest->buf+m1, pp, sizeof(mrb_value)*len);
+ memcpy(rest->ptr+m1, pp, sizeof(mrb_value)*len);
}
if (m2 > 0) {
- memcpy(rest->buf+m1+len, stack+m1+1, sizeof(mrb_value)*m2);
+ memcpy(rest->ptr+m1+len, stack+m1+1, sizeof(mrb_value)*m2);
}
rest->len = m1+len+m2;
}
regs[a+1] = stack[m1+r+m2];
+ mrb->arena_idx = ai;
NEXT;
}
@@ -914,12 +960,13 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
int argc = mrb->ci->argc;
mrb_value *argv = regs+1;
int len = m1 + o + r + m2;
+ mrb_value *blk = &argv[argc < 0 ? 1 : argc];
if (argc < 0) {
struct RArray *ary = mrb_ary_ptr(regs[1]);
- argv = ary->buf;
+ argv = ary->ptr;
argc = ary->len;
- regs[len+2] = regs[1]; /* save argary in register */
+ mrb_gc_protect(mrb, regs[1]);
}
if (mrb->ci->proc && MRB_PROC_STRICT_P(mrb->ci->proc)) {
if (argc >= 0) {
@@ -931,17 +978,19 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
}
else if (len > 1 && argc == 1 && argv[0].tt == MRB_TT_ARRAY) {
argc = mrb_ary_ptr(argv[0])->len;
- argv = mrb_ary_ptr(argv[0])->buf;
+ argv = mrb_ary_ptr(argv[0])->ptr;
}
mrb->ci->argc = len;
if (argc < len) {
- regs[len+1] = argv[argc]; /* move block */
+ regs[len+1] = *blk; /* move block */
memmove(&regs[1], argv, sizeof(mrb_value)*(argc-m2)); /* m1 + o */
memmove(&regs[len-m2+1], &argv[argc-m2], sizeof(mrb_value)*m2); /* m2 */
if (r) { /* r */
regs[m1+o+1] = mrb_ary_new_capa(mrb, 0);
}
- pc += argc - m1 - m2 + 1;
+ if (o == 0) pc++;
+ else
+ pc += argc - m1 - m2 + 1;
}
else {
memmove(&regs[1], argv, sizeof(mrb_value)*(m1+o)); /* m1 + o */
@@ -949,7 +998,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
regs[m1+o+1] = mrb_ary_new_elts(mrb, argc-m1-o-m2, argv+m1+o);
}
memmove(&regs[m1+o+r+1], &argv[argc-m2], sizeof(mrb_value)*m2);
- regs[len+1] = argv[argc]; /* move block */
+ regs[len+1] = *blk; /* move block */
pc += o + 1;
}
JUMP;
@@ -972,16 +1021,25 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
L_RETURN:
if (mrb->exc) {
mrb_callinfo *ci;
+ int eidx;
L_RAISE:
ci = mrb->ci;
+ eidx = mrb->ci->eidx;
if (ci == mrb->cibase) goto L_STOP;
while (ci[0].ridx == ci[-1].ridx) {
cipop(mrb);
ci = mrb->ci;
+ if (ci->acc < 0) {
+ mrb->jmp = prev_jmp;
+ longjmp(*(jmp_buf*)mrb->jmp, 1);
+ }
+ while (eidx > mrb->ci->eidx) {
+ ecall(mrb, --eidx);
+ }
if (ci == mrb->cibase) {
if (ci->ridx == 0) {
- mrb->stack = mrb->stbase;
+ regs = mrb->stack = mrb->stbase;
goto L_STOP;
}
break;
@@ -1076,7 +1134,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
/* replace callinfo */
- mrb->ci = ci = &mrb->ci[-1];
+ ci = mrb->ci;
ci->mid = mid;
ci->target_class = m->target_class;
ci->argc = n;
@@ -1120,6 +1178,10 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
if (lv == 0) stack = regs + 1;
else {
struct REnv *e = uvenv(mrb, lv-1);
+ if (!e) {
+ localjump_error(mrb, "yield");
+ goto L_RAISE;
+ }
stack = e->stack + 1;
}
regs[a] = stack[m1+r+m2];
@@ -1131,12 +1193,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
regs[a].value.v1 = regs[a].value.v1 op regs[a+1].value.v2;\
} while(0)
-#define OP_MATH(op) do {\
+#define OP_MATH(op,iop,s) do {\
int a = GETARG_A(i);\
- /* need to check if - is overridden */\
+ /* need to check if op is overridden */\
switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\
- OP_MATH_BODY(op,i,i); \
+ regs[a] = iop(mrb, regs[a], regs[a+1]);\
break;\
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):\
{\
@@ -1151,7 +1213,9 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\
OP_MATH_BODY(op,f,f);\
break;\
+ s\
default:\
+ SET_NIL_VALUE(regs[a+2]);\
i = MKOP_ABC(OP_SEND, a, GETARG_B(i), GETARG_C(i));\
goto L_SEND;\
}\
@@ -1159,50 +1223,29 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_ADD) {
/* A B C R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1)*/
- int a = GETARG_A(i);
-
- switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
- case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
- OP_MATH_BODY(+,i,i);
- break;
- case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
- {
- mrb_int x = regs[a].value.i;
- mrb_float y = regs[a+1].value.f;
- SET_FLOAT_VALUE(regs[a], (mrb_float)x + y);
- }
- break;
- case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
- OP_MATH_BODY(+,f,i);
- break;
- case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
- OP_MATH_BODY(+,f,f);
- break;
+ OP_MATH(+,mrb_fixnum_plus,
case TYPES2(MRB_TT_STRING,MRB_TT_STRING):
regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]);
- break;
- default:
- i = MKOP_ABC(OP_SEND, a, GETARG_B(i), GETARG_C(i));
- goto L_SEND;
- }
+ break;);
+ mrb->arena_idx = ai;
NEXT;
}
CASE(OP_SUB) {
/* A B C R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1)*/
- OP_MATH(-);
+ OP_MATH(-,mrb_fixnum_minus,;);
NEXT;
}
CASE(OP_MUL) {
/* A B C R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1)*/
- OP_MATH(*);
+ OP_MATH(*,mrb_fixnum_mul,;);
NEXT;
}
CASE(OP_DIV) {
/* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1)*/
- OP_MATH(/);
+ OP_MATH(/,mrb_num_div,;);
NEXT;
}
@@ -1219,6 +1262,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
regs[a].value.f += GETARG_C(i);
break;
default:
+ SET_NIL_VALUE(regs[a+2]);
SET_INT_VALUE(regs[a+1], GETARG_C(i));
i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1);
goto L_SEND;
@@ -1239,6 +1283,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
regs[a].value.f -= GETARG_C(i);
break;
default:
+ SET_NIL_VALUE(regs[a+2]);
SET_INT_VALUE(regs[a+1], GETARG_C(i));
i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1);
goto L_SEND;
@@ -1272,6 +1317,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
OP_CMP_BODY(op,f,f);\
break;\
default:\
+ SET_NIL_VALUE(regs[a+2]);\
i = MKOP_ABC(OP_SEND, a, GETARG_B(i), GETARG_C(i));\
goto L_SEND;\
}\
@@ -1317,6 +1363,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
mrb_ary_push(mrb, ary, regs[b++]);
}
regs[GETARG_A(i)] = ary;
+ mrb->arena_idx = ai;
NEXT;
}
@@ -1324,6 +1371,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
/* A B mrb_ary_concat(R(A),R(B)) */
mrb_ary_concat(mrb, regs[GETARG_A(i)],
mrb_ary_splat(mrb, regs[GETARG_B(i)]));
+ mrb->arena_idx = ai;
NEXT;
}
@@ -1379,15 +1427,15 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
int i;
if (len > pre + post) {
- regs[a++] = mrb_ary_new_elts(mrb, len - pre - post, ary->buf+pre);
+ regs[a++] = mrb_ary_new_elts(mrb, len - pre - post, ary->ptr+pre);
while (post--) {
- regs[a++] = ary->buf[len-post-1];
+ regs[a++] = ary->ptr[len-post-1];
}
}
else {
regs[a++] = mrb_ary_new_capa(mrb, 0);
for (i=0; i+pre<len; i++) {
- regs[a+i] = ary->buf[pre+i];
+ regs[a+i] = ary->ptr[pre+i];
}
while (i < post) {
SET_NIL_VALUE(regs[a+i]);
@@ -1395,12 +1443,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
}
}
}
+ mrb->arena_idx = ai;
NEXT;
}
CASE(OP_STRING) {
/* A Bx R(A) := str_new(Lit(Bx)) */
regs[GETARG_A(i)] = mrb_str_literal(mrb, pool[GETARG_Bx(i)]);
+ mrb->arena_idx = ai;
NEXT;
}
@@ -1422,6 +1472,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
b+=2;
}
regs[GETARG_A(i)] = hash;
+ mrb->arena_idx = ai;
NEXT;
}
@@ -1438,6 +1489,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
}
if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT;
regs[GETARG_A(i)] = mrb_obj_value(p);
+ mrb->arena_idx = ai;
NEXT;
}
@@ -1461,6 +1513,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
}
c = mrb_vm_define_class(mrb, base, super, id);
regs[a] = mrb_obj_value(c);
+ mrb->arena_idx = ai;
NEXT;
}
@@ -1477,6 +1530,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
}
c = mrb_vm_define_module(mrb, base, id);
regs[a] = mrb_obj_value(c);
+ mrb->arena_idx = ai;
NEXT;
}
@@ -1494,7 +1548,10 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci->mid = 0;
ci->stackidx = mrb->stack - mrb->stbase;
ci->argc = 0;
- ci->target_class = mrb_class_ptr(regs[GETARG_A(i)]);
+ ci->target_class = mrb_class_ptr(recv);
+
+ /* prepare stack */
+ mrb->stack += a;
p = mrb_proc_new(mrb, mrb->irep[irep->idx+GETARG_Bx(i)]);
p->target_class = ci->target_class;
@@ -1510,12 +1567,11 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
NEXT;
}
else {
- /* setup environment for calling method */
irep = p->body.irep;
pool = irep->pool;
syms = irep->syms;
- mrb->stack += a;
stack_extend(mrb, irep->nregs, 1);
+ ci->nregs = irep->nregs;
regs = mrb->stack;
pc = irep->iseq;
JUMP;
@@ -1528,17 +1584,25 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
struct RClass *c = mrb_class_ptr(regs[a]);
mrb_define_method_vm(mrb, c, syms[GETARG_B(i)], regs[a+1]);
+ mrb->arena_idx = ai;
NEXT;
}
CASE(OP_SCLASS) {
/* A B R(A) := R(B).singleton_class */
regs[GETARG_A(i)] = mrb_singleton_class(mrb, regs[GETARG_B(i)]);
+ mrb->arena_idx = ai;
NEXT;
}
CASE(OP_TCLASS) {
/* A B R(A) := target_class */
+ 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);
+ goto L_RAISE;
+ }
regs[GETARG_A(i)] = mrb_obj_value(mrb->ci->target_class);
NEXT;
}
@@ -1547,18 +1611,30 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
/* A B C R(A) := range_new(R(B),R(B+1),C) */
int b = GETARG_B(i);
regs[GETARG_A(i)] = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i));
+ mrb->arena_idx = ai;
NEXT;
}
CASE(OP_DEBUG) {
/* A debug print R(A),R(B),R(C) */
+#ifdef ENABLE_STDIO
printf("OP_DEBUG %d %d %d\n", GETARG_A(i), GETARG_B(i), GETARG_C(i));
+#else
+ abort();
+#endif
NEXT;
}
CASE(OP_STOP) {
/* stop VM */
L_STOP:
+ {
+ int n = mrb->ci->eidx;
+
+ while (n--) {
+ ecall(mrb, n);
+ }
+ }
mrb->jmp = prev_jmp;
if (mrb->exc) {
return mrb_obj_value(mrb->exc);
@@ -1569,11 +1645,11 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_ERR) {
/* Bx raise RuntimeError with message Lit(Bx) */
mrb_value msg = pool[GETARG_Bx(i)];
- mrb_value exc = mrb_exc_new3(mrb, mrb->eRuntimeError_class, msg);
+ mrb_value exc = mrb_exc_new3(mrb, E_RUNTIME_ERROR, msg);
mrb->exc = (struct RObject*)mrb_object(exc);
goto L_RAISE;
}
}
- END_DISPACTH;
+ END_DISPATCH;
}
diff --git a/test/Makefile b/test/Makefile
index 170c1dac8..921442b28 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -20,12 +20,19 @@ OBJS := driver.o $(MLIB)
LIBS = -lm
INCLUDES = -I$(BASEDIR)/../src -I$(BASEDIR)/../include
-DEBUG_MODE = 1
-ifeq ($(DEBUG_MODE),1)
-CFLAGS = -g
-else
-CFLAGS = -O3
+ifeq ($(strip $(COMPILE_MODE)),)
+ # default compile option
+ COMPILE_MODE = debug
+endif
+
+ifeq ($(COMPILE_MODE),debug)
+ CFLAGS = -g -O3
+else ifeq ($(COMPILE_MODE),release)
+ CFLAGS = -O3
+else ifeq ($(COMPILE_MODE),small)
+ CFLAGS = -Os
endif
+
ALL_CFLAGS = -Wall -Werror-implicit-function-declaration $(CFLAGS)
ifeq ($(OS),Windows_NT)
MAKE_FLAGS = CC=$(CC) LL=$(LL) ALL_CFLAGS="$(ALL_CFLAGS)"
diff --git a/test/assert.rb b/test/assert.rb
index 239730cb9..89e820a00 100644
--- a/test/assert.rb
+++ b/test/assert.rb
@@ -2,6 +2,7 @@ $ok_test = 0
$ko_test = 0
$kill_test = 0
$asserts = []
+$test_start = Time.now if Object.const_defined?(:Time)
##
# Print the assertion in a readable way
@@ -32,7 +33,7 @@ def assert(str = 'Assertion failed', iso = '')
$ok_test += 1
print('.')
end
- rescue => e
+ rescue Exception => e
$asserts.push(['Error: ', str, iso, e])
$kill_test += 1
print('X')
@@ -68,18 +69,24 @@ def report()
print('Crash: ')
print($kill_test)
print("\n")
+
+ if Object.const_defined?(:Time)
+ print(' Time: ')
+ print(Time.now - $test_start)
+ print(" seconds\n")
+ end
end
##
# Performs fuzzy check for equality on methods returning floats
# on the basis of the Math::TOLERANCE constant.
def check_float(a, b)
+ tolerance = Math::TOLERANCE
a = a.to_f
b = b.to_f
if a.finite? and b.finite?
- (a-b).abs < Math::TOLERANCE
+ (a-b).abs < tolerance
else
true
end
end
-
diff --git a/test/driver.c b/test/driver.c
index 4651d75fc..d2ad31b26 100644
--- a/test/driver.c
+++ b/test/driver.c
@@ -11,6 +11,7 @@
#include <mruby/proc.h>
#include <mruby/data.h>
#include <mruby/compile.h>
+#include <mruby/variable.h>
void
mrb_init_mrbtest(mrb_state *);
@@ -23,39 +24,47 @@ void print_hint(void)
printf("Thanks :)\n\n");
}
+static int
+check_error(mrb_state *mrb)
+{
+ /* Error check */
+ /* $ko_test and $kill_test should be 0 */
+ mrb_value ko_test = mrb_gv_get(mrb, mrb_intern(mrb, "$ko_test"));
+ mrb_value kill_test = mrb_gv_get(mrb, mrb_intern(mrb, "$kill_test"));
+
+ return FIXNUM_P(ko_test) && mrb_fixnum(ko_test) == 0 && FIXNUM_P(kill_test) && mrb_fixnum(kill_test) == 0;
+}
+
int
main(void)
{
- struct mrb_parser_state *parser;
mrb_state *mrb;
mrb_value return_value;
- int byte_code;
const char *prog = "report()";
+ int ret = EXIT_SUCCESS;
print_hint();
/* new interpreter instance */
mrb = mrb_open();
- mrb_init_mrbtest(mrb);
- parser = mrb_parse_nstring(mrb, prog, strlen(prog));
-
- /* generate bytecode */
- byte_code = mrb_generate_code(mrb, parser->tree);
+ if (mrb == NULL) {
+ fprintf(stderr, "Invalid mrb_state, exiting test driver");
+ return EXIT_FAILURE;
+ }
- /* evaluate the bytecode */
- return_value = mrb_run(mrb,
- /* pass a proc for evaulation */
- mrb_proc_new(mrb, mrb->irep[byte_code]),
- mrb_top_self(mrb));
+ 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 {
- /* no */
+ else if (!check_error(mrb)) {
+ ret = EXIT_FAILURE;
}
mrb_close(mrb);
- return 0;
+ return ret;
}
diff --git a/test/t/argumenterror.rb b/test/t/argumenterror.rb
index ca998f8de..71cf38e26 100644
--- a/test/t/argumenterror.rb
+++ b/test/t/argumenterror.rb
@@ -13,3 +13,8 @@ assert('ArgumentError', '15.2.24') do
ArgumentError.class == Class and e2.class == ArgumentError
end
+
+assert('ArgumentError superclass', '15.2.24.2') do
+ ArgumentError.superclass == StandardError
+end
+
diff --git a/test/t/array.rb b/test/t/array.rb
index dba1b035d..cb99cea6a 100644
--- a/test/t/array.rb
+++ b/test/t/array.rb
@@ -5,6 +5,10 @@ assert('Array', '15.2.12') do
Array.class == Class
end
+assert('Array superclass', '15.2.12.2') do
+ Array.superclass == Object
+end
+
assert('Array.[]', '15.2.12.4.1') do
Array.[](1,2,3) == [1, 2, 3]
end
@@ -61,6 +65,7 @@ assert('Array#[]=', '15.2.12.5.5') do
end
[1,2,3].[]=(1,4) == [1, 4, 3] and
+ [1,2,3].[]=(1,2,3) == [1, 3] and
e2.class == ArgumentError and
e3.class == ArgumentError
end
@@ -113,7 +118,24 @@ assert('Array#first', '15.2.12.5.13') do
a = []
b = [1,2,3]
- a.first == nil and b.first == 1
+ e2 = nil
+ e3 = nil
+ begin
+ # this will cause an exception due to the wrong argument
+ [1,2,3].first(-1)
+ rescue => e1
+ e2 = e1
+ end
+ begin
+ # this will cause an exception due to the wrong argument
+ [1,2,3].first(1,2)
+ rescue => e1
+ e3 = e1
+ end
+
+ a.first == nil and b.first == 1 and b.first(0) == [] and
+ b.first(1) == [1] and b.first(4) == [1,2,3] and
+ e2.class == ArgumentError and e3.class == ArgumentError
end
assert('Array#index', '15.2.12.5.14') do
@@ -148,7 +170,15 @@ end
assert('Array#last', '15.2.12.5.18') do
a = [1,2,3]
- a.last == 3 and [].last == nil
+ e2 = nil
+ begin
+ # this will cause an exception due to the wrong argument
+ [1,2,3].last(-1)
+ rescue => e1
+ e2 = e1
+ end
+
+ a.last == 3 and [].last == nil and e2.class == ArgumentError
end
assert('Array#length', '15.2.12.5.19') do
@@ -218,7 +248,9 @@ assert('Array#size', '15.2.12.5.28') do
end
assert('Array#slice', '15.2.12.5.29') do
- [1,2,3].[](1) == 2
+ a = "12345".slice(1, 3)
+ b = a.slice(0)
+ "#{b}:" == "2:" and [1,2,3].[](1) == 2
end
assert('Array#unshift', '15.2.12.5.30') do
@@ -228,4 +260,35 @@ assert('Array#unshift', '15.2.12.5.30') do
a == [1,2,3] and b == [1,2,3]
end
+assert('Array#to_s', '15.2.12.5.31') do
+ a = [2, 3, 4, 5]
+ r1 = a.to_s
+ r2 = a.inspect
+
+ r1 == r2 and r1 == "[2, 3, 4, 5]"
+end
+
+assert('Array#==', '15.2.12.5.33') do
+ r1 = [ "a", "c" ] == [ "a", "c", 7 ] #=> false
+ r2 = [ "a", "c", 7 ] == [ "a", "c", 7 ] #=> true
+ r3 = [ "a", "c", 7 ] == [ "a", "d", "f" ] #=> false
+
+ r1 == false and r2 == true and r3 == false
+end
+
+assert('Array#<=>', '15.2.12.5.36') do
+ r1 = [ "a", "a", "c" ] <=> [ "a", "b", "c" ] #=> -1
+ r2 = [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ] #=> +1
+
+ r1 == -1 and r2 == +1
+end
+
# Not ISO specified
+
+assert("Array (Shared Array Corruption)") do
+ a = [ "a", "b", "c", "d", "e", "f" ]
+ b = a.slice(1, 3)
+ a.clear
+ b.clear
+end
+
diff --git a/test/t/basicobject.rb b/test/t/basicobject.rb
new file mode 100644
index 000000000..f7e95af89
--- /dev/null
+++ b/test/t/basicobject.rb
@@ -0,0 +1,11 @@
+##
+# BasicObject
+
+assert('BasicObject') do
+ BasicObject.class == Class
+end
+
+assert('BasicObject superclass') do
+ BasicObject.superclass == nil
+end
+
diff --git a/test/t/bs_block.rb b/test/t/bs_block.rb
index b290cb914..bef9a8564 100644
--- a/test/t/bs_block.rb
+++ b/test/t/bs_block.rb
@@ -62,11 +62,11 @@ end
assert('BS Block 7') do
ans = []
for m in 1..3
- for n in 1..3
+ for n in 2..4
a = [m, n]
ans << a
end
- end == 1..3
+ end == (1..3)
end
assert('BS Block 8') do
@@ -322,28 +322,28 @@ assert('BS Block [ruby-dev:31147]') do
def m
yield
end
- m{|&b| b}.inspect == 'nil'
+ m{|&b| b} == nil
end
assert('BS Block [ruby-dev:31160]') do
def m()
yield
end
- m {|(v,(*))|}.inspect == 'nil'
+ m {|(v,(*))|} == nil
end
assert('BS Block 31') do
def m()
yield
end
- m {|((*))|}.inspect == 'nil'
+ m {|((*))|} == nil
end
assert('BS Block [ruby-dev:31440]') do
def m
yield [0]
end
- m{|v, &b| v}.inspect == '[0]'
+ m{|v, &b| v} == [0]
end
assert('BS Block 32') do
diff --git a/test/t/class.rb b/test/t/class.rb
index 92f3df51d..d6c4715dd 100644
--- a/test/t/class.rb
+++ b/test/t/class.rb
@@ -5,39 +5,124 @@ assert('Class', '15.2.3') do
Class.class == Class
end
+assert('Class superclass', '15.2.3.2') do
+ Class.superclass == Module
+end
+
+assert('Class#new', '15.2.3.3.3') do
+ # at the moment no exception on singleton class
+ #e1 = nil
+ #begin
+ # class1 = e1.singleton_class.new
+ #rescue => e1
+ # e2 = e1
+ #end
+
+ class TestClass
+ def initialize args, &block
+ @result = if not args.nil? and block.nil?
+ # only arguments
+ :only_args
+ elsif not args.nil? and not block.nil?
+ # args and block is given
+ :args_and_block
+ else
+ # this should never happen
+ :broken
+ end
+ end
+
+ def result; @result; end
+ end
+
+ TestClass.new(:arg).result == :only_args
+ # with block doesn't work yet
+end
+
+assert('Class#superclass', '15.2.3.3.4') do
+ class SubClass < String; end
+ SubClass.superclass == String
+end
+
# Not ISO specified
assert('Class 1') do
- class C; end
- C.class == Class
+ class C1; end
+ C1.class == Class
end
assert('Class 2') do
- class C; end
- C.new.class == C
+ class C2; end
+ C2.new.class == C2
end
assert('Class 3') do
- class C; end
- C.new.class.class == Class
+ class C3; end
+ C3.new.class.class == Class
end
assert('Class 4') do
- class A; end
- class C < A; end
- C.class == Class
+ class C4_A; end
+ class C4 < C4_A; end
+ C4.class == Class
end
assert('Class 5') do
- class A; end
- class C < A; end
- C.new.class == C
+ class C5_A; end
+ class C5 < C5_A; end
+ C5.new.class == C5
end
assert('Class 6') do
- class A; end
- class C < A; end
- C.new.class.class == Class
+ class C6_A; end
+ class C6 < C6_A; end
+ C6.new.class.class == Class
+end
+
+assert('Class 7') do
+ class C7_A; end
+ class C7_B; end
+
+ class C7 < C7_A; end
+
+ error = false
+ begin
+ # Different superclass.
+ class C7 < C7_B; end
+ rescue TypeError
+ error = true
+ end
+
+ error
+end
+
+assert('Class 8') do
+ class C8_A; end
+
+ class C8; end # superclass is Object
+
+ error = false
+ begin
+ # Different superclass.
+ class C8 < C8_A; end
+ rescue TypeError
+ error = true
+ end
+
+ error
+end
+
+assert('Class 9') do
+ Class9Const = "a"
+
+ error = false
+ begin
+ class Class9Const; end
+ rescue TypeError
+ error = true
+ end
+
+ error
end
assert('Class Module 1') do
diff --git a/test/t/comparable.rb b/test/t/comparable.rb
new file mode 100644
index 000000000..f3c03a9b5
--- /dev/null
+++ b/test/t/comparable.rb
@@ -0,0 +1,56 @@
+
+assert('<', '15.3.3.2.1') do
+ class Foo
+ include Comparable
+ def <=>(x)
+ 0
+ end
+ end
+
+ (Foo.new < Foo.new) == false
+end
+
+assert('<=', '15.3.3.2.2') do
+ class Foo
+ include Comparable
+ def <=>(x)
+ 0
+ end
+ end
+
+ (Foo.new <= Foo.new) == true
+end
+
+assert('==', '15.3.3.2.3') do
+ class Foo
+ include Comparable
+ def <=>(x)
+ 0
+ end
+ end
+
+ (Foo.new == Foo.new) == true
+end
+
+assert('>', '15.3.3.2.4') do
+ class Foo
+ include Comparable
+ def <=>(x)
+ 0
+ end
+ end
+
+ (Foo.new > Foo.new) == false
+end
+
+assert('>=', '15.3.3.2.5') do
+ class Foo
+ include Comparable
+ def <=>(x)
+ 0
+ end
+ end
+
+ (Foo.new >= Foo.new) == true
+end
+
diff --git a/test/t/exception.rb b/test/t/exception.rb
index 6b46314d0..0aed0e2e6 100644
--- a/test/t/exception.rb
+++ b/test/t/exception.rb
@@ -5,6 +5,10 @@ assert('Exception', '15.2.22') do
Exception.class == Class
end
+assert('Exception superclass', '15.2.22.2') do
+ Exception.superclass == Object
+end
+
assert('Exception.exception', '15.2.22.4.1') do
e = Exception.exception('a')
@@ -20,7 +24,7 @@ end
assert('Exception#message', '15.2.22.5.2') do
e = Exception.exception('a')
-
+
e.message == 'a'
end
@@ -37,6 +41,26 @@ assert('Exception.exception', '15.2.22.4.1') do
e.message == 'a'
end
+assert('ScriptError', '15.2.37') do
+ begin
+ raise ScriptError.new
+ rescue ScriptError
+ true
+ else
+ false
+ end
+end
+
+assert('SyntaxError', '15.2.38') do
+ begin
+ raise SyntaxError.new
+ rescue SyntaxError
+ true
+ else
+ false
+ end
+end
+
# Not ISO specified
assert('Exception 1') do
@@ -193,3 +217,39 @@ assert('Exception 10') do
7+7
end == 12
end
+
+assert('Exception 11') do
+ a = :ok
+ begin
+ begin
+ raise Exception
+ rescue
+ a = :ng
+ end
+ rescue Exception
+ end
+ a == :ok
+end
+
+assert('Exception 12') do
+ a = :ok
+ begin
+ raise Exception rescue a = :ng
+ rescue Exception
+ end
+ a == :ok
+end
+
+assert('Exception 13') do
+ a = :ng
+ begin
+ raise StandardError
+ rescue TypeError, ArgumentError
+ a = :ng
+ rescue
+ a = :ok
+ else
+ a = :ng
+ end
+ a == :ok
+end
diff --git a/test/t/false.rb b/test/t/false.rb
index c2db283c8..50ba5623a 100644
--- a/test/t/false.rb
+++ b/test/t/false.rb
@@ -5,22 +5,26 @@ assert('FalseClass', '15.2.6') do
FalseClass.class == Class
end
+assert('FalseClass superclass', '15.2.6.2') do
+ FalseClass.superclass == Object
+end
+
assert('FalseClass false', '15.2.6.1') do
not false
end
assert('FalseClass#&', '15.2.6.3.1') do
- not FalseClass.new.&(true) and not FalseClass.new.&(false)
+ not false.&(true) and not false.&(false)
end
assert('FalseClass#^', '15.2.6.3.2') do
- FalseClass.new.^(true) and not FalseClass.new.^(false)
+ false.^(true) and not false.^(false)
end
assert('FalseClass#to_s', '15.2.6.3.3') do
- FalseClass.new.to_s == 'false'
+ false.to_s == 'false'
end
assert('FalseClass#|', '15.2.6.3.4') do
- FalseClass.new.|(true) and not FalseClass.new.|(false)
+ false.|(true) and not false.|(false)
end
diff --git a/test/t/float.rb b/test/t/float.rb
index fc87a5b22..e2c139c03 100644
--- a/test/t/float.rb
+++ b/test/t/float.rb
@@ -5,6 +5,10 @@ assert('Float', '15.2.9') do
Float.class == Class
end
+assert('Float superclass', '15.2.9.2') do
+ Float.superclass == Numeric
+end
+
assert('Float#+', '15.2.9.3.1') do
a = 3.123456788 + 0.000000001
b = 3.123456789 + 1
@@ -22,11 +26,11 @@ assert('Float#-', '15.2.9.3.2') do
end
assert('Float#*', '15.2.9.3.3') do
- a = 3.123456789 * 3.123456789
- b = 3.123456789 * 1
+ a = 3.125 * 3.125
+ b = 3.125 * 1
- check_float(a, 9.75598231275019) and
- check_float(b, 3.123456789)
+ check_float(a, 9.765625) and
+ check_float(b, 3.125)
end
assert('Float#/', '15.2.9.3.4') do
@@ -38,19 +42,19 @@ assert('Float#/', '15.2.9.3.4') do
end
assert('Float#%', '15.2.9.3.5') do
- a = 3.123456789 % 3.123456789
- b = 3.123456789 % 1
+ a = 3.125 % 3.125
+ b = 3.125 % 1
check_float(a, 0.0) and
- check_float(b, 0.123456789)
+ check_float(b, 0.125)
end
assert('Float#<=>', '15.2.9.3.6') do
- a = 3.123456789 <=> 3.123456788
- b = 3.123456789 <=> 3.123456789
- c = 3.123456789 <=> 3.123456790
- a2 = 3.123456789 <=> 3
- c2 = 3.123456789 <=> 4
+ a = 3.125 <=> 3.123
+ b = 3.125 <=> 3.125
+ c = 3.125 <=> 3.126
+ a2 = 3.125 <=> 3
+ c2 = 3.125 <=> 4
a == 1 and b == 0 and c == -1 and
a2 == 1 and c2 == -1
@@ -61,7 +65,11 @@ assert('Float#==', '15.2.9.3.7') do
end
assert('Float#ceil', '15.2.9.3.8') do
- 3.123456789.ceil == 4
+ a = 3.123456789.ceil
+ b = 3.0.ceil
+ c = -3.123456789.ceil
+ d = -3.0.ceil
+ a == 4 and b == 3 and c == -3 and d == -3
end
assert('Float#finite?', '15.2.9.3.9') do
@@ -70,20 +78,34 @@ assert('Float#finite?', '15.2.9.3.9') do
end
assert('Float#floor', '15.2.9.3.10') do
- 3.123456789.floor == 3
+ a = 3.123456789.floor
+ b = 3.0.floor
+ c = -3.123456789.floor
+ d = -3.0.floor
+ a == 3 and b == 3 and c == -4 and d == -3
end
assert('Float#infinite?', '15.2.9.3.11') do
- not 3.123456789.infinite? and
- (1.0 / 0.0).infinite?
+ a = 3.123456789.infinite?
+ b = (1.0 / 0.0).infinite?
+ c = (-1.0 / 0.0).infinite?
+
+ a == nil and b == 1 and c == -1
end
assert('Float#round', '15.2.9.3.12') do
a = 3.123456789.round
b = 3.5.round
- c = 3.499999999.round
+ c = 3.4999.round
+ d = (-3.123456789).round
+ e = (-3.5).round
+ f = 12345.67.round(-1)
+ g = 3.423456789.round(0)
+ h = 3.423456789.round(1)
+ i = 3.423456789.round(3)
- a == 3 and b == 4 and c == 3
+ a == 3 and b == 4 and c == 3 and d == -3 and e == -4 and
+ f == 12350 and g == 3 and h == 3.4 and i == 3.423
end
assert('Float#to_f', '15.2.9.3.13') do
@@ -97,5 +119,5 @@ assert('Float#to_i', '15.2.9.3.14') do
end
assert('Float#truncate', '15.2.9.3.15') do
- 3.123456789.truncate == 3
+ 3.123456789.truncate == 3 and -3.1.truncate == -3
end
diff --git a/test/t/hash.rb b/test/t/hash.rb
index af662688a..04a9a1c24 100644
--- a/test/t/hash.rb
+++ b/test/t/hash.rb
@@ -5,6 +5,10 @@ assert('Hash', '15.2.13') do
Hash.class == Class
end
+assert('Hash superclass', '15.2.13.2') do
+ Hash.superclass == Object
+end
+
assert('Hash#==', '15.2.13.4.1') do
({ 'abc' => 'abc' } == { 'abc' => 'abc' }) and
not ({ 'abc' => 'abc' } == { 'cba' => 'cba' })
@@ -224,3 +228,42 @@ assert('Hash#values', '15.2.13.4.28') do
a.values == ['abc_value']
end
+
+# Not ISO specified
+
+assert('Hash#reject') do
+ h = {:one => 1, :two => 2, :three => 3, :four => 4}
+ ret = h.reject do |k,v|
+ v % 2 == 0
+ end
+ ret == {:one => 1, :three => 3} and
+ h == {:one => 1, :two => 2, :three => 3, :four => 4}
+end
+
+assert('Hash#reject!') do
+ h = {:one => 1, :two => 2, :three => 3, :four => 4}
+ ret = h.reject! do |k,v|
+ v % 2 == 0
+ end
+ ret == {:one => 1, :three => 3} and
+ h == {:one => 1, :three => 3}
+end
+
+assert('Hash#select') do
+ h = {:one => 1, :two => 2, :three => 3, :four => 4}
+ ret = h.select do |k,v|
+ v % 2 == 0
+ end
+ ret == {:two => 2, :four => 4} and
+ h == {:one => 1, :two => 2, :three => 3, :four => 4}
+end
+
+assert('Hash#select!') do
+ h = {:one => 1, :two => 2, :three => 3, :four => 4}
+ ret = h.select! do |k,v|
+ v % 2 == 0
+ end
+ ret == {:two => 2, :four => 4} and
+ h == {:two => 2, :four => 4}
+end
+
diff --git a/test/t/indexerror.rb b/test/t/indexerror.rb
index d0cb81f32..d7c8ba148 100644
--- a/test/t/indexerror.rb
+++ b/test/t/indexerror.rb
@@ -4,3 +4,8 @@
assert('IndexError', '15.2.33') do
IndexError.class == Class
end
+
+assert('IndexError superclass', '15.2.33.2') do
+ IndexError.superclass == StandardError
+end
+
diff --git a/test/t/integer.rb b/test/t/integer.rb
index 8c112861a..872723445 100644
--- a/test/t/integer.rb
+++ b/test/t/integer.rb
@@ -5,6 +5,10 @@ assert('Integer', '15.2.8') do
Integer.class == Class
end
+assert('Integer superclass', '15.2.8.2') do
+ Integer.superclass == Numeric
+end
+
assert('Integer#+', '15.2.8.3.1') do
a = 1+1
b = 1+1.0
diff --git a/test/t/kernel.rb b/test/t/kernel.rb
index cd1f2d99e..b96e85134 100644
--- a/test/t/kernel.rb
+++ b/test/t/kernel.rb
@@ -6,7 +6,21 @@ assert('Kernel', '15.3.1') do
end
assert('Kernel.block_given?', '15.3.1.2.2') do
- Kernel.block_given? == false
+ def bg_try(&b)
+ if Kernel.block_given?
+ yield
+ else
+ "no block"
+ end
+ end
+
+ (Kernel.block_given? == false) and
+ # test without block
+ (bg_try == "no block") and
+ # test with block
+ ((bg_try { "block" }) == "block") and
+ # test with block
+ ((bg_try do "block" end) == "block")
end
assert('Kernel.global_variables', '15.3.1.2.4') do
@@ -22,13 +36,16 @@ assert('Kernel.lambda', '15.3.1.2.6') do
true
end
- l.call and l.class == Proc
-end
+ m = Kernel.lambda(&l)
-assert('Kernel.local_variables', '15.3.1.2.7') do
- Kernel.local_variables.class == Array
+ l.call and l.class == Proc and m.call and m.class == Proc
end
+# Not implemented at the moment
+#assert('Kernel.local_variables', '15.3.1.2.7') do
+# Kernel.local_variables.class == Array
+#end
+
assert('Kernel.loop', '15.3.1.2.8') do
i = 0
@@ -55,28 +72,182 @@ assert('Kernel.puts', '15.3.1.2.11') do
true
end
-# TODO fails at the moment without arguments
assert('Kernel.raise', '15.3.1.2.12') do
e_list = []
begin
- raise RuntimeError.new
+ Kernel.raise
rescue => e
e_list << e
end
- e_list[0].class == RuntimeError
+ begin
+ Kernel.raise RuntimeError.new
+ rescue => e
+ e_list << e
+ end
+
+ # result without argument
+ e_list[0].class == RuntimeError and
+ # result with RuntimeError argument
+ e_list[1].class == RuntimeError
+end
+
+assert('Kernel#__id__', '15.3.1.3.3') do
+ __id__.class == Fixnum
+end
+
+assert('Kernel#__send__', '15.3.1.3.4') do
+ # test with block
+ l = __send__(:lambda) do
+ true
+ end
+
+ l.call and l.class == Proc and
+ # test with argument
+ __send__(:respond_to?, :nil?) and
+ # test without argument and without block
+ __send__(:public_methods).class == Array
+end
+
+assert('Kernel#block_given?', '15.3.1.3.6') do
+ def bg_try(&b)
+ if block_given?
+ yield
+ else
+ "no block"
+ end
+ end
+
+ (block_given? == false) and
+ (bg_try == "no block") and
+ ((bg_try { "block" }) == "block") and
+ ((bg_try do "block" end) == "block")
+end
+
+assert('Kernel#class', '15.3.1.3.7') do
+ Kernel.class == Module
+end
+
+assert('Kernel#clone', '15.3.1.3.8') do
+ class KernelCloneTest
+ def initialize
+ @v = 0
+ end
+
+ def get
+ @v
+ end
+
+ def set(v)
+ @v = v
+ end
+ end
+
+ a = KernelCloneTest.new
+ a.set(1)
+ b = a.clone
+
+ def a.test
+ end
+ a.set(2)
+ c = a.clone
+
+ a.get == 2 and b.get == 1 and c.get == 2 &&
+ a.respond_to?(:test) == true and
+ b.respond_to?(:test) == false and
+ c.respond_to?(:test) == true
+end
+
+assert('Kernel#dup', '15.3.1.3.9') do
+ class KernelDupTest
+ def initialize
+ @v = 0
+ end
+
+ def get
+ @v
+ end
+
+ def set(v)
+ @v = v
+ end
+ end
+
+ a = KernelDupTest.new
+ a.set(1)
+ b = a.dup
+
+ def a.test
+ end
+ a.set(2)
+ c = a.dup
+
+ a.get == 2 and b.get == 1 and c.get == 2 and
+ a.respond_to?(:test) == true and
+ b.respond_to?(:test) == false and
+ c.respond_to?(:test) == false
+end
+
+assert('Kernel#extend', '15.3.1.3.13') do
+ class Test4ExtendClass
+ end
+
+ module Test4ExtendModule
+ def test_method; end
+ end
+
+ a = Test4ExtendClass.new
+ a.extend(Test4ExtendModule)
+ b = Test4ExtendClass.new
+
+ a.respond_to?(:test_method) == true && b.respond_to?(:test_method) == false
+end
+
+assert('Kernel#global_variables', '15.3.1.3.14') do
+ global_variables.class == Array
end
-assert('Kernel#hash', '15.3.1.2.15') do
+assert('Kernel#hash', '15.3.1.3.15') do
hash == hash
end
-assert('Kernel#local_variables', '15.3.1.2.28') do
- local_variables.class == Array
+assert('Kernel#inspect', '15.3.1.3.17') do
+ inspect.class == String
+end
+
+assert('Kernel#instance_variables', '15.3.1.3.23') do
+ instance_variables.class == Array
+end
+
+assert('Kernel#is_a?', '15.3.1.3.24') do
+ is_a?(Kernel) and not is_a?(Array)
+end
+
+assert('Kernel#iterator?', '15.3.1.3.25') do
+ iterator? == false
+end
+
+assert('Kernel#kind_of?', '15.3.1.3.26') do
+ kind_of?(Kernel) and not kind_of?(Array)
end
-assert('Kernel#loop', '15.3.1.2.29') do
+assert('Kernel#lambda', '15.3.1.3.27') do
+ l = lambda do
+ true
+ end
+
+ m = lambda(&l)
+
+ l.call and l.class == Proc and m.call and m.class == Proc
+end
+
+# Not implemented yet
+#assert('Kernel#local_variables', '15.3.1.3.28') do
+# local_variables.class == Array
+#end
+
+assert('Kernel#loop', '15.3.1.3.29') do
i = 0
loop do
@@ -87,38 +258,78 @@ assert('Kernel#loop', '15.3.1.2.29') do
i == 100
end
-assert('Kernel#methods', '15.3.1.2.31') do
+assert('Kernel#methods', '15.3.1.3.31') do
methods.class == Array
end
-assert('Kernel#nil?', '15.3.1.2.32') do
- # TODO why is Kernel nil ????
- nil? == true
+assert('Kernel#nil?', '15.3.1.3.32') do
+ nil.nil? == true
+end
+
+assert('Kernel#object_id', '15.3.1.3.33') do
+ object_id.class == Fixnum
end
-assert('Kernel#private_methods', '15.3.1.2.36') do
- private_methods.class == Array
+assert('Kernel#private_methods', '15.3.1.3.36') do
+ private_methods.class == Array
end
-assert('Kernel#protected_methods', '15.3.1.2.37') do
+assert('Kernel#protected_methods', '15.3.1.3.37') do
protected_methods.class == Array
end
-assert('Kernel#public_methods', '15.3.1.2.38') do
+assert('Kernel#public_methods', '15.3.1.3.38') do
public_methods.class == Array
end
-assert('Kernel#respond_to?', '15.3.1.2.43') do
- respond_to? :nil?
+assert('Kernel#raise', '15.3.1.3.40') do
+ e_list = []
+
+ begin
+ raise
+ rescue => e
+ e_list << e
+ end
+
+ begin
+ raise RuntimeError.new
+ rescue => e
+ e_list << e
+ end
+
+ # result without argument
+ e_list[0].class == RuntimeError and
+ # result with RuntimeError argument
+ e_list[1].class == RuntimeError
+end
+
+assert('Kernel#respond_to?', '15.3.1.3.43') do
+ class Test4RespondTo
+ def test_method; end
+ undef test_method
+ end
+
+ respond_to?(:nil?) and Test4RespondTo.new.respond_to?(:test_method) == false
end
-# TODO at the moment doesn't comply to ISO assert('Kernel#send', '15.3.1.2.44') do
+assert('Kernel#send', '15.3.1.3.44') do
+ # test with block
+ l = send(:lambda) do
+ true
+ end
+
+ l.call and l.class == Proc and
+ # test with argument
+ send(:respond_to?, :nil?) and
+ # test without argument and without block
+ send(:public_methods).class == Array
+end
-assert('Kernel#singleton_methods', '15.3.1.2.45') do
+assert('Kernel#singleton_methods', '15.3.1.3.45') do
singleton_methods.class == Array
end
-assert('Kernel#to_s', '15.3.1.2.46') do
+assert('Kernel#to_s', '15.3.1.3.46') do
# TODO looks strange..
to_s == ''
end
diff --git a/test/t/math.rb b/test/t/math.rb
index 5b9da4cb3..d71e44fc9 100644
--- a/test/t/math.rb
+++ b/test/t/math.rb
@@ -1,105 +1,117 @@
##
# Math Test
-assert('Math.sin 0') do
- check_float(Math.sin(0), 0)
-end
+if Object.const_defined?(:Math)
+ assert('Math.sin 0') do
+ check_float(Math.sin(0), 0)
+ end
-assert('Math.sin PI/2') do
- check_float(Math.sin(Math::PI / 2), 1)
-end
+ assert('Math.sin PI/2') do
+ check_float(Math.sin(Math::PI / 2), 1)
+ end
+ assert('Fundamental trig identities') do
+ result = true
+ N = 13
+ N.times do |i|
+ a = Math::PI / N * i
+ ca = Math::PI / 2 - a
+ s = Math.sin(a)
+ c = Math.cos(a)
+ t = Math.tan(a)
+ result &= check_float(s, Math.cos(ca))
+ result &= check_float(t, 1 / Math.tan(ca))
+ result &= check_float(s ** 2 + c ** 2, 1)
+ result &= check_float(t ** 2 + 1, (1/c) ** 2)
+ result &= check_float((1/t) ** 2 + 1, (1/s) ** 2)
+ end
+ result
+ end
-assert('Fundamental trig identities') do
- result = true
- N = 15
- N.times do |i|
- a = Math::PI / N * i
- ca = Math::PI / 2 - a
- s = Math.sin(a)
- c = Math.cos(a)
- t = Math.tan(a)
- result &= check_float(s, Math.cos(ca))
- result &= check_float(t, 1 / Math.tan(ca))
- result &= check_float(s ** 2 + c ** 2, 1)
- result &= check_float(t ** 2 + 1, (1/c) ** 2)
- result &= check_float((1/t) ** 2 + 1, (1/s) ** 2)
- end
- result
-end
+ assert('Math.erf 0') do
+ check_float(Math.erf(0), 0)
+ end
-assert('Math.erf 0') do
- check_float(Math.erf(0), 0)
-end
+ assert('Math.exp 0') do
+ check_float(Math.exp(0), 1.0)
+ end
-assert('Math.exp 0') do
- check_float(Math.exp(0), 1.0)
-end
+ assert('Math.exp 1') do
+ check_float(Math.exp(1), 2.718281828459045)
+ end
-assert('Math.exp 1') do
- check_float(Math.exp(1), 2.718281828459045)
-end
+ assert('Math.exp 1.5') do
+ check_float(Math.exp(1.5), 4.4816890703380645)
+ end
-assert('Math.exp 1.5') do
- check_float(Math.exp(1.5), 4.4816890703380645)
-end
+ assert('Math.log 1') do
+ check_float(Math.log(1), 0)
+ end
-assert('Math.log 1') do
- check_float(Math.log(1), 0)
-end
+ assert('Math.log E') do
+ check_float(Math.log(Math::E), 1.0)
+ end
-assert('Math.log E') do
- check_float(Math.log(Math::E), 1.0)
-end
+ assert('Math.log E**3') do
+ check_float(Math.log(Math::E**3), 3.0)
+ end
-assert('Math.log E**3') do
- check_float(Math.log(Math::E**3), 3.0)
-end
+ assert('Math.log2 1') do
+ check_float(Math.log2(1), 0.0)
+ end
-assert('Math.log2 1') do
- check_float(Math.log2(1), 0.0)
-end
+ assert('Math.log2 2') do
+ check_float(Math.log2(2), 1.0)
+ end
-assert('Math.log2 2') do
- check_float(Math.log2(2), 1.0)
-end
+ assert('Math.log10 1') do
+ check_float(Math.log10(1), 0.0)
+ end
-assert('Math.log10 1') do
- check_float(Math.log10(1), 0.0)
-end
+ assert('Math.log10 10') do
+ check_float(Math.log10(10), 1.0)
+ end
-assert('Math.log10 10') do
- check_float(Math.log10(10), 1.0)
-end
+ assert('Math.log10 10**100') do
+ check_float(Math.log10(10**100), 100.0)
+ end
-assert('Math.log10 10**100') do
- check_float(Math.log10(10**100), 100.0)
-end
+ assert('Math.sqrt') do
+ num = [0.0, 1.0, 2.0, 3.0, 4.0]
+ sqr = [0, 1, 4, 9, 16]
+ result = true
+ sqr.each_with_index do |v,i|
+ result &= check_float(Math.sqrt(v), num[i])
+ end
+ result
+ end
-assert('Math.cbrt') do
- num = [-2.0, -1.0, 0.0, 1.0, 2.0]
- cub = [-8, -1, 0, 1, 8]
- result = true
- cub.each_with_index do |v,i|
- result &= check_float(Math.cbrt(v), num[i])
+ assert('Math.cbrt') do
+ num = [-2.0, -1.0, 0.0, 1.0, 2.0]
+ cub = [-8, -1, 0, 1, 8]
+ result = true
+ cub.each_with_index do |v,i|
+ result &= check_float(Math.cbrt(v), num[i])
+ end
+ result
end
- result
-end
-assert('Math.hypot') do
- check_float(Math.hypot(3, 4), 5.0)
-end
+ assert('Math.hypot') do
+ check_float(Math.hypot(3, 4), 5.0)
+ end
-assert('Math.frexp 1234') do
- n = 1234
- fraction, exponent = Math.frexp(n)
- check_float(Math.ldexp(fraction, exponent), n)
-end
+ assert('Math.frexp 1234') do
+ n = 1234
+ fraction, exponent = Math.frexp(n)
+ check_float(Math.ldexp(fraction, exponent), n)
+ end
-assert('Math.erf 1') do
- check_float(Math.erf(1), 0.842700792949715)
-end
+ assert('Math.erf 1') do
+ check_float(Math.erf(1), 0.842700792949715)
+ end
-assert('Math.erfc 1') do
- check_float(Math.erfc(1), 0.157299207050285)
+ assert('Math.erfc 1') do
+ check_float(Math.erfc(1), 0.157299207050285)
+ end
end
+
diff --git a/test/t/module.rb b/test/t/module.rb
index 854be75a5..5b847e8b7 100644
--- a/test/t/module.rb
+++ b/test/t/module.rb
@@ -5,6 +5,103 @@ assert('Module', '15.2.2') do
Module.class == Class
end
-# TODO not implemented ATM assert('Module.constants', '15.2.2') do
+assert('Module superclass', '15.2.2.2') do
+ Module.superclass == Object
+end
+
+# TODO not implemented ATM assert('Module.constants', '15.2.2.3.1') do
+
+# TODO not implemented ATM assert('Module.nesting', '15.2.2.3.2') do
+
+assert('Module#ancestors', '15.2.2.4.9') do
+ r = String.ancestors
+ r.class == Array and r.include?(String) and r.include?(Object)
+end
+
+assert('Module#append_features', '15.2.2.4.10') do
+ module Test4AppendFeatures
+ def self.append_features(mod)
+ Test4AppendFeatures2.const_set(:Const4AppendFeatures2, mod)
+ end
+ end
+ module Test4AppendFeatures2
+ include Test4AppendFeatures
+ end
+
+ Test4AppendFeatures2.const_get(:Const4AppendFeatures2) == Test4AppendFeatures2
+end
+
+assert('Module#const_defined?', '15.2.2.4.20') do
+ module Test4ConstDefined
+ Const4Test4ConstDefined = true
+ end
+
+ Test4ConstDefined.const_defined?(:Const4Test4ConstDefined) and
+ not Test4ConstDefined.const_defined?(:NotExisting)
+end
+
+assert('Module#const_get', '15.2.2.4.21') do
+ module Test4ConstGet
+ Const4Test4ConstGet = 42
+ end
+
+ Test4ConstGet.const_get(:Const4Test4ConstGet) == 42
+end
+
+assert('Module.const_missing', '15.2.2.4.22') do
+ e1 = nil
-# TODO not implemented ATM assert('Module.nesting', '15.2.2') do
+ module Test4ConstMissing
+ def self.const_missing(sym)
+ 42 # the answer to everything
+ end
+ end
+
+ Test4ConstMissing.const_get(:ConstDoesntExist) == 42
+end
+
+assert('Module#const_get', '15.2.2.4.23') do
+ module Test4ConstSet
+ Const4Test4ConstSet = 42
+ end
+
+ Test4ConstSet.const_set(:Const4Test4ConstSet, 23)
+ Test4ConstSet.const_get(:Const4Test4ConstSet) == 23
+end
+
+assert('Module#include', '15.2.2.4.27') do
+ module Test4Include
+ Const4Include = 42
+ end
+ module Test4Include2
+ include Test4Include
+ end
+
+ Test4Include2.const_get(:Const4Include) == 42
+end
+
+assert('Module#included', '15.2.2.4.29') do
+ module Test4Included
+ Const4Included = 42
+ def self.included mod
+ Test4Included.const_set(:Const4Included2, mod)
+ end
+ end
+ module Test4Included2
+ include Test4Included
+ end
+
+ Test4Included2.const_get(:Const4Included) == 42 and
+ Test4Included2.const_get(:Const4Included2) == Test4Included2
+end
+
+assert('Module#included_modules', '15.2.2.4.30') do
+ module Test4includedModules
+ end
+ module Test4includedModules2
+ include Test4includedModules
+ end
+
+ r = Test4includedModules2.included_modules
+ r.class == Array and r.include?(Test4includedModules)
+end
diff --git a/test/t/nameerror.rb b/test/t/nameerror.rb
index 67451ecf8..8e57ac18b 100644
--- a/test/t/nameerror.rb
+++ b/test/t/nameerror.rb
@@ -5,6 +5,10 @@ assert('NameError', '15.2.31') do
NameError.class == Class
end
+assert('NameError superclass', '15.2.31.2') do
+ NameError.superclass == StandardError
+end
+
# TODO 15.2.31.2.1 NameError#name
assert('NameError#initialize', '15.2.31.2.2') do
diff --git a/test/t/nomethoderror.rb b/test/t/nomethoderror.rb
index 9eb122158..caab04a41 100644
--- a/test/t/nomethoderror.rb
+++ b/test/t/nomethoderror.rb
@@ -11,3 +11,8 @@ assert('NoMethodError', '15.2.32') do
NoMethodError.class == Class and e2.class == NoMethodError
end
+
+assert('NoMethodError superclass', '15.2.32.2') do
+ NoMethodError.superclass == NameError
+end
+
diff --git a/test/t/numeric.rb b/test/t/numeric.rb
index 924889a0e..3cdb9a8cf 100644
--- a/test/t/numeric.rb
+++ b/test/t/numeric.rb
@@ -5,6 +5,10 @@ assert('Numeric', '15.2.7') do
Numeric.class == Class
end
+assert('Numeric superclass', '15.2.7.2') do
+ Numeric.superclass == Object
+end
+
assert('Numeric#+@', '15.2.7.4.1') do
+1 == +1
end
diff --git a/test/t/object.rb b/test/t/object.rb
index 96929031b..7dfaf6589 100644
--- a/test/t/object.rb
+++ b/test/t/object.rb
@@ -4,3 +4,8 @@
assert('Object', '15.2.1') do
Object.class == Class
end
+
+assert('Object superclass', '15.2.1.2') do
+ Object.superclass == BasicObject
+end
+
diff --git a/test/t/proc.rb b/test/t/proc.rb
index 6d98cb40c..c0a1cf90f 100644
--- a/test/t/proc.rb
+++ b/test/t/proc.rb
@@ -5,6 +5,10 @@ assert('Proc', '15.2.17') do
Proc.class == Class
end
+assert('Proc superclass', '15.2.17.2') do
+ Proc.superclass == Object
+end
+
assert('Proc.new', '15.2.17.3.1') do
a = nil
diff --git a/test/t/range.rb b/test/t/range.rb
index 05bac8779..691ca7898 100644
--- a/test/t/range.rb
+++ b/test/t/range.rb
@@ -5,6 +5,10 @@ assert('Range', '15.2.14') do
Range.class == Class
end
+assert('Range superclass', '15.2.14.2') do
+ Range.superclass == Object
+end
+
assert('Range#==', '15.2.14.4.1') do
(1..10) == (1..10) and not (1..10) == (1..100)
end
diff --git a/test/t/rangeerror.rb b/test/t/rangeerror.rb
index 7edb5d2d9..57afdc4bd 100644
--- a/test/t/rangeerror.rb
+++ b/test/t/rangeerror.rb
@@ -4,3 +4,8 @@
assert('RangeError', '15.2.26') do
RangeError.class == Class
end
+
+assert('RangeError superclass', '15.2.26.2') do
+ RangeError.superclass == StandardError
+end
+
diff --git a/test/t/standarderror.rb b/test/t/standarderror.rb
index 550c337c1..3868d7567 100644
--- a/test/t/standarderror.rb
+++ b/test/t/standarderror.rb
@@ -4,3 +4,8 @@
assert('StandardError', '15.2.23') do
StandardError.class == Class
end
+
+assert('StandardError superclass', '15.2.23.2') do
+ StandardError.superclass == Exception
+end
+
diff --git a/test/t/string.rb b/test/t/string.rb
index f38790c17..3338e4318 100644
--- a/test/t/string.rb
+++ b/test/t/string.rb
@@ -5,6 +5,10 @@ assert('String', '15.2.10') do
String.class == Class
end
+assert('String superclass', '15.2.10.2') do
+ String.superclass == Object
+end
+
assert('String#*', '15.2.10.5.1') do
'a' * 5 == 'aaaaa'
end
@@ -252,6 +256,9 @@ assert('String#slice', '15.2.10.5.34') do
d1 = 'abc'.slice(0, 0)
e1 = 'abc'.slice(1, 2)
+ # slice of shared string
+ e11 = e1.slice(0)
+
# args is RegExp
# TODO SEGFAULT ATM
@@ -261,16 +268,17 @@ assert('String#slice', '15.2.10.5.34') do
a == 'a' and b == 'c' and c == nil and d == nil and
a1 == nil and b1 == nil and c1 == nil and d1 == '' and
- e1 == 'bc' and
+ e1 == 'bc' and e11 == 'b' and
a3 == 'bc' and b3 == nil
end
# TODO Broken ATM
assert('String#split', '15.2.10.5.35') do
# without RegExp behavior is actually unspecified
- a = 'abc abc abc'.split
-
- a == ['abc', 'abc', 'abc']
+ 'abc abc abc'.split == ['abc', 'abc', 'abc'] and
+ 'a,b,c,,d'.split(',') == ["a", "b", "c", "", "d"] and
+ 'abc abc abc'.split(nil) == ['abc', 'abc', 'abc'] and
+ 'abc'.split("") == ['a', 'b', 'c']
end
# TODO ATM broken assert('String#sub', '15.2.10.5.36') do
@@ -319,3 +327,11 @@ assert('String#upcase!', '15.2.10.5.43') do
a == 'ABC'
end
+
+# Not ISO specified
+
+assert('String interpolation (mrb_str_concat for shared strings)') do
+ a = "A" * 32
+ "#{a}:" == "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:"
+end
+
diff --git a/test/t/struct.rb b/test/t/struct.rb
index c41319f8a..5cf6929b8 100644
--- a/test/t/struct.rb
+++ b/test/t/struct.rb
@@ -1,6 +1,71 @@
##
# Struct ISO Test
-assert('Struct', '15.2.18') do
- Struct.class == Class
+if Object.const_defined?(:Struct)
+ assert('Struct', '15.2.18') do
+ Struct.class == Class
+ end
+
+ assert('Struct superclass', '15.2.18.2') do
+ Struct.superclass == Object
+ end
+
+ assert('Struct.new', '15.2.18.3.1') do
+ c = Struct.new(:m1, :m2)
+ c.superclass == Struct and
+ c.members == [:m1,:m2]
+ end
+
+ assert('Struct#==', '15.2.18.4.1') do
+ c = Struct.new(:m1, :m2)
+ cc1 = c.new(1,2)
+ cc2 = c.new(1,2)
+ cc1 == cc2
+ end
+
+ assert('Struct#[]', '15.2.18.4.2') do
+ c = Struct.new(:m1, :m2)
+ cc = c.new(1,2)
+ cc[:m1] == 1 and cc["m2"] == 2
+ end
+
+ assert('Struct#[]=', '15.2.18.4.3') do
+ c = Struct.new(:m1, :m2)
+ cc = c.new(1,2)
+ cc[:m1] = 3
+ cc[:m1] == 3
+ end
+
+ assert('Struct#each', '15.2.18.4.4') do
+ c = Struct.new(:m1, :m2)
+ cc = c.new(1,2)
+ a = []
+ cc.each{|x|
+ a << x
+ }
+ a[0] == 1 and a[1] == 2
+ end
+
+ assert('Struct#each_pair', '15.2.18.4.5') do
+ c = Struct.new(:m1, :m2)
+ cc = c.new(1,2)
+ a = []
+ cc.each_pair{|k,v|
+ a << [k,v]
+ }
+ a[0] == [:m1, 1] and a[1] == [:m2, 2]
+ end
+
+ assert('Struct#members', '15.2.18.4.6') do
+ c = Struct.new(:m1, :m2)
+ cc = c.new(1,2)
+ cc.members == [:m1,:m2]
+ end
+
+ assert('Struct#select', '15.2.18.4.7') do
+ c = Struct.new(:m1, :m2)
+ cc = c.new(1,2)
+ cc.select{|v| v % 2 == 0} == [2]
+ end
end
+
diff --git a/test/t/symbol.rb b/test/t/symbol.rb
index e9c310971..b28573e92 100644
--- a/test/t/symbol.rb
+++ b/test/t/symbol.rb
@@ -5,6 +5,10 @@ assert('Symbol', '15.2.11') do
Symbol.class == Class
end
+assert('Symbol superclass', '15.2.11.2') do
+ Symbol.superclass == Object
+end
+
assert('Symbol#===', '15.2.11.3.1') do
:abc === :abc and not :abc === :cba
end
diff --git a/test/t/syntax.rb b/test/t/syntax.rb
new file mode 100644
index 000000000..7898a0b7d
--- /dev/null
+++ b/test/t/syntax.rb
@@ -0,0 +1,47 @@
+assert('super', '11.3.4') do
+ test = false
+ begin
+ super
+ rescue NoMethodError
+ test = true
+ end
+
+ class SuperFoo
+ def foo
+ true
+ end
+ def bar(*a)
+ a
+ end
+ end
+ class SuperBar < SuperFoo
+ def foo
+ super
+ end
+ def bar(*a)
+ super(*a)
+ end
+ end
+ bar = SuperBar.new
+ test &&= bar.foo
+ test &&= (bar.bar(1,2,3) == [1,2,3])
+ test
+end
+
+assert('yield', '11.3.5') do
+ begin
+ yield
+ rescue LocalJumpError
+ true
+ else
+ false
+ end
+end
+
+assert('Abbreviated variable assignment', '11.4.2.3.2') do
+ a ||= 1
+ b &&= 1
+ c = 1
+ c += 2
+ a == 1 and b == nil and c == 3
+end
diff --git a/test/t/time.rb b/test/t/time.rb
index 22fc2e7c3..6140be1a8 100644
--- a/test/t/time.rb
+++ b/test/t/time.rb
@@ -1,73 +1,191 @@
##
# Time ISO Test
-assert('Time', '15.2.19') do
- Time.class == Class
-end
+if Object.const_defined?(:Time)
+ assert('Time.new', '15.2.3.3.3') do
+ Time.new.class == Time
+ end
-assert('Time.at', '15.2.19.6.1') do
- Time.at(1300000000.0)
-end
+ assert('Time', '15.2.19') do
+ Time.class == Class
+ end
-assert('Time.gm', '15.2.19.6.2') do
- Time.gm(2012, 12, 23)
-end
+ assert('Time superclass', '15.2.19.2') do
+ Time.superclass == Object
+ end
-assert('Time#asctime', '15.2.19.7.4') do
- Time.at(1300000000.0).utc.asctime == "Sun Mar 13 07:06:40 UTC 2011"
-end
+ assert('Time.at', '15.2.19.6.1') do
+ Time.at(1300000000.0)
+ end
-assert('Time#initialize_copy', '15.2.19.7.17') do
- time_tmp_2 = Time.at(7.0e6)
- time_tmp_2.clone == time_tmp_2
-end
+ assert('Time.gm', '15.2.19.6.2') do
+ Time.gm(2012, 12, 23)
+ end
-assert('Time#mday', '15.2.19.7.19') do
- Time.gm(2012, 12, 23).mday == 23
-end
+ assert('Time.local', '15.2.19.6.3') do
+ Time.local(2012, 12, 23)
+ end
-assert('Time#month', '15.2.19.7.22') do
- Time.gm(2012, 12, 23).month == 12
-end
+ assert('Time.mktime', '15.2.19.6.4') do
+ Time.mktime(2012, 12, 23)
+ end
-assert('Time#to_f', '15.2.19.7.24') do
- Time.at(1300000000.0).to_f == 1300000000.0
-end
+ assert('Time.now', '15.2.19.6.5') do
+ Time.now.class == Time
+ end
-assert('Time#to_i', '15.2.19.7.25') do
- Time.at(1300000000.0).to_i == 1300000000
-end
+ assert('Time.utc', '15.2.19.6.6') do
+ Time.utc(2012, 12, 23)
+ end
-assert('Time#usec', '15.2.19.7.26') do
- Time.at(1300000000.0).usec == 0
-end
+ assert('Time#+', '15.2.19.7.1') do
+ t1 = Time.at(1300000000.0)
+ t2 = t1.+(60)
-assert('Time#utc', '15.2.19.7.27') do
- Time.at(1300000000.0).utc
-end
+ t2.utc.asctime == "Sun Mar 13 07:07:40 UTC 2011"
+ end
-assert('Time#utc?', '15.2.19.7.28') do
- Time.at(1300000000.0).utc.utc?
-end
+ assert('Time#-', '15.2.19.7.2') do
+ t1 = Time.at(1300000000.0)
+ t2 = t1.-(60)
-assert('Time#wday', '15.2.19.7.30') do
- Time.at(1300000000.0).utc.wday == 0
-end
+ t2.utc.asctime == "Sun Mar 13 07:05:40 UTC 2011"
+ end
-assert('Time#yday', '15.2.19.7.31') do
- Time.at(1300000000.0).utc.yday == 71
-end
+ assert('Time#<=>', '15.2.19.7.3') do
+ t1 = Time.at(1300000000.0)
+ t2 = Time.at(1400000000.0)
+ t3 = Time.at(1500000000.0)
-assert('Time#year', '15.2.19.7.32') do
- Time.gm(2012, 12, 23).year == 2012
-end
+ t2.<=>(t1) == 1 and
+ t2.<=>(t2) == 0 and
+ t2.<=>(t3) == -1 and
+ t2.<=>(nil) == nil
+ end
-assert('Time#zone', '15.2.19.7.33') do
- Time.at(1300000000.0).utc.zone == 'UTC'
-end
+ assert('Time#asctime', '15.2.19.7.4') do
+ Time.at(1300000000.0).utc.asctime == "Sun Mar 13 07:06:40 UTC 2011"
+ end
+
+ assert('Time#ctime', '15.2.19.7.5') do
+ Time.at(1300000000.0).utc.ctime == "Sun Mar 13 07:06:40 UTC 2011"
+ end
+
+ assert('Time#day', '15.2.19.7.6') do
+ Time.gm(2012, 12, 23).day == 23
+ end
+
+ assert('Time#dst?', '15.2.19.7.7') do
+ not Time.gm(2012, 12, 23).utc.dst?
+ end
+
+ assert('Time#getgm', '15.2.19.7.8') do
+ Time.at(1300000000.0).getgm.asctime == "Sun Mar 13 07:06:40 UTC 2011"
+ end
+
+ assert('Time#getlocal', '15.2.19.7.9') do
+ t1 = Time.at(1300000000.0)
+ t2 = Time.at(1300000000.0)
+ t3 = t1.getlocal
+
+ t1 == t3 and t3 == t2.getlocal
+ end
+
+ assert('Time#getutc', '15.2.19.7.10') do
+ Time.at(1300000000.0).getutc.asctime == "Sun Mar 13 07:06:40 UTC 2011"
+ end
-# Not ISO specified
+ assert('Time#gmt?', '15.2.19.7.11') do
+ Time.at(1300000000.0).utc.gmt?
+ end
-assert('Time#new') do
- Time.new.class == Time
+ # ATM not implemented
+ # assert('Time#gmt_offset', '15.2.19.7.12') do
+
+ assert('Time#gmtime', '15.2.19.7.13') do
+ Time.at(1300000000.0).gmtime
+ end
+
+ # ATM not implemented
+ # assert('Time#gmtoff', '15.2.19.7.14') do
+
+ assert('Time#hour', '15.2.19.7.15') do
+ Time.gm(2012, 12, 23, 7, 6).hour == 7
+ end
+
+ # ATM doesn't really work
+ # assert('Time#initialize', '15.2.19.7.16') do
+
+ assert('Time#initialize_copy', '15.2.19.7.17') do
+ time_tmp_2 = Time.at(7.0e6)
+ time_tmp_2.clone == time_tmp_2
+ end
+
+ assert('Time#localtime', '15.2.19.7.18') do
+ t1 = Time.at(1300000000.0)
+ t2 = Time.at(1300000000.0)
+
+ t1.localtime
+ t1 == t2.getlocal
+ end
+
+ assert('Time#mday', '15.2.19.7.19') do
+ Time.gm(2012, 12, 23).mday == 23
+ end
+
+ assert('Time#min', '15.2.19.7.20') do
+ Time.gm(2012, 12, 23, 7, 6).min == 6
+ end
+
+ assert('Time#mon', '15.2.19.7.21') do
+ Time.gm(2012, 12, 23).mon == 12
+ end
+
+ assert('Time#month', '15.2.19.7.22') do
+ Time.gm(2012, 12, 23).month == 12
+ end
+
+ assert('Times#sec', '15.2.19.7.23') do
+ Time.gm(2012, 12, 23, 7, 6, 40).sec == 40
+ end
+
+ assert('Time#to_f', '15.2.19.7.24') do
+ Time.at(1300000000.0).to_f == 1300000000.0
+ end
+
+ assert('Time#to_i', '15.2.19.7.25') do
+ Time.at(1300000000.0).to_i == 1300000000
+ end
+
+ assert('Time#usec', '15.2.19.7.26') do
+ Time.at(1300000000.0).usec == 0
+ end
+
+ assert('Time#utc', '15.2.19.7.27') do
+ Time.at(1300000000.0).utc
+ end
+
+ assert('Time#utc?', '15.2.19.7.28') do
+ Time.at(1300000000.0).utc.utc?
+ end
+
+ # ATM not implemented
+ # assert('Time#utc_offset', '15.2.19.7.29') do
+
+ assert('Time#wday', '15.2.19.7.30') do
+ Time.gm(2012, 12, 23).wday == 0
+ end
+
+ assert('Time#yday', '15.2.19.7.31') do
+ Time.gm(2012, 12, 23).yday == 357
+ end
+
+ assert('Time#year', '15.2.19.7.32') do
+ Time.gm(2012, 12, 23).year == 2012
+ end
+
+ assert('Time#zone', '15.2.19.7.33') do
+ Time.at(1300000000.0).utc.zone == 'UTC'
+ end
end
+
diff --git a/test/t/true.rb b/test/t/true.rb
index bb648a7cd..ae83e0baa 100644
--- a/test/t/true.rb
+++ b/test/t/true.rb
@@ -5,22 +5,26 @@ assert('TrueClass', '15.2.5') do
TrueClass.class == Class
end
+assert('TrueClass superclass', '15.2.5.2') do
+ TrueClass.superclass == Object
+end
+
assert('TrueClass true', '15.2.5.1') do
true
end
assert('TrueClass#&', '15.2.5.3.1') do
- TrueClass.new.&(true) and not TrueClass.new.&(false)
+ true.&(true) and not true.&(false)
end
assert('TrueClass#^', '15.2.5.3.2') do
- not TrueClass.new.^(true) and TrueClass.new.^(false)
+ not true.^(true) and true.^(false)
end
assert('TrueClass#to_s', '15.2.5.3.3') do
- TrueClass.new.to_s == 'true'
+ true.to_s == 'true'
end
assert('TrueClass#|', '15.2.5.3.4') do
- TrueClass.new.|(true) and TrueClass.new.|(false)
+ true.|(true) and true.|(false)
end
diff --git a/test/t/typeerror.rb b/test/t/typeerror.rb
index c4434aa24..d48db111a 100644
--- a/test/t/typeerror.rb
+++ b/test/t/typeerror.rb
@@ -4,3 +4,8 @@
assert('TypeError', '15.2.29') do
TypeError.class == Class
end
+
+assert('TypeError superclass', '15.2.29.2') do
+ TypeError.superclass == StandardError
+end
+
diff --git a/tools/mirb/Makefile b/tools/mirb/Makefile
index ba307227c..52941f242 100644
--- a/tools/mirb/Makefile
+++ b/tools/mirb/Makefile
@@ -21,12 +21,19 @@ EXTS := $(EXT1)
LIBS = -lm
INCLUDES = -I$(BASEDIR) -I$(BASEDIR)/../include
-DEBUG_MODE = 1
-ifeq ($(DEBUG_MODE),1)
+ifeq ($(strip $(COMPILE_MODE)),)
+ # default compile option
+ COMPILE_MODE = debug
+endif
+
+ifeq ($(COMPILE_MODE),debug)
CFLAGS = -g -O3
-else
+else ifeq ($(COMPILE_MODE),release)
CFLAGS = -O3
+else ifeq ($(COMPILE_MODE),small)
+ CFLAGS = -Os
endif
+
ALL_CFLAGS = -Wall -Werror-implicit-function-declaration $(CFLAGS)
ifeq ($(OS),Windows_NT)
MAKE_FLAGS = CC=$(CC) LL=$(LL) ALL_CFLAGS="$(ALL_CFLAGS)"
diff --git a/tools/mirb/mirb.c b/tools/mirb/mirb.c
index 59e5046cb..54588d57e 100644
--- a/tools/mirb/mirb.c
+++ b/tools/mirb/mirb.c
@@ -13,6 +13,19 @@
#include <mruby/data.h>
#include <mruby/compile.h>
+#ifndef ENABLE_STDIO
+#include <mruby/string.h>
+static void
+p(mrb_state *mrb, mrb_value obj)
+{
+ obj = mrb_funcall(mrb, obj, "inspect", 0);
+ fwrite(RSTRING_PTR(obj), RSTRING_LEN(obj), 1, stdout);
+ putc('\n', stdout);
+}
+#else
+#define p(mrb,obj) mrb_p(mrb,obj)
+#endif
+
/* Guess if the user might want to enter more
* or if he wants an evaluation of his code now */
int
@@ -37,10 +50,10 @@ is_code_block_open(struct mrb_parser_state *parser)
code_block_open = TRUE;
}
else if (strcmp(message, "syntax error, unexpected keyword_end") == 0) {
- code_block_open = TRUE;
+ code_block_open = FALSE;
}
else if (strcmp(message, "syntax error, unexpected tREGEXP_BEG") == 0) {
- code_block_open = TRUE;
+ code_block_open = FALSE;
}
return code_block_open;
}
@@ -132,18 +145,24 @@ main(void)
{
char last_char, ruby_code[1024], last_code_line[1024];
int char_index;
+ mrbc_context *cxt;
struct mrb_parser_state *parser;
- mrb_state *mrb_interpreter;
- mrb_value mrb_return_value;
- int byte_code;
+ mrb_state *mrb;
+ mrb_value result;
+ int n;
int code_block_open = FALSE;
print_hint();
/* new interpreter instance */
- mrb_interpreter = mrb_open();
- /* new parser instance */
- parser = mrb_parser_new(mrb_interpreter);
+ mrb = mrb_open();
+ if (mrb == NULL) {
+ fprintf(stderr, "Invalid mrb interpreter, exiting mirb");
+ return EXIT_FAILURE;
+ }
+
+ cxt = mrbc_context_new(mrb);
+ cxt->capture_errors = 1;
memset(ruby_code, 0, sizeof(*ruby_code));
memset(last_code_line, 0, sizeof(*last_code_line));
@@ -187,11 +206,11 @@ main(void)
}
/* parse code */
+ parser = mrb_parser_new(mrb);
parser->s = ruby_code;
parser->send = ruby_code + strlen(ruby_code);
- parser->capture_errors = 1;
parser->lineno = 1;
- mrb_parser_parse(parser);
+ mrb_parser_parse(parser, cxt);
code_block_open = is_code_block_open(parser);
if (code_block_open) {
@@ -204,31 +223,32 @@ main(void)
}
else {
/* generate bytecode */
- byte_code = mrb_generate_code(mrb_interpreter, parser->tree);
+ n = mrb_generate_code(mrb, parser->tree);
/* evaluate the bytecode */
- mrb_return_value = mrb_run(mrb_interpreter,
+ result = mrb_run(mrb,
/* pass a proc for evaulation */
- mrb_proc_new(mrb_interpreter, mrb_interpreter->irep[byte_code]),
- mrb_top_self(mrb_interpreter));
+ mrb_proc_new(mrb, mrb->irep[n]),
+ mrb_top_self(mrb));
/* did an exception occur? */
- if (mrb_interpreter->exc) {
- mrb_p(mrb_interpreter, mrb_obj_value(mrb_interpreter->exc));
- mrb_interpreter->exc = 0;
+ if (mrb->exc) {
+ p(mrb, mrb_obj_value(mrb->exc));
+ mrb->exc = 0;
}
else {
/* no */
printf(" => ");
- mrb_p(mrb_interpreter, mrb_return_value);
+ p(mrb, result);
}
}
-
memset(ruby_code, 0, sizeof(*ruby_code));
memset(ruby_code, 0, sizeof(*last_code_line));
}
+ mrb_parser_free(parser);
}
}
- mrb_close(mrb_interpreter);
+ mrbc_context_free(mrb, cxt);
+ mrb_close(mrb);
return 0;
}
diff --git a/tools/mrbc/Makefile b/tools/mrbc/Makefile
index 99f5830e6..eea0c02cb 100644
--- a/tools/mrbc/Makefile
+++ b/tools/mrbc/Makefile
@@ -23,12 +23,19 @@ LIBS = -lm
INCLUDES = -I$(BASEDIR) -I$(BASEDIR)/../include
# compiler, linker (gcc)
-DEBUG_MODE = 1
-ifeq ($(DEBUG_MODE),1)
-CFLAGS = -g -O3
-else
-CFLAGS = -O3
+ifeq ($(strip $(COMPILE_MODE)),)
+ # default compile option
+ COMPILE_MODE = debug
+endif
+
+ifeq ($(COMPILE_MODE),debug)
+ CFLAGS = -g -O3
+else ifeq ($(COMPILE_MODE),release)
+ CFLAGS = -O3
+else ifeq ($(COMPILE_MODE),small)
+ CFLAGS = -Os
endif
+
ALL_CFLAGS = -Wall -Werror-implicit-function-declaration $(CFLAGS)
ifeq ($(OS),Windows_NT)
MAKE_FLAGS = CC=$(CC) LL=$(LL) ALL_CFLAGS="$(ALL_CFLAGS)"
diff --git a/tools/mrbc/mrbc.c b/tools/mrbc/mrbc.c
index 3553fe646..f9810aa4f 100644
--- a/tools/mrbc/mrbc.c
+++ b/tools/mrbc/mrbc.c
@@ -114,6 +114,8 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
}
else return -3;
return 0;
+ default:
+ break;
}
}
else if (args->rfp == NULL) {
@@ -133,7 +135,10 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
if (outfile == NULL)
outfile = get_outfilename(infile, args->ext);
- if ((args->wfp = fopen(outfile, "wb")) == NULL) {
+ if (strcmp("-", outfile) == 0) {
+ args->wfp = stdout;
+ }
+ else if ((args->wfp = fopen(outfile, "wb")) == NULL) {
printf("%s: Cannot open output file. (%s)\n", *origargv, outfile);
return 0;
}
@@ -142,12 +147,13 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
}
static void
-cleanup(struct _args *args)
+cleanup(mrb_state *mrb, struct _args *args)
{
if (args->rfp)
fclose(args->rfp);
if (args->wfp)
fclose(args->wfp);
+ mrb_close(mrb);
}
int
@@ -156,37 +162,34 @@ main(int argc, char **argv)
mrb_state *mrb = mrb_open();
int n = -1;
struct _args args;
- struct mrb_parser_state *p;
+ mrbc_context *c;
+ mrb_value result;
- n = parse_args(mrb, argc, argv, &args);
+ if (mrb == NULL) {
+ fprintf(stderr, "Invalid mrb_state, exiting mrbc");
+ return EXIT_FAILURE;
+ }
+ n = parse_args(mrb, argc, argv, &args);
if (n < 0 || args.rfp == NULL) {
- cleanup(&args);
+ cleanup(mrb, &args);
usage(argv[0]);
- mrb_close(mrb);
return n;
}
- p = mrb_parse_file(mrb, args.rfp);
- if (!p || !p->tree || p->nerr) {
- cleanup(&args);
- mrb_close(mrb);
- return -1;
- }
-
- if (args.verbose)
- parser_dump(mrb, p->tree, 0);
-
- n = mrb_generate_code(mrb, p->tree);
- mrb_pool_close(p->pool);
-
+ c = mrbc_context_new(mrb);
if (args.verbose)
- codedump_all(mrb, n);
-
- if (n < 0 || args.check_syntax) {
- cleanup(&args);
- mrb_close(mrb);
- return n;
+ c->dump_result = 1;
+ c->no_exec = 1;
+ result = mrb_load_file_cxt(mrb, args.rfp, c);
+ if (mrb_undef_p(result) || mrb_fixnum(result) < 0) {
+ cleanup(mrb, &args);
+ return EXIT_FAILURE;
+ }
+ if (args.check_syntax) {
+ printf("Syntax OK\n");
+ cleanup(mrb, &args);
+ return EXIT_SUCCESS;
}
if (args.initname) {
if (args.dump_type == DUMP_TYPE_BIN)
@@ -198,14 +201,11 @@ main(int argc, char **argv)
n = mrb_dump_irep(mrb, n, args.wfp);
}
- cleanup(&args);
- mrb_close(mrb);
-
- return n;
+ cleanup(mrb, &args);
+ return EXIT_SUCCESS;
}
void
mrb_init_mrblib(mrb_state *mrb)
{
}
-
diff --git a/tools/mruby/Makefile b/tools/mruby/Makefile
index 0442bd422..9955b4302 100644
--- a/tools/mruby/Makefile
+++ b/tools/mruby/Makefile
@@ -26,12 +26,19 @@ LIBS = -lm
INCLUDES = -I$(BASEDIR) -I$(BASEDIR)/../include
# compiler, linker (gcc)
-DEBUG_MODE = 1
-ifeq ($(DEBUG_MODE),1)
-CFLAGS = -g -O3
-else
-CFLAGS = -O3
+ifeq ($(strip $(COMPILE_MODE)),)
+ # default compile option
+ COMPILE_MODE = debug
+endif
+
+ifeq ($(COMPILE_MODE),debug)
+ CFLAGS = -g -O3
+else ifeq ($(COMPILE_MODE),release)
+ CFLAGS = -O3
+else ifeq ($(COMPILE_MODE),small)
+ CFLAGS = -Os
endif
+
ALL_CFLAGS = -Wall -Werror-implicit-function-declaration $(CFLAGS)
ifeq ($(OS),Windows_NT)
MAKE_FLAGS = CC=$(CC) LL=$(LL) ALL_CFLAGS="$(ALL_CFLAGS)"
diff --git a/tools/mruby/mruby.c b/tools/mruby/mruby.c
index 8b227df5d..e6a088672 100644
--- a/tools/mruby/mruby.c
+++ b/tools/mruby/mruby.c
@@ -7,10 +7,20 @@
#include <stdio.h>
#include <string.h>
+#ifndef ENABLE_STDIO
+static void
+p(mrb_state *mrb, mrb_value obj)
+{
+ obj = mrb_funcall(mrb, obj, "inspect", 0);
+ fwrite(RSTRING_PTR(obj), RSTRING_LEN(obj), 1, stdout);
+ putc('\n', stdout);
+}
+#else
+#define p(mrb,obj) mrb_p(mrb,obj)
+#endif
+
void mrb_show_version(mrb_state *);
void mrb_show_copyright(mrb_state *);
-void parser_dump(mrb_state*, struct mrb_ast_node*, int);
-void codedump_all(mrb_state*, int);
struct _args {
FILE *rfp;
@@ -51,12 +61,14 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
memset(args, 0, sizeof(*args));
for (argc--,argv++; argc > 0; argc--,argv++) {
+ char *item;
if (argv[0][0] != '-') break;
if (strlen(*argv) <= 1)
return -1;
- switch ((*argv)[1]) {
+ item = argv[0] + 1;
+ switch (*item++) {
case 'b':
args->mrbfile = 1;
break;
@@ -64,19 +76,24 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
args->check_syntax = 1;
break;
case 'e':
- if (argc > 1) {
+ if (item[0]) {
+ goto append_cmdline;
+ }
+ else if (argc > 1) {
argc--; argv++;
+ item = argv[0];
+append_cmdline:
if (!args->cmdline) {
char *buf;
- buf = mrb_malloc(mrb, strlen(argv[0])+1);
- strcpy(buf, argv[0]);
+ buf = (char *)mrb_malloc(mrb, strlen(item)+1);
+ strcpy(buf, item);
args->cmdline = buf;
}
else {
- args->cmdline = mrb_realloc(mrb, args->cmdline, strlen(args->cmdline)+strlen(argv[0])+2);
+ args->cmdline = (char *)mrb_realloc(mrb, args->cmdline, strlen(args->cmdline)+strlen(item)+2);
strcat(args->cmdline, "\n");
- strcat(args->cmdline, argv[0]);
+ strcat(args->cmdline, item);
}
}
else {
@@ -103,6 +120,8 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
}
else return -3;
return 0;
+ default:
+ break;
}
}
@@ -114,7 +133,7 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
return 0;
}
}
- args->argv = mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
+ args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
memcpy(args->argv, argv, (argc+1) * sizeof(char*));
args->argc = argc;
@@ -140,7 +159,12 @@ main(int argc, char **argv)
int n = -1;
int i;
struct _args args;
- struct mrb_parser_state *p;
+ mrb_value ARGV;
+
+ if (mrb == NULL) {
+ fprintf(stderr, "Invalid mrb_state, exiting mruby");
+ return EXIT_FAILURE;
+ }
n = parse_args(mrb, argc, argv, &args);
if (n < 0 || (args.cmdline == NULL && args.rfp == NULL)) {
@@ -149,51 +173,50 @@ main(int argc, char **argv)
return n;
}
+ ARGV = mrb_ary_new(mrb);
+ for (i = 0; i < args.argc; i++) {
+ mrb_ary_push(mrb, ARGV, mrb_str_new(mrb, args.argv[i], strlen(args.argv[i])));
+ }
+ mrb_define_global_const(mrb, "ARGV", ARGV);
+
if (args.mrbfile) {
n = mrb_load_irep(mrb, args.rfp);
- }
- else {
- if (args.cmdline) {
- p = mrb_parse_string(mrb, (char*)args.cmdline);
- }
- else {
- p = mrb_parser_new(mrb);
- if (p) {
- mrb_parser_filename(p, argv[1]);
- p->f = args.rfp;
- mrb_parser_parse(p);
+ if (n >= 0) {
+ if (!args.check_syntax) {
+ mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));
+ if (mrb->exc) {
+ p(mrb, mrb_obj_value(mrb->exc));
+ }
}
}
- if (!p || !p->tree || p->nerr) {
- cleanup(mrb, &args);
- return -1;
- }
-
- if (args.verbose)
- parser_dump(mrb, p->tree, 0);
-
- n = mrb_generate_code(mrb, p->tree);
- mrb_pool_close(p->pool);
}
-
- if (n >= 0) {
- mrb_value ARGV = mrb_ary_new(mrb);
- for (i = 0; i < args.argc; i++) {
- mrb_ary_push(mrb, ARGV, mrb_str_new(mrb, args.argv[i], strlen(args.argv[i])));
- }
- mrb_define_global_const(mrb, "ARGV", ARGV);
+ else {
+ mrbc_context *c = mrbc_context_new(mrb);
+ mrb_value v;
if (args.verbose)
- codedump_all(mrb, n);
+ c->dump_result = 1;
+ if (args.check_syntax)
+ c->no_exec = 1;
- if (!args.check_syntax) {
- mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));
- if (mrb->exc) {
- mrb_p(mrb, mrb_obj_value(mrb->exc));
+ if (args.cmdline) {
+ mrbc_filename(mrb, c, "-e");
+ v = mrb_load_string_cxt(mrb, (char*)args.cmdline, c);
+ }
+ else {
+ mrbc_filename(mrb, c, argv[1]);
+ v = mrb_load_file_cxt(mrb, args.rfp, c);
+ }
+ mrbc_context_free(mrb, c);
+ if (mrb->exc) {
+ if (!mrb_undef_p(v)) {
+ p(mrb, mrb_obj_value(mrb->exc));
}
}
+ else if (args.check_syntax) {
+ printf("Syntax OK\n");
+ }
}
-
cleanup(mrb, &args);
return n > 0 ? 0 : 1;
diff --git a/tools/xpcat/xpcat.c b/tools/xpcat/xpcat.c
index c9d1abe73..ce3d5854e 100644
--- a/tools/xpcat/xpcat.c
+++ b/tools/xpcat/xpcat.c
@@ -60,9 +60,7 @@ main(int argc, char *argv[])
}
}
-done:
fclose(outfile);
-
return EXIT_SUCCESS;
}
diff --git a/xcode/mruby.xcodeproj/project.pbxproj b/xcode/mruby.xcodeproj/project.pbxproj
index 48ac5b1ea..a04426232 100644
--- a/xcode/mruby.xcodeproj/project.pbxproj
+++ b/xcode/mruby.xcodeproj/project.pbxproj
@@ -7,20 +7,22 @@
objects = {
/* Begin PBXAggregateTarget section */
- 88C19D95157D7593002ABAEA /* all binaries */ = {
+ 88D0984E15CFF54A002E0BE8 /* build all */ = {
isa = PBXAggregateTarget;
- buildConfigurationList = 88C19D98157D7594002ABAEA /* Build configuration list for PBXAggregateTarget "all binaries" */;
+ buildConfigurationList = 88D0985115CFF54A002E0BE8 /* Build configuration list for PBXAggregateTarget "build all" */;
buildPhases = (
- 88C19DA2157D75F2002ABAEA /* ShellScript */,
);
dependencies = (
- 88C19D9B157D759D002ABAEA /* PBXTargetDependency */,
- 88C19D9D157D75A1002ABAEA /* PBXTargetDependency */,
- 88C19D9F157D75A3002ABAEA /* PBXTargetDependency */,
- 88C19DA1157D75A6002ABAEA /* PBXTargetDependency */,
+ 88D0985415CFF561002E0BE8 /* PBXTargetDependency */,
+ 88D0985615CFF561002E0BE8 /* PBXTargetDependency */,
+ 88D0985815CFF561002E0BE8 /* PBXTargetDependency */,
+ 88D0985A15CFF561002E0BE8 /* PBXTargetDependency */,
+ 88D0985C15CFF561002E0BE8 /* PBXTargetDependency */,
+ 88D0985E15CFF561002E0BE8 /* PBXTargetDependency */,
+ 88D0986015CFF561002E0BE8 /* PBXTargetDependency */,
);
- name = "all binaries";
- productName = binaries;
+ name = "build all";
+ productName = "make all";
};
/* End PBXAggregateTarget section */
@@ -141,34 +143,55 @@
remoteGlobalIDString = 88760AA115759B4F00113BFB;
remoteInfo = ruby_lib;
};
- 88C19D9A157D759D002ABAEA /* PBXContainerItemProxy */ = {
+ 88D0985315CFF561002E0BE8 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 88BF3371156C992100F12AC7 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 88760AE415759EFE00113BFB;
+ remoteInfo = mruby_core;
+ };
+ 88D0985515CFF561002E0BE8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 88BF3371156C992100F12AC7 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 88760A8A157590F000113BFB;
remoteInfo = mrbc;
};
- 88C19D9C157D75A1002ABAEA /* PBXContainerItemProxy */ = {
+ 88D0985715CFF561002E0BE8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 88BF3371156C992100F12AC7 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = 88760B3215769F3000113BFB;
- remoteInfo = mirb;
+ remoteGlobalIDString = 88760AA115759B4F00113BFB;
+ remoteInfo = ruby_lib;
};
- 88C19D9E157D75A3002ABAEA /* PBXContainerItemProxy */ = {
+ 88D0985915CFF561002E0BE8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 88BF3371156C992100F12AC7 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 88760B2315769E6100113BFB;
remoteInfo = mruby;
};
- 88C19DA0157D75A6002ABAEA /* PBXContainerItemProxy */ = {
+ 88D0985B15CFF561002E0BE8 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 88BF3371156C992100F12AC7 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 88760B3215769F3000113BFB;
+ remoteInfo = mirb;
+ };
+ 88D0985D15CFF561002E0BE8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 88BF3371156C992100F12AC7 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 8844358E1577301B007F95A4;
remoteInfo = mrbtest;
};
+ 88D0985F15CFF561002E0BE8 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 88BF3371156C992100F12AC7 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 88760B731576A33100113BFB;
+ remoteInfo = mruby_fw;
+ };
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
@@ -832,7 +855,7 @@
88BF3371156C992100F12AC7 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0430;
+ LastUpgradeCheck = 0440;
};
buildConfigurationList = 88BF3374156C992100F12AC7 /* Build configuration list for PBXProject "mruby" */;
compatibilityVersion = "Xcode 3.2";
@@ -854,7 +877,7 @@
88760B3215769F3000113BFB /* mirb */,
8844358E1577301B007F95A4 /* mrbtest */,
88760B731576A33100113BFB /* mruby_fw */,
- 88C19D95157D7593002ABAEA /* all binaries */,
+ 88D0984E15CFF54A002E0BE8 /* build all */,
);
};
/* End PBXProject section */
@@ -923,19 +946,6 @@
shellPath = /bin/sh;
shellScript = "cd ../mrblib\ncat ./*.rb > mrblib.rbtmp\n../Xcode/build/mrbc -Bmrblib_irep -omrblib.ctmp mrblib.rbtmp\ncat init_mrblib.c mrblib.ctmp > mrblib.c";
};
- 88C19DA2157D75F2002ABAEA /* ShellScript */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = build/mrbtest;
- };
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -1067,25 +1077,40 @@
target = 88760AA115759B4F00113BFB /* ruby_lib */;
targetProxy = 88760B891576A35C00113BFB /* PBXContainerItemProxy */;
};
- 88C19D9B157D759D002ABAEA /* PBXTargetDependency */ = {
+ 88D0985415CFF561002E0BE8 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 88760AE415759EFE00113BFB /* mruby_core */;
+ targetProxy = 88D0985315CFF561002E0BE8 /* PBXContainerItemProxy */;
+ };
+ 88D0985615CFF561002E0BE8 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 88760A8A157590F000113BFB /* mrbc */;
- targetProxy = 88C19D9A157D759D002ABAEA /* PBXContainerItemProxy */;
+ targetProxy = 88D0985515CFF561002E0BE8 /* PBXContainerItemProxy */;
};
- 88C19D9D157D75A1002ABAEA /* PBXTargetDependency */ = {
+ 88D0985815CFF561002E0BE8 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = 88760B3215769F3000113BFB /* mirb */;
- targetProxy = 88C19D9C157D75A1002ABAEA /* PBXContainerItemProxy */;
+ target = 88760AA115759B4F00113BFB /* ruby_lib */;
+ targetProxy = 88D0985715CFF561002E0BE8 /* PBXContainerItemProxy */;
};
- 88C19D9F157D75A3002ABAEA /* PBXTargetDependency */ = {
+ 88D0985A15CFF561002E0BE8 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 88760B2315769E6100113BFB /* mruby */;
- targetProxy = 88C19D9E157D75A3002ABAEA /* PBXContainerItemProxy */;
+ targetProxy = 88D0985915CFF561002E0BE8 /* PBXContainerItemProxy */;
};
- 88C19DA1157D75A6002ABAEA /* PBXTargetDependency */ = {
+ 88D0985C15CFF561002E0BE8 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 88760B3215769F3000113BFB /* mirb */;
+ targetProxy = 88D0985B15CFF561002E0BE8 /* PBXContainerItemProxy */;
+ };
+ 88D0985E15CFF561002E0BE8 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 8844358E1577301B007F95A4 /* mrbtest */;
- targetProxy = 88C19DA0157D75A6002ABAEA /* PBXContainerItemProxy */;
+ targetProxy = 88D0985D15CFF561002E0BE8 /* PBXContainerItemProxy */;
+ };
+ 88D0986015CFF561002E0BE8 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 88760B731576A33100113BFB /* mruby_fw */;
+ targetProxy = 88D0985F15CFF561002E0BE8 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
@@ -1113,6 +1138,7 @@
);
INSTALL_PATH = /;
PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = "";
};
name = Debug;
};
@@ -1128,6 +1154,7 @@
);
INSTALL_PATH = /;
PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = "";
};
name = Release;
};
@@ -1137,6 +1164,7 @@
DEPLOYMENT_LOCATION = YES;
INSTALL_PATH = /;
PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = "";
};
name = Debug;
};
@@ -1146,12 +1174,14 @@
DEPLOYMENT_LOCATION = YES;
INSTALL_PATH = /;
PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = "";
};
name = Release;
};
88760AA415759B4F00113BFB /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
DEPLOYMENT_LOCATION = YES;
EXECUTABLE_PREFIX = lib;
GCC_C_LANGUAGE_STANDARD = "compiler-default";
@@ -1161,12 +1191,14 @@
);
INSTALL_PATH = /lib;
PRODUCT_NAME = mruby;
+ SDKROOT = "";
};
name = Debug;
};
88760AA515759B4F00113BFB /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
DEPLOYMENT_LOCATION = YES;
EXECUTABLE_PREFIX = lib;
GCC_C_LANGUAGE_STANDARD = "compiler-default";
@@ -1176,12 +1208,14 @@
);
INSTALL_PATH = /lib;
PRODUCT_NAME = mruby;
+ SDKROOT = "";
};
name = Release;
};
88760AE715759EFE00113BFB /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
DEPLOYMENT_LOCATION = YES;
EXECUTABLE_PREFIX = lib;
GCC_C_LANGUAGE_STANDARD = "compiler-default";
@@ -1193,6 +1227,7 @@
INSTALL_PATH = /lib;
LIBRARY_STYLE = STATIC;
PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = "";
USE_HEADERMAP = "$(inherited)";
};
name = Debug;
@@ -1200,6 +1235,7 @@
88760AE815759EFE00113BFB /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
DEPLOYMENT_LOCATION = YES;
EXECUTABLE_PREFIX = lib;
GCC_C_LANGUAGE_STANDARD = "compiler-default";
@@ -1210,6 +1246,7 @@
INSTALL_PATH = /lib;
LIBRARY_STYLE = STATIC;
PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = "";
USE_HEADERMAP = "$(inherited)";
};
name = Release;
@@ -1225,6 +1262,7 @@
);
INSTALL_PATH = /;
PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = "";
};
name = Debug;
};
@@ -1239,6 +1277,7 @@
);
INSTALL_PATH = /;
PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = "";
};
name = Release;
};
@@ -1249,6 +1288,7 @@
GCC_C_LANGUAGE_STANDARD = "compiler-default";
INSTALL_PATH = /;
PRODUCT_NAME = mirb;
+ SDKROOT = "";
};
name = Debug;
};
@@ -1259,12 +1299,14 @@
GCC_C_LANGUAGE_STANDARD = "compiler-default";
INSTALL_PATH = /;
PRODUCT_NAME = mirb;
+ SDKROOT = "";
};
name = Release;
};
88760B871576A33100113BFB /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
DEPLOYMENT_LOCATION = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
@@ -1279,6 +1321,7 @@
INFOPLIST_FILE = "mruby_fw/mruby_fw-Info.plist";
INSTALL_PATH = /;
PRODUCT_NAME = mruby;
+ SDKROOT = "";
WRAPPER_EXTENSION = framework;
};
name = Debug;
@@ -1286,6 +1329,7 @@
88760B881576A33100113BFB /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
DEPLOYMENT_LOCATION = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
@@ -1300,6 +1344,7 @@
INFOPLIST_FILE = "mruby_fw/mruby_fw-Info.plist";
INSTALL_PATH = /;
PRODUCT_NAME = mruby;
+ SDKROOT = "";
WRAPPER_EXTENSION = framework;
};
name = Release;
@@ -1365,6 +1410,7 @@
88BF3596156CA10D00F12AC7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
DEBUGGING_SYMBOLS = YES;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -1377,23 +1423,26 @@
88BF3597156CA10D00F12AC7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
- 88C19D96157D7594002ABAEA /* Debug */ = {
+ 88D0984F15CFF54A002E0BE8 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = "";
};
name = Debug;
};
- 88C19D97157D7594002ABAEA /* Release */ = {
+ 88D0985015CFF54A002E0BE8 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = "";
};
name = Release;
};
@@ -1481,11 +1530,11 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 88C19D98157D7594002ABAEA /* Build configuration list for PBXAggregateTarget "all binaries" */ = {
+ 88D0985115CFF54A002E0BE8 /* Build configuration list for PBXAggregateTarget "build all" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 88C19D96157D7594002ABAEA /* Debug */,
- 88C19D97157D7594002ABAEA /* Release */,
+ 88D0984F15CFF54A002E0BE8 /* Debug */,
+ 88D0985015CFF54A002E0BE8 /* Release */,
);
defaultConfigurationIsVisible = 0;
};