mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge branch 'mruby2-draft'
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
.DS_Store
|
||||
.ccmalloc
|
||||
.svn
|
||||
.vscode
|
||||
/.git
|
||||
cscope.files
|
||||
cscope.out
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user