mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Updated Xcode project build settings in conformity with 10.8/Xcode 4.4
This commit is contained in:
@@ -6,3 +6,6 @@ Original Authors "mruby developers" are:
|
||||
Daniel Bovensiepen
|
||||
Jon Maken
|
||||
Bjorn De Meyer
|
||||
Yuichiro MASUI
|
||||
Masamitsu MURASE
|
||||
Masaki Muranaka
|
||||
|
||||
+5
-4
@@ -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)
|
||||
|
||||
@@ -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)'
|
||||
|
||||
@@ -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)
|
||||
d = -@p.vdot(@n)
|
||||
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
|
||||
@@ -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
|
||||
@@ -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}")
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
+53
-13
@@ -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
|
||||
|
||||
+23
-31
@@ -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);
|
||||
|
||||
+21
-14
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
+34
-15
@@ -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" { */
|
||||
|
||||
+8
-10
@@ -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
|
||||
|
||||
+90
-52
@@ -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))
|
||||
#define khash_power2(v) do { \
|
||||
v--;\
|
||||
v |= v >> 1;\
|
||||
v |= v >> 2;\
|
||||
v |= v >> 4;\
|
||||
v |= v >> 8;\
|
||||
v |= v >> 16;\
|
||||
v++;\
|
||||
} while (0);
|
||||
|
||||
|
||||
/* struct kh_xxx
|
||||
/* 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" { */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" { */
|
||||
|
||||
+11
-14
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" { */
|
||||
|
||||
+12
-5
@@ -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)"
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
##
|
||||
|
||||
+6
-30
@@ -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
|
||||
|
||||
##
|
||||
|
||||
+68
-39
@@ -3,47 +3,76 @@
|
||||
#
|
||||
# ISO 15.3.1
|
||||
module Kernel
|
||||
|
||||
##
|
||||
# Invoke method +print+ on STDOUT and passing +*args+
|
||||
#
|
||||
# ISO 15.3.1.2.10
|
||||
def print(*args)
|
||||
i = 0
|
||||
len = args.size
|
||||
while i < len
|
||||
__printstr__ args[i].to_s
|
||||
i += 1
|
||||
unless Kernel.respond_to?(:__printstr__)
|
||||
def print(*a)
|
||||
raise NotImplementedError.new('print not available')
|
||||
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
|
||||
def puts(*a)
|
||||
raise NotImplementedError.new('puts not available')
|
||||
end
|
||||
__printstr__ "\n" if len == 0
|
||||
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
|
||||
def p(*a)
|
||||
raise NotImplementedError.new('p not available')
|
||||
end
|
||||
def printf(*args)
|
||||
raise NotImplementedError.new('printf not available')
|
||||
end
|
||||
else
|
||||
unless Kernel.respond_to?(:sprintf)
|
||||
def printf(*args)
|
||||
raise NotImplementedError.new('printf not available')
|
||||
end
|
||||
def sprintf(*args)
|
||||
raise NotImplementedError.new('sprintf not available')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Invoke method +print+ on STDOUT and passing +*args+
|
||||
#
|
||||
# ISO 15.3.1.2.10
|
||||
def print(*args)
|
||||
i = 0
|
||||
len = args.size
|
||||
while i < len
|
||||
__printstr__ args[i].to_s
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Invoke method +puts+ on STDOUT and passing +*args*+
|
||||
#
|
||||
# ISO 15.3.1.2.11
|
||||
def puts(*args)
|
||||
i = 0
|
||||
len = args.size
|
||||
while i < len
|
||||
__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]
|
||||
end
|
||||
|
||||
def printf(*args)
|
||||
__printstr__(sprintf(*args))
|
||||
end
|
||||
args[0]
|
||||
end
|
||||
end
|
||||
|
||||
+16
-7
@@ -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
|
||||
|
||||
+41
-37
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
+12
-5
@@ -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)
|
||||
|
||||
|
||||
|
||||
+311
-197
@@ -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)
|
||||
{
|
||||
size_t capa = a->capa;
|
||||
if (a->flags & MRB_ARY_SHARED) {
|
||||
struct mrb_shared_array *shared = a->aux.shared;
|
||||
|
||||
#ifdef LONG_MAX
|
||||
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)
|
||||
{
|
||||
int capa = a->aux.capa;
|
||||
|
||||
#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", ×);
|
||||
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,21 +427,13 @@ 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)
|
||||
{
|
||||
@@ -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) */
|
||||
}
|
||||
|
||||
+27
-24
@@ -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("}");
|
||||
|
||||
|
||||
+408
-154
@@ -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 (!c) {
|
||||
struct RClass *s = 0;
|
||||
|
||||
if (!mrb_nil_p(super)) {
|
||||
mrb_check_type(mrb, super, MRB_TT_CLASS);
|
||||
s = mrb_class_ptr(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));
|
||||
}
|
||||
}
|
||||
if (!s) {
|
||||
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;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
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;
|
||||
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);
|
||||
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);
|
||||
|
||||
tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int");
|
||||
*p = mrb_fixnum(tmp);
|
||||
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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++; sp++;
|
||||
sp++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
{
|
||||
mrb_sym *symp;
|
||||
|
||||
symp = va_arg(ap, mrb_sym*);
|
||||
if (i < argc) {
|
||||
mrb_value ss;
|
||||
|
||||
ss = *sp++;
|
||||
if (mrb_type(ss) == MRB_TT_SYMBOL) {
|
||||
*symp = mrb_symbol(ss);
|
||||
}
|
||||
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_append_features(mrb_state *mrb, mrb_value mod)
|
||||
{
|
||||
mrb_value klass;
|
||||
|
||||
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 mod;
|
||||
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_get_args(mrb, "o", &mod);
|
||||
mrb_check_type(mrb, mod, MRB_TT_MODULE);
|
||||
mrb_include_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod));
|
||||
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");
|
||||
}
|
||||
|
||||
+329
-150
@@ -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);
|
||||
genop(s, MKOP_sBx(OP_JMP, 0));
|
||||
lp->pc2 = new_label(s);
|
||||
codegen(s, tree->cdr, NOVAL);
|
||||
dispatch(s, lp->pc1);
|
||||
codegen(s, tree->car, VAL);
|
||||
pop();
|
||||
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);
|
||||
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);
|
||||
genop(s, MKOP_sBx(OP_JMP, 0));
|
||||
lp->pc2 = new_label(s);
|
||||
codegen(s, tree->cdr, NOVAL);
|
||||
dispatch(s, lp->pc1);
|
||||
codegen(s, tree->car, VAL);
|
||||
pop();
|
||||
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);
|
||||
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
|
||||
|
||||
@@ -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)
|
||||
|
||||
+33
-26
@@ -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);
|
||||
|
||||
+50
-137
@@ -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;
|
||||
|
||||
if (RSTRING_LEN(exc) > 0) {
|
||||
mrb_str_cat2(mrb, str, ": ");
|
||||
mrb_str_append(mrb, str, exc);
|
||||
}
|
||||
|
||||
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, ">");
|
||||
|
||||
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
|
||||
@@ -185,25 +166,20 @@ mrb_exc_raise(mrb_state *mrb, mrb_value exc)
|
||||
longjmp(*(jmp_buf*)mrb->jmp, 1);
|
||||
}
|
||||
|
||||
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 */
|
||||
}
|
||||
|
||||
@@ -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, ...);
|
||||
|
||||
@@ -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);
|
||||
|
||||
int
|
||||
return id;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
+54
-52
@@ -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;
|
||||
@@ -330,16 +328,10 @@ mrb_hash_aget(mrb_state *mrb, mrb_value self)
|
||||
return mrb_hash_get(mrb, self, key);
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
+12
-4
@@ -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);
|
||||
|
||||
|
||||
+106
-374
@@ -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
|
||||
* obj.hash -> fixnum
|
||||
*
|
||||
* Returns an array of the names of global variables.
|
||||
*
|
||||
* 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 */
|
||||
return val;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
+30
-34
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+74
-45
@@ -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);
|
||||
}
|
||||
|
||||
@@ -463,6 +466,25 @@ math_log10(mrb_state *mrb, mrb_value obj)
|
||||
return mrb_float_value(x);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -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_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_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, "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, "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, "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);
|
||||
|
||||
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, "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, "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, "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, "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, "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, "frexp", math_frexp, 1);
|
||||
mrb_define_module_function(mrb, mrb_math, "ldexp", math_ldexp, 2);
|
||||
mrb_define_module_function(mrb, mrb_math, "hypot", math_hypot, ARGS_REQ(2));
|
||||
|
||||
mrb_define_module_function(mrb, mrb_math, "hypot", math_hypot, 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 */
|
||||
|
||||
-26
@@ -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;
|
||||
|
||||
+161
-144
@@ -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;
|
||||
|
||||
x = mrb_fixnum(self);
|
||||
mrb_get_args(mrb, "i", &y);
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
return mrb_fixnum_plus(mrb, self, other);
|
||||
}
|
||||
|
||||
DEBUG(printf("%d + %d = %d\n", x, y, x+y));
|
||||
return mrb_fixnum_value(x + 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;
|
||||
|
||||
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;
|
||||
mrb_value other;
|
||||
|
||||
x = mrb_fixnum(self);
|
||||
mrb_get_args(mrb, "i", &y);
|
||||
|
||||
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 */
|
||||
|
||||
+14
-37
@@ -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);
|
||||
|
||||
+9
-9
@@ -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)
|
||||
|
||||
|
||||
+350
-211
File diff suppressed because it is too large
Load Diff
+16
-7
@@ -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;
|
||||
|
||||
+22
-10
@@ -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
|
||||
|
||||
+62
-8
@@ -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 */
|
||||
}
|
||||
|
||||
+52
-92
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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]
|
||||
|
||||
+4
-4
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+4
-4
@@ -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
|
||||
|
||||
+28
-24
@@ -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 */
|
||||
|
||||
@@ -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*);
|
||||
|
||||
+4
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+262
-250
File diff suppressed because it is too large
Load Diff
+92
-126
@@ -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;
|
||||
const char *name;
|
||||
int i, len;
|
||||
mrb_sym mid;
|
||||
mrb_value members, slot, *ptr, *ptr_members;
|
||||
|
||||
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;
|
||||
}
|
||||
/* 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 */
|
||||
|
||||
+134
-45
@@ -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;
|
||||
}
|
||||
|
||||
const char*
|
||||
mrb_sym2name(mrb_state *mrb, mrb_sym sym)
|
||||
mrb_sym
|
||||
mrb_intern(mrb_state *mrb, const char *name)
|
||||
{
|
||||
khash_t(s2n) *h = mrb->sym2name;
|
||||
khiter_t k;
|
||||
return mrb_intern2(mrb, name, strlen(name));
|
||||
}
|
||||
|
||||
k = kh_get(s2n, h, sym);
|
||||
if (k == kh_end(h)) {
|
||||
return NULL; /* missing */
|
||||
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_len(mrb_state *mrb, mrb_sym sym, int *lenp)
|
||||
{
|
||||
khash_t(n2s) *h = mrb->name2sym;
|
||||
khiter_t k;
|
||||
symbol_name sname;
|
||||
|
||||
for (k = kh_begin(h); k != kh_end(h); k++) {
|
||||
if (kh_exist(h, k)) {
|
||||
if (kh_value(h, k) == sym) break;
|
||||
}
|
||||
}
|
||||
return kh_value(h, k);
|
||||
if (k == kh_end(h)) {
|
||||
*lenp = 0;
|
||||
return NULL; /* missing */
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
+173
-109
@@ -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
|
||||
|
||||
+121
-67
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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(®s[1], argv, sizeof(mrb_value)*(argc-m2)); /* m1 + o */
|
||||
memmove(®s[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(®s[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(®s[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;
|
||||
}
|
||||
|
||||
+12
-5
@@ -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)"
|
||||
|
||||
+10
-3
@@ -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
|
||||
|
||||
|
||||
+24
-15
@@ -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();
|
||||
if (mrb == NULL) {
|
||||
fprintf(stderr, "Invalid mrb_state, exiting test driver");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
mrb_init_mrbtest(mrb);
|
||||
parser = mrb_parse_nstring(mrb, prog, strlen(prog));
|
||||
|
||||
/* generate bytecode */
|
||||
byte_code = mrb_generate_code(mrb, parser->tree);
|
||||
|
||||
/* 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));
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+66
-3
@@ -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
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
##
|
||||
# BasicObject
|
||||
|
||||
assert('BasicObject') do
|
||||
BasicObject.class == Class
|
||||
end
|
||||
|
||||
assert('BasicObject superclass') do
|
||||
BasicObject.superclass == nil
|
||||
end
|
||||
|
||||
+6
-6
@@ -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
|
||||
|
||||
+100
-15
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+61
-1
@@ -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
|
||||
|
||||
+8
-4
@@ -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
|
||||
|
||||
+41
-19
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+236
-25
@@ -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,12 +36,15 @@ assert('Kernel.lambda', '15.3.1.2.6') do
|
||||
true
|
||||
end
|
||||
|
||||
l.call and l.class == Proc
|
||||
m = Kernel.lambda(&l)
|
||||
|
||||
l.call and l.class == Proc and m.call and m.class == Proc
|
||||
end
|
||||
|
||||
assert('Kernel.local_variables', '15.3.1.2.7') do
|
||||
Kernel.local_variables.class == Array
|
||||
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#hash', '15.3.1.2.15') do
|
||||
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.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#loop', '15.3.1.2.29') do
|
||||
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#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#private_methods', '15.3.1.2.36') do
|
||||
private_methods.class == Array
|
||||
assert('Kernel#object_id', '15.3.1.3.33') do
|
||||
object_id.class == Fixnum
|
||||
end
|
||||
|
||||
assert('Kernel#protected_methods', '15.3.1.2.37') do
|
||||
assert('Kernel#private_methods', '15.3.1.3.36') do
|
||||
private_methods.class == Array
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
# TODO at the moment doesn't comply to ISO assert('Kernel#send', '15.3.1.2.44') do
|
||||
assert('Kernel#respond_to?', '15.3.1.3.43') do
|
||||
class Test4RespondTo
|
||||
def test_method; end
|
||||
undef test_method
|
||||
end
|
||||
|
||||
assert('Kernel#singleton_methods', '15.3.1.2.45') do
|
||||
respond_to?(:nil?) and Test4RespondTo.new.respond_to?(:test_method) == false
|
||||
end
|
||||
|
||||
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.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
|
||||
|
||||
+109
-97
@@ -1,105 +1,117 @@
|
||||
##
|
||||
# Math Test
|
||||
|
||||
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('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)
|
||||
if Object.const_defined?(:Math)
|
||||
assert('Math.sin 0') do
|
||||
check_float(Math.sin(0), 0)
|
||||
end
|
||||
result
|
||||
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 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.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**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 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 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.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.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('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 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.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**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 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 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.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])
|
||||
end
|
||||
result
|
||||
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.erf 1') do
|
||||
check_float(Math.erf(1), 0.842700792949715)
|
||||
end
|
||||
|
||||
assert('Math.erfc 1') do
|
||||
check_float(Math.erfc(1), 0.157299207050285)
|
||||
end
|
||||
result
|
||||
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.erf 1') do
|
||||
check_float(Math.erf(1), 0.842700792949715)
|
||||
end
|
||||
|
||||
assert('Math.erfc 1') do
|
||||
check_float(Math.erfc(1), 0.157299207050285)
|
||||
end
|
||||
|
||||
+99
-2
@@ -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.nesting', '15.2.2') do
|
||||
# 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
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+20
-4
@@ -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
|
||||
|
||||
|
||||
+67
-2
@@ -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
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user