Merge branch 'mruby2-draft'

This commit is contained in:
Yukihiro "Matz" Matsumoto
2018-08-28 22:13:52 +09:00
28 changed files with 2850 additions and 2039 deletions
+1
View File
@@ -15,6 +15,7 @@
.DS_Store
.ccmalloc
.svn
.vscode
/.git
cscope.files
cscope.out
+22
View File
@@ -205,3 +205,25 @@ trace (most recent call last):
[0] -e:1
-e:1: undefined method 'binding' (NoMethodError)
```
## Keyword arguments
mruby keyword arguments behave slightly different from CRuby 2.5
to make the behavior simpler and less confusing. Maybe in the
future, the simpler behavior will be adopted to CRuby as well.
#### Ruby [ruby 2.5.1p57 (2018-03-29 revision 63029)]
```
$ ruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
[[{"a"=>1}], {:b=>2}]
```
#### mruby []
```
$ ./bin/mruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
trace (most recent call last):
[0] -e:1
-e:1: keyword argument hash with non symbol keys (ArgumentError)
```
+127
View File
@@ -0,0 +1,127 @@
# The new bytecode
We will reimplement VM to use 8bit instruction code. By
bytecode, we mean real byte code. The whole purpose is
reducing the memory consumption of mruby VM.
# Instructions
Instructions are bytes. There can be 256 instructions. Currently we
have 94 instructions. Instructions can take 0 to 3 operands.
## operands
The size of operands can be either 8bits, 16bits or 24bits.
In the table.1 below, the second field describes the size (and
sign) of operands.
* B: 8bit
* sB: signed 8bit
* S: 16bit
* sS: signed 16bit
* W: 24bit
First two byte operands may be extended to 16bit. When those byte
operands are bigger than 256, the instruction will be prefixed by
`OP_EXT1` (means 1st operand is 16bit) or `OP_EXT2` (means 2nd operand
is 16bit) or `OP_EXT3` (means 1st and 2nd operands are 16bit).
For instructions marked by `'`, `OP_EXT1` can be prefixed. For those
with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
## table.1 Instruction Table
|Instruction Name |Operand type |Semantics
|-----------------|-------------|-----------------
|OP_NOP | - |
|OP_MOVE" |BB |R(a) = R(b)
|OP_LOADL" |BB |R(a) = Pool(b)
|OP_LOADI" |BsB |R(a) = mrb_int(b)
|OP_LOADI_0' |B |R(a) = 0
|OP_LOADI_1' |B |R(a) = 1
|OP_LOADI_2' |B |R(a) = 2
|OP_LOADI_3' |B |R(a) = 3
|OP_LOADSYM" |BB |R(a) = Syms(b)
|OP_LOADNIL' |B |R(a) = nil
|OP_LOADSELF' |B |R(a) = self
|OP_LOADT' |B |R(a) = true
|OP_LOADF' |B |R(a) = false
|OP_GETGV" |BB |R(a) = getglobal(Syms(b))
|OP_SETGV" |BB |setglobal(Syms(b), R(a))
|OP_GETSV" |BB |R(a) = Special[b]
|OP_SETSV" |BB |Special[b] = R(a)
|OP_GETIV" |BB |R(a) = ivget(Syms(b))
|OP_SETIV" |BB |ivset(Syms(b),R(a))
|OP_GETCV" |BB |R(a) = cvget(Syms(b))
|OP_SETCV" |BB |cvset(Syms(b),R(a))
|OP_GETCONST" |BB |R(a) = constget(Syms(b))
|OP_SETCONST" |BB |constset(Syms(b),R(a))
|OP_GETMCNST" |BB |R(a) = R(a)::Syms(b)
|OP_SETMCNST" |BB |R(a+1)::Syms(b) = R(a)
|OP_GETUPVAR' |BBB |R(a) = uvget(b,c)
|OP_SETUPVAR' |BBB |uvset(b,c,R(a))
|OP_JMP |S |pc+=a
|OP_JMPIF' |SB |if R(b) pc+=a
|OP_JMPNOT' |SB |if !R(b) pc+=a
|OP_ONERR |sS |rescue_push(pc+a)
|OP_EXCEPT' |B |R(a) = exc
|OP_RESCUE" |BB |R(b) = R(a).isa?(R(b))
|OP_POPERR |B |a.times{rescue_pop()}
|OP_RAISE' |B |raise(R(a))
|OP_EPUSH' |B |ensure_push(SEQ[a])
|OP_EPOP |B |A.times{ensure_pop().call}
|OP_SENDV" |BB |R(a) = call(R(a),Syms(b),*R(a+1))
|OP_SENDVB" |BB |R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2))
|OP_SEND" |BBB |R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c))
|OP_SENDB" |BBB |R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1))
|OP_CALL' |B |R(a) = self.call(frame.argc, frame.argv)
|OP_SUPER' |BB |R(a) = super(R(a+1),... ,R(a+b+1))
|OP_ARGARY' |BS |R(a) = argument array (16=5:1:5:1:4)
|OP_ENTER |W |arg setup according to flags (23=5:5:1:5:5:1:1)
|OP_KARG" |BB |R(a) = kdict[Syms(Bx)] # todo
|OP_KARG2" |BB |R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo
|OP_RETURN' |B |return R(a) (normal)
|OP_RETURN_BLK' |B |return R(a) (in-block return)
|OP_BREAK' |B |break R(a)
|OP_BLKPUSH' |BS |R(a) = block (16=5:1:5:1:4)
|OP_ADD" |BB |R(a) = R(a)+R(a+1) (Syms[b]=:+)
|OP_ADDI" |BBB |R(a) = R(a)+mrb_int(c) (Syms[b]=:+)
|OP_SUB" |BB |R(a) = R(a)-R(a+1) (Syms[b]=:-)
|OP_SUBI" |BB |R(a) = R(a)-C (Syms[b]=:-)
|OP_MUL" |BB |R(a) = R(a)*R(a+1) (Syms[b]=:*)
|OP_DIV" |BB |R(a) = R(a)/R(a+1) (Syms[b]=:/)
|OP_EQ" |BB |R(a) = R(a)==R(a+1) (Syms[b]=:==)
|OP_LT" |BB |R(a) = R(a)<R(a+1) (Syms[b]=:<)
|OP_LE" |BB |R(a) = R(a)<=R(a+1) (Syms[b]=:<=)
|OP_GT" |BB |R(a) = R(a)>R(a+1) (Syms[b]=:>)
|OP_GE" |BB |R(a) = R(a)>=R(a+1) (Syms[b]=:>=)
|OP_ARRAY' |BB |R(a) = ary_new(R(a),R(a+1)..R(a+b))
|OP_ARRAY2" |BB |R(a) = ary_new(R(b),R(b+1)..R(b+c))
|OP_ARYCAT' |B |ary_cat(R(a),R(a+1))
|OP_ARYPUSH' |B |ary_push(R(a),R(a+1))
|OP_AREF' |BB |R(a) = R(a)[b]
|OP_ASET' |BB |R(a)[b] = R(a+1)
|OP_APOST' |BB |*R(a),R(A+1)..R(A+C) = R(a)[B..]
|OP_STRING" |BB |R(a) = str_dup(Lit(b))
|OP_STRCAT' |B |str_cat(R(a),R(a+1))
|OP_HASH' |BB |R(a) = hash_new(R(a),R(a+1)..R(a+b))
|OP_HASHADD' |BB |R(a) = hash_push(R(a),R(a+1)..R(a+b))
|OP_LAMBDA" |BB |R(a) = lambda(SEQ[b],OP_L_LAMBDA)
|OP_BLOCK" |BB |R(a) = lambda(SEQ[b],OP_L_BLOCK)
|OP_METHOD" |BB |R(a) = lambda(SEQ[b],OP_L_METHOD)
|OP_RANGE_INC' |B |R(a) = range_new(R(a),R(a+1),FALSE)
|OP_RANGE_EXC' |B |R(a) = range_new(R(a),R(a+1),TRUE)
|OP_OCLASS' |B |R(a) = ::Object
|OP_CLASS" |BB |R(a) = newclass(R(a),Syms(b),R(a+1))
|OP_MODULE" |BB |R(a) = newmodule(R(a),Syms(b))
|OP_EXEC" |BB |R(a) = blockexec(R(a),SEQ[b])
|OP_DEF" |BB |R(a).newmethod(Syms(b),R(a+1))
|OP_ALIAS' |B |alias_method(R(a),R(a+1),R(a+2))
|OP_UNDEF" |BB |undef_method(R(a),Syms(b))
|OP_SCLASS' |B |R(a) = R(a).singleton_class
|OP_TCLASS' |B |R(a) = target_class
|OP_ERR' |B |raise(RuntimeError, Lit(Bx))
|OP_EXT1 |- |make 1st operand 16bit
|OP_EXT2 |- |make 2nd operand 16bit
|OP_EXT3 |- |make 1st and 2nd operands 16bit
|OP_STOP |- |stop VM
+8 -8
View File
@@ -93,7 +93,7 @@
*/
MRB_BEGIN_DECL
typedef uint32_t mrb_code;
typedef uint8_t mrb_code;
/**
* Required arguments signature type.
@@ -123,8 +123,8 @@ typedef struct {
mrb_sym mid;
struct RProc *proc;
mrb_value *stackent;
int ridx;
int epos;
uint16_t ridx;
uint16_t epos;
struct REnv *env;
mrb_code *pc; /* return address */
mrb_code *err; /* error position */
@@ -151,10 +151,10 @@ struct mrb_context {
mrb_callinfo *ci;
mrb_callinfo *cibase, *ciend;
mrb_code **rescue; /* exception handler stack */
uint16_t *rescue; /* exception handler stack */
int rsize;
struct RProc **ensure; /* ensure handler stack */
int esize, eidx;
uint8_t esize, eidx;
enum mrb_fiber_state status;
mrb_bool vmexec;
@@ -485,9 +485,10 @@ MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_
* }
* @param [mrb_state*] mrb_state* The mruby state reference.
* @param [struct RClass*] RClass* A class the method will be undefined from.
* @param [const char*] constchar* The name of the method to be undefined.
* @param [const char] const char* The name of the method to be undefined.
*/
MRB_API void mrb_undef_method(mrb_state*, struct RClass*, const char*);
MRB_API void mrb_undef_method_id(mrb_state*, struct RClass*, mrb_sym);
/**
* Undefine a class method.
@@ -1196,7 +1197,6 @@ typedef enum call_type {
CALL_TYPE_MAX
} call_type;
MRB_API void mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2);
MRB_API const char *mrb_class_name(mrb_state *mrb, struct RClass* klass);
MRB_API void mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val);
@@ -1234,7 +1234,7 @@ MRB_API mrb_value mrb_fiber_alive_p(mrb_state *mrb, mrb_value fib);
* @mrbgem mruby-fiber
*/
#define E_FIBER_ERROR (mrb_exc_get(mrb, "FiberError"))
MRB_API void mrb_stack_extend(mrb_state*, int);
MRB_API void mrb_stack_extend(mrb_state*, mrb_int);
/* memory pool implementation */
typedef struct mrb_pool mrb_pool;
+2 -1
View File
@@ -79,7 +79,8 @@ MRB_API struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb
MRB_API struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym);
MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, mrb_method_t);
MRB_API void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec);
MRB_API void mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b);
MRB_API void mrb_alias_method(mrb_state*, struct RClass *c, mrb_sym a, mrb_sym b);
MRB_API void mrb_define_alias(mrb_state*, struct RClass *c, const char* a, const char* b);
MRB_API mrb_method_t mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym);
MRB_API mrb_method_t mrb_method_search(mrb_state*, struct RClass*, mrb_sym);
+2
View File
@@ -33,6 +33,7 @@ typedef struct mrbc_context {
mrb_bool no_exec:1;
mrb_bool keep_lv:1;
mrb_bool no_optimize:1;
mrb_bool on_eval:1;
size_t parser_nerr;
} mrbc_context;
@@ -151,6 +152,7 @@ struct mrb_parser_state {
mrb_ast_node *tree;
mrb_bool no_optimize:1;
mrb_bool on_eval:1;
mrb_bool capture_errors:1;
struct mrb_parser_message error_buffer[10];
struct mrb_parser_message warn_buffer[10];
+35 -2
View File
@@ -25,6 +25,7 @@ struct RHash {
#define mrb_hash_value(p) mrb_obj_value((void*)(p))
MRB_API mrb_value mrb_hash_new_capa(mrb_state*, mrb_int);
MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
/*
* Initializes a new hash.
@@ -110,7 +111,19 @@ MRB_API mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value
* @return An array with the keys of the hash.
*/
MRB_API mrb_value mrb_hash_keys(mrb_state *mrb, mrb_value hash);
MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
/*
* Check if the hash has the key.
*
* Equivalent to:
*
* hash.key?(key)
*
* @param mrb The mruby state reference.
* @param hash The target hash.
* @param key The key to check existence.
* @return True if the hash has the key
*/
MRB_API mrb_bool mrb_hash_key_p(mrb_state *mrb, mrb_value hash, mrb_value key);
/*
* Check if the hash is empty
@@ -123,7 +136,7 @@ MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
* @param self The target hash.
* @return True if the hash is empty, false otherwise.
*/
MRB_API mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self);
MRB_API mrb_bool mrb_hash_empty_p(mrb_state *mrb, mrb_value self);
/*
* Gets an array of values.
@@ -151,6 +164,26 @@ MRB_API mrb_value mrb_hash_values(mrb_state *mrb, mrb_value hash);
*/
MRB_API mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash);
/*
* Copies the hash.
*
*
* @param mrb The mruby state reference.
* @param hash The target hash.
* @return The copy of the hash
*/
MRB_API mrb_value mrb_hash_dup(mrb_state *mrb, mrb_value hash);
/*
* Merges two hashes. The first hash will be modified by the
* second hash.
*
* @param mrb The mruby state reference.
* @param hash1 The target hash.
* @param hash2 Updating hash
*/
MRB_API void mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2);
/* declaration of struct kh_ht */
/* be careful when you touch the internal */
typedef struct {
+10 -1
View File
@@ -44,7 +44,7 @@ typedef struct mrb_irep {
uint16_t *lines;
struct mrb_irep_debug_info* debug_info;
int ilen, plen, slen, rlen, refcnt;
uint16_t ilen, plen, slen, rlen, refcnt;
} mrb_irep;
#define MRB_ISEQ_NO_FREE 1
@@ -58,6 +58,15 @@ void mrb_irep_decref(mrb_state*, struct mrb_irep*);
void mrb_irep_cutref(mrb_state*, struct mrb_irep*);
void mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep);
struct mrb_insn_data {
uint8_t insn;
uint16_t a;
uint16_t b;
uint8_t c;
};
struct mrb_insn_data mrb_decode_insn(mrb_code *pc);
MRB_END_DECL
#endif /* MRUBY_IREP_H */
+47 -139
View File
@@ -7,145 +7,10 @@
#ifndef MRUBY_OPCODE_H
#define MRUBY_OPCODE_H
#define MAXARG_Bx (0xffff)
#define MAXARG_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */
/* instructions: packed 32 bit */
/* ------------------------------- */
/* A:B:C:OP = 9: 9: 7: 7 */
/* A:Bx:OP = 9:16: 7 */
/* Ax:OP = 25: 7 */
/* A:Bz:Cz:OP = 9:14: 2: 7 */
#define GET_OPCODE(i) ((int)(((mrb_code)(i)) & 0x7f))
#define GETARG_A(i) ((int)((((mrb_code)(i)) >> 23) & 0x1ff))
#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) ((int32_t)((((mrb_code)(i)) >> 7) & 0x1ffffff))
#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+(n2))) & (((1<<(n1))-1))))
#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<(n2))-1))))
#define GETARG_b(i) GETARG_UNPACK_b(i,14,2)
#define GETARG_c(i) GETARG_UNPACK_c(i,14,2)
#define MKOPCODE(op) ((op) & 0x7f)
#define MKARG_A(c) ((mrb_code)((c) & 0x1ff) << 23)
#define MKARG_B(c) ((mrb_code)((c) & 0x1ff) << 14)
#define MKARG_C(c) (((c) & 0x7f) << 7)
#define MKARG_Bx(v) ((mrb_code)((v) & 0xffff) << 7)
#define MKARG_sBx(v) MKARG_Bx((v)+MAXARG_sBx)
#define MKARG_Ax(v) ((mrb_code)((v) & 0x1ffffff) << 7)
#define MKARG_PACK(b,n1,c,n2) ((((b) & ((1<<n1)-1)) << (7+n2))|(((c) & ((1<<n2)-1)) << 7))
#define MKARG_bc(b,c) MKARG_PACK(b,14,c,2)
#define MKOP_A(op,a) (MKOPCODE(op)|MKARG_A(a))
#define MKOP_AB(op,a,b) (MKOP_A(op,a)|MKARG_B(b))
#define MKOP_ABC(op,a,b,c) (MKOP_AB(op,a,b)|MKARG_C(c))
#define MKOP_ABx(op,a,bx) (MKOP_A(op,a)|MKARG_Bx(bx))
#define MKOP_Bx(op,bx) (MKOPCODE(op)|MKARG_Bx(bx))
#define MKOP_sBx(op,sbx) (MKOPCODE(op)|MKARG_sBx(sbx))
#define MKOP_AsBx(op,a,sbx) (MKOP_A(op,a)|MKARG_sBx(sbx))
#define MKOP_Ax(op,ax) (MKOPCODE(op)|MKARG_Ax(ax))
#define MKOP_Abc(op,a,b,c) (MKOP_A(op,a)|MKARG_bc(b,c))
enum {
/*-----------------------------------------------------------------------
operation code operand description
------------------------------------------------------------------------*/
OP_NOP=0,/* */
OP_MOVE,/* A B R(A) := R(B) */
OP_LOADL,/* A Bx R(A) := Pool(Bx) */
OP_LOADI,/* A sBx R(A) := sBx */
OP_LOADSYM,/* A Bx R(A) := Syms(Bx) */
OP_LOADNIL,/* A R(A) := nil */
OP_LOADSELF,/* A R(A) := self */
OP_LOADT,/* A R(A) := true */
OP_LOADF,/* A R(A) := false */
OP_GETGLOBAL,/* A Bx R(A) := getglobal(Syms(Bx)) */
OP_SETGLOBAL,/* A Bx setglobal(Syms(Bx), R(A)) */
OP_GETSPECIAL,/*A Bx R(A) := Special[Bx] */
OP_SETSPECIAL,/*A Bx Special[Bx] := R(A) */
OP_GETIV,/* A Bx R(A) := ivget(Syms(Bx)) */
OP_SETIV,/* A Bx ivset(Syms(Bx),R(A)) */
OP_GETCV,/* A Bx R(A) := cvget(Syms(Bx)) */
OP_SETCV,/* A Bx cvset(Syms(Bx),R(A)) */
OP_GETCONST,/* A Bx R(A) := constget(Syms(Bx)) */
OP_SETCONST,/* A Bx constset(Syms(Bx),R(A)) */
OP_GETMCNST,/* A Bx R(A) := R(A)::Syms(Bx) */
OP_SETMCNST,/* A Bx R(A+1)::Syms(Bx) := R(A) */
OP_GETUPVAR,/* A B C R(A) := uvget(B,C) */
OP_SETUPVAR,/* A B C uvset(B,C,R(A)) */
OP_JMP,/* sBx pc+=sBx */
OP_JMPIF,/* A sBx if R(A) pc+=sBx */
OP_JMPNOT,/* A sBx if !R(A) pc+=sBx */
OP_ONERR,/* sBx rescue_push(pc+sBx) */
OP_RESCUE,/* A B C if A (if C exc=R(A) else R(A) := exc);
if B R(B) := exc.isa?(R(B)); clear(exc) */
OP_POPERR,/* A A.times{rescue_pop()} */
OP_RAISE,/* A raise(R(A)) */
OP_EPUSH,/* Bx ensure_push(SEQ[Bx]) */
OP_EPOP,/* A A.times{ensure_pop().call} */
OP_SEND,/* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C)) */
OP_SENDB,/* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C),&R(A+C+1))*/
OP_FSEND,/* A B C R(A) := fcall(R(A),Syms(B),R(A+1),...,R(A+C-1)) */
OP_CALL,/* A R(A) := self.call(frame.argc, frame.argv) */
OP_SUPER,/* A C R(A) := super(R(A+1),... ,R(A+C+1)) */
OP_ARGARY,/* A Bx R(A) := argument array (16=6:1:5:4) */
OP_ENTER,/* Ax arg setup according to flags (23=5:5:1:5:5:1:1) */
OP_KARG,/* A B C R(A) := kdict[Syms(B)]; if C kdict.rm(Syms(B)) */
OP_KDICT,/* A C R(A) := kdict */
OP_RETURN,/* A B return R(A) (B=normal,in-block return/break) */
OP_TAILCALL,/* A B C return call(R(A),Syms(B),*R(C)) */
OP_BLKPUSH,/* A Bx R(A) := block (16=6:1:5:4) */
OP_ADD,/* A B C R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1) */
OP_ADDI,/* A B C R(A) := R(A)+C (Syms[B]=:+) */
OP_SUB,/* A B C R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1) */
OP_SUBI,/* A B C R(A) := R(A)-C (Syms[B]=:-) */
OP_MUL,/* A B C R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1) */
OP_DIV,/* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1) */
OP_EQ,/* A B C R(A) := R(A)==R(A+1) (Syms[B]=:==,C=1) */
OP_LT,/* A B C R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1) */
OP_LE,/* A B C R(A) := R(A)<=R(A+1) (Syms[B]=:<=,C=1) */
OP_GT,/* A B C R(A) := R(A)>R(A+1) (Syms[B]=:>,C=1) */
OP_GE,/* A B C R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1) */
OP_ARRAY,/* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */
OP_ARYCAT,/* A B ary_cat(R(A),R(B)) */
OP_ARYPUSH,/* A B ary_push(R(A),R(B)) */
OP_AREF,/* A B C R(A) := R(B)[C] */
OP_ASET,/* A B C R(B)[C] := R(A) */
OP_APOST,/* A B C *R(A),R(A+1)..R(A+C) := R(A)[B..] */
OP_STRING,/* A Bx R(A) := str_dup(Lit(Bx)) */
OP_STRCAT,/* A B str_cat(R(A),R(B)) */
OP_HASH,/* A B C R(A) := hash_new(R(B),R(B+1)..R(B+C)) */
OP_LAMBDA,/* A Bz Cz R(A) := lambda(SEQ[Bz],Cz) */
OP_RANGE,/* A B C R(A) := range_new(R(B),R(B+1),C) */
OP_OCLASS,/* A R(A) := ::Object */
OP_CLASS,/* A B R(A) := newclass(R(A),Syms(B),R(A+1)) */
OP_MODULE,/* A B R(A) := newmodule(R(A),Syms(B)) */
OP_EXEC,/* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */
OP_METHOD,/* A B R(A).newmethod(Syms(B),R(A+1)) */
OP_SCLASS,/* A B R(A) := R(B).singleton_class */
OP_TCLASS,/* A R(A) := target_class */
OP_DEBUG,/* A B C print R(A),R(B),R(C) */
OP_STOP,/* stop VM */
OP_ERR,/* Bx raise RuntimeError with message Lit(Bx) */
OP_RSVD1,/* reserved instruction #1 */
OP_RSVD2,/* reserved instruction #2 */
OP_RSVD3,/* reserved instruction #3 */
OP_RSVD4,/* reserved instruction #4 */
OP_RSVD5,/* reserved instruction #5 */
enum mrb_insn {
#define OPCODE(x,_) OP_ ## x,
#include "mruby/ops.h"
#undef OPCODE
};
#define OP_L_STRICT 1
@@ -158,4 +23,47 @@ enum {
#define OP_R_BREAK 1
#define OP_R_RETURN 2
#define PEEK_B(pc) (*(pc))
#define PEEK_S(pc) ((pc)[0]<<8|(pc)[1])
#define PEEK_W(pc) ((pc)[0]<<16|(pc)[1]<<8|(pc)[2])
#define READ_B() PEEK_B(pc++)
#define READ_S() (pc+=2, PEEK_S(pc-2))
#define READ_W() (pc+=3, PEEK_W(pc-3))
#define FETCH_Z() /* nothing */
#define FETCH_B() do {a=READ_B();} while (0)
#define FETCH_BB() do {a=READ_B(); b=READ_B();} while (0)
#define FETCH_BBB() do {a=READ_B(); b=READ_B(); c=READ_B();} while (0)
#define FETCH_BS() do {a=READ_B(); b=READ_S();} while (0)
#define FETCH_S() do {a=READ_S();} while (0)
#define FETCH_W() do {a=READ_W();} while (0)
/* with OP_EXT1 (1st 16bit) */
#define FETCH_Z_1() FETCH_Z()
#define FETCH_B_1() FETCH_S()
#define FETCH_BB_1() do {a=READ_S(); b=READ_B();} while (0)
#define FETCH_BBB_1() do {a=READ_S(); b=READ_B(); c=READ_B();} while (0)
#define FETCH_BS_1() do {a=READ_S(); b=READ_S();} while (0)
#define FETCH_S_1() FETCH_S()
#define FETCH_W_1() FETCH_W()
/* with OP_EXT2 (2nd 16bit) */
#define FETCH_Z_2() FETCH_Z()
#define FETCH_B_2() FETCH_B()
#define FETCH_BB_2() do {a=READ_B(); b=READ_S();} while (0)
#define FETCH_BBB_2() do {a=READ_B(); b=READ_S(); c=READ_B();} while (0)
#define FETCH_BS_2() FETCH_BS()
#define FETCH_S_2() FETCH_S()
#define FETCH_W_2() FETCH_W()
/* with OP_EXT3 (1st & 2nd 16bit) */
#define FETCH_Z_3() FETCH_Z()
#define FETCH_B_3() FETCH_B()
#define FETCH_BB_3() do {a=READ_S(); b=READ_S();} while (0)
#define FETCH_BBB_3() do {a=READ_S(); b=READ_S(); c=READ_B();} while (0)
#define FETCH_BS_3() do {a=READ_S(); b=READ_S();} while (0)
#define FETCH_S_3() FETCH_S()
#define FETCH_W_3() FETCH_W()
#endif /* MRUBY_OPCODE_H */
+117
View File
@@ -0,0 +1,117 @@
/* operand types:
+ Z: no operand (Z,Z,Z,Z)
+ B: 8bit (B,S,B,B)
+ BB: 8+8bit (BB,SB,BS,SS)
+ BBB: 8+8+8bit (BBB,SBB,BSB,SSB)
+ BS: 8+16bit (BS,SS,BS,BS)
+ S: 16bit (S,S,S,S)
+ W: 24bit (W,W,W,W)
*/
/*-----------------------------------------------------------------------
operation code operands semantics
------------------------------------------------------------------------*/
OPCODE(NOP, Z) /* no operation */
OPCODE(MOVE, BB) /* R(a) = R(b) */
OPCODE(LOADL, BB) /* R(a) = Pool(b) */
OPCODE(LOADI, BB) /* R(a) = mrb_int(b) */
OPCODE(LOADINEG, BB) /* R(a) = mrb_int(-b) */
OPCODE(LOADI__1, B) /* R(a) = mrb_int(-1) */
OPCODE(LOADI_0, B) /* R(a) = mrb_int(0) */
OPCODE(LOADI_1, B) /* R(a) = mrb_int(1) */
OPCODE(LOADI_2, B) /* R(a) = mrb_int(2) */
OPCODE(LOADI_3, B) /* R(a) = mrb_int(3) */
OPCODE(LOADI_4, B) /* R(a) = mrb_int(4) */
OPCODE(LOADI_5, B) /* R(a) = mrb_int(5) */
OPCODE(LOADI_6, B) /* R(a) = mrb_int(6) */
OPCODE(LOADI_7, B) /* R(a) = mrb_int(7) */
OPCODE(LOADSYM, BB) /* R(a) = Syms(b) */
OPCODE(LOADNIL, B) /* R(a) = nil */
OPCODE(LOADSELF, B) /* R(a) = self */
OPCODE(LOADT, B) /* R(a) = true */
OPCODE(LOADF, B) /* R(a) = false */
OPCODE(GETGV, BB) /* R(a) = getglobal(Syms(b)) */
OPCODE(SETGV, BB) /* setglobal(Syms(b), R(a)) */
OPCODE(GETSV, BB) /* R(a) = Special[Syms(b)] */
OPCODE(SETSV, BB) /* Special[Syms(b)] = R(a) */
OPCODE(GETIV, BB) /* R(a) = ivget(Syms(b)) */
OPCODE(SETIV, BB) /* ivset(Syms(b),R(a)) */
OPCODE(GETCV, BB) /* R(a) = cvget(Syms(b)) */
OPCODE(SETCV, BB) /* cvset(Syms(b),R(a)) */
OPCODE(GETCONST, BB) /* R(a) = constget(Syms(b)) */
OPCODE(SETCONST, BB) /* constset(Syms(b),R(a)) */
OPCODE(GETMCNST, BB) /* R(a) = R(a)::Syms(b) */
OPCODE(SETMCNST, BB) /* R(a+1)::Syms(b) = R(a) */
OPCODE(GETUPVAR, BBB) /* R(a) = uvget(b,c) */
OPCODE(SETUPVAR, BBB) /* uvset(b,c,R(a)) */
OPCODE(JMP, S) /* pc=a */
OPCODE(JMPIF, BS) /* if R(b) pc=a */
OPCODE(JMPNOT, BS) /* if !R(b) pc=a */
OPCODE(JMPNIL, BS) /* if R(b)==nil pc=a */
OPCODE(ONERR, S) /* rescue_push(a) */
OPCODE(EXCEPT, B) /* R(a) = exc */
OPCODE(RESCUE, BB) /* R(b) = R(a).isa?(R(b)) */
OPCODE(POPERR, B) /* a.times{rescue_pop()} */
OPCODE(RAISE, B) /* raise(R(a)) */
OPCODE(EPUSH, B) /* ensure_push(SEQ[a]) */
OPCODE(EPOP, B) /* A.times{ensure_pop().call} */
OPCODE(SENDV, BB) /* R(a) = call(R(a),Syms(b),*R(a+1)) */
OPCODE(SENDVB, BB) /* R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2)) */
OPCODE(SEND, BBB) /* R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c)) */
OPCODE(SENDB, BBB) /* R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1)) */
OPCODE(CALL, Z) /* R(0) = self.call(frame.argc, frame.argv) */
OPCODE(SUPER, BB) /* R(a) = super(R(a+1),... ,R(a+b+1)) */
OPCODE(ARGARY, BS) /* R(a) = argument array (16=m5:r1:m5:d1:lv4) */
OPCODE(ENTER, W) /* arg setup according to flags (23=m5:o5:r1:m5:k5:d1:b1) */
OPCODE(KEY_P, BB) /* R(a) = kdict.key?(Syms(b)) # todo */
OPCODE(KEYEND, Z) /* raise unless kdict.empty? # todo */
OPCODE(KARG, BB) /* R(a) = kdict[Syms(b)]; kdict.delete(Syms(b)) # todo */
OPCODE(RETURN, B) /* return R(a) (normal) */
OPCODE(RETURN_BLK, B) /* return R(a) (in-block return) */
OPCODE(BREAK, B) /* break R(a) */
OPCODE(BLKPUSH, BS) /* R(a) = block (16=m5:r1:m5:d1:lv4) */
OPCODE(ADD, BB) /* R(a) = R(a)+R(a+1) (Syms[b]=:+) */
OPCODE(ADDI, BBB) /* R(a) = R(a)+mrb_int(c) (Syms[b]=:+) */
OPCODE(SUB, BB) /* R(a) = R(a)-R(a+1) (Syms[b]=:-) */
OPCODE(SUBI, BBB) /* R(a) = R(a)-C (Syms[b]=:-) */
OPCODE(MUL, BB) /* R(a) = R(a)*R(a+1) (Syms[b]=:*) */
OPCODE(DIV, BB) /* R(a) = R(a)/R(a+1) (Syms[b]=:/) */
OPCODE(EQ, BB) /* R(a) = R(a)==R(a+1) (Syms[b]=:==) */
OPCODE(LT, BB) /* R(a) = R(a)<R(a+1) (Syms[b]=:<) */
OPCODE(LE, BB) /* R(a) = R(a)<=R(a+1) (Syms[b]=:<=) */
OPCODE(GT, BB) /* R(a) = R(a)>R(a+1) (Syms[b]=:>) */
OPCODE(GE, BB) /* R(a) = R(a)>=R(a+1) (Syms[b]=:>=) */
OPCODE(ARRAY, BB) /* R(a) = ary_new(R(a),R(a+1)..R(a+b)) */
OPCODE(ARRAY2, BBB) /* R(a) = ary_new(R(b),R(b+1)..R(b+c)) */
OPCODE(ARYCAT, B) /* ary_cat(R(a),R(a+1)) */
OPCODE(ARYPUSH, B) /* ary_push(R(a),R(a+1)) */
OPCODE(ARYDUP, B) /* R(a) = ary_dup(R(a)) */
OPCODE(AREF, BBB) /* R(a) = R(b)[c] */
OPCODE(ASET, BBB) /* R(a)[c] = R(b) */
OPCODE(APOST, BBB) /* *R(a),R(a+1)..R(a+C) = R(a)[b..] */
OPCODE(INTERN, B) /* R(a) = intern(R(a)) */
OPCODE(STRING, BB) /* R(a) = str_dup(Lit(b)) */
OPCODE(STRCAT, B) /* str_cat(R(a),R(a+1)) */
OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b)) */
OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b)) */
OPCODE(HASHCAT, B) /* R(a) = hash_cat(R(a),R(a+1)) */
OPCODE(LAMBDA, BB) /* R(a) = lambda(SEQ[b],L_LAMBDA) */
OPCODE(BLOCK, BB) /* R(a) = lambda(SEQ[b],L_BLOCK) */
OPCODE(METHOD, BB) /* R(a) = lambda(SEQ[b],L_METHOD) */
OPCODE(RANGE_INC, B) /* R(a) = range_new(R(a),R(a+1),FALSE) */
OPCODE(RANGE_EXC, B) /* R(a) = range_new(R(a),R(a+1),TRUE) */
OPCODE(OCLASS, B) /* R(a) = ::Object */
OPCODE(CLASS, BB) /* R(a) = newclass(R(a),Syms(b),R(a+1)) */
OPCODE(MODULE, BB) /* R(a) = newmodule(R(a),Syms(b)) */
OPCODE(EXEC, BB) /* R(a) = blockexec(R(a),SEQ[b]) */
OPCODE(DEF, BB) /* R(a).newmethod(Syms(b),R(a+1)) */
OPCODE(ALIAS, BB) /* alias_method(target_class,Syms(a),Syms(b)) */
OPCODE(UNDEF, B) /* undef_method(target_class,Syms(a)) */
OPCODE(SCLASS, B) /* R(a) = R(a).singleton_class */
OPCODE(TCLASS, B) /* R(a) = target_class */
OPCODE(DEBUG, BBB) /* print a,b,c */
OPCODE(ERR, B) /* raise(LocalJumpError, Lit(a)) */
OPCODE(EXT1, Z) /* make 1st operand 16bit */
OPCODE(EXT2, Z) /* make 2nd operand 16bit */
OPCODE(EXT3, Z) /* make 1st and 2nd operands 16bit */
OPCODE(STOP, Z) /* stop VM */
+5 -3
View File
@@ -510,6 +510,7 @@ check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value
mrb_sym sym;
int32_t bpno;
mrb_bool isCfunc;
struct mrb_insn_data insn;
mrb_debug_context *dbg = mrb_debug_context_get(mrb);
@@ -517,11 +518,12 @@ check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value
bpno = dbg->method_bpno;
dbg->method_bpno = 0;
switch(GET_OPCODE(*pc)) {
insn = mrb_decode_insn(pc);
switch(insn.insn) {
case OP_SEND:
case OP_SENDB:
c = mrb_class(mrb, regs[GETARG_A(*pc)]);
sym = irep->syms[GETARG_B(*pc)];
c = mrb_class(mrb, regs[insn.a]);
sym = irep->syms[insn.b];
break;
case OP_SUPER:
c = mrb->c->ci->target_class->super;
File diff suppressed because it is too large Load Diff
+4 -20
View File
@@ -9,14 +9,11 @@
enum node_type {
NODE_METHOD,
NODE_FBODY,
NODE_CFUNC,
NODE_SCOPE,
NODE_BLOCK,
NODE_IF,
NODE_CASE,
NODE_WHEN,
NODE_OPT_N,
NODE_WHILE,
NODE_UNTIL,
NODE_ITER,
@@ -40,12 +37,12 @@ enum node_type {
NODE_CALL,
NODE_SCALL,
NODE_FCALL,
NODE_VCALL,
NODE_SUPER,
NODE_ZSUPER,
NODE_ARRAY,
NODE_ZARRAY,
NODE_HASH,
NODE_KW_HASH,
NODE_RETURN,
NODE_YIELD,
NODE_LVAR,
@@ -57,8 +54,6 @@ enum node_type {
NODE_NTH_REF,
NODE_BACK_REF,
NODE_MATCH,
NODE_MATCH2,
NODE_MATCH3,
NODE_INT,
NODE_FLOAT,
NODE_NEGATE,
@@ -71,10 +66,10 @@ enum node_type {
NODE_REGX,
NODE_DREGX,
NODE_DREGX_ONCE,
NODE_LIST,
NODE_ARG,
NODE_ARGSCAT,
NODE_ARGSPUSH,
NODE_ARGS_TAIL,
NODE_KW_ARG,
NODE_KW_REST_ARGS,
NODE_SPLAT,
NODE_TO_ARY,
NODE_SVALUE,
@@ -88,26 +83,15 @@ enum node_type {
NODE_SCLASS,
NODE_COLON2,
NODE_COLON3,
NODE_CREF,
NODE_DOT2,
NODE_DOT3,
NODE_FLIP2,
NODE_FLIP3,
NODE_ATTRSET,
NODE_SELF,
NODE_NIL,
NODE_TRUE,
NODE_FALSE,
NODE_DEFINED,
NODE_NEWLINE,
NODE_POSTEXE,
NODE_ALLOCA,
NODE_DMETHOD,
NODE_BMETHOD,
NODE_MEMO,
NODE_IFUNC,
NODE_DSYM,
NODE_ATTRASGN,
NODE_HEREDOC,
NODE_LITERAL_DELIM,
NODE_WORDS,
+330 -174
View File
@@ -568,6 +568,13 @@ new_hash(parser_state *p, node *a)
return cons((node*)NODE_HASH, a);
}
/* (:kw_hash (k . v) (k . v)...) */
static node*
new_kw_hash(parser_state *p, node *a)
{
return cons((node*)NODE_KW_HASH, a);
}
/* (:sym . a) */
static node*
new_sym(parser_state *p, mrb_sym sym)
@@ -671,23 +678,61 @@ new_arg(parser_state *p, mrb_sym sym)
return cons((node*)NODE_ARG, nsym(sym));
}
/* (m o r m2 b) */
/* (m o r m2 tail) */
/* m: (a b c) */
/* o: ((a . e1) (b . e2)) */
/* r: a */
/* m2: (a b c) */
/* b: a */
static node*
new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2, mrb_sym blk)
new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2, node *tail)
{
node *n;
n = cons(m2, nsym(blk));
n = cons(m2, tail);
n = cons(nsym(rest), n);
n = cons(opt, n);
return cons(m, n);
}
/* (:args_tail keywords rest_keywords_sym block_sym) */
static node*
new_args_tail(parser_state *p, node *kws, node *kwrest, mrb_sym blk)
{
node *k;
/* allocate register for keywords hash */
if (kws || kwrest) {
local_add_f(p, (kwrest && kwrest->cdr)? sym(kwrest->cdr) : mrb_intern_lit(p->mrb, "**"));
}
/* allocate register for block */
local_add_f(p, blk? blk : mrb_intern_lit(p->mrb, "&"));
// allocate register for keywords arguments
// order is for Proc#parameters
for (k = kws; k; k = k->cdr) {
if (!k->car->cdr->cdr->car) { // allocate required keywords
local_add_f(p, sym(k->car->cdr->car));
}
}
for (k = kws; k; k = k->cdr) {
if (k->car->cdr->cdr->car) { // allocate keywords with default
local_add_f(p, sym(k->car->cdr->car));
}
}
return list4((node*)NODE_ARGS_TAIL, kws, kwrest, nsym(blk));
}
/* (:kw_arg kw_sym def_arg) */
static node*
new_kw_arg(parser_state *p, mrb_sym kw, node *def_arg)
{
mrb_assert(kw);
return list3((node*)NODE_KW_ARG, nsym(kw), def_arg);
}
/* (:block_arg . a) */
static node*
new_block_arg(parser_state *p, node *a)
@@ -1134,6 +1179,10 @@ heredoc_end(parser_state *p)
%type <nd> heredoc words symbols
%type <num> call_op call_op2 /* 0:'&.', 1:'.', 2:'::' */
%type <nd> args_tail opt_args_tail f_kwarg f_kw f_kwrest
%type <nd> f_block_kwarg f_block_kw block_args_tail opt_block_args_tail
%type <id> f_label
%token tUPLUS /* unary+ */
%token tUMINUS /* unary- */
%token tPOW /* ** */
@@ -1159,6 +1208,7 @@ heredoc_end(parser_state *p)
%token tLBRACE /* { */
%token tLBRACE_ARG /* { */
%token tSTAR /* * */
%token tDSTAR /* ** */
%token tAMPER /* & */
%token tLAMBDA /* -> */
%token tANDDOT /* &. */
@@ -1736,6 +1786,7 @@ op : '|' { $$ = intern_c('|'); }
| '/' { $$ = intern_c('/'); }
| '%' { $$ = intern_c('%'); }
| tPOW { $$ = intern("**",2); }
| tDSTAR { $$ = intern("**",2); }
| '!' { $$ = intern_c('!'); }
| '~' { $$ = intern_c('~'); }
| tUPLUS { $$ = intern("+@",2); }
@@ -1944,11 +1995,11 @@ aref_args : none
}
| args comma assocs trailer
{
$$ = push($1, new_hash(p, $3));
$$ = push($1, new_kw_hash(p, $3));
}
| assocs trailer
{
$$ = cons(new_hash(p, $1), 0);
$$ = cons(new_kw_hash(p, $1), 0);
NODE_LINENO($$, $1);
}
;
@@ -1984,12 +2035,12 @@ opt_call_args : none
}
| args comma assocs ','
{
$$ = cons(push($1, new_hash(p, $3)), 0);
$$ = cons(push($1, new_kw_hash(p, $3)), 0);
NODE_LINENO($$, $1);
}
| assocs ','
{
$$ = cons(list1(new_hash(p, $1)), 0);
$$ = cons(list1(new_kw_hash(p, $1)), 0);
NODE_LINENO($$, $1);
}
;
@@ -2007,12 +2058,12 @@ call_args : command
}
| assocs opt_block_arg
{
$$ = cons(list1(new_hash(p, $1)), $2);
$$ = cons(list1(new_kw_hash(p, $1)), $2);
NODE_LINENO($$, $1);
}
| args comma assocs opt_block_arg
{
$$ = cons(push($1, new_hash(p, $3)), $4);
$$ = cons(push($1, new_kw_hash(p, $3)), $4);
NODE_LINENO($$, $1);
}
| block_arg
@@ -2451,23 +2502,51 @@ f_margs : f_marg_list
}
;
block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg
{
$$ = new_args_tail(p, $1, $3, $4);
}
| f_block_kwarg opt_f_block_arg
{
$$ = new_args_tail(p, $1, 0, $2);
}
| f_kwrest opt_f_block_arg
{
$$ = new_args_tail(p, 0, $1, $2);
}
| f_block_arg
{
$$ = new_args_tail(p, 0, 0, $1);
}
;
opt_block_args_tail : ',' block_args_tail
{
$$ = $2;
}
| /* none */
{
$$ = new_args_tail(p, 0, 0, 0);
}
;
block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail
{
$$ = new_args(p, $1, $3, $5, 0, $6);
}
| f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
| f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail
{
$$ = new_args(p, $1, $3, $5, $7, $8);
}
| f_arg ',' f_block_optarg opt_f_block_arg
| f_arg ',' f_block_optarg opt_block_args_tail
{
$$ = new_args(p, $1, $3, 0, 0, $4);
}
| f_arg ',' f_block_optarg ',' f_arg opt_f_block_arg
| f_arg ',' f_block_optarg ',' f_arg opt_block_args_tail
{
$$ = new_args(p, $1, $3, 0, $5, $6);
}
| f_arg ',' f_rest_arg opt_f_block_arg
| f_arg ',' f_rest_arg opt_block_args_tail
{
$$ = new_args(p, $1, 0, $3, 0, $4);
}
@@ -2475,39 +2554,39 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
{
$$ = new_args(p, $1, 0, 0, 0, 0);
}
| f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
| f_arg ',' f_rest_arg ',' f_arg opt_block_args_tail
{
$$ = new_args(p, $1, 0, $3, $5, $6);
}
| f_arg opt_f_block_arg
| f_arg opt_block_args_tail
{
$$ = new_args(p, $1, 0, 0, 0, $2);
}
| f_block_optarg ',' f_rest_arg opt_f_block_arg
| f_block_optarg ',' f_rest_arg opt_block_args_tail
{
$$ = new_args(p, 0, $1, $3, 0, $4);
}
| f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
| f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail
{
$$ = new_args(p, 0, $1, $3, $5, $6);
}
| f_block_optarg opt_f_block_arg
| f_block_optarg opt_block_args_tail
{
$$ = new_args(p, 0, $1, 0, 0, $2);
}
| f_block_optarg ',' f_arg opt_f_block_arg
| f_block_optarg ',' f_arg opt_block_args_tail
{
$$ = new_args(p, 0, $1, 0, $3, $4);
}
| f_rest_arg opt_f_block_arg
| f_rest_arg opt_block_args_tail
{
$$ = new_args(p, 0, 0, $1, 0, $2);
}
| f_rest_arg ',' f_arg opt_f_block_arg
| f_rest_arg ',' f_arg opt_block_args_tail
{
$$ = new_args(p, 0, 0, $1, $3, $4);
}
| f_block_arg
| block_args_tail
{
$$ = new_args(p, 0, 0, 0, 0, $1);
}
@@ -3021,65 +3100,151 @@ f_arglist : '(' f_args rparen
}
;
f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
f_label : tIDENTIFIER tLABEL_TAG
;
f_kw : f_label arg
{
void_expr_error(p, $2);
$$ = new_kw_arg(p, $1, $2);
}
| f_label
{
$$ = new_kw_arg(p, $1, 0);
}
;
f_block_kw : f_label primary_value
{
$$ = new_kw_arg(p, $1, $2);
}
| f_label
{
$$ = new_kw_arg(p, $1, 0);
}
;
f_block_kwarg : f_block_kw
{
$$ = list1($1);
}
| f_block_kwarg ',' f_block_kw
{
$$ = push($1, $3);
}
;
f_kwarg : f_kw
{
$$ = list1($1);
}
| f_kwarg ',' f_kw
{
$$ = push($1, $3);
}
;
kwrest_mark : tPOW
| tDSTAR
;
f_kwrest : kwrest_mark tIDENTIFIER
{
$$ = cons((node*)NODE_KW_REST_ARGS, nsym($2));
}
| kwrest_mark
{
$$ = cons((node*)NODE_KW_REST_ARGS, 0);
}
;
args_tail : f_kwarg ',' f_kwrest opt_f_block_arg
{
$$ = new_args_tail(p, $1, $3, $4);
}
| f_kwarg opt_f_block_arg
{
$$ = new_args_tail(p, $1, 0, $2);
}
| f_kwrest opt_f_block_arg
{
$$ = new_args_tail(p, 0, $1, $2);
}
| f_block_arg
{
$$ = new_args_tail(p, 0, 0, $1);
}
;
opt_args_tail : ',' args_tail
{
$$ = $2;
}
| /* none */
{
$$ = new_args_tail(p, 0, 0, 0);
}
;
f_args : f_arg ',' f_optarg ',' f_rest_arg opt_args_tail
{
$$ = new_args(p, $1, $3, $5, 0, $6);
}
| f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
| f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_args_tail
{
$$ = new_args(p, $1, $3, $5, $7, $8);
}
| f_arg ',' f_optarg opt_f_block_arg
| f_arg ',' f_optarg opt_args_tail
{
$$ = new_args(p, $1, $3, 0, 0, $4);
}
| f_arg ',' f_optarg ',' f_arg opt_f_block_arg
| f_arg ',' f_optarg ',' f_arg opt_args_tail
{
$$ = new_args(p, $1, $3, 0, $5, $6);
}
| f_arg ',' f_rest_arg opt_f_block_arg
| f_arg ',' f_rest_arg opt_args_tail
{
$$ = new_args(p, $1, 0, $3, 0, $4);
}
| f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
| f_arg ',' f_rest_arg ',' f_arg opt_args_tail
{
$$ = new_args(p, $1, 0, $3, $5, $6);
}
| f_arg opt_f_block_arg
| f_arg opt_args_tail
{
$$ = new_args(p, $1, 0, 0, 0, $2);
}
| f_optarg ',' f_rest_arg opt_f_block_arg
| f_optarg ',' f_rest_arg opt_args_tail
{
$$ = new_args(p, 0, $1, $3, 0, $4);
}
| f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
| f_optarg ',' f_rest_arg ',' f_arg opt_args_tail
{
$$ = new_args(p, 0, $1, $3, $5, $6);
}
| f_optarg opt_f_block_arg
| f_optarg opt_args_tail
{
$$ = new_args(p, 0, $1, 0, 0, $2);
}
| f_optarg ',' f_arg opt_f_block_arg
| f_optarg ',' f_arg opt_args_tail
{
$$ = new_args(p, 0, $1, 0, $3, $4);
}
| f_rest_arg opt_f_block_arg
| f_rest_arg opt_args_tail
{
$$ = new_args(p, 0, 0, $1, 0, $2);
}
| f_rest_arg ',' f_arg opt_f_block_arg
| f_rest_arg ',' f_arg opt_args_tail
{
$$ = new_args(p, 0, 0, $1, $3, $4);
}
| f_block_arg
| args_tail
{
$$ = new_args(p, 0, 0, 0, 0, $1);
}
| /* none */
{
local_add_f(p, 0);
local_add_f(p, mrb_intern_lit(p->mrb, "&"));
$$ = new_args(p, 0, 0, 0, 0, 0);
}
;
@@ -3189,7 +3354,7 @@ f_rest_arg : restarg_mark tIDENTIFIER
}
| restarg_mark
{
local_add_f(p, 0);
local_add_f(p, mrb_intern_lit(p->mrb, "*"));
$$ = -1;
}
;
@@ -3200,7 +3365,6 @@ blkarg_mark : '&'
f_block_arg : blkarg_mark tIDENTIFIER
{
local_add_f(p, $2);
$$ = $2;
}
;
@@ -3211,7 +3375,6 @@ opt_f_block_arg : ',' f_block_arg
}
| none
{
local_add_f(p, 0);
$$ = 0;
}
;
@@ -3285,6 +3448,11 @@ assoc : arg tASSOC arg
$$ = cons(new_sym(p, new_strsym(p, $1)), $3);
}
}
| tDSTAR arg
{
void_expr_error(p, $2);
$$ = cons(cons((node*)NODE_KW_REST_ARGS, 0), $2);
}
;
operation : tIDENTIFIER
@@ -3450,13 +3618,13 @@ backref_error(parser_state *p, node *n)
{
int c;
c = (int)(intptr_t)n->car;
c = intn(n->car);
if (c == NODE_NTH_REF) {
yyerror_i(p, "can't set variable $%" MRB_PRId, (int)(intptr_t)n->cdr);
yyerror_i(p, "can't set variable $%" MRB_PRId, intn(n->cdr));
}
else if (c == NODE_BACK_REF) {
yyerror_i(p, "can't set variable $%c", (int)(intptr_t)n->cdr);
yyerror_i(p, "can't set variable $%c", intn(n->cdr));
}
else {
mrb_bug(p->mrb, "Internal error in backref_error() : n=>car == %S", mrb_fixnum_value(c));
@@ -3469,7 +3637,7 @@ void_expr_error(parser_state *p, node *n)
int c;
if (n == NULL) return;
c = (int)(intptr_t)n->car;
c = intn(n->car);
switch (c) {
case NODE_BREAK:
case NODE_RETURN:
@@ -3508,7 +3676,7 @@ nextc(parser_state *p)
if (p->pb) {
node *tmp;
c = (int)(intptr_t)p->pb->car;
c = intn(p->pb->car);
tmp = p->pb;
p->pb = p->pb->cdr;
cons_free(tmp);
@@ -3557,7 +3725,7 @@ pushback(parser_state *p, int c)
if (c >= 0) {
p->column--;
}
p->pb = cons((node*)(intptr_t)c, p->pb);
p->pb = cons(nint(c), p->pb);
}
static void
@@ -3582,7 +3750,7 @@ peekc_n(parser_state *p, int n)
c0 = nextc(p);
if (c0 == -1) return c0; /* do not skip partial EOF */
if (c0 >= 0) --p->column;
list = push(list, (node*)(intptr_t)c0);
list = push(list, nint(c0));
} while(n--);
if (p->pb) {
p->pb = append((node*)list, p->pb);
@@ -4019,11 +4187,11 @@ parse_string(parser_state *p)
}
else if (c == beg) {
nest_level++;
p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
p->lex_strterm->cdr->car = nint(nest_level);
}
else if (c == end) {
nest_level--;
p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
p->lex_strterm->cdr->car = nint(nest_level);
}
else if (c == '\\') {
c = nextc(p);
@@ -4365,7 +4533,16 @@ parser_yylex(parser_state *p)
return tOP_ASGN;
}
pushback(p, c);
c = tPOW;
if (IS_SPCARG(c)) {
yywarning(p, "`**' interpreted as argument prefix");
c = tDSTAR;
}
else if (IS_BEG()) {
c = tDSTAR;
}
else {
c = tPOW; /* "**", "argument prefix" */
}
}
else {
if (c == '=') {
@@ -5534,6 +5711,7 @@ parser_init_cxt(parser_state *p, mrbc_context *cxt)
}
p->capture_errors = cxt->capture_errors;
p->no_optimize = cxt->no_optimize;
p->on_eval = cxt->on_eval;
if (cxt->partial_hook) {
p->cxt = cxt;
}
@@ -5546,7 +5724,7 @@ parser_update_cxt(parser_state *p, mrbc_context *cxt)
int i = 0;
if (!cxt) return;
if ((int)(intptr_t)p->tree->car != NODE_SCOPE) return;
if (intn(p->tree->car) != NODE_SCOPE) return;
n0 = n = p->tree->cdr->car;
while (n) {
i++;
@@ -5896,6 +6074,48 @@ dump_recur(mrb_state *mrb, node *tree, int offset)
}
}
static void
dump_args(mrb_state *mrb, node *n, int offset)
{
if (n->car) {
dump_prefix(n, offset+1);
printf("mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("optional args:\n");
{
node *n2 = n->car;
while (n2) {
dump_prefix(n2, offset+2);
printf("%s=\n", mrb_sym2name(mrb, sym(n2->car->car)));
mrb_parser_dump(mrb, n2->car->cdr, offset+3);
n2 = n2->cdr;
}
}
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("post mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n) {
mrb_assert(intn(n->car) == NODE_ARGS_TAIL);
mrb_parser_dump(mrb, n, offset);
}
}
#endif
void
@@ -5907,7 +6127,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
if (!tree) return;
again:
dump_prefix(tree, offset);
nodetype = (int)(intptr_t)tree->car;
nodetype = intn(tree->car);
tree = tree->cdr;
switch (nodetype) {
case NODE_BEGIN:
@@ -5967,7 +6187,8 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
case NODE_LAMBDA:
printf("NODE_BLOCK:\n");
printf("NODE_LAMBDA:\n");
dump_prefix(tree, offset);
goto block;
case NODE_BLOCK:
@@ -5975,43 +6196,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
printf("NODE_BLOCK:\n");
tree = tree->cdr;
if (tree->car) {
node *n = tree->car;
if (n->car) {
dump_prefix(n, offset+1);
printf("mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("optional args:\n");
{
node *n2 = n->car;
while (n2) {
dump_prefix(n2, offset+2);
printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
mrb_parser_dump(mrb, n2->car->cdr, 0);
n2 = n2->cdr;
}
}
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("post mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
if (n->cdr) {
dump_prefix(n, offset+1);
printf("blk=&%s\n", mrb_sym2name(mrb, sym(n->cdr)));
}
dump_args(mrb, tree->car, offset+1);
}
dump_prefix(tree, offset+1);
printf("body:\n");
@@ -6163,7 +6348,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
dump_prefix(tree, offset+1);
printf("method='%s' (%d)\n",
mrb_sym2name(mrb, sym(tree->cdr->car)),
(int)(intptr_t)tree->cdr->car);
intn(tree->cdr->car));
tree = tree->cdr->cdr->car;
if (tree) {
dump_prefix(tree, offset+1);
@@ -6218,6 +6403,19 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
}
break;
case NODE_KW_HASH:
printf("NODE_KW_HASH:\n");
while (tree) {
dump_prefix(tree, offset+1);
printf("key:\n");
mrb_parser_dump(mrb, tree->car->car, offset+2);
dump_prefix(tree, offset+1);
printf("value:\n");
mrb_parser_dump(mrb, tree->car->cdr, offset+2);
tree = tree->cdr;
}
break;
case NODE_SPLAT:
printf("NODE_SPLAT:\n");
mrb_parser_dump(mrb, tree, offset+1);
@@ -6280,7 +6478,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
mrb_parser_dump(mrb, tree->car, offset+2);
tree = tree->cdr;
dump_prefix(tree, offset+1);
printf("op='%s' (%d)\n", mrb_sym2name(mrb, sym(tree->car)), (int)(intptr_t)tree->car);
printf("op='%s' (%d)\n", mrb_sym2name(mrb, sym(tree->car)), intn(tree->car));
tree = tree->cdr;
mrb_parser_dump(mrb, tree->car, offset+1);
break;
@@ -6362,11 +6560,11 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
case NODE_BACK_REF:
printf("NODE_BACK_REF: $%c\n", (int)(intptr_t)tree);
printf("NODE_BACK_REF: $%c\n", intn(tree));
break;
case NODE_NTH_REF:
printf("NODE_NTH_REF: $%" MRB_PRId "\n", (mrb_int)(intptr_t)tree);
printf("NODE_NTH_REF: $%d\n", intn(tree));
break;
case NODE_ARG:
@@ -6379,7 +6577,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
case NODE_INT:
printf("NODE_INT %s base %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr->car);
printf("NODE_INT %s base %d\n", (char*)tree->car, intn(tree->cdr->car));
break;
case NODE_FLOAT:
@@ -6392,7 +6590,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
case NODE_STR:
printf("NODE_STR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr);
printf("NODE_STR \"%s\" len %d\n", (char*)tree->car, intn(tree->cdr));
break;
case NODE_DSTR:
@@ -6401,7 +6599,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
case NODE_XSTR:
printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr);
printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car, intn(tree->cdr));
break;
case NODE_DXSTR:
@@ -6430,7 +6628,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
case NODE_SYM:
printf("NODE_SYM :%s (%d)\n", mrb_sym2name(mrb, sym(tree)),
(int)(intptr_t)tree);
intn(tree));
break;
case NODE_SELF:
@@ -6546,43 +6744,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
}
tree = tree->cdr;
if (tree->car) {
node *n = tree->car;
if (n->car) {
dump_prefix(n, offset+1);
printf("mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("optional args:\n");
{
node *n2 = n->car;
while (n2) {
dump_prefix(n2, offset+2);
printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
mrb_parser_dump(mrb, n2->car->cdr, 0);
n2 = n2->cdr;
}
}
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("post mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
if (n->cdr) {
dump_prefix(n, offset+1);
printf("blk=&%s\n", mrb_sym2name(mrb, sym(n->cdr)));
}
dump_args(mrb, tree->car, offset);
}
mrb_parser_dump(mrb, tree->cdr->car, offset+1);
break;
@@ -6595,44 +6757,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
printf(":%s\n", mrb_sym2name(mrb, sym(tree->car)));
tree = tree->cdr->cdr;
if (tree->car) {
node *n = tree->car;
if (n->car) {
dump_prefix(n, offset+1);
printf("mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("optional args:\n");
{
node *n2 = n->car;
while (n2) {
dump_prefix(n2, offset+2);
printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
mrb_parser_dump(mrb, n2->car->cdr, 0);
n2 = n2->cdr;
}
}
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("post mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n) {
dump_prefix(n, offset+1);
printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
}
dump_args(mrb, tree->car, offset+1);
}
tree = tree->cdr;
mrb_parser_dump(mrb, tree->car, offset+1);
@@ -6648,6 +6773,37 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
dump_recur(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
break;
case NODE_ARGS_TAIL:
printf("NODE_ARGS_TAIL:\n");
{
node *kws = tree->car;
while (kws) {
mrb_parser_dump(mrb, kws->car, offset+1);
kws = kws->cdr;
}
}
tree = tree->cdr;
if (tree->car) {
mrb_assert(intn(tree->car->car) == NODE_KW_REST_ARGS);
mrb_parser_dump(mrb, tree->car, offset+1);
}
tree = tree->cdr;
if (tree->car) {
dump_prefix(tree, offset+1);
printf("block='%s'\n", mrb_sym2name(mrb, sym(tree->car)));
}
break;
case NODE_KW_ARG:
printf("NODE_KW_ARG %s\n", mrb_sym2name(mrb, sym(tree->car)));
mrb_parser_dump(mrb, tree->cdr->car, offset + 1);
break;
case NODE_KW_REST_ARGS:
printf("NODE_KW_REST_ARGS %s\n", mrb_sym2name(mrb, sym(tree)));
break;
default:
printf("node type: %d (0x%x)\n", nodetype, (unsigned)nodetype);
break;
+75 -37
View File
@@ -44,7 +44,7 @@ search_irep(mrb_irep *top, int bnest, int lev, mrb_irep *bottom)
return NULL;
}
static inline mrb_code
static uint16_t
search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
{
mrb_irep *virep;
@@ -57,7 +57,7 @@ search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
}
for (pos = 0; pos < virep->nlocals - 1; pos++) {
if (vsym == virep->lv[pos].name) {
return (MKARG_B(pos + 1) | MKARG_C(level + bnest));
return (pos+1)<<8 | (level+bnest);
}
}
}
@@ -71,8 +71,8 @@ irep_argc(mrb_irep *irep)
mrb_code c;
c = irep->iseq[0];
if (GET_OPCODE(c) == OP_ENTER) {
mrb_aspec ax = GETARG_Ax(c);
if (c == OP_ENTER) {
mrb_aspec ax = PEEK_W(irep->iseq+1);
/* extra 1 means a slot for block */
return MRB_ASPEC_REQ(ax)+MRB_ASPEC_OPT(ax)+MRB_ASPEC_REST(ax)+MRB_ASPEC_POST(ax)+1;
}
@@ -88,95 +88,132 @@ potential_upvar_p(struct mrb_locals *lv, uint16_t v, int argc, uint16_t nlocals)
return TRUE;
}
extern uint8_t mrb_insn_size[];
extern uint8_t mrb_insn_size1[];
extern uint8_t mrb_insn_size2[];
extern uint8_t mrb_insn_size3[];
static void
patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
{
int i;
mrb_code c;
uint32_t a;
uint16_t b;
uint8_t c;
mrb_code insn;
int argc = irep_argc(irep);
for (i = 0; i < irep->ilen; i++) {
c = irep->iseq[i];
switch(GET_OPCODE(c)){
for (i = 0; i < irep->ilen; ) {
insn = irep->iseq[i];
switch(insn){
case OP_EPUSH:
patch_irep(mrb, irep->reps[GETARG_Bx(c)], bnest + 1, top);
b = PEEK_S(irep->iseq+i+1);
patch_irep(mrb, irep->reps[b], bnest + 1, top);
break;
case OP_LAMBDA:
{
int arg_c = GETARG_c(c);
if (arg_c & OP_L_CAPTURE) {
patch_irep(mrb, irep->reps[GETARG_b(c)], bnest + 1, top);
}
}
case OP_BLOCK:
a = PEEK_B(irep->iseq+i+1);
b = PEEK_B(irep->iseq+i+2);
patch_irep(mrb, irep->reps[b], bnest + 1, top);
break;
case OP_SEND:
if (GETARG_C(c) != 0) {
b = PEEK_B(irep->iseq+i+2);
c = PEEK_B(irep->iseq+i+3);
if (c != 0) {
break;
}
else {
mrb_code arg = search_variable(mrb, irep->syms[GETARG_B(c)], bnest);
uint16_t arg = search_variable(mrb, irep->syms[b], bnest);
if (arg != 0) {
/* must replace */
irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
irep->iseq[i] = OP_GETUPVAR;
irep->iseq[i+2] = arg >> 8;
irep->iseq[i+3] = arg & 0xff;
}
}
break;
case OP_MOVE:
a = PEEK_B(irep->iseq+i+1);
b = PEEK_B(irep->iseq+i+2);
/* src part */
if (potential_upvar_p(irep->lv, GETARG_B(c), argc, irep->nlocals)) {
mrb_code arg = search_variable(mrb, irep->lv[GETARG_B(c) - 1].name, bnest);
if (potential_upvar_p(irep->lv, b, argc, irep->nlocals)) {
uint16_t arg = search_variable(mrb, irep->lv[b - 1].name, bnest);
if (arg != 0) {
/* must replace */
irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
irep->iseq[i] = insn = OP_GETUPVAR;
irep->iseq[i+2] = arg >> 8;
irep->iseq[i+3] = arg & 0xff;
}
}
/* dst part */
if (potential_upvar_p(irep->lv, GETARG_A(c), argc, irep->nlocals)) {
mrb_code arg = search_variable(mrb, irep->lv[GETARG_A(c) - 1].name, bnest);
if (potential_upvar_p(irep->lv, a, argc, irep->nlocals)) {
uint16_t arg = search_variable(mrb, irep->lv[a - 1].name, bnest);
if (arg != 0) {
/* must replace */
irep->iseq[i] = MKOPCODE(OP_SETUPVAR) | MKARG_A(GETARG_B(c)) | arg;
irep->iseq[i] = insn = OP_SETUPVAR;
irep->iseq[i+1] = (mrb_code)b;
irep->iseq[i+2] = arg >> 8;
irep->iseq[i+3] = arg & 0xff;
}
}
break;
case OP_GETUPVAR:
a = PEEK_B(irep->iseq+i+1);
b = PEEK_B(irep->iseq+i+2);
c = PEEK_B(irep->iseq+i+3);
{
int lev = GETARG_C(c)+1;
int lev = c+1;
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
if (potential_upvar_p(tmp->lv, GETARG_B(c), irep_argc(tmp), tmp->nlocals)) {
mrb_code arg = search_variable(mrb, tmp->lv[GETARG_B(c)-1].name, bnest);
if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) {
uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
if (arg != 0) {
/* must replace */
irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
irep->iseq[i] = OP_GETUPVAR;
irep->iseq[i+2] = arg >> 8;
irep->iseq[i+3] = arg & 0xff;
}
}
}
break;
case OP_SETUPVAR:
a = PEEK_B(irep->iseq+i+1);
b = PEEK_B(irep->iseq+i+2);
c = PEEK_B(irep->iseq+i+3);
{
int lev = GETARG_C(c)+1;
int lev = c+1;
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
if (potential_upvar_p(tmp->lv, GETARG_B(c), irep_argc(tmp), tmp->nlocals)) {
mrb_code arg = search_variable(mrb, tmp->lv[GETARG_B(c)-1].name, bnest);
if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) {
uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
if (arg != 0) {
/* must replace */
irep->iseq[i] = MKOPCODE(OP_SETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
irep->iseq[i] = OP_SETUPVAR;
irep->iseq[i+1] = a;
irep->iseq[i+2] = arg >> 8;
irep->iseq[i+3] = arg & 0xff;
}
}
}
break;
case OP_STOP:
if (mrb->c->ci->acc >= 0) {
irep->iseq[i] = MKOP_AB(OP_RETURN, irep->nlocals, OP_R_NORMAL);
}
break;
case OP_EXT1:
insn = PEEK_B(irep->iseq+1);
i += mrb_insn_size1[insn];
continue;
case OP_EXT2:
insn = PEEK_B(irep->iseq+1);
i += mrb_insn_size2[insn];
continue;
case OP_EXT3:
insn = PEEK_B(irep->iseq+1);
i += mrb_insn_size3[insn];
continue;
}
i+=mrb_insn_size[insn];
}
}
@@ -203,6 +240,7 @@ create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding,
mrbc_filename(mrb, cxt, file ? file : "(eval)");
cxt->capture_errors = TRUE;
cxt->no_optimize = TRUE;
cxt->on_eval = TRUE;
p = mrb_parse_nstring(mrb, s, len, cxt);
+3 -3
View File
@@ -387,7 +387,7 @@ mrb_mruby_method_gem_init(mrb_state* mrb)
mrb_define_method(mrb, unbound_method, "bind", unbound_method_bind, MRB_ARGS_REQ(1));
mrb_define_method(mrb, unbound_method, "super_method", method_super_method, MRB_ARGS_NONE());
mrb_define_method(mrb, unbound_method, "==", method_eql, MRB_ARGS_REQ(1));
mrb_alias_method(mrb, unbound_method, mrb_intern_lit(mrb, "eql?"), mrb_intern_lit(mrb, "=="));
mrb_define_alias(mrb, unbound_method, "eql?", "==");
mrb_define_method(mrb, unbound_method, "to_s", method_to_s, MRB_ARGS_NONE());
mrb_define_method(mrb, unbound_method, "inspect", method_to_s, MRB_ARGS_NONE());
mrb_define_method(mrb, unbound_method, "arity", method_arity, MRB_ARGS_NONE());
@@ -396,11 +396,11 @@ mrb_mruby_method_gem_init(mrb_state* mrb)
mrb_undef_class_method(mrb, method, "new");
mrb_define_method(mrb, method, "==", method_eql, MRB_ARGS_REQ(1));
mrb_alias_method(mrb, method, mrb_intern_lit(mrb, "eql?"), mrb_intern_lit(mrb, "=="));
mrb_define_alias(mrb, method, "eql?", "==");
mrb_define_method(mrb, method, "to_s", method_to_s, MRB_ARGS_NONE());
mrb_define_method(mrb, method, "inspect", method_to_s, MRB_ARGS_NONE());
mrb_define_method(mrb, method, "call", method_call, MRB_ARGS_ANY());
mrb_alias_method(mrb, method, mrb_intern_lit(mrb, "[]"), mrb_intern_lit(mrb, "call"));
mrb_define_alias(mrb, method, "[]", "call");
mrb_define_method(mrb, method, "unbind", method_unbind, MRB_ARGS_NONE());
mrb_define_method(mrb, method, "super_method", method_super_method, MRB_ARGS_NONE());
mrb_define_method(mrb, method, "arity", method_arity, MRB_ARGS_NONE());
@@ -57,7 +57,7 @@ os_count_objects(mrb_state *mrb, mrb_value self)
hash = mrb_hash_new(mrb);
}
if (!mrb_test(mrb_hash_empty_p(mrb, hash))) {
if (!mrb_hash_empty_p(mrb, hash)) {
mrb_hash_clear(mrb, hash);
}
+17 -5
View File
@@ -109,6 +109,7 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self)
mrb_aspec aspec;
mrb_value sname, parameters;
int i, j;
int max = -1;
if (MRB_PROC_CFUNC_P(proc)) {
// TODO cfunc aspec is not implemented yet
@@ -120,7 +121,7 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self)
if (!irep->lv) {
return mrb_ary_new(mrb);
}
if (GET_OPCODE(*irep->iseq) != OP_ENTER) {
if (*irep->iseq != OP_ENTER) {
return mrb_ary_new(mrb);
}
@@ -129,7 +130,7 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self)
parameters_list[3].name = "opt";
}
aspec = GETARG_Ax(*irep->iseq);
aspec = PEEK_W(irep->iseq+1);
parameters_list[0].size = MRB_ASPEC_REQ(aspec);
parameters_list[1].size = MRB_ASPEC_OPT(aspec);
parameters_list[2].size = MRB_ASPEC_REST(aspec);
@@ -138,14 +139,25 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self)
parameters = mrb_ary_new_capa(mrb, irep->nlocals-1);
max = irep->nlocals-1;
for (i = 0, p = parameters_list; p->name; p++) {
if (p->size <= 0) continue;
sname = mrb_symbol_value(mrb_intern_cstr(mrb, p->name));
for (j = 0; j < p->size; i++, j++) {
mrb_value a = mrb_ary_new(mrb);
mrb_value a;
a = mrb_ary_new(mrb);
mrb_ary_push(mrb, a, sname);
if (irep->lv[i].name) {
mrb_ary_push(mrb, a, mrb_symbol_value(irep->lv[i].name));
if (i < max && irep->lv[i].name) {
mrb_sym sym = irep->lv[i].name;
const char *name = mrb_sym2name(mrb, sym);
switch (name[0]) {
case '*': case '&':
break;
default:
mrb_ary_push(mrb, a, mrb_symbol_value(sym));
break;
}
}
mrb_ary_push(mrb, parameters, a);
}
+2 -2
View File
@@ -627,8 +627,8 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb)
mrb_define_method(mrb, s, "chr", mrb_str_chr, MRB_ARGS_NONE());
mrb_define_method(mrb, s, "succ", mrb_str_succ, MRB_ARGS_NONE());
mrb_define_method(mrb, s, "succ!", mrb_str_succ_bang, MRB_ARGS_NONE());
mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next"), mrb_intern_lit(mrb, "succ"));
mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next!"), mrb_intern_lit(mrb, "succ!"));
mrb_define_alias(mrb, s, "next", "succ");
mrb_define_alias(mrb, s, "next!", "succ!");
mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE());
mrb_define_method(mrb, s, "delete_prefix!", mrb_str_del_prefix_bang, MRB_ARGS_REQ(1));
mrb_define_method(mrb, s, "delete_prefix", mrb_str_del_prefix, MRB_ARGS_REQ(1));
-5
View File
@@ -341,11 +341,6 @@ class Hash
}
self.replace(h)
end
def __update(h)
h.each_key{|k| self[k] = h[k]}
self
end
end
##
+4 -4
View File
@@ -1953,8 +1953,8 @@ mrb_mod_alias(mrb_state *mrb, mrb_value mod)
return mrb_nil_value();
}
static void
undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a)
void
mrb_undef_method_id(mrb_state *mrb, struct RClass *c, mrb_sym a)
{
if (!mrb_obj_respond_to(mrb, c, a)) {
mrb_name_error(mrb, a, "undefined method '%S' for class '%S'", mrb_sym2str(mrb, a), mrb_obj_value(c));
@@ -1970,7 +1970,7 @@ undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a)
MRB_API void
mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name)
{
undef_method(mrb, c, mrb_intern_cstr(mrb, name));
mrb_undef_method_id(mrb, c, mrb_intern_cstr(mrb, name));
}
MRB_API void
@@ -1988,7 +1988,7 @@ mrb_mod_undef(mrb_state *mrb, mrb_value mod)
mrb_get_args(mrb, "*", &argv, &argc);
while (argc--) {
undef_method(mrb, c, to_sym(mrb, *argv));
mrb_undef_method_id(mrb, c, to_sym(mrb, *argv));
argv++;
}
return mrb_nil_value();
+392 -322
View File
@@ -6,451 +6,521 @@
#include <mruby/proc.h>
#ifndef MRB_DISABLE_STDIO
static int
print_r(mrb_state *mrb, mrb_irep *irep, size_t n, int pre)
static void
print_r(mrb_state *mrb, mrb_irep *irep, size_t n)
{
size_t i;
if (n == 0) return 0;
if (n == 0) return;
for (i=0; i+1<irep->nlocals; i++) {
if (irep->lv[i].r == n) {
mrb_sym sym = irep->lv[i].name;
if (pre) printf(" ");
printf("R%d:%s", (int)n, mrb_sym2name(mrb, sym));
return 1;
printf(" R%d:%s", (int)n, mrb_sym2name(mrb, sym));
}
}
return 0;
}
#define RA 1
#define RB 2
#define RAB 3
static void
print_lv(mrb_state *mrb, mrb_irep *irep, mrb_code c, int r)
print_lv_a(mrb_state *mrb, mrb_irep *irep, uint16_t a)
{
int pre = 0;
if (!irep->lv
|| ((!(r & RA) || GETARG_A(c) >= irep->nlocals)
&& (!(r & RB) || GETARG_B(c) >= irep->nlocals))) {
if (!irep->lv || a >= irep->nlocals || a == 0) {
printf("\n");
return;
}
printf("\t; ");
if (r & RA) {
pre = print_r(mrb, irep, GETARG_A(c), 0);
}
if (r & RB) {
print_r(mrb, irep, GETARG_B(c), pre);
printf("\t;");
print_r(mrb, irep, a);
printf("\n");
}
static void
print_lv_ab(mrb_state *mrb, mrb_irep *irep, uint16_t a, uint16_t b)
{
if (!irep->lv || (a >= irep->nlocals && b >= irep->nlocals) || a+b == 0) {
printf("\n");
return;
}
printf("\t;");
if (a > 0) print_r(mrb, irep, a);
if (b > 0) print_r(mrb, irep, b);
printf("\n");
}
#endif
static void
print_header(mrb_irep *irep, ptrdiff_t i)
{
int32_t line;
line = mrb_debug_get_line(irep, i);
if (line < 0) {
printf(" ");
}
else {
printf("%5d ", line);
}
printf("%03d ", (int)i);
}
#define CASE(insn,ops) case insn: FETCH_ ## ops (); L_ ## insn
static void
codedump(mrb_state *mrb, mrb_irep *irep)
{
#ifndef MRB_DISABLE_STDIO
int i;
int ai;
mrb_code c;
mrb_code *pc, *pcend;
mrb_code ins;
const char *file = NULL, *next_file;
int32_t line;
if (!irep) return;
printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d\n", (void*)irep,
irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen);
for (i = 0; i < (int)irep->ilen; i++) {
if (irep->lv) {
int i;
printf("local variable names:\n");
for (i = 1; i < irep->nlocals; ++i) {
char const *n = mrb_sym2name(mrb, irep->lv[i - 1].name);
printf(" R%d:%s\n", irep->lv[i - 1].r, n? n : "");
}
}
pc = irep->iseq;
pcend = pc + irep->ilen;
while (pc < pcend) {
ptrdiff_t i;
uint32_t a;
uint16_t b;
uint8_t c;
ai = mrb_gc_arena_save(mrb);
i = pc - irep->iseq;
next_file = mrb_debug_get_filename(irep, i);
if (next_file && file != next_file) {
printf("file: %s\n", next_file);
file = next_file;
}
line = mrb_debug_get_line(irep, i);
if (line < 0) {
printf(" ");
}
else {
printf("%5d ", line);
}
printf("%03d ", i);
c = irep->iseq[i];
switch (GET_OPCODE(c)) {
case OP_NOP:
print_header(irep, i);
ins = READ_B();
switch (ins) {
CASE(OP_NOP, Z):
printf("OP_NOP\n");
break;
case OP_MOVE:
printf("OP_MOVE\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
print_lv(mrb, irep, c, RAB);
CASE(OP_MOVE, BB):
printf("OP_MOVE\tR%d\tR%d\t", a, b);
print_lv_ab(mrb, irep, a, b);
break;
case OP_LOADL:
CASE(OP_LOADL, BB):
{
mrb_value v = irep->pool[GETARG_Bx(c)];
mrb_value v = irep->pool[b];
mrb_value s = mrb_inspect(mrb, v);
printf("OP_LOADL\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s));
printf("OP_LOADL\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s));
}
print_lv(mrb, irep, c, RA);
print_lv_a(mrb, irep, a);
break;
case OP_LOADI:
printf("OP_LOADI\tR%d\t%d\t", GETARG_A(c), GETARG_sBx(c));
print_lv(mrb, irep, c, RA);
CASE(OP_LOADI, BB):
printf("OP_LOADI\tR%d\t%d\t", a, b);
print_lv_a(mrb, irep, a);
break;
case OP_LOADSYM:
printf("OP_LOADSYM\tR%d\t:%s", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
print_lv(mrb, irep, c, RA);
CASE(OP_LOADINEG, BB):
printf("OP_LOADI\tR%d\t-%d\t", a, b);
print_lv_a(mrb, irep, a);
break;
case OP_LOADNIL:
printf("OP_LOADNIL\tR%d\t\t", GETARG_A(c));
print_lv(mrb, irep, c, RA);
CASE(OP_LOADI__1, B):
printf("OP_LOADI__1\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
break;
case OP_LOADSELF:
printf("OP_LOADSELF\tR%d\t\t", GETARG_A(c));
print_lv(mrb, irep, c, RA);
CASE(OP_LOADI_0, B): goto L_LOADI;
CASE(OP_LOADI_1, B): goto L_LOADI;
CASE(OP_LOADI_2, B): goto L_LOADI;
CASE(OP_LOADI_3, B): goto L_LOADI;
CASE(OP_LOADI_4, B): goto L_LOADI;
CASE(OP_LOADI_5, B): goto L_LOADI;
CASE(OP_LOADI_6, B): goto L_LOADI;
CASE(OP_LOADI_7, B):
L_LOADI:
printf("OP_LOADI_%d\tR%d\t\t", ins-(int)OP_LOADI_0, a);
print_lv_a(mrb, irep, a);
break;
case OP_LOADT:
printf("OP_LOADT\tR%d\t\t", GETARG_A(c));
print_lv(mrb, irep, c, RA);
CASE(OP_LOADSYM, BB):
printf("OP_LOADSYM\tR%d\t:%s\t", a, mrb_sym2name(mrb, irep->syms[b]));
print_lv_a(mrb, irep, a);
break;
case OP_LOADF:
printf("OP_LOADF\tR%d\t\t", GETARG_A(c));
print_lv(mrb, irep, c, RA);
CASE(OP_LOADNIL, B):
printf("OP_LOADNIL\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
break;
case OP_GETGLOBAL:
printf("OP_GETGLOBAL\tR%d\t:%s", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
print_lv(mrb, irep, c, RA);
CASE(OP_LOADSELF, B):
printf("OP_LOADSELF\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
break;
case OP_SETGLOBAL:
printf("OP_SETGLOBAL\t:%s\tR%d\t",
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
GETARG_A(c));
print_lv(mrb, irep, c, RA);
CASE(OP_LOADT, B):
printf("OP_LOADT\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
break;
case OP_GETCONST:
printf("OP_GETCONST\tR%d\t:%s", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
print_lv(mrb, irep, c, RA);
CASE(OP_LOADF, B):
printf("OP_LOADF\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
break;
case OP_SETCONST:
printf("OP_SETCONST\t:%s\tR%d\t",
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
GETARG_A(c));
print_lv(mrb, irep, c, RA);
CASE(OP_GETGV, BB):
printf("OP_GETGV\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
print_lv_a(mrb, irep, a);
break;
case OP_GETMCNST:
printf("OP_GETMCNST\tR%d\tR%d::%s", GETARG_A(c), GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
print_lv(mrb, irep, c, RAB);
CASE(OP_SETGV, BB):
printf("OP_SETGV\t:%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
print_lv_a(mrb, irep, a);
break;
case OP_SETMCNST:
printf("OP_SETMCNST\tR%d::%s\tR%d", GETARG_A(c)+1,
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
GETARG_A(c));
print_lv(mrb, irep, c, RA);
CASE(OP_GETSV, BB):
printf("OP_GETSV\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
print_lv_a(mrb, irep, a);
break;
case OP_GETIV:
printf("OP_GETIV\tR%d\t%s", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
print_lv(mrb, irep, c, RA);
CASE(OP_SETSV, BB):
printf("OP_SETSV\t:%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
print_lv_a(mrb, irep, a);
break;
case OP_SETIV:
printf("OP_SETIV\t%s\tR%d",
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
GETARG_A(c));
print_lv(mrb, irep, c, RA);
CASE(OP_GETCONST, BB):
printf("OP_GETCONST\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
print_lv_a(mrb, irep, a);
break;
case OP_GETUPVAR:
printf("OP_GETUPVAR\tR%d\t%d\t%d",
GETARG_A(c), GETARG_B(c), GETARG_C(c));
print_lv(mrb, irep, c, RA);
CASE(OP_SETCONST, BB):
printf("OP_SETCONST\t:%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
print_lv_a(mrb, irep, a);
break;
case OP_SETUPVAR:
printf("OP_SETUPVAR\tR%d\t%d\t%d",
GETARG_A(c), GETARG_B(c), GETARG_C(c));
print_lv(mrb, irep, c, RA);
CASE(OP_GETMCNST, BB):
printf("OP_GETMCNST\tR%d\tR%d::%s", a, a, mrb_sym2name(mrb, irep->syms[b]));
print_lv_a(mrb, irep, a);
break;
case OP_GETCV:
printf("OP_GETCV\tR%d\t%s", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
print_lv(mrb, irep, c, RA);
CASE(OP_SETMCNST, BB):
printf("OP_SETMCNST\tR%d::%s\tR%d", a+1, mrb_sym2name(mrb, irep->syms[b]), a);
print_lv_a(mrb, irep, a);
break;
case OP_SETCV:
printf("OP_SETCV\t%s\tR%d",
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
GETARG_A(c));
print_lv(mrb, irep, c, RA);
CASE(OP_GETIV, BB):
printf("OP_GETIV\tR%d\t%s", a, mrb_sym2name(mrb, irep->syms[b]));
print_lv_a(mrb, irep, a);
break;
case OP_JMP:
printf("OP_JMP\t%03d (%d)\n", i+GETARG_sBx(c), GETARG_sBx(c));
CASE(OP_SETIV, BB):
printf("OP_SETIV\t%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
print_lv_a(mrb, irep, a);
break;
case OP_JMPIF:
printf("OP_JMPIF\tR%d\t%03d (%d)\n", GETARG_A(c), i+GETARG_sBx(c), GETARG_sBx(c));
CASE(OP_GETUPVAR, BBB):
printf("OP_GETUPVAR\tR%d\t%d\t%d", a, b, c);
print_lv_a(mrb, irep, a);
break;
case OP_JMPNOT:
printf("OP_JMPNOT\tR%d\t%03d (%d)\n", GETARG_A(c), i+GETARG_sBx(c), GETARG_sBx(c));
CASE(OP_SETUPVAR, BBB):
printf("OP_SETUPVAR\tR%d\t%d\t%d", a, b, c);
print_lv_a(mrb, irep, a);
break;
case OP_SEND:
printf("OP_SEND\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
CASE(OP_GETCV, BB):
printf("OP_GETCV\tR%d\t%s", a, mrb_sym2name(mrb, irep->syms[b]));
print_lv_a(mrb, irep, a);
break;
case OP_SENDB:
printf("OP_SENDB\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
CASE(OP_SETCV, BB):
printf("OP_SETCV\t%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
print_lv_a(mrb, irep, a);
break;
case OP_CALL:
printf("OP_CALL\tR%d\n", GETARG_A(c));
CASE(OP_JMP, S):
printf("OP_JMP\t\t%03d\n", a);
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));
CASE(OP_JMPIF, BS):
printf("OP_JMPIF\tR%d\t%03d\t", a, b);
print_lv_a(mrb, irep, a);
break;
case OP_SUPER:
printf("OP_SUPER\tR%d\t%d\n", GETARG_A(c),
GETARG_C(c));
CASE(OP_JMPNOT, BS):
printf("OP_JMPNOT\tR%d\t%03d\t", a, b);
print_lv_a(mrb, irep, a);
break;
case OP_ARGARY:
printf("OP_ARGARY\tR%d\t%d:%d:%d:%d", GETARG_A(c),
(GETARG_Bx(c)>>10)&0x3f,
(GETARG_Bx(c)>>9)&0x1,
(GETARG_Bx(c)>>4)&0x1f,
(GETARG_Bx(c)>>0)&0xf);
print_lv(mrb, irep, c, RA);
CASE(OP_JMPNIL, BS):
printf("OP_JMPNIL\tR%d\t%03d\t", a, b);
print_lv_a(mrb, irep, a);
break;
case OP_ENTER:
CASE(OP_SENDV, BB):
printf("OP_SENDV\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b]));
break;
CASE(OP_SENDVB, BB):
printf("OP_SENDVB\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b]));
break;
CASE(OP_SEND, BBB):
printf("OP_SEND\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c);
break;
CASE(OP_SENDB, BBB):
printf("OP_SENDB\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c);
break;
CASE(OP_CALL, Z):
printf("OP_CALL\n");
break;
CASE(OP_SUPER, BB):
printf("OP_SUPER\tR%d\t%d\n", a, b);
break;
CASE(OP_ARGARY, BS):
printf("OP_ARGARY\tR%d\t%d:%d:%d:%d (%d)", a,
(b>>11)&0x3f,
(b>>10)&0x1,
(b>>5)&0x1f,
(b>>4)&0x1,
(b>>0)&0xf);
print_lv_a(mrb, irep, a);
break;
CASE(OP_ENTER, W):
printf("OP_ENTER\t%d:%d:%d:%d:%d:%d:%d\n",
(GETARG_Ax(c)>>18)&0x1f,
(GETARG_Ax(c)>>13)&0x1f,
(GETARG_Ax(c)>>12)&0x1,
(GETARG_Ax(c)>>7)&0x1f,
(GETARG_Ax(c)>>2)&0x1f,
(GETARG_Ax(c)>>1)&0x1,
GETARG_Ax(c) & 0x1);
(a>>18)&0x1f,
(a>>13)&0x1f,
(a>>12)&0x1,
(a>>7)&0x1f,
(a>>2)&0x1f,
(a>>1)&0x1,
a & 0x1);
break;
case OP_RETURN:
printf("OP_RETURN\tR%d", GETARG_A(c));
switch (GETARG_B(c)) {
case OP_R_NORMAL:
printf("\tnormal\t"); break;
case OP_R_RETURN:
printf("\treturn\t"); break;
case OP_R_BREAK:
printf("\tbreak\t"); break;
default:
printf("\tbroken\t"); break;
}
print_lv(mrb, irep, c, RA);
CASE(OP_KEY_P, BB):
printf("OP_KEY_P\tR%d\t:%s\t", a, mrb_sym2name(mrb, irep->syms[b]));
print_lv_a(mrb, irep, a);
break;
case OP_BLKPUSH:
printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d", GETARG_A(c),
(GETARG_Bx(c)>>10)&0x3f,
(GETARG_Bx(c)>>9)&0x1,
(GETARG_Bx(c)>>4)&0x1f,
(GETARG_Bx(c)>>0)&0xf);
print_lv(mrb, irep, c, RA);
CASE(OP_KEYEND, Z):
printf("OP_KEYEND\n");
break;
case OP_LAMBDA:
printf("OP_LAMBDA\tR%d\tI(%+d)\t", GETARG_A(c), GETARG_b(c)+1);
switch (GETARG_c(c)) {
case OP_L_METHOD:
printf("method"); break;
case OP_L_BLOCK:
printf("block"); break;
case OP_L_LAMBDA:
printf("lambda"); break;
}
print_lv(mrb, irep, c, RA);
CASE(OP_KARG, BB):
printf("OP_KARG\tR%d\t:%s\t", a, mrb_sym2name(mrb, irep->syms[b]));
print_lv_a(mrb, irep, a);
break;
case OP_RANGE:
printf("OP_RANGE\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
print_lv(mrb, irep, c, RAB);
CASE(OP_RETURN, B):
printf("OP_RETURN\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
break;
case OP_METHOD:
printf("OP_METHOD\tR%d\t:%s", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
print_lv(mrb, irep, c, RA);
CASE(OP_RETURN_BLK, B):
printf("OP_RETURN_BLK\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
break;
case OP_ADD:
printf("OP_ADD\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
CASE(OP_BREAK, B):
printf("OP_BREAK\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
break;
case OP_ADDI:
printf("OP_ADDI\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
CASE(OP_BLKPUSH, BS):
printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d (%d)", a,
(b>>11)&0x3f,
(b>>10)&0x1,
(b>>5)&0x1f,
(b>>4)&0x1,
(b>>0)&0xf);
print_lv_a(mrb, irep, a);
break;
case OP_SUB:
printf("OP_SUB\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
CASE(OP_LAMBDA, BB):
printf("OP_LAMBDA\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]);
break;
case OP_SUBI:
printf("OP_SUBI\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
CASE(OP_BLOCK, BB):
printf("OP_BLOCK\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]);
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));
CASE(OP_METHOD, BB):
printf("OP_METHOD\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]);
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));
CASE(OP_RANGE_INC, B):
printf("OP_RANGE_INC\tR%d\n", a);
break;
case OP_LT:
printf("OP_LT\t\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
CASE(OP_RANGE_EXC, B):
printf("OP_RANGE_EXC\tR%d\n", a);
break;
case OP_LE:
printf("OP_LE\t\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
CASE(OP_DEF, BB):
printf("OP_DEF\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b]));
break;
case OP_GT:
printf("OP_GT\t\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
CASE(OP_UNDEF, B):
printf("OP_UNDEF\t:%s\n", mrb_sym2name(mrb, irep->syms[a]));
break;
case OP_GE:
printf("OP_GE\t\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
CASE(OP_ALIAS, BB):
printf("OP_ALIAS\t:%s\t%s\n", mrb_sym2name(mrb, irep->syms[a]), mrb_sym2name(mrb, irep->syms[b]));
break;
case OP_EQ:
printf("OP_EQ\t\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
CASE(OP_ADD, BB):
printf("OP_ADD\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
break;
case OP_STOP:
printf("OP_STOP\n");
CASE(OP_ADDI, BBB):
printf("OP_ADDI\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c);
break;
case OP_ARRAY:
printf("OP_ARRAY\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
print_lv(mrb, irep, c, RAB);
CASE(OP_SUB, BB):
printf("OP_SUB\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
break;
case OP_ARYCAT:
printf("OP_ARYCAT\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
print_lv(mrb, irep, c, RAB);
CASE(OP_SUBI, BBB):
printf("OP_SUBI\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c);
break;
case OP_ARYPUSH:
printf("OP_ARYPUSH\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
print_lv(mrb, irep, c, RAB);
CASE(OP_MUL, BB):
printf("OP_MUL\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
break;
case OP_AREF:
printf("OP_AREF\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
print_lv(mrb, irep, c, RAB);
CASE(OP_DIV, BB):
printf("OP_DIV\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
break;
case OP_APOST:
printf("OP_APOST\tR%d\t%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
print_lv(mrb, irep, c, RA);
CASE(OP_LT, BB):
printf("OP_LT\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
break;
case OP_STRING:
CASE(OP_LE, BB):
printf("OP_LE\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
break;
CASE(OP_GT, BB):
printf("OP_GT\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
break;
CASE(OP_GE, BB):
printf("OP_GE\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
break;
CASE(OP_EQ, BB):
printf("OP_EQ\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b]));
break;
CASE(OP_ARRAY, BB):
printf("OP_ARRAY\tR%d\t%d\t", a, b);
print_lv_a(mrb, irep, a);
break;
CASE(OP_ARRAY2, BBB):
printf("OP_ARRAY\tR%d\tR%d\t%d\t", a, b, c);
print_lv_ab(mrb, irep, a, b);
break;
CASE(OP_ARYCAT, B):
printf("OP_ARYCAT\tR%d\t", a);
print_lv_a(mrb, irep, a);
break;
CASE(OP_ARYPUSH, B):
printf("OP_ARYPUSH\tR%d\t", a);
print_lv_a(mrb, irep, a);
break;
CASE(OP_ARYDUP, B):
printf("OP_ARYDUP\tR%d\t", a);
print_lv_a(mrb, irep, a);
break;
CASE(OP_AREF, BBB):
printf("OP_AREF\tR%d\tR%d\t%d", a, b, c);
print_lv_ab(mrb, irep, a, b);
break;
CASE(OP_ASET, BBB):
printf("OP_ASET\tR%d\tR%d\t%d", a, b, c);
print_lv_ab(mrb, irep, a, b);
break;
CASE(OP_APOST, BBB):
printf("OP_APOST\tR%d\t%d\t%d", a, b, c);
print_lv_a(mrb, irep, a);
break;
CASE(OP_INTERN, B):
printf("OP_INTERN\tR%d", a);
print_lv_a(mrb, irep, a);
break;
CASE(OP_STRING, BB):
{
mrb_value v = irep->pool[GETARG_Bx(c)];
mrb_value v = irep->pool[b];
mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
printf("OP_STRING\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s));
printf("OP_STRING\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s));
}
print_lv(mrb, irep, c, RA);
print_lv_a(mrb, irep, a);
break;
case OP_STRCAT:
printf("OP_STRCAT\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
print_lv(mrb, irep, c, RAB);
CASE(OP_STRCAT, B):
printf("OP_STRCAT\tR%d\t", a);
print_lv_a(mrb, irep, a);
break;
case OP_HASH:
printf("OP_HASH\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
print_lv(mrb, irep, c, RAB);
CASE(OP_HASH, BB):
printf("OP_HASH\tR%d\t%d\t", a, b);
print_lv_a(mrb, irep, a);
break;
CASE(OP_HASHADD, BB):
printf("OP_HASHADD\tR%d\t%d\t", a, b);
print_lv_a(mrb, irep, a);
break;
CASE(OP_HASHCAT, B):
printf("OP_HASHCAT\tR%d\t", a);
print_lv_a(mrb, irep, a);
break;
case OP_OCLASS:
printf("OP_OCLASS\tR%d\t\t", GETARG_A(c));
print_lv(mrb, irep, c, RA);
CASE(OP_OCLASS, B):
printf("OP_OCLASS\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
break;
case OP_CLASS:
printf("OP_CLASS\tR%d\t:%s", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
print_lv(mrb, irep, c, RA);
CASE(OP_CLASS, BB):
printf("OP_CLASS\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
print_lv_a(mrb, irep, a);
break;
case OP_MODULE:
printf("OP_MODULE\tR%d\t:%s", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
print_lv(mrb, irep, c, RA);
CASE(OP_MODULE, BB):
printf("OP_MODULE\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
print_lv_a(mrb, irep, a);
break;
case OP_EXEC:
printf("OP_EXEC\tR%d\tI(%+d)", GETARG_A(c), GETARG_Bx(c)+1);
print_lv(mrb, irep, c, RA);
CASE(OP_EXEC, BB):
printf("OP_EXEC\tR%d\tI(%d:%p)", a, b, irep->reps[b]);
print_lv_a(mrb, irep, a);
break;
case OP_SCLASS:
printf("OP_SCLASS\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
print_lv(mrb, irep, c, RAB);
CASE(OP_SCLASS, B):
printf("OP_SCLASS\tR%d\t", a);
print_lv_a(mrb, irep, a);
break;
case OP_TCLASS:
printf("OP_TCLASS\tR%d\t\t", GETARG_A(c));
print_lv(mrb, irep, c, RA);
CASE(OP_TCLASS, B):
printf("OP_TCLASS\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
break;
case OP_ERR:
CASE(OP_ERR, B):
{
mrb_value v = irep->pool[GETARG_Bx(c)];
mrb_value v = irep->pool[a];
mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
printf("OP_ERR\t%s\n", RSTRING_PTR(s));
}
break;
case OP_EPUSH:
printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c)+1);
CASE(OP_EPUSH, B):
printf("OP_EPUSH\t\t:I(%d:%p)\n", a, irep->reps[a]);
break;
case OP_ONERR:
printf("OP_ONERR\t%03d\n", i+GETARG_sBx(c));
CASE(OP_ONERR, S):
printf("OP_ONERR\t%03d\n", a);
break;
CASE(OP_EXCEPT, B):
printf("OP_EXCEPT\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
break;
CASE(OP_RESCUE, BB):
printf("OP_RESCUE\tR%d\tR%d", a, b);
print_lv_ab(mrb, irep, a, b);
break;
CASE(OP_RAISE, B):
printf("OP_RAISE\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
break;
CASE(OP_POPERR, B):
printf("OP_POPERR\t%d\t\t\n", a);
break;
CASE(OP_EPOP, B):
printf("OP_EPOP\t%d\n", a);
break;
case OP_RESCUE:
{
int a = GETARG_A(c);
int b = GETARG_B(c);
int cnt = GETARG_C(c);
if (b == 0) {
printf("OP_RESCUE\tR%d\t\t%s", a, cnt ? "cont" : "");
print_lv(mrb, irep, c, RA);
break;
}
else {
printf("OP_RESCUE\tR%d\tR%d\t%s", a, b, cnt ? "cont" : "");
print_lv(mrb, irep, c, RAB);
break;
}
CASE(OP_DEBUG, BBB):
printf("OP_DEBUG\t%d\t%d\t%d\n", a, b, c);
break;
CASE(OP_STOP, Z):
printf("OP_STOP\n");
break;
CASE(OP_EXT1, Z):
ins = READ_B();
printf("OP_EXT1\n");
print_header(irep, pc-irep->iseq-2);
switch (ins) {
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); goto L_OP_ ## i;
#include "mruby/ops.h"
#undef OPCODE
}
break;
case OP_RAISE:
printf("OP_RAISE\tR%d\t\t", GETARG_A(c));
print_lv(mrb, irep, c, RA);
CASE(OP_EXT2, Z):
ins = READ_B();
printf("OP_EXT2\n");
print_header(irep, pc-irep->iseq-2);
switch (ins) {
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); goto L_OP_ ## i;
#include "mruby/ops.h"
#undef OPCODE
}
break;
case OP_POPERR:
printf("OP_POPERR\t%d\t\t\n", GETARG_A(c));
CASE(OP_EXT3, Z):
ins = READ_B();
printf("OP_EXT3\n");
print_header(irep, pc-irep->iseq-2);
switch (ins) {
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); goto L_OP_ ## i;
#include "mruby/ops.h"
#undef OPCODE
}
break;
case OP_EPOP:
printf("OP_EPOP\t%d\n", GETARG_A(c));
break;
default:
printf("OP_unknown %d\t%d\t%d\t%d\n", GET_OPCODE(c),
GETARG_A(c), GETARG_B(c), GETARG_C(c));
printf("OP_unknown (0x%x)\n", ins);
break;
}
mrb_gc_arena_restore(mrb, ai);
+108 -11
View File
@@ -208,6 +208,54 @@ mrb_hash_init_copy(mrb_state *mrb, mrb_value self)
return vret;
}
void
mrb_hash_check_kdict(mrb_state *mrb, mrb_value self)
{
khash_t(ht) *orig_h;
khiter_t k;
int nosym = FALSE;
orig_h = RHASH_TBL(self);
if (!orig_h || kh_size(orig_h) == 0) return;
for (k = kh_begin(orig_h); k != kh_end(orig_h); k++) {
if (kh_exist(orig_h, k)) {
mrb_value key = kh_key(orig_h, k);
if (!mrb_symbol_p(key)) nosym = TRUE;
}
}
if (nosym) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "keyword argument hash with non symbol keys");
}
}
MRB_API mrb_value
mrb_hash_dup(mrb_state *mrb, mrb_value self)
{
struct RHash* copy;
khash_t(ht) *orig_h;
orig_h = RHASH_TBL(self);
copy = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
copy->ht = kh_init(ht, mrb);
if (orig_h && kh_size(orig_h) > 0) {
int ai = mrb_gc_arena_save(mrb);
khash_t(ht) *copy_h = copy->ht;
khiter_t k, copy_k;
for (k = kh_begin(orig_h); k != kh_end(orig_h); k++) {
if (kh_exist(orig_h, k)) {
copy_k = kh_put(ht, mrb, copy_h, KEY(kh_key(orig_h, k)));
mrb_gc_arena_restore(mrb, ai);
kh_val(copy_h, copy_k).v = kh_val(orig_h, k).v;
kh_val(copy_h, copy_k).n = kh_size(copy_h)-1;
}
}
}
return mrb_obj_value(copy);
}
MRB_API mrb_value
mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key)
{
@@ -716,13 +764,21 @@ mrb_hash_size_m(mrb_state *mrb, mrb_value self)
* {}.empty? #=> true
*
*/
MRB_API mrb_value
MRB_API mrb_bool
mrb_hash_empty_p(mrb_state *mrb, mrb_value self)
{
khash_t(ht) *h = RHASH_TBL(self);
if (h) return mrb_bool_value(kh_size(h) == 0);
return mrb_true_value();
if (h) return kh_size(h) == 0;
return TRUE;
}
static mrb_value
mrb_hash_empty_m(mrb_state *mrb, mrb_value self)
{
if (mrb_hash_empty_p(mrb, self))
return mrb_true_value();
return mrb_false_value();
}
/* 15.2.13.4.29 (x)*/
@@ -833,21 +889,29 @@ mrb_hash_values(mrb_state *mrb, mrb_value hash)
*
*/
static mrb_value
mrb_hash_has_key(mrb_state *mrb, mrb_value hash)
MRB_API mrb_bool
mrb_hash_key_p(mrb_state *mrb, mrb_value hash, mrb_value key)
{
mrb_value key;
khash_t(ht) *h;
khiter_t k;
mrb_get_args(mrb, "o", &key);
h = RHASH_TBL(hash);
if (h) {
k = kh_get(ht, mrb, h, key);
return mrb_bool_value(k != kh_end(h));
return k != kh_end(h);
}
return mrb_false_value();
return FALSE;
}
static mrb_value
mrb_hash_has_key(mrb_state *mrb, mrb_value hash)
{
mrb_value key;
mrb_bool key_p;
mrb_get_args(mrb, "o", &key);
key_p = mrb_hash_key_p(mrb, hash, key);
return mrb_bool_value(key_p);
}
/* 15.2.13.4.14 */
@@ -887,6 +951,39 @@ mrb_hash_has_value(mrb_state *mrb, mrb_value hash)
return mrb_false_value();
}
MRB_API void
mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2)
{
khash_t(ht) *h1;
khash_t(ht) *h2;
khiter_t k;
mrb_hash_modify(mrb, hash1);
hash2 = mrb_check_hash_type(mrb, hash2);
h1 = RHASH_TBL(hash1);
h2 = RHASH_TBL(hash2);
if (!h1) {
RHASH_TBL(hash1) = kh_copy(ht, mrb, h2);
return;
}
for (k = kh_begin(h2); k != kh_end(h2); k++) {
khiter_t k1;
int r;
if (!kh_exist(h2, k)) continue;
k1 = kh_put2(ht, mrb, h1, kh_key(h2, k), &r);
kh_value(h1, k1).v = kh_value(h2,k).v;
if (r != 0) {
/* expand */
kh_key(h1, k1) = kh_key(h2, k);
kh_value(h1, k1).n = kh_size(h1)-1;
}
}
mrb_write_barrier(mrb, (struct RBasic*)RHASH(hash1));
return;
}
void
mrb_init_hash(mrb_state *mrb)
{
@@ -904,7 +1001,7 @@ mrb_init_hash(mrb_state *mrb)
mrb_define_method(mrb, h, "default_proc", mrb_hash_default_proc,MRB_ARGS_NONE()); /* 15.2.13.4.7 */
mrb_define_method(mrb, h, "default_proc=", mrb_hash_set_default_proc,MRB_ARGS_REQ(1)); /* 15.2.13.4.7 */
mrb_define_method(mrb, h, "__delete", mrb_hash_delete, MRB_ARGS_REQ(1)); /* core of 15.2.13.4.8 */
mrb_define_method(mrb, h, "empty?", mrb_hash_empty_p, MRB_ARGS_NONE()); /* 15.2.13.4.12 */
mrb_define_method(mrb, h, "empty?", mrb_hash_empty_m, MRB_ARGS_NONE()); /* 15.2.13.4.12 */
mrb_define_method(mrb, h, "has_key?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.13 */
mrb_define_method(mrb, h, "has_value?", mrb_hash_has_value, MRB_ARGS_REQ(1)); /* 15.2.13.4.14 */
mrb_define_method(mrb, h, "include?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.15 */
+10 -2
View File
@@ -1194,7 +1194,15 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
if (!irep->lv) break;
for (i = 0; i + 1 < irep->nlocals; ++i) {
if (irep->lv[i].name) {
mrb_hash_set(mrb, vars, mrb_symbol_value(irep->lv[i].name), mrb_true_value());
mrb_sym sym = irep->lv[i].name;
const char *name = mrb_sym2name(mrb, sym);
switch (name[0]) {
case '*': case '&':
break;
default:
mrb_hash_set(mrb, vars, mrb_symbol_value(sym), mrb_true_value());
break;
}
}
}
if (!MRB_PROC_ENV_P(proc)) break;
@@ -1266,5 +1274,5 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method(mrb, krn, "class_defined?", mrb_krn_class_defined, MRB_ARGS_REQ(1));
mrb_include_module(mrb, mrb->object_class, mrb->kernel_module);
mrb_alias_method(mrb, mrb->module_class, mrb_intern_lit(mrb, "dup"), mrb_intern_lit(mrb, "clone"));
mrb_define_alias(mrb, mrb->module_class, "dup", "clone"); /* XXX */
}
+3 -3
View File
@@ -68,7 +68,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
/* Binary Data Section */
/* ISEQ BLOCK */
irep->ilen = (size_t)bin_to_uint32(src);
irep->ilen = (uint16_t)bin_to_uint32(src);
src += sizeof(uint32_t);
src += skip_padding(src);
@@ -79,7 +79,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
if ((flags & FLAG_SRC_MALLOC) == 0 &&
(flags & FLAG_BYTEORDER_NATIVE)) {
irep->iseq = (mrb_code*)src;
src += sizeof(uint32_t) * irep->ilen;
src += sizeof(mrb_code) * irep->ilen;
irep->flags |= MRB_ISEQ_NO_FREE;
}
else {
@@ -157,7 +157,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
}
/* SYMS BLOCK */
irep->slen = (size_t)bin_to_uint32(src); /* syms length */
irep->slen = (uint16_t)bin_to_uint32(src); /* syms length */
src += sizeof(uint32_t);
if (irep->slen > 0) {
if (SIZE_ERROR_MUL(irep->slen, sizeof(mrb_sym))) {
+5 -5
View File
@@ -10,7 +10,7 @@
#include <mruby/opcode.h>
static mrb_code call_iseq[] = {
MKOP_A(OP_CALL, 0),
OP_CALL,
};
struct RProc*
@@ -223,7 +223,7 @@ mrb_proc_arity(mrb_state *mrb, mrb_value self)
{
struct RProc *p = mrb_proc_ptr(self);
struct mrb_irep *irep;
mrb_code *iseq;
mrb_code *pc;
mrb_aspec aspec;
int ma, op, ra, pa, arity;
@@ -237,13 +237,13 @@ mrb_proc_arity(mrb_state *mrb, mrb_value self)
return mrb_fixnum_value(0);
}
iseq = irep->iseq;
pc = irep->iseq;
/* arity is depend on OP_ENTER */
if (GET_OPCODE(*iseq) != OP_ENTER) {
if (*pc != OP_ENTER) {
return mrb_fixnum_value(0);
}
aspec = GETARG_Ax(*iseq);
aspec = PEEK_W(pc+1);
ma = MRB_ASPEC_REQ(aspec);
op = MRB_ASPEC_OPT(aspec);
ra = MRB_ASPEC_REST(aspec);
+525 -590
View File
File diff suppressed because it is too large Load Diff
+184
View File
@@ -403,6 +403,9 @@ assert('External command execution.') do
assert_equal 'test dynamic `', t
assert_equal ['test', 'test dynamic `', 'test', 'test dynamic `'], results
results = []
assert_equal 'test sym test sym test', `test #{:sym} test #{:sym} test`
alias_method sym, :old_cmd
end
true
@@ -466,3 +469,184 @@ this is a comment that has extra after =begin and =end with tabs after it
=end xxxxxxxxxxxxxxxxxxxxxxxxxx
assert_equal(line + 4, __LINE__)
end
assert 'keyword arguments' do
def m(a, b:) [a, b] end
assert_equal [1, 2], m(1, b: 2)
assert_raise(ArgumentError) { m b: 1 }
assert_raise(ArgumentError) { m 1 }
def m(a:) a end
assert_equal 1, m(a: 1)
assert_raise(ArgumentError) { m }
assert_raise(ArgumentError) { m 'a' => 1, a: 1 }
h = { a: 1 }
assert_equal 1, m(h)
assert_equal({ a: 1 }, h)
def m(a: 1) a end
assert_equal 1, m
assert_equal 2, m(a: 2)
assert_raise(ArgumentError) { m 1 }
def m(**) end
assert_nil m
assert_nil m a: 1, b: 2
assert_raise(ArgumentError) { m 2 }
def m(a, **) a end
assert_equal 1, m(1)
assert_equal 1, m(1, a: 2, b: 3)
assert_equal({ 'a' => 1, b: 2 }, m('a' => 1, b: 2))
def m(a, **k) [a, k] end
assert_equal [1, {}], m(1)
assert_equal [1, {a: 2, b: 3}], m(1, a: 2, b: 3)
assert_equal [{'a' => 1, b: 2}, {}], m('a' => 1, b: 2)
def m(a=1, **) a end
assert_equal 1, m
assert_equal 2, m(2, a: 1, b: 0)
assert_raise(ArgumentError) { m('a' => 1, a: 2) }
def m(a=1, **k) [a, k] end
assert_equal [1, {}], m
assert_equal [1, {a: 1}], m(a: 1)
assert_equal [2, {a: 1, b: 2}], m(2, a: 1, b: 2)
assert_equal [{a: 1}, {b: 2}], m({a: 1}, {b: 2})
def m(*, a:) a end
assert_equal 1, m(a: 1)
assert_equal 3, m(1, 2, a: 3)
assert_raise(ArgumentError) { m('a' => 1, a: 2) }
def m(*a, b:) [a, b] end
assert_equal [[], 1], m(b: 1)
assert_equal [[1, 2], 3], m(1, 2, b: 3)
assert_raise(ArgumentError) { m('a' => 1, b: 2) }
def m(*a, b: 1) [a, b] end
assert_equal [[], 1], m
assert_equal [[1, 2, 3], 4], m(1, 2, 3, b: 4)
assert_raise(ArgumentError) { m('a' => 1, b: 2) }
def m(*, **) end
assert_nil m()
assert_nil m(a: 1, b: 2)
assert_nil m(1, 2, 3, a: 4, b: 5)
def m(*a, **) a end
assert_equal [], m()
assert_equal [1, 2, 3], m(1, 2, 3, a: 4, b: 5)
assert_raise(ArgumentError) { m("a" => 1, a: 1) }
assert_equal [1], m(1, **{a: 2})
def m(*, **k) k end
assert_equal({}, m())
assert_equal({a: 4, b: 5}, m(1, 2, 3, a: 4, b: 5))
assert_raise(ArgumentError) { m("a" => 1, a: 1) }
def m(a = nil, b = nil, **k) [a, k] end
assert_equal [nil, {}], m()
assert_equal([nil, {a: 1}], m(a: 1))
assert_raise(ArgumentError) { m("a" => 1, a: 1) }
assert_equal([{"a" => 1}, {a: 1}], m({ "a" => 1 }, a: 1))
assert_equal([{a: 1}, {}], m({a: 1}, {}))
assert_equal([nil, {}], m({}))
def m(*a, **k) [a, k] end
assert_equal([[], {}], m())
assert_equal([[1], {}], m(1))
assert_equal([[], {a: 1, b: 2}], m(a: 1, b: 2))
assert_equal([[1, 2, 3], {a: 2}], m(1, 2, 3, a: 2))
assert_raise(ArgumentError) { m("a" => 1, a: 1) }
assert_raise(ArgumentError) { m("a" => 1) }
assert_equal([[], {a: 1}], m(a: 1))
assert_raise(ArgumentError) { m("a" => 1, a: 1) }
assert_equal([[{"a" => 1}], {a: 1}], m({ "a" => 1 }, a: 1))
assert_equal([[{a: 1}], {}], m({a: 1}, {}))
assert_raise(ArgumentError) { m({a: 1}, {"a" => 1}) }
def m(a:, b:) [a, b] end
assert_equal([1, 2], m(a: 1, b: 2))
assert_raise(ArgumentError) { m("a" => 1, a: 1, b: 2) }
def m(a:, b: 1) [a, b] end
assert_equal([1, 1], m(a: 1))
assert_equal([1, 2], m(a: 1, b: 2))
assert_raise(ArgumentError) { m("a" => 1, a: 1, b: 2) }
def m(a:, **) a end
assert_equal(1, m(a: 1))
assert_equal(1, m(a: 1, b: 2))
assert_raise(ArgumentError) { m("a" => 1, a: 1, b: 2) }
def m(a:, **k) [a, k] end
assert_equal([1, {}], m(a: 1))
assert_equal([1, {b: 2, c: 3}], m(a: 1, b: 2, c: 3))
assert_raise(ArgumentError) { m("a" => 1, a: 1, b: 2) }
=begin
def m(a:, &b) [a, b] end
assert_equal([1, nil], m(a: 1))
assert_equal([1, l], m(a: 1, &(l = ->{})))
=end
def m(a: 1, b:) [a, b] end
assert_equal([1, 0], m(b: 0))
assert_equal([3, 2], m(b: 2, a: 3))
assert_raise(ArgumentError) { m a: 1 }
def m(a: def m(a: 1) a end, b:)
[a, b]
end
assert_equal([2, 3], m(a: 2, b: 3))
assert_equal([:m, 1], m(b: 1))
# Note the default value of a: in the original method.
assert_equal(1, m())
def m(a: 1, b: 2) [a, b] end
assert_equal([1, 2], m())
assert_equal([4, 3], m(b: 3, a: 4))
def m(a: 1, **) a end
assert_equal(1, m())
assert_equal(2, m(a: 2, b: 1))
def m(a: 1, **k) [a, k] end
assert_equal([1, {b: 2, c: 3}], m(b: 2, c: 3))
def m(a:, **) yield end
assert_raise(ArgumentError) { m { :blk } }
assert_equal :blk, m(a: 1){ :blk }
def m(a:, **k, &b) [b.call, k] end
assert_raise(ArgumentError) { m { :blk } }
assert_equal [:blk, {b: 2}], m(a: 1, b: 2){ :blk }
def m(**k, &b) [k, b] end
assert_equal([{ a: 1, b: 2}, nil], m(a: 1, b: 2))
assert_equal :blk, m{ :blk }[1].call
def m(hsh = {}) hsh end
assert_equal({ a: 1, b: 2 }, m(a: 1, b: 2))
assert_equal({ a: 1, 'b' => 2 }, m(a: 1, 'b' => 2))
def m(hsh) hsh end
assert_equal({ a: 1, b: 2 }, m(a: 1, b: 2))
assert_equal({ a: 1, 'b' => 2 }, m(a: 1, 'b' => 2))
=begin
def m(a, b=1, *c, (*d, (e)), f: 2, g:, h:, **k, &l)
[a, b, c, d, e, f, g, h, k, l]
end
result = m(9, 8, 7, 6, f: 5, g: 4, h: 3, &(l = ->{}))
assert_equal([9, 8, [7], [], 6, 5, 4, 3, {}, l], result)
def m a, b=1, *c, d, e:, f: 2, g:, **k, &l
[a, b, c, d, e, f, g, k, l]
end
result = m(1, 2, e: 3, g: 4, h: 5, i: 6, &(l = ->{}))
assert_equal([1, 1, [], 2, 3, 2, 4, { h: 5, i: 6 }, l], result)
=end
end