From e050cfb349ba11f7962df70dbff953daf456b68e Mon Sep 17 00:00:00 2001 From: take-cheeze Date: Wed, 20 Jun 2018 18:20:26 +0900 Subject: Add forgotten `mkdir_p`s. --- mrbgems/mruby-compiler/mrbgem.rake | 1 + 1 file changed, 1 insertion(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/mrbgem.rake b/mrbgems/mruby-compiler/mrbgem.rake index 3bf6d6ae3..6decd643b 100644 --- a/mrbgems/mruby-compiler/mrbgem.rake +++ b/mrbgems/mruby-compiler/mrbgem.rake @@ -27,6 +27,7 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec| # Parser file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y"] do |t| + FileUtils.mkdir_p File.dirname t.name yacc.run t.name, t.prerequisites.first end -- cgit v1.2.3 From dfddc6a09f6c287f76d5276cb9dfa43444708f12 Mon Sep 17 00:00:00 2001 From: take-cheeze Date: Wed, 20 Jun 2018 18:21:33 +0900 Subject: Fix dependencies. --- mrbgems/mruby-bin-mruby-config/mrbgem.rake | 5 +++-- mrbgems/mruby-compiler/mrbgem.rake | 3 +-- mrbgems/mruby-test/mrbgem.rake | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-bin-mruby-config/mrbgem.rake b/mrbgems/mruby-bin-mruby-config/mrbgem.rake index 66d6ef80b..32ae2164b 100644 --- a/mrbgems/mruby-bin-mruby-config/mrbgem.rake +++ b/mrbgems/mruby-bin-mruby-config/mrbgem.rake @@ -19,9 +19,10 @@ MRuby.each_target do mruby_config_path = "#{build_dir}/bin/#{mruby_config}" @bins << mruby_config - file mruby_config_path => libfile("#{build_dir}/lib/libmruby") do |t| + make_cfg = "#{build_dir}/lib/libmruby.flags.mak" + file mruby_config_path => [libfile("#{build_dir}/lib/libmruby"), make_cfg] do |t| FileUtils.copy "#{File.dirname(__FILE__)}/#{mruby_config}", t.name - config = Hash[open("#{build_dir}/lib/libmruby.flags.mak").read.split("\n").map {|x| a = x.split(/\s*=\s*/, 2); [a[0], a[1].gsub('\\"', '"') ]}] + config = Hash[open(make_cfg).read.split("\n").map {|x| a = x.split(/\s*=\s*/, 2); [a[0], a[1].gsub('\\"', '"') ]}] IO.write(t.name, File.open(t.name) {|f| f.read.gsub (/echo (MRUBY_CFLAGS|MRUBY_LIBS|MRUBY_LDFLAGS_BEFORE_LIBS|MRUBY_LDFLAGS|MRUBY_LIBMRUBY_PATH)/) {|x| config[$1].empty? ? '' : "echo #{config[$1]}"} }) diff --git a/mrbgems/mruby-compiler/mrbgem.rake b/mrbgems/mruby-compiler/mrbgem.rake index 6decd643b..e9e0cc2c7 100644 --- a/mrbgems/mruby-compiler/mrbgem.rake +++ b/mrbgems/mruby-compiler/mrbgem.rake @@ -23,10 +23,9 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec| cc.run t.name, t.prerequisites.first, [], ["#{current_dir}/core"] end end - file objfile("#{current_build_dir}/core/y.tab") => lex_def # Parser - file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y"] do |t| + file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y", lex_def] do |t| FileUtils.mkdir_p File.dirname t.name yacc.run t.name, t.prerequisites.first end diff --git a/mrbgems/mruby-test/mrbgem.rake b/mrbgems/mruby-test/mrbgem.rake index 27c635a5d..b9b10fc60 100644 --- a/mrbgems/mruby-test/mrbgem.rake +++ b/mrbgems/mruby-test/mrbgem.rake @@ -31,7 +31,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec| mrbtest_objs << assert_lib file assert_lib => assert_c - file assert_c => assert_rb do |t| + file assert_c => [assert_rb, build.mrbcfile] do |t| open(t.name, 'w') do |f| mrbc.run f, assert_rb, 'mrbtest_assert_irep' end @@ -45,7 +45,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec| dep_list = build.gems.tsort_dependencies(g.test_dependencies, gem_table).select(&:generate_functions) file test_rbobj => g.test_rbireps - file g.test_rbireps => [g.test_rbfiles].flatten do |t| + file g.test_rbireps => [g.test_rbfiles, build.mrbcfile].flatten do |t| FileUtils.mkdir_p File.dirname(t.name) open(t.name, 'w') do |f| g.print_gem_test_header(f) @@ -169,7 +169,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec| file clib => active_gems_path file mlib => clib - file clib => init do |t| + file clib => [init, build.mrbcfile] do |t| _pp "GEN", "*.rb", "#{clib.relative_path}" FileUtils.mkdir_p File.dirname(clib) open(clib, 'w') do |f| -- cgit v1.2.3 From 5fef38e4c77cb3700750fe0020063289a49242d6 Mon Sep 17 00:00:00 2001 From: yuri Date: Tue, 10 Jul 2018 15:44:25 +0900 Subject: move mrb_irep_remove_lv to codegen.c in mruby-compiler --- mrbgems/mruby-compiler/core/codegen.c | 15 +++++++++++++++ src/dump.c | 15 --------------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index f71de9b4b..fec747f0c 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -3092,3 +3092,18 @@ mrb_generate_code(mrb_state *mrb, parser_state *p) { return generate_code(mrb, p, VAL); } + +void +mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep) +{ + int i; + + if (irep->lv) { + mrb_free(mrb, irep->lv); + irep->lv = NULL; + } + + for (i = 0; i < irep->rlen; ++i) { + mrb_irep_remove_lv(mrb, irep->reps[i]); + } +} diff --git a/src/dump.c b/src/dump.c index d0f0850fe..df1e171e4 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1103,19 +1103,4 @@ mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, con return result; } -void -mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep) -{ - int i; - - if (irep->lv) { - mrb_free(mrb, irep->lv); - irep->lv = NULL; - } - - for (i = 0; i < irep->rlen; ++i) { - mrb_irep_remove_lv(mrb, irep->reps[i]); - } -} - #endif /* MRB_DISABLE_STDIO */ -- cgit v1.2.3 From 891839b976c75c77f238931123ac472e3284e95d Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 May 2018 15:19:06 +0900 Subject: New bytecode implementation of mruby VM. --- .gitignore | 1 + doc/opcode.md | 260 +++++ include/mruby.h | 16 +- include/mruby/class.h | 3 +- include/mruby/compile.h | 2 + include/mruby/irep.h | 2 +- include/mruby/opcode.h | 186 +--- include/mruby/ops.h | 116 +++ mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c | 2 +- mrbgems/mruby-compiler/core/codegen.c | 1351 +++++++++++++------------- mrbgems/mruby-compiler/core/parse.y | 15 + mrbgems/mruby-eval/src/eval.c | 112 ++- mrbgems/mruby-method/src/method.c | 6 +- mrbgems/mruby-proc-ext/src/proc.c | 12 +- mrbgems/mruby-string-ext/src/string.c | 4 +- src/class.c | 8 +- src/codedump.c | 772 ++++++++------- src/kernel.c | 2 +- src/load.c | 2 +- src/proc.c | 10 +- src/vm.c | 986 ++++++++----------- 21 files changed, 2072 insertions(+), 1796 deletions(-) create mode 100644 doc/opcode.md create mode 100644 include/mruby/ops.h (limited to 'mrbgems/mruby-compiler') diff --git a/.gitignore b/.gitignore index bccfaf218..9c34b5f29 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ .DS_Store .ccmalloc .svn +.vscode /.git cscope.files cscope.out diff --git a/doc/opcode.md b/doc/opcode.md new file mode 100644 index 000000000..d904256e5 --- /dev/null +++ b/doc/opcode.md @@ -0,0 +1,260 @@ +<<<<<<< HEAD +# 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=6:1:5: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_KDICT' |B |R(a) = kdict # 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=6:1:5: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_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 +||||||| parent of b6821923... New bytecode implementation of mruby VM. +======= +# 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=6:1:5: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_KDICT' |B |R(a) = kdict # 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=6:1:5: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_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 +>>>>>>> b6821923... New bytecode implementation of mruby VM. diff --git a/include/mruby.h b/include/mruby.h index b0bfe78b5..7cbc690b3 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -93,7 +93,7 @@ */ MRB_BEGIN_DECL -typedef uint32_t mrb_code; +typedef uint8_t mrb_code; /** * Required arguments signature type. @@ -123,9 +123,9 @@ typedef struct { mrb_sym mid; struct RProc *proc; mrb_value *stackent; - int nregs; - int ridx; - int epos; + uint16_t nregs; + uint16_t ridx; + uint16_t epos; struct REnv *env; mrb_code *pc; /* return address */ mrb_code *err; /* error position */ @@ -152,10 +152,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; @@ -486,9 +486,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. @@ -1197,7 +1198,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); diff --git a/include/mruby/class.h b/include/mruby/class.h index ea35d8e17..706a4d37c 100644 --- a/include/mruby/class.h +++ b/include/mruby/class.h @@ -76,7 +76,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); diff --git a/include/mruby/compile.h b/include/mruby/compile.h index d7d029616..a85460415 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -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]; diff --git a/include/mruby/irep.h b/include/mruby/irep.h index ad227be5d..c98d008db 100644 --- a/include/mruby/irep.h +++ b/include/mruby/irep.h @@ -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 diff --git a/include/mruby/opcode.h b/include/mruby/opcode.h index a5e3af158..d513ca472 100644 --- a/include/mruby/opcode.h +++ b/include/mruby/opcode.h @@ -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<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 */ diff --git a/include/mruby/ops.h b/include/mruby/ops.h new file mode 100644 index 000000000..882ad6f25 --- /dev/null +++ b/include/mruby/ops.h @@ -0,0 +1,116 @@ +/* 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=6:1:5:4) */ +OPCODE(ENTER, W) /* arg setup according to flags (23=5:5:1:5:5:1:1) */ +OPCODE(KARG, BB) /* R(a) = kdict[Syms(Bx)] # todo */ +OPCODE(KARG2, BB) /* R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo */ +OPCODE(KDICT, B) /* R(a) = kdict # 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=6:1:5:4) */ +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(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(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 */ diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c index 0588dfca5..1b17128fd 100644 --- a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c +++ b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c @@ -517,7 +517,7 @@ 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)) { + switch(*pc) { case OP_SEND: case OP_SENDB: c = mrb_class(mrb, regs[GETARG_A(*pc)]); diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index fec747f0c..3ba2324fb 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -23,6 +23,8 @@ #define MRB_CODEGEN_LEVEL_MAX 1024 #endif +#define MAXARG_S (1<<16) + typedef mrb_ast_node node; typedef struct mrb_parser_state parser_state; @@ -36,7 +38,7 @@ enum looptype { struct loopinfo { enum looptype type; - int pc1, pc2, pc3, acc; + int pc0, pc1, pc2, pc3, acc; int ensure_level; struct loopinfo *prev; }; @@ -50,9 +52,10 @@ typedef struct scope { node *lv; - int sp; - int pc; - int lastlabel; + uint16_t sp; + uint16_t pc; + uint16_t lastpc; + uint16_t lastlabel; int ainfo:15; mrb_bool mscope:1; @@ -63,10 +66,10 @@ typedef struct scope { mrb_code *iseq; uint16_t *lines; - int icapa; + uint32_t icapa; mrb_irep *irep; - int pcapa, scapa, rcapa; + uint32_t pcapa, scapa, rcapa; uint16_t nlocals; uint16_t nregs; @@ -142,38 +145,141 @@ codegen_realloc(codegen_scope *s, void *p, size_t len) static int new_label(codegen_scope *s) { - s->lastlabel = s->pc; - return s->pc; + return s->lastlabel = s->pc; } -static inline int -genop(codegen_scope *s, mrb_code i) +static void +emit_B(codegen_scope *s, uint32_t pc, uint8_t i) { - if (s->pc >= s->icapa) { + if (pc >= s->icapa) { s->icapa *= 2; - if (s->pc >= MAXARG_sBx) { + if (pc >= MAXARG_S) { codegen_error(s, "too big code block"); } - if (s->icapa > MAXARG_sBx) { - s->icapa = MAXARG_sBx; + if (s->icapa > MAXARG_S) { + s->icapa = MAXARG_S; } s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa); if (s->lines) { - s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa); + s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->icapa); s->irep->lines = s->lines; } } - s->iseq[s->pc] = i; if (s->lines) { - s->lines[s->pc] = s->lineno; + s->lines[pc] = s->lineno; + } + s->iseq[pc] = i; +} + +static void +emit_S(codegen_scope *s, int pc, uint16_t i) +{ + uint8_t hi = i>>8; + uint8_t lo = i&0xff; + + emit_B(s, pc, hi); + emit_B(s, pc+1, lo); +} + +static void +gen_B(codegen_scope *s, uint8_t i) +{ + emit_B(s, s->pc++, i); +} + +static void +gen_S(codegen_scope *s, uint16_t i) +{ + emit_S(s, s->pc, i); + s->pc += 2; +} + +static void +genop_0(codegen_scope *s, mrb_code i) +{ + s->lastpc = s->pc; + gen_B(s, i); +} + +static void +genop_1(codegen_scope *s, mrb_code i, uint16_t a) +{ + s->lastpc = s->pc; + if (a > 0xff) { + gen_B(s, OP_EXT1); + gen_B(s, i); + gen_S(s, a); + } + else { + gen_B(s, i); + gen_B(s, (uint8_t)a); + } +} + +static void +genop_2(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b) +{ + s->lastpc = s->pc; + if (a > 0xff && b > 0xff) { + gen_B(s, OP_EXT3); + gen_B(s, i); + gen_S(s, a); + gen_S(s, b); + } + else if (b > 0xff) { + gen_B(s, OP_EXT2); + gen_B(s, i); + gen_B(s, (uint8_t)a); + gen_S(s, b); + } + else if (a > 0xff) { + gen_B(s, OP_EXT1); + gen_B(s, i); + gen_S(s, a); + gen_B(s, (uint8_t)b); + } + else { + gen_B(s, i); + gen_B(s, (uint8_t)a); + gen_B(s, (uint8_t)b); } - return s->pc++; +} + +static void +genop_3(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b, uint8_t c) +{ + s->lastpc = s->pc; + genop_2(s, i, a, b); + gen_B(s, c); +} + +static void +genop_2S(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b) +{ + s->lastpc = s->pc; + genop_1(s, i, a); + gen_S(s, b); +} + +static void +genop_W(codegen_scope *s, mrb_code i, uint32_t a) +{ + uint8_t a1 = (a>>16) & 0xff; + uint8_t a2 = (a>>8) & 0xff; + uint8_t a3 = a & 0xff; + + s->lastpc = s->pc; + gen_B(s, i); + gen_B(s, a1); + gen_B(s, a2); + gen_B(s, a3); } #define NOVAL 0 #define VAL 1 -static mrb_bool +//static +mrb_bool no_optimize(codegen_scope *s) { if (s && s->parser && s->parser->no_optimize) @@ -181,269 +287,228 @@ no_optimize(codegen_scope *s) return FALSE; } -static int -genop_peep(codegen_scope *s, mrb_code i, int val) +static +mrb_bool +on_eval(codegen_scope *s) { - /* peephole optimization */ - if (!no_optimize(s) && s->lastlabel != s->pc && s->pc > 0) { - mrb_code i0 = s->iseq[s->pc-1]; - int c1 = GET_OPCODE(i); - int c0 = GET_OPCODE(i0); + if (s && s->parser && s->parser->on_eval) + return TRUE; + return FALSE; +} - switch (c1) { - case OP_MOVE: - if (GETARG_A(i) == GETARG_B(i)) { - /* skip useless OP_MOVE */ - return 0; - } - if (val) break; - switch (c0) { - case OP_MOVE: - if (GETARG_A(i) == GETARG_A(i0)) { - /* skip overriden OP_MOVE */ - s->pc--; - s->iseq[s->pc] = i; - } - if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0)) { - /* skip swapping OP_MOVE */ - return 0; - } - if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { - s->pc--; - return genop_peep(s, MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0)), val); - } - break; - case OP_LOADI: - if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { - s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, GETARG_A(i), GETARG_sBx(i0)); - return 0; - } - break; - case OP_ARRAY: - case OP_HASH: - case OP_RANGE: - case OP_AREF: - case OP_GETUPVAR: - if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { - s->iseq[s->pc-1] = MKOP_ABC(c0, GETARG_A(i), GETARG_B(i0), GETARG_C(i0)); - return 0; - } - break; - case OP_LOADSYM: - case OP_GETGLOBAL: - case OP_GETIV: - case OP_GETCV: - case OP_GETCONST: - case OP_GETSPECIAL: - case OP_LOADL: - case OP_STRING: - if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { - s->iseq[s->pc-1] = MKOP_ABx(c0, GETARG_A(i), GETARG_Bx(i0)); - return 0; - } - break; - case OP_SCLASS: - if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { - s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0)); - return 0; - } - break; - case OP_LOADNIL: - case OP_LOADSELF: - case OP_LOADT: - case OP_LOADF: - case OP_OCLASS: - if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { - s->iseq[s->pc-1] = MKOP_A(c0, GETARG_A(i)); - return 0; - } - break; - default: - break; - } - break; - case OP_SETIV: - case OP_SETCV: - case OP_SETCONST: - case OP_SETMCNST: - case OP_SETGLOBAL: - if (val) break; - if (c0 == OP_MOVE) { - if (GETARG_A(i) == GETARG_A(i0)) { - s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i)); - return 0; - } - } - break; - case OP_SETUPVAR: - if (val) break; - if (c0 == OP_MOVE) { - if (GETARG_A(i) == GETARG_A(i0)) { - s->iseq[s->pc-1] = MKOP_ABC(c1, GETARG_B(i0), GETARG_B(i), GETARG_C(i)); - return 0; - } - } - break; - case OP_GETUPVAR: - if (c0 == OP_SETUPVAR) { - if (GETARG_B(i) == GETARG_B(i0) && GETARG_C(i) == GETARG_C(i0)) { - if (GETARG_A(i) == GETARG_A(i0)) { - /* just skip OP_SETUPVAR */ - return 0; - } - else { - return genop(s, MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_A(i0))); - } - } - } - break; - case OP_EPOP: - if (c0 == OP_EPOP) { - s->iseq[s->pc-1] = MKOP_A(OP_EPOP, GETARG_A(i0)+GETARG_A(i)); - return 0; - } - break; - case OP_POPERR: - if (c0 == OP_POPERR) { - s->iseq[s->pc-1] = MKOP_A(OP_POPERR, GETARG_A(i0)+GETARG_A(i)); - return 0; - } - break; - case OP_RETURN: - switch (c0) { - case OP_RETURN: - return 0; - case OP_MOVE: - if (GETARG_A(i0) >= s->nlocals) { - s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL); - return 0; - } - break; - case OP_SETIV: - case OP_SETCV: - case OP_SETCONST: - case OP_SETMCNST: - case OP_SETUPVAR: - case OP_SETGLOBAL: - s->pc--; - genop_peep(s, i0, NOVAL); - i0 = s->iseq[s->pc-1]; - return genop(s, MKOP_AB(OP_RETURN, GETARG_A(i0), OP_R_NORMAL)); -#if 0 - case OP_SEND: - if (GETARG_B(i) == OP_R_NORMAL && GETARG_A(i) == GETARG_A(i0)) { - s->iseq[s->pc-1] = MKOP_ABC(OP_TAILCALL, GETARG_A(i0), GETARG_B(i0), GETARG_C(i0)); - return; - } - break; -#endif - default: - break; - } - break; - case OP_ADD: - case OP_SUB: - if (c0 == OP_LOADI) { - int c = GETARG_sBx(i0); - - if (c1 == OP_SUB) c = -c; - if (c > 127 || c < -127) break; - if (0 <= c) - s->iseq[s->pc-1] = MKOP_ABC(OP_ADDI, GETARG_A(i), GETARG_B(i), c); - else - s->iseq[s->pc-1] = MKOP_ABC(OP_SUBI, GETARG_A(i), GETARG_B(i), -c); - return 0; - } - break; - case OP_ARYCAT: - case OP_ARYPUSH: - if (c0 == OP_MOVE && GETARG_A(i0) >= s->nlocals) { - s->iseq[s->pc-1] = MKOP_AB(c1, GETARG_A(i), GETARG_B(i0)); - return 0; - } - break; - case OP_STRCAT: - if (c0 == OP_STRING) { - mrb_value v = s->irep->pool[GETARG_Bx(i0)]; +struct mrb_insn_data { + uint8_t insn; + uint16_t a; + uint16_t b; + uint8_t c; +}; - if (mrb_string_p(v) && RSTRING_LEN(v) == 0) { - s->pc--; - return 0; - } - } - if (c0 == OP_LOADNIL) { - if (GETARG_B(i) == GETARG_A(i0)) { - s->pc--; - return 0; - } - } - break; - case OP_JMPIF: - case OP_JMPNOT: - if (c0 == OP_MOVE && GETARG_A(i) == GETARG_A(i0)) { - s->iseq[s->pc-1] = MKOP_AsBx(c1, GETARG_B(i0), GETARG_sBx(i)); - return s->pc-1; - } - break; - default: - break; +struct mrb_insn_data +mrb_decode_insn(codegen_scope *s, mrb_code *pc) +{ + struct mrb_insn_data data = { 0 }; + mrb_code insn = READ_B(); + uint16_t a = 0; + uint16_t b = 0; + uint8_t c = 0; + + switch (insn) { +#define FETCH_Z() /* empty */ +#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x (); break; +#include "mruby/ops.h" +#undef OPCODE + } + switch (insn) { + case OP_EXT1: + insn = READ_B(); + switch (insn) { +#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); break; +#include "mruby/ops.h" +#undef OPCODE + } + break; + case OP_EXT2: + insn = READ_B(); + switch (insn) { +#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); break; +#include "mruby/ops.h" +#undef OPCODE + } + break; + case OP_EXT3: + insn = READ_B(); + switch (insn) { +#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); break; +#include "mruby/ops.h" +#undef OPCODE + } + break; + default: + break; + } + data.insn = insn; + data.a = a; + data.b = b; + data.c = c; + return data; +} + +struct mrb_insn_data +mrb_last_insn(codegen_scope *s) +{ + if (s->pc == s->lastpc) { + struct mrb_insn_data data; + + data.insn = OP_NOP; + return data; + } + return mrb_decode_insn(s, &s->iseq[s->lastpc]); +} + +static mrb_bool +no_peephole(codegen_scope *s) +{ + return no_optimize(s) || s->lastlabel == s->pc || s->pc == 0 || s->pc == s->lastpc; +} + +static uint16_t +genjmp(codegen_scope *s, mrb_code i, uint16_t pc) +{ + uint16_t pos; + + s->lastpc = s->pc; + gen_B(s, i); + pos = s->pc; + gen_S(s, pc); + return pos; +} + +static uint16_t +genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val) +{ + uint16_t pos; + + if (!no_peephole(s) && !val) { + struct mrb_insn_data data = mrb_last_insn(s); + + if (data.insn == OP_MOVE && data.a == a) { + s->pc = s->lastpc; + a = data.b; } } - return genop(s, i); + + s->lastpc = s->pc; + if (a > 0xff) { + gen_B(s, OP_EXT1); + gen_B(s, i); + gen_S(s, a); + pos = s->pc; + gen_S(s, pc); + } + else { + gen_B(s, i); + gen_B(s, a); + pos = s->pc; + gen_S(s, pc); + } + return pos; } static void -scope_error(codegen_scope *s) +gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep) { - exit(EXIT_FAILURE); + if (no_peephole(s)) { + normal: + genop_2(s, OP_MOVE, dst, src); + return; + } + else { + struct mrb_insn_data data = mrb_last_insn(s); + + switch (data.insn) { + case OP_MOVE: + if (dst == src) return; /* remove useless MOVE */ + if (data.b == dst && data.a == src) /* skip swapping MOVE */ + return; + goto normal; + case OP_LOADNIL: case OP_LOADSELF: case OP_LOADT: case OP_LOADF: + case OP_LOADI__1: + case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3: + case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7: + if (nopeep || data.a != src || data.a < s->nlocals) goto normal; + s->pc = s->lastpc; + genop_1(s, data.insn, dst); + break; + case OP_LOADI: case OP_LOADINEG: case OP_LOADL: case OP_LOADSYM: + case OP_GETGV: case OP_GETSV: case OP_GETIV: case OP_GETCV: + case OP_GETCONST: case OP_STRING: + case OP_LAMBDA: case OP_BLOCK: case OP_METHOD: case OP_BLKPUSH: + if (nopeep || data.a != src || data.a < s->nlocals) goto normal; + s->pc = s->lastpc; + genop_2(s, data.insn, dst, data.b); + break; + default: + goto normal; + } + } } static void -distcheck(codegen_scope *s, int diff) +gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst, uint16_t idx) { - if (diff > MAXARG_sBx || diff < -MAXARG_sBx) { - codegen_error(s, "too distant jump address"); + if (no_peephole(s)) { + normal: + genop_2(s, op, dst, idx); + return; + } + else { + struct mrb_insn_data data = mrb_last_insn(s); + + switch (data.insn) { + case OP_LOADI__1: + if (op == OP_ADD) op = OP_SUB; + else op = OP_ADD; + data.b = 1; + goto replace; + case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3: + case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7: + data.b = data.insn - OP_LOADI_0; + /* fall through */ + case OP_LOADI: + replace: + if (data.b >= 128) goto normal; + s->pc = s->lastpc; + if (op == OP_ADD) { + genop_3(s, OP_ADDI, dst, idx, data.b); + } + else { + genop_3(s, OP_SUBI, dst, idx, data.b); + } + break; + default: + goto normal; + } } } -static inline void -dispatch(codegen_scope *s, int pc) +static int +dispatch(codegen_scope *s, uint16_t pos0) { - int diff = s->pc - pc; - mrb_code i = s->iseq[pc]; - int c = GET_OPCODE(i); + uint16_t newpos; s->lastlabel = s->pc; - switch (c) { - case OP_JMP: - case OP_JMPIF: - case OP_JMPNOT: - case OP_ONERR: - break; - default: -#ifndef MRB_DISABLE_STDIO - fprintf(stderr, "bug: dispatch on non JMP op\n"); -#endif - scope_error(s); - break; - } - distcheck(s, diff); - s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff); + newpos = PEEK_S(s->iseq+pos0); + emit_S(s, pos0, s->pc); + return newpos; } static void -dispatch_linked(codegen_scope *s, int pc) +dispatch_linked(codegen_scope *s, uint16_t pos) { - mrb_code i; - int pos; - - if (!pc) return; + if (pos==0) return; for (;;) { - i = s->iseq[pc]; - pos = GETARG_sBx(i); - dispatch(s, pc); - if (!pos) break; - pc = pos; + pos = dispatch(s, pos); + if (pos==0) break; } } @@ -451,7 +516,7 @@ dispatch_linked(codegen_scope *s, int pc) static void push_(codegen_scope *s) { - if (s->sp > 511) { + if (s->sp >= 0xffff) { codegen_error(s, "too complex expression"); } s->sp++; @@ -461,7 +526,7 @@ push_(codegen_scope *s) static void push_n_(codegen_scope *s, int n) { - if (s->sp+n > 511) { + if (s->sp+n >= 0xffff) { codegen_error(s, "too complex expression"); } s->sp+=n; @@ -545,52 +610,23 @@ new_lit(codegen_scope *s, mrb_value val) return i; } -/* method symbols should be fit in 9 bits */ -#define MAXMSYMLEN 512 /* maximum symbol numbers */ -#define MAXSYMLEN 65536 +#define MAXSYMLEN 0x10000 static int -new_msym(codegen_scope *s, mrb_sym sym) +new_sym(codegen_scope *s, mrb_sym sym) { int i, len; mrb_assert(s->irep); len = s->irep->slen; - if (len > MAXMSYMLEN) len = MAXMSYMLEN; for (i=0; iirep->syms[i] == sym) return i; - if (s->irep->syms[i] == 0) break; } - if (i == MAXMSYMLEN) { - codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXMSYMLEN) ")"); - } - s->irep->syms[i] = sym; - if (i == s->irep->slen) s->irep->slen++; - return i; -} - -static int -new_sym(codegen_scope *s, mrb_sym sym) -{ - int i; - - for (i=0; iirep->slen; i++) { - if (s->irep->syms[i] == sym) return i; - } - if (s->irep->slen == MAXSYMLEN) { - codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXSYMLEN) ")"); - } - - if (s->irep->slen > MAXMSYMLEN/2 && s->scapa == MAXMSYMLEN) { - s->scapa = MAXSYMLEN; - s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*MAXSYMLEN); - for (i = s->irep->slen; i < MAXMSYMLEN; i++) { - static const mrb_sym mrb_sym_zero = { 0 }; - s->irep->syms[i] = mrb_sym_zero; - } - s->irep->slen = MAXMSYMLEN; + if (s->irep->slen >= s->scapa) { + s->scapa *= 2; + s->irep->syms = (mrb_sym*)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*s->scapa); } s->irep->syms[s->irep->slen] = sym; return s->irep->slen++; @@ -631,7 +667,6 @@ for_body(codegen_scope *s, node *tree) int idx; struct loopinfo *lp; node *n2; - mrb_code c; /* generate receiver */ codegen(s, tree->cdr->car, VAL); @@ -645,7 +680,7 @@ for_body(codegen_scope *s, node *tree) /* generate loop variable */ n2 = tree->car; - genop(s, MKOP_Ax(OP_ENTER, 0x40000)); + genop_W(s, OP_ENTER, 0x40000); if (n2->car && !n2->car->cdr && !n2->cdr) { gen_assignment(s, n2->car->car, 1, NOVAL); } @@ -659,25 +694,20 @@ for_body(codegen_scope *s, node *tree) /* loop body */ codegen(s, tree->cdr->cdr->car, VAL); pop(); - if (s->pc > 0) { - c = s->iseq[s->pc-1]; - if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) - genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); - } + genop_1(s, OP_RETURN, cursp()); loop_pop(s, NOVAL); scope_finish(s); s = prev; - genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK)); + genop_2(s, OP_BLOCK, cursp(), s->irep->rlen-1); push();pop(); /* space for a block */ pop(); - idx = new_msym(s, mrb_intern_lit(s->mrb, "each")); - genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0)); + idx = new_sym(s, mrb_intern_lit(s->mrb, "each")); + genop_3(s, OP_SENDB, cursp(), idx, 0); } static int lambda_body(codegen_scope *s, node *tree, int blk) { - mrb_code c; codegen_scope *parent = s; s = scope_new(s->mrb, s, tree->car); if (s == NULL) { @@ -688,7 +718,7 @@ lambda_body(codegen_scope *s, node *tree, int blk) if (blk) { struct loopinfo *lp = loop_push(s, LOOP_BLOCK); - lp->pc1 = new_label(s); + lp->pc0 = new_label(s); } tree = tree->cdr; if (tree->car) { @@ -721,45 +751,36 @@ lambda_body(codegen_scope *s, node *tree, int blk) s->ainfo = (((ma+oa) & 0x3f) << 6) /* (12bits = 6:1:5) */ | ((ra & 1) << 5) | (pa & 0x1f); - genop(s, MKOP_Ax(OP_ENTER, a)); + genop_W(s, OP_ENTER, a); pos = new_label(s); for (i=0; i 0) { - genop(s, MKOP_sBx(OP_JMP, 0)); + genjmp(s, OP_JMP, 0); } opt = tree->car->cdr->car; i = 0; while (opt) { int idx; - dispatch(s, pos+i); + dispatch(s, pos+i*3+1); codegen(s, opt->car->cdr, VAL); - idx = lv_idx(s, nsym(opt->car->car)); pop(); - genop_peep(s, MKOP_AB(OP_MOVE, idx, cursp()), NOVAL); + idx = lv_idx(s, nsym(opt->car->car)); + gen_move(s, idx, cursp(), 0); i++; opt = opt->cdr; } if (oa > 0) { - dispatch(s, pos+i); + dispatch(s, pos+i*3+1); } } codegen(s, tree->cdr->car, VAL); pop(); if (s->pc > 0) { - c = s->iseq[s->pc-1]; - if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) { - if (s->nregs == 0) { - genop(s, MKOP_A(OP_LOADNIL, 0)); - genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); - } - else { - genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); - } - } + genop_1(s, OP_RETURN, cursp()); } if (blk) { loop_pop(s, NOVAL); @@ -773,24 +794,13 @@ scope_body(codegen_scope *s, node *tree, int val) { codegen_scope *scope = scope_new(s->mrb, s, tree->car); if (scope == NULL) { - raise_error(s, "unexpected scope"); + codegen_error(s, "unexpected scope"); } codegen(scope, tree->cdr, VAL); + genop_1(scope, OP_RETURN, scope->sp-1); if (!s->iseq) { - genop(scope, MKOP_A(OP_STOP, 0)); - } - else if (!val) { - genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); - } - else { - if (scope->nregs == 0) { - genop(scope, MKOP_A(OP_LOADNIL, 0)); - genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); - } - else { - genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp-1, OP_R_NORMAL), NOVAL); - } + genop_0(scope, OP_STOP); } scope_finish(scope); if (!s->irep) { @@ -854,15 +864,15 @@ gen_values(codegen_scope *s, node *t, int val, int extra) } else { pop_n(n); - genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n)); + genop_2(s, OP_ARRAY, cursp(), n); push(); codegen(s, t->car, VAL); pop(); pop(); if (is_splat) { - genop_peep(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1), NOVAL); + genop_1(s, OP_ARYCAT, cursp()); } else { - genop_peep(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1), NOVAL); + genop_1(s, OP_ARYPUSH, cursp()); } } t = t->cdr; @@ -871,10 +881,10 @@ gen_values(codegen_scope *s, node *t, int val, int extra) codegen(s, t->car, VAL); pop(); pop(); if (nint(t->car->car) == NODE_SPLAT) { - genop_peep(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1), NOVAL); + genop_1(s, OP_ARYCAT, cursp()); } else { - genop_peep(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1), NOVAL); + genop_1(s, OP_ARYPUSH, cursp()); } t = t->cdr; } @@ -905,16 +915,10 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) codegen(s, tree->car, VAL); /* receiver */ if (safe) { int recv = cursp()-1; - genop(s, MKOP_A(OP_LOADNIL, cursp())); - push(); - genop(s, MKOP_AB(OP_MOVE, cursp(), recv)); - push_n(2); pop_n(2); /* space for one arg and a block */ - pop(); - idx = new_msym(s, mrb_intern_lit(s->mrb, "==")); - genop(s, MKOP_ABC(OP_EQ, cursp(), idx, 1)); - skip = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0)); + gen_move(s, cursp(), recv, 0); + skip = genjmp2(s, OP_JMPNIL, cursp(), 0, val); } - idx = new_msym(s, sym); + idx = new_sym(s, sym); tree = tree->cdr->cdr->car; if (tree) { n = gen_values(s, tree->car, VAL, sp?1:0); @@ -923,14 +927,15 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) push(); } } - if (sp) { + if (sp) { /* last argument pushed (attr=) */ if (sendv) { + gen_move(s, cursp(), sp, 0); pop(); - genop(s, MKOP_AB(OP_ARYPUSH, cursp(), sp)); + genop_1(s, OP_ARYPUSH, cursp()); push(); } else { - genop(s, MKOP_AB(OP_MOVE, cursp(), sp)); + gen_move(s, cursp(), sp, 0); push(); n++; } @@ -939,9 +944,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) noop = 1; codegen(s, tree->cdr, VAL); pop(); - } - else { - blk = cursp(); + blk = 1; } push();pop(); pop_n(n+1); @@ -950,39 +953,38 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen); if (!noop && symlen == 1 && symname[0] == '+' && n == 1) { - genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, n), val); + gen_addsub(s, OP_ADD, cursp(), idx); } else if (!noop && symlen == 1 && symname[0] == '-' && n == 1) { - genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, n), val); + gen_addsub(s, OP_SUB, cursp(), idx); } else if (!noop && symlen == 1 && symname[0] == '*' && n == 1) { - genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n)); + genop_2(s, OP_MUL, cursp(), idx); } else if (!noop && symlen == 1 && symname[0] == '/' && n == 1) { - genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n)); + genop_2(s, OP_DIV, cursp(), idx); } else if (!noop && symlen == 1 && symname[0] == '<' && n == 1) { - genop(s, MKOP_ABC(OP_LT, cursp(), idx, n)); + genop_2(s, OP_LT, cursp(), idx); } else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=' && n == 1) { - genop(s, MKOP_ABC(OP_LE, cursp(), idx, n)); + genop_2(s, OP_LE, cursp(), idx); } else if (!noop && symlen == 1 && symname[0] == '>' && n == 1) { - genop(s, MKOP_ABC(OP_GT, cursp(), idx, n)); + genop_2(s, OP_GT, cursp(), idx); } else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=' && n == 1) { - genop(s, MKOP_ABC(OP_GE, cursp(), idx, n)); + genop_2(s, OP_GE, cursp(), idx); } else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=' && n == 1) { - genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n)); + genop_2(s, OP_EQ, cursp(), idx); } else { - if (sendv) n = CALL_MAXARGS; - if (blk > 0) { /* no block */ - genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n)); + if (sendv) { + genop_2(s, blk ? OP_SENDVB : OP_SENDV, cursp(), idx); } else { - genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, n)); + genop_3(s, blk ? OP_SENDB : OP_SEND, cursp(), idx, n); } } } @@ -1004,13 +1006,14 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val) switch (type) { case NODE_GVAR: idx = new_sym(s, nsym(tree)); - genop_peep(s, MKOP_ABx(OP_SETGLOBAL, sp, idx), val); + genop_2(s, OP_SETGV, sp, idx); break; case NODE_LVAR: idx = lv_idx(s, nsym(tree)); if (idx > 0) { if (idx != sp) { - genop_peep(s, MKOP_AB(OP_MOVE, idx, sp), val); + gen_move(s, idx, sp, val); + if (val && on_eval(s)) genop_0(s, OP_NOP); } break; } @@ -1021,7 +1024,7 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val) while (up) { idx = lv_idx(up, nsym(tree)); if (idx > 0) { - genop_peep(s, MKOP_ABC(OP_SETUPVAR, sp, idx, lv), val); + genop_3(s, OP_SETUPVAR, sp, idx, lv); break; } lv++; @@ -1031,23 +1034,23 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val) break; case NODE_IVAR: idx = new_sym(s, nsym(tree)); - genop_peep(s, MKOP_ABx(OP_SETIV, sp, idx), val); + genop_2(s, OP_SETIV, sp, idx); break; case NODE_CVAR: idx = new_sym(s, nsym(tree)); - genop_peep(s, MKOP_ABx(OP_SETCV, sp, idx), val); + genop_2(s, OP_SETCV, sp, idx); break; case NODE_CONST: idx = new_sym(s, nsym(tree)); - genop_peep(s, MKOP_ABx(OP_SETCONST, sp, idx), val); + genop_2(s, OP_SETCONST, sp, idx); break; case NODE_COLON2: - idx = new_sym(s, nsym(tree->cdr)); - genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), NOVAL); + gen_move(s, cursp(), sp, 0); push(); codegen(s, tree->car, VAL); pop_n(2); - genop_peep(s, MKOP_ABx(OP_SETMCNST, cursp(), idx), val); + idx = new_sym(s, nsym(tree->cdr)); + genop_2(s, OP_SETMCNST, sp, idx); break; case NODE_CALL: @@ -1057,7 +1060,7 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val) type == NODE_SCALL); pop(); if (val) { - genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), val); + gen_move(s, cursp(), sp, 0); } break; @@ -1090,7 +1093,7 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) while (t) { int sp = cursp(); - genop(s, MKOP_ABC(OP_AREF, sp, rhs, n)); + genop_3(s, OP_AREF, sp, rhs, n); push(); gen_assignment(s, t->car, sp, NOVAL); pop(); @@ -1107,10 +1110,10 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) p = p->cdr; } } - genop(s, MKOP_AB(OP_MOVE, cursp(), rhs)); + gen_move(s, cursp(), rhs, val); push_n(post+1); pop_n(post+1); - genop(s, MKOP_ABC(OP_APOST, cursp(), n, post)); + genop_3(s, OP_APOST, cursp(), n, post); n = 1; if (t->car) { /* rest */ gen_assignment(s, t->car, cursp(), NOVAL); @@ -1124,19 +1127,19 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) } } if (val) { - genop(s, MKOP_AB(OP_MOVE, cursp(), rhs)); + gen_move(s, cursp(), rhs, 0); } } } static void -gen_send_intern(codegen_scope *s) +gen_intern(codegen_scope *s) { - push();pop(); /* space for a block */ pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0)); + genop_1(s, OP_INTERN, cursp()); push(); } + static void gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val) { @@ -1159,25 +1162,25 @@ gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val) j = 0; ++i; if (sym) - gen_send_intern(s); + gen_intern(s); } break; } - if (j >= 2) { + while (j >= 2) { pop(); pop(); - genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); + genop_1(s, OP_STRCAT, cursp()); push(); - j = 1; + j--; } tree = tree->cdr; } if (j > 0) { ++i; if (sym) - gen_send_intern(s); + gen_intern(s); } pop_n(i); - genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i)); + genop_2(s, OP_ARRAY, cursp(), i); push(); } else { @@ -1196,7 +1199,7 @@ raise_error(codegen_scope *s, const char *msg) { int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg)); - genop(s, MKOP_ABx(OP_ERR, 1, idx)); + genop_1(s, OP_ERR, idx); } #ifndef MRB_WITHOUT_FLOAT @@ -1274,11 +1277,9 @@ static void gen_retval(codegen_scope *s, node *tree) { if (nint(tree->car) == NODE_SPLAT) { - genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), 0)); - push(); codegen(s, tree, VAL); - pop(); pop(); - genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1)); + pop(); + genop_1(s, OP_ARYDUP, cursp()); } else { codegen(s, tree, VAL); @@ -1294,7 +1295,7 @@ codegen(codegen_scope *s, node *tree, int val) if (!tree) { if (val) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop_1(s, OP_LOADNIL, cursp()); push(); } return; @@ -1318,7 +1319,7 @@ codegen(codegen_scope *s, node *tree, int val) switch (nt) { case NODE_BEGIN: if (val && !tree) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop_1(s, OP_LOADNIL, cursp()); push(); } while (tree) { @@ -1329,18 +1330,18 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_RESCUE: { - int onerr, noexc, exend, pos1, pos2, tmp; + int noexc, exend, pos1, pos2, tmp; struct loopinfo *lp; if (tree->car == NULL) goto exit; - onerr = genop(s, MKOP_Bx(OP_ONERR, 0)); lp = loop_push(s, LOOP_BEGIN); - lp->pc1 = onerr; + lp->pc0 = new_label(s); + lp->pc1 = genjmp(s, OP_ONERR, 0); codegen(s, tree->car, VAL); pop(); lp->type = LOOP_RESCUE; - noexc = genop(s, MKOP_Bx(OP_JMP, 0)); - dispatch(s, onerr); + noexc = genjmp(s, OP_JMP, 0); + dispatch(s, lp->pc1); tree = tree->cdr; exend = 0; pos1 = 0; @@ -1348,7 +1349,7 @@ codegen(codegen_scope *s, node *tree, int val) node *n2 = tree->car; int exc = cursp(); - genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0)); + genop_1(s, OP_EXCEPT, exc); push(); while (n2) { node *n3 = n2->car; @@ -1359,30 +1360,29 @@ codegen(codegen_scope *s, node *tree, int val) do { if (n4 && n4->car && nint(n4->car->car) == NODE_SPLAT) { codegen(s, n4->car, VAL); - genop(s, MKOP_AB(OP_MOVE, cursp(), exc)); + gen_move(s, cursp(), exc, 0); push_n(2); pop_n(2); /* space for one arg and a block */ pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1)); + genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1); } else { if (n4) { codegen(s, n4->car, VAL); } else { - genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError")))); + genop_2(s, OP_GETCONST, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "StandardError"))); push(); } pop(); - genop(s, MKOP_ABC(OP_RESCUE, exc, cursp(), 1)); + genop_2(s, OP_RESCUE, exc, cursp()); } - distcheck(s, pos2); - tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); + tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, val); pos2 = tmp; if (n4) { n4 = n4->cdr; } } while (n4); - pos1 = genop(s, MKOP_sBx(OP_JMP, 0)); + pos1 = genjmp(s, OP_JMP, 0); dispatch_linked(s, pos2); pop(); @@ -1393,21 +1393,20 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, n3->cdr->cdr->car, val); if (val) pop(); } - distcheck(s, exend); - tmp = genop(s, MKOP_sBx(OP_JMP, exend)); + tmp = genjmp(s, OP_JMP, exend); exend = tmp; n2 = n2->cdr; push(); } if (pos1) { dispatch(s, pos1); - genop(s, MKOP_A(OP_RAISE, exc)); + genop_1(s, OP_RAISE, exc); } } pop(); tree = tree->cdr; dispatch(s, noexc); - genop(s, MKOP_A(OP_POPERR, 1)); + genop_1(s, OP_POPERR, 1); if (tree->car) { codegen(s, tree->car, val); } @@ -1424,15 +1423,13 @@ codegen(codegen_scope *s, node *tree, int val) (nint(tree->cdr->cdr->car) == NODE_BEGIN && tree->cdr->cdr->cdr)) { int idx; - int epush = s->pc; - genop(s, MKOP_Bx(OP_EPUSH, 0)); s->ensure_level++; - codegen(s, tree->car, val); idx = scope_body(s, tree->cdr, NOVAL); - s->iseq[epush] = MKOP_Bx(OP_EPUSH, idx); + genop_1(s, OP_EPUSH, idx); + codegen(s, tree->car, val); s->ensure_level--; - genop_peep(s, MKOP_A(OP_EPOP, 1), NOVAL); + genop_1(s, OP_EPOP, 1); } else { /* empty ensure ignored */ codegen(s, tree->car, val); @@ -1443,7 +1440,7 @@ codegen(codegen_scope *s, node *tree, int val) if (val) { int idx = lambda_body(s, tree, 1); - genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_LAMBDA)); + genop_2(s, OP_LAMBDA, cursp(), idx); push(); } break; @@ -1452,7 +1449,7 @@ codegen(codegen_scope *s, node *tree, int val) if (val) { int idx = lambda_body(s, tree, 1); - genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_BLOCK)); + genop_2(s, OP_BLOCK, cursp(), idx); push(); } break; @@ -1460,10 +1457,10 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_IF: { int pos1, pos2; - node *e = tree->cdr->cdr->car; + node *elsepart = tree->cdr->cdr->car; if (!tree->car) { - codegen(s, e, val); + codegen(s, elsepart, val); goto exit; } switch (nint(tree->car->car)) { @@ -1474,27 +1471,27 @@ codegen(codegen_scope *s, node *tree, int val) goto exit; case NODE_FALSE: case NODE_NIL: - codegen(s, e, val); + codegen(s, elsepart, val); goto exit; } codegen(s, tree->car, VAL); pop(); - pos1 = genop_peep(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0), NOVAL); + pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val); codegen(s, tree->cdr->car, val); - if (e) { + if (elsepart) { if (val) pop(); - pos2 = genop(s, MKOP_sBx(OP_JMP, 0)); + pos2 = genjmp(s, OP_JMP, 0); dispatch(s, pos1); - codegen(s, e, val); + codegen(s, elsepart, val); dispatch(s, pos2); } else { if (val) { pop(); - pos2 = genop(s, MKOP_sBx(OP_JMP, 0)); + pos2 = genjmp(s, OP_JMP, 0); dispatch(s, pos1); - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop_1(s, OP_LOADNIL, cursp()); dispatch(s, pos2); push(); } @@ -1511,7 +1508,7 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree->car, VAL); pop(); - pos = genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0)); + pos = genjmp2(s, OP_JMPNOT, cursp(), 0, val); codegen(s, tree->cdr, val); dispatch(s, pos); } @@ -1523,7 +1520,7 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree->car, VAL); pop(); - pos = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0)); + pos = genjmp2(s, OP_JMPIF, cursp(), 0, val); codegen(s, tree->cdr, val); dispatch(s, pos); } @@ -1533,14 +1530,14 @@ codegen(codegen_scope *s, node *tree, int val) { struct loopinfo *lp = loop_push(s, LOOP_NORMAL); - lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0)); + lp->pc0 = new_label(s); + lp->pc1 = genjmp(s, OP_JMP, 0); lp->pc2 = new_label(s); codegen(s, tree->cdr, NOVAL); dispatch(s, lp->pc1); codegen(s, tree->car, VAL); pop(); - distcheck(s, lp->pc2 - s->pc); - genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc)); + genjmp2(s, OP_JMPIF, cursp(), lp->pc2, NOVAL); loop_pop(s, val); } @@ -1550,14 +1547,14 @@ codegen(codegen_scope *s, node *tree, int val) { struct loopinfo *lp = loop_push(s, LOOP_NORMAL); - lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0)); + lp->pc0 = new_label(s); + lp->pc1 = genjmp(s, OP_JMP, 0); lp->pc2 = new_label(s); codegen(s, tree->cdr, NOVAL); dispatch(s, lp->pc1); codegen(s, tree->car, VAL); pop(); - distcheck(s, lp->pc2 - s->pc); - genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc)); + genjmp2(s, OP_JMPNOT, cursp(), lp->pc2, NOVAL); loop_pop(s, val); } @@ -1586,43 +1583,40 @@ codegen(codegen_scope *s, node *tree, int val) while (n) { codegen(s, n->car, VAL); if (head) { - genop(s, MKOP_AB(OP_MOVE, cursp(), head)); - push_n(2); pop_n(2); /* space for one arg and a block */ - pop(); + gen_move(s, cursp(), head, 0); + push(); push(); pop(); pop(); pop(); if (nint(n->car->car) == NODE_SPLAT) { - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1)); + genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1); } else { - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1)); + genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "===")), 1); } } else { pop(); } - distcheck(s, pos2); - tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); + tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, NOVAL); pos2 = tmp; n = n->cdr; } if (tree->car->car) { - pos1 = genop(s, MKOP_sBx(OP_JMP, 0)); + pos1 = genjmp(s, OP_JMP, 0); dispatch_linked(s, pos2); } codegen(s, tree->car->cdr, val); if (val) pop(); - distcheck(s, pos3); - tmp = genop(s, MKOP_sBx(OP_JMP, pos3)); + tmp = genjmp(s, OP_JMP, pos3); pos3 = tmp; if (pos1) dispatch(s, pos1); tree = tree->cdr; } if (val) { int pos = cursp(); - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop_1(s, OP_LOADNIL, cursp()); if (pos3) dispatch_linked(s, pos3); if (head) pop(); if (cursp() != pos) { - genop(s, MKOP_AB(OP_MOVE, cursp(), pos)); + gen_move(s, cursp(), pos, 0); } push(); } @@ -1654,7 +1648,7 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree->cdr, val); if (val) { pop(); pop(); - genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), FALSE)); + genop_1(s, OP_RANGE_INC, cursp()); push(); } break; @@ -1664,7 +1658,7 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree->cdr, val); if (val) { pop(); pop(); - genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), TRUE)); + genop_1(s, OP_RANGE_EXC, cursp()); push(); } break; @@ -1675,7 +1669,7 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree->car, VAL); pop(); - genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); + genop_2(s, OP_GETMCNST, cursp(), sym); if (val) push(); } break; @@ -1684,8 +1678,8 @@ codegen(codegen_scope *s, node *tree, int val) { int sym = new_sym(s, nsym(tree)); - genop(s, MKOP_A(OP_OCLASS, cursp())); - genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); + genop_1(s, OP_OCLASS, cursp()); + genop_2(s, OP_GETMCNST, cursp(), sym); if (val) push(); } break; @@ -1698,7 +1692,7 @@ codegen(codegen_scope *s, node *tree, int val) if (n >= 0) { if (val) { pop_n(n); - genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n)); + genop_2(s, OP_ARRAY, cursp(), n); push(); } } @@ -1718,12 +1712,14 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree->car->cdr, val); len++; tree = tree->cdr; - if (val && len == 126) { + if (val && len == 255) { pop_n(len*2); - genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len)); - if (update) { + if (!update) { + genop_2(s, OP_HASH, cursp(), len); + } + else { pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1)); + genop_2(s, OP_HASHADD, cursp(), len); } push(); update = TRUE; @@ -1732,10 +1728,12 @@ codegen(codegen_scope *s, node *tree, int val) } if (val) { pop_n(len*2); - genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len)); - if (update) { + if (!update) { + genop_2(s, OP_HASH, cursp(), len); + } + else { pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1)); + genop_2(s, OP_HASHADD, cursp(), len); } push(); } @@ -1776,7 +1774,7 @@ codegen(codegen_scope *s, node *tree, int val) n++; } else { - genop(s, MKOP_A(OP_LOADNIL, rhs+n)); + genop_1(s, OP_LOADNIL, rhs+n); gen_assignment(s, t->car, rhs+n, NOVAL); } t = t->cdr; @@ -1800,7 +1798,7 @@ codegen(codegen_scope *s, node *tree, int val) else { rn = len - post - n; } - genop(s, MKOP_ABC(OP_ARRAY, cursp(), rhs+n, rn)); + genop_3(s, OP_ARRAY2, cursp(), rhs+n, rn); gen_assignment(s, t->car, cursp(), NOVAL); n += rn; } @@ -1815,7 +1813,7 @@ codegen(codegen_scope *s, node *tree, int val) } pop_n(len); if (val) { - genop(s, MKOP_ABC(OP_ARRAY, rhs, rhs, len)); + genop_2(s, OP_ARRAY, rhs, len); push(); } } @@ -1843,17 +1841,17 @@ codegen(codegen_scope *s, node *tree, int val) int onerr, noexc, exc; struct loopinfo *lp; - onerr = genop(s, MKOP_Bx(OP_ONERR, 0)); + onerr = genjmp(s, OP_ONERR, 0); lp = loop_push(s, LOOP_BEGIN); lp->pc1 = onerr; exc = cursp(); codegen(s, tree->car, VAL); lp->type = LOOP_RESCUE; - genop(s, MKOP_A(OP_POPERR, 1)); - noexc = genop(s, MKOP_Bx(OP_JMP, 0)); + genop_1(s, OP_POPERR, 1); + noexc = genjmp(s, OP_JMP, 0); dispatch(s, onerr); - genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0)); - genop(s, MKOP_A(OP_LOADF, exc)); + genop_1(s, OP_EXCEPT, exc); + genop_1(s, OP_LOADF, exc); dispatch(s, noexc); loop_pop(s, NOVAL); } @@ -1867,7 +1865,7 @@ codegen(codegen_scope *s, node *tree, int val) push(); } codegen(s, n->car, VAL); /* receiver */ - idx = new_msym(s, nsym(n->cdr->car)); + idx = new_sym(s, nsym(n->cdr->car)); base = cursp()-1; if (n->cdr->cdr->car) { nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1); @@ -1881,12 +1879,12 @@ codegen(codegen_scope *s, node *tree, int val) } } /* copy receiver and arguments */ - genop(s, MKOP_AB(OP_MOVE, cursp(), base)); + gen_move(s, cursp(), base, 0); for (i=0; i= 0) { - genop(s, MKOP_AB(OP_MOVE, vsp, cursp())); + gen_move(s, vsp, cursp(), 0); } - pos = genop(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0)); + pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val); } else { - pos = genop_peep(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0), NOVAL); + pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val); } codegen(s, tree->cdr->cdr->car, VAL); pop(); if (val && vsp >= 0) { - genop(s, MKOP_AB(OP_MOVE, vsp, cursp())); + gen_move(s, vsp, cursp(), 0); } if (nint(tree->car->car) == NODE_CALL) { if (callargs == CALL_MAXARGS) { pop(); - genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1)); + genop_1(s, OP_ARYPUSH, cursp()); } else { pop_n(callargs); callargs++; } pop(); - idx = new_msym(s, attrsym(s, nsym(tree->car->cdr->cdr->car))); - genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs)); + idx = new_sym(s, attrsym(s, nsym(tree->car->cdr->cdr->car))); + genop_3(s, OP_SEND, cursp(), idx, callargs); } else { gen_assignment(s, tree->car, cursp(), val); @@ -1935,52 +1933,52 @@ codegen(codegen_scope *s, node *tree, int val) push(); pop(); pop(); pop(); - idx = new_msym(s, sym); + idx = new_sym(s, sym); if (len == 1 && name[0] == '+') { - genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, 1), val); + gen_addsub(s, OP_ADD, cursp(), idx); } else if (len == 1 && name[0] == '-') { - genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, 1), val); + gen_addsub(s, OP_SUB, cursp(), idx); } else if (len == 1 && name[0] == '*') { - genop(s, MKOP_ABC(OP_MUL, cursp(), idx, 1)); + genop_2(s, OP_MUL, cursp(), idx); } else if (len == 1 && name[0] == '/') { - genop(s, MKOP_ABC(OP_DIV, cursp(), idx, 1)); + genop_2(s, OP_DIV, cursp(), idx); } else if (len == 1 && name[0] == '<') { - genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1)); + genop_2(s, OP_LT, cursp(), idx); } else if (len == 2 && name[0] == '<' && name[1] == '=') { - genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1)); + genop_2(s, OP_LE, cursp(), idx); } else if (len == 1 && name[0] == '>') { - genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1)); + genop_2(s, OP_GT, cursp(), idx); } else if (len == 2 && name[0] == '>' && name[1] == '=') { - genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1)); + genop_2(s, OP_GE, cursp(), idx); } else { - genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1)); + genop_3(s, OP_SEND, cursp(), idx, 1); } if (callargs < 0) { gen_assignment(s, tree->car, cursp(), val); } else { if (val && vsp >= 0) { - genop(s, MKOP_AB(OP_MOVE, vsp, cursp())); + gen_move(s, vsp, cursp(), 0); } if (callargs == CALL_MAXARGS) { pop(); - genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1)); + genop_1(s, OP_ARYPUSH, cursp()); } else { pop_n(callargs); callargs++; } pop(); - idx = new_msym(s, attrsym(s,nsym(tree->car->cdr->cdr->car))); - genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs)); + idx = new_sym(s, attrsym(s,nsym(tree->car->cdr->cdr->car))); + genop_3(s, OP_SEND, cursp(), idx, callargs); } } break; @@ -1997,7 +1995,7 @@ codegen(codegen_scope *s, node *tree, int val) s2 = s2->prev; if (!s2) break; } - genop(s, MKOP_ABx(OP_ARGARY, cursp(), (lv & 0xf))); + genop_2S(s, OP_ARGARY, cursp(), (lv & 0xf)); push(); push(); /* ARGARY pushes two values */ pop(); pop(); if (tree) { @@ -2015,12 +2013,12 @@ codegen(codegen_scope *s, node *tree, int val) pop(); } else { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop_1(s, OP_LOADNIL, cursp()); push(); pop(); } pop_n(n+1); if (sendv) n = CALL_MAXARGS; - genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n)); + genop_2(s, OP_SUPER, cursp(), n); if (val) push(); } break; @@ -2037,14 +2035,14 @@ codegen(codegen_scope *s, node *tree, int val) if (!s2) break; } if (s2) ainfo = s2->ainfo; - genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf))); + genop_2S(s, OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf)); push(); push(); pop(); /* ARGARY pushes two values */ if (tree && tree->cdr) { codegen(s, tree->cdr, VAL); pop(); } pop(); pop(); - genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS)); + genop_2(s, OP_SUPER, cursp(), CALL_MAXARGS); if (val) push(); } break; @@ -2054,13 +2052,13 @@ codegen(codegen_scope *s, node *tree, int val) gen_retval(s, tree); } else { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop_1(s, OP_LOADNIL, cursp()); } if (s->loop) { - genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN)); + genop_1(s, OP_RETURN_BLK, cursp()); } else { - genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); + genop_1(s, OP_RETURN, cursp()); } if (val) push(); break; @@ -2087,9 +2085,9 @@ codegen(codegen_scope *s, node *tree, int val) } push();pop(); /* space for a block */ pop_n(n+1); - genop(s, MKOP_ABx(OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf))); + genop_2S(s, OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf)); if (sendv) n = CALL_MAXARGS; - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n)); + genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "call")), n); if (val) push(); } break; @@ -2105,11 +2103,10 @@ codegen(codegen_scope *s, node *tree, int val) } else if (s->loop->type == LOOP_NORMAL) { if (s->ensure_level > s->loop->ensure_level) { - genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL); + genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level); } codegen(s, tree, NOVAL); - distcheck(s, s->loop->pc1 - s->pc); - genop(s, MKOP_sBx(OP_JMP, s->loop->pc1 - s->pc)); + genjmp(s, OP_JMP, s->loop->pc0); } else { if (tree) { @@ -2117,9 +2114,9 @@ codegen(codegen_scope *s, node *tree, int val) pop(); } else { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop_1(s, OP_LOADNIL, cursp()); } - genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); + genop_1(s, OP_RETURN, cursp()); } if (val) push(); break; @@ -2130,10 +2127,9 @@ codegen(codegen_scope *s, node *tree, int val) } else { if (s->ensure_level > s->loop->ensure_level) { - genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL); + genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level); } - distcheck(s, s->loop->pc2 - s->pc); - genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc)); + genjmp(s, OP_JMP, s->loop->pc2); } if (val) push(); break; @@ -2160,13 +2156,12 @@ codegen(codegen_scope *s, node *tree, int val) } else { if (n > 0) { - genop_peep(s, MKOP_A(OP_POPERR, n), NOVAL); + genop_1(s, OP_POPERR, n); } if (s->ensure_level > lp->ensure_level) { - genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - lp->ensure_level), NOVAL); + genop_1(s, OP_EPOP, s->ensure_level - lp->ensure_level); } - distcheck(s, s->loop->pc1 - s->pc); - genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc)); + genjmp(s, OP_JMP, lp->pc0); } } if (val) push(); @@ -2178,7 +2173,8 @@ codegen(codegen_scope *s, node *tree, int val) int idx = lv_idx(s, nsym(tree)); if (idx > 0) { - genop_peep(s, MKOP_AB(OP_MOVE, cursp(), idx), NOVAL); + gen_move(s, cursp(), idx, val); + if (val && on_eval(s)) genop_0(s, OP_NOP); } else { int lv = 0; @@ -2187,7 +2183,7 @@ codegen(codegen_scope *s, node *tree, int val) while (up) { idx = lv_idx(up, nsym(tree)); if (idx > 0) { - genop_peep(s, MKOP_ABC(OP_GETUPVAR, cursp(), idx, lv), VAL); + genop_3(s, OP_GETUPVAR, cursp(), idx, lv); break; } lv++; @@ -2199,29 +2195,29 @@ codegen(codegen_scope *s, node *tree, int val) break; case NODE_GVAR: - if (val) { + { int sym = new_sym(s, nsym(tree)); - genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); - push(); + genop_2(s, OP_GETGV, cursp(), sym); + if (val) push(); } break; case NODE_IVAR: - if (val) { + { int sym = new_sym(s, nsym(tree)); - genop(s, MKOP_ABx(OP_GETIV, cursp(), sym)); - push(); + genop_2(s, OP_GETIV, cursp(), sym); + if (val) push(); } break; case NODE_CVAR: - if (val) { + { int sym = new_sym(s, nsym(tree)); - genop(s, MKOP_ABx(OP_GETCV, cursp(), sym)); - push(); + genop_2(s, OP_GETCV, cursp(), sym); + if (val) push(); } break; @@ -2229,15 +2225,13 @@ codegen(codegen_scope *s, node *tree, int val) { int sym = new_sym(s, nsym(tree)); - genop(s, MKOP_ABx(OP_GETCONST, cursp(), sym)); - if (val) { - push(); - } + genop_2(s, OP_GETCONST, cursp(), sym); + if (val) push(); } break; case NODE_DEFINED: - codegen(s, tree, VAL); + codegen(s, tree, val); break; case NODE_BACK_REF: @@ -2249,7 +2243,7 @@ codegen(codegen_scope *s, node *tree, int val) buf[1] = nchar(tree); buf[2] = 0; sym = new_sym(s, mrb_intern_cstr(s->mrb, buf)); - genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); + genop_2(s, OP_GETGV, cursp(), sym); push(); } break; @@ -2262,7 +2256,7 @@ codegen(codegen_scope *s, node *tree, int val) str = mrb_format(mrb, "$%S", mrb_fixnum_value(nint(tree))); sym = new_sym(s, mrb_intern_str(mrb, str)); - genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); + genop_2(s, OP_GETGV, cursp(), sym); push(); } break; @@ -2272,7 +2266,7 @@ codegen(codegen_scope *s, node *tree, int val) break; case NODE_BLOCK_ARG: - codegen(s, tree, VAL); + codegen(s, tree, val); break; case NODE_INT: @@ -2280,7 +2274,6 @@ codegen(codegen_scope *s, node *tree, int val) char *p = (char*)tree->car; int base = nint(tree->cdr->car); mrb_int i; - mrb_code co; mrb_bool overflow; i = readint_mrb_int(s, p, base, FALSE, &overflow); @@ -2289,19 +2282,19 @@ codegen(codegen_scope *s, node *tree, int val) double f = readint_float(s, p, base); int off = new_lit(s, mrb_float_value(s->mrb, f)); - genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); + genop_2(s, OP_LOADL, cursp(), off); } else #endif { - if (i < MAXARG_sBx && i > -MAXARG_sBx) { - co = MKOP_AsBx(OP_LOADI, cursp(), i); - } + if (i == -1) genop_1(s, OP_LOADI__1, cursp()); + else if (i < 0) genop_2(s, OP_LOADINEG, cursp(), -i); + else if (i < 8) genop_1(s, OP_LOADI_0 + i, cursp()); + else if (i <= 0xffff) genop_2(s, OP_LOADI, cursp(), i); else { int off = new_lit(s, mrb_fixnum_value(i)); - co = MKOP_ABx(OP_LOADL, cursp(), off); + genop_2(s, OP_LOADL, cursp(), off); } - genop(s, co); } push(); } @@ -2314,7 +2307,7 @@ codegen(codegen_scope *s, node *tree, int val) mrb_float f = mrb_float_read(p, NULL); int off = new_lit(s, mrb_float_value(s->mrb, f)); - genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); + genop_2(s, OP_LOADL, cursp(), off); push(); } break; @@ -2332,7 +2325,7 @@ codegen(codegen_scope *s, node *tree, int val) mrb_float f = mrb_float_read(p, NULL); int off = new_lit(s, mrb_float_value(s->mrb, -f)); - genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); + genop_2(s, OP_LOADL, cursp(), off); push(); } break; @@ -2343,7 +2336,6 @@ codegen(codegen_scope *s, node *tree, int val) char *p = (char*)tree->car; int base = nint(tree->cdr->car); mrb_int i; - mrb_code co; mrb_bool overflow; i = readint_mrb_int(s, p, base, TRUE, &overflow); @@ -2352,18 +2344,18 @@ codegen(codegen_scope *s, node *tree, int val) double f = readint_float(s, p, base); int off = new_lit(s, mrb_float_value(s->mrb, -f)); - genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); + genop_2(s, OP_LOADL, cursp(), off); } else { #endif - if (i < MAXARG_sBx && i > -MAXARG_sBx) { - co = MKOP_AsBx(OP_LOADI, cursp(), i); + if (i == -1) genop_1(s, OP_LOADI__1, cursp()); + else if (i >= -0xffff) { + genop_2(s, OP_LOADINEG, cursp(), -i); } else { int off = new_lit(s, mrb_fixnum_value(i)); - co = MKOP_ABx(OP_LOADL, cursp(), off); + genop_2(s, OP_LOADL, cursp(), off); } - genop(s, co); #ifndef MRB_WITHOUT_FLOAT } #endif @@ -2373,13 +2365,13 @@ codegen(codegen_scope *s, node *tree, int val) default: if (val) { - int sym = new_msym(s, mrb_intern_lit(s->mrb, "-")); + int sym = new_sym(s, mrb_intern_lit(s->mrb, "-")); - genop(s, MKOP_ABx(OP_LOADI, cursp(), 0)); + genop_1(s, OP_LOADI_0, cursp()); push(); codegen(s, tree, VAL); pop(); pop(); - genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2)); + genop_2(s, OP_SUB, cursp(), sym); } else { codegen(s, tree, NOVAL); @@ -2397,7 +2389,7 @@ codegen(codegen_scope *s, node *tree, int val) int off = new_lit(s, mrb_str_new(s->mrb, p, len)); mrb_gc_arena_restore(s->mrb, ai); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + genop_2(s, OP_STRING, cursp(), off); push(); } break; @@ -2410,7 +2402,7 @@ codegen(codegen_scope *s, node *tree, int val) node *n = tree; if (!n) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop_1(s, OP_LOADNIL, cursp()); push(); break; } @@ -2419,7 +2411,7 @@ codegen(codegen_scope *s, node *tree, int val) while (n) { codegen(s, n->car, VAL); pop(); pop(); - genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); + genop_1(s, OP_STRCAT, cursp()); push(); n = n->cdr; } @@ -2450,7 +2442,7 @@ codegen(codegen_scope *s, node *tree, int val) int ai = mrb_gc_arena_save(s->mrb); int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel")); - genop(s, MKOP_A(OP_LOADSELF, cursp())); + genop_1(s, OP_LOADSELF, cursp()); push(); codegen(s, tree->car, VAL); n = tree->cdr; @@ -2461,14 +2453,14 @@ codegen(codegen_scope *s, node *tree, int val) } codegen(s, n->car, VAL); pop(); pop(); - genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); + genop_1(s, OP_STRCAT, cursp()); push(); n = n->cdr; } push(); /* for block */ pop_n(3); sym = new_sym(s, mrb_intern_lit(s->mrb, "`")); - genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1)); + genop_3(s, OP_SEND, cursp(), sym, 1); if (val) push(); mrb_gc_arena_restore(s->mrb, ai); } @@ -2482,13 +2474,13 @@ codegen(codegen_scope *s, node *tree, int val) int off = new_lit(s, mrb_str_new(s->mrb, p, len)); int sym; - genop(s, MKOP_A(OP_LOADSELF, cursp())); + genop_1(s, OP_LOADSELF, cursp()); push(); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + genop_2(s, OP_STRING, cursp(), off); push(); push(); pop_n(3); sym = new_sym(s, mrb_intern_lit(s->mrb, "`")); - genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1)); + genop_3(s, OP_SEND, cursp(), sym, 1); if (val) push(); mrb_gc_arena_restore(s->mrb, ai); } @@ -2504,24 +2496,24 @@ codegen(codegen_scope *s, node *tree, int val) int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1)); int argc = 1; - genop(s, MKOP_A(OP_OCLASS, cursp())); - genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); + genop_1(s, OP_OCLASS, cursp()); + genop_2(s, OP_GETMCNST, cursp(), sym); push(); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + genop_2(s, OP_STRING, cursp(), off); push(); if (p2 || p3) { if (p2) { /* opt */ off = new_lit(s, mrb_str_new_cstr(s->mrb, p2)); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + genop_2(s, OP_STRING, cursp(), off); } else { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop_1(s, OP_LOADNIL, cursp()); } push(); argc++; if (p3) { /* enc */ off = new_lit(s, mrb_str_new(s->mrb, p3, 1)); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + genop_2(s, OP_STRING, cursp(), off); push(); argc++; } @@ -2529,7 +2521,7 @@ codegen(codegen_scope *s, node *tree, int val) push(); /* space for a block */ pop_n(argc+2); sym = new_sym(s, mrb_intern_lit(s->mrb, "compile")); - genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); + genop_3(s, OP_SEND, cursp(), sym, argc); mrb_gc_arena_restore(s->mrb, ai); push(); } @@ -2544,15 +2536,15 @@ codegen(codegen_scope *s, node *tree, int val) int off; char *p; - genop(s, MKOP_A(OP_OCLASS, cursp())); - genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); + genop_1(s, OP_OCLASS, cursp()); + genop_2(s, OP_GETMCNST, cursp(), sym); push(); codegen(s, n->car, VAL); n = n->cdr; while (n) { codegen(s, n->car, VAL); pop(); pop(); - genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); + genop_1(s, OP_STRCAT, cursp()); push(); n = n->cdr; } @@ -2561,29 +2553,29 @@ codegen(codegen_scope *s, node *tree, int val) p = (char*)n->car; off = new_lit(s, mrb_str_new_cstr(s->mrb, p)); codegen(s, tree->car, VAL); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + genop_2(s, OP_STRING, cursp(), off); pop(); - genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); + genop_1(s, OP_STRCAT, cursp()); push(); } if (n->cdr->car) { /* opt */ char *p2 = (char*)n->cdr->car; off = new_lit(s, mrb_str_new_cstr(s->mrb, p2)); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + genop_2(s, OP_STRING, cursp(), off); push(); argc++; } if (n->cdr->cdr) { /* enc */ char *p2 = (char*)n->cdr->cdr; off = new_lit(s, mrb_str_new_cstr(s->mrb, p2)); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + genop_2(s, OP_STRING, cursp(), off); push(); argc++; } push(); /* space for a block */ pop_n(argc+2); sym = new_sym(s, mrb_intern_lit(s->mrb, "compile")); - genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); + genop_3(s, OP_SEND, cursp(), sym, argc); mrb_gc_arena_restore(s->mrb, ai); push(); } @@ -2603,7 +2595,7 @@ codegen(codegen_scope *s, node *tree, int val) if (val) { int sym = new_sym(s, nsym(tree)); - genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym)); + genop_2(s, OP_LOADSYM, cursp(), sym); push(); } break; @@ -2611,55 +2603,46 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_DSYM: codegen(s, tree, val); if (val) { - gen_send_intern(s); + gen_intern(s); } break; case NODE_SELF: if (val) { - genop(s, MKOP_A(OP_LOADSELF, cursp())); + genop_1(s, OP_LOADSELF, cursp()); push(); } break; case NODE_NIL: if (val) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop_1(s, OP_LOADNIL, cursp()); push(); } break; case NODE_TRUE: if (val) { - genop(s, MKOP_A(OP_LOADT, cursp())); + genop_1(s, OP_LOADT, cursp()); push(); } break; case NODE_FALSE: if (val) { - genop(s, MKOP_A(OP_LOADF, cursp())); + genop_1(s, OP_LOADF, cursp()); push(); } break; case NODE_ALIAS: { - int a = new_msym(s, nsym(tree->car)); - int b = new_msym(s, nsym(tree->cdr)); - int c = new_msym(s, mrb_intern_lit(s->mrb, "alias_method")); + int a = new_sym(s, nsym(tree->car)); + int b = new_sym(s, nsym(tree->cdr)); - genop(s, MKOP_A(OP_TCLASS, cursp())); - push(); - genop(s, MKOP_ABx(OP_LOADSYM, cursp(), a)); - push(); - genop(s, MKOP_ABx(OP_LOADSYM, cursp(), b)); - push(); - genop(s, MKOP_A(OP_LOADNIL, cursp())); - push(); /* space for a block */ - pop_n(4); - genop(s, MKOP_ABC(OP_SEND, cursp(), c, 2)); + genop_2(s, OP_ALIAS, a, b); if (val) { + genop_1(s, OP_LOADNIL, cursp()); push(); } } @@ -2667,41 +2650,15 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_UNDEF: { - int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method")); - int num = 0; node *t = tree; - genop(s, MKOP_A(OP_TCLASS, cursp())); - push(); while (t) { - int symbol; - if (num >= CALL_MAXARGS - 1) { - pop_n(num); - genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), num)); - while (t) { - symbol = new_msym(s, nsym(t->car)); - push(); - genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol)); - pop(); - genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1)); - t = t->cdr; - } - num = CALL_MAXARGS; - break; - } - symbol = new_msym(s, nsym(t->car)); - genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol)); - push(); + int symbol = new_sym(s, nsym(t->car)); + genop_1(s, OP_UNDEF, symbol); t = t->cdr; - num++; - } - push();pop(); /* space for a block */ - pop(); - if (num < CALL_MAXARGS) { - pop_n(num); } - genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num)); if (val) { + genop_1(s, OP_LOADNIL, cursp()); push(); } } @@ -2710,13 +2667,14 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_CLASS: { int idx; + node *body; if (tree->car->car == (node*)0) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop_1(s, OP_LOADNIL, cursp()); push(); } else if (tree->car->car == (node*)1) { - genop(s, MKOP_A(OP_OCLASS, cursp())); + genop_1(s, OP_OCLASS, cursp()); push(); } else { @@ -2726,14 +2684,17 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree->cdr->car, VAL); } else { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop_1(s, OP_LOADNIL, cursp()); push(); } pop(); pop(); - idx = new_msym(s, nsym(tree->car->cdr)); - genop(s, MKOP_AB(OP_CLASS, cursp(), idx)); - idx = scope_body(s, tree->cdr->cdr->car, val); - genop(s, MKOP_ABx(OP_EXEC, cursp(), idx)); + idx = new_sym(s, nsym(tree->car->cdr)); + genop_2(s, OP_CLASS, cursp(), idx); + body = tree->cdr->cdr->car; + if (!(nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL)) { + idx = scope_body(s, body, val); + genop_2(s, OP_EXEC, cursp(), idx); + } if (val) { push(); } @@ -2745,21 +2706,24 @@ codegen(codegen_scope *s, node *tree, int val) int idx; if (tree->car->car == (node*)0) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop_1(s, OP_LOADNIL, cursp()); push(); } else if (tree->car->car == (node*)1) { - genop(s, MKOP_A(OP_OCLASS, cursp())); + genop_1(s, OP_OCLASS, cursp()); push(); } else { codegen(s, tree->car->car, VAL); } pop(); - idx = new_msym(s, nsym(tree->car->cdr)); - genop(s, MKOP_AB(OP_MODULE, cursp(), idx)); - idx = scope_body(s, tree->cdr->car, val); - genop(s, MKOP_ABx(OP_EXEC, cursp(), idx)); + idx = new_sym(s, nsym(tree->car->cdr)); + genop_2(s, OP_MODULE, cursp(), idx); + if (!(nint(tree->cdr->car->cdr->car) == NODE_BEGIN && + tree->cdr->car->cdr->cdr == NULL)) { + idx = scope_body(s, tree->cdr->car, val); + genop_2(s, OP_EXEC, cursp(), idx); + } if (val) { push(); } @@ -2772,9 +2736,12 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree->car, VAL); pop(); - genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp())); - idx = scope_body(s, tree->cdr->car, val); - genop(s, MKOP_ABx(OP_EXEC, cursp(), idx)); + genop_1(s, OP_SCLASS, cursp()); + if (!(nint(tree->cdr->car->cdr->car) == NODE_BEGIN && + tree->cdr->car->cdr->cdr == NULL)) { + idx = scope_body(s, tree->cdr->car, val); + genop_2(s, OP_EXEC, cursp(), idx); + } if (val) { push(); } @@ -2783,17 +2750,17 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_DEF: { - int sym = new_msym(s, nsym(tree->car)); + int sym = new_sym(s, nsym(tree->car)); int idx = lambda_body(s, tree->cdr, 0); - genop(s, MKOP_A(OP_TCLASS, cursp())); + genop_1(s, OP_TCLASS, cursp()); push(); - genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD)); + genop_2(s, OP_METHOD, cursp(), idx); push(); pop(); pop(); - genop(s, MKOP_AB(OP_METHOD, cursp(), sym)); + genop_2(s, OP_DEF, cursp(), sym); if (val) { - genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym)); + genop_2(s, OP_LOADSYM, cursp(), sym); push(); } } @@ -2802,18 +2769,18 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_SDEF: { node *recv = tree->car; - int sym = new_msym(s, nsym(tree->cdr->car)); + int sym = new_sym(s, nsym(tree->cdr->car)); int idx = lambda_body(s, tree->cdr->cdr, 0); codegen(s, recv, VAL); pop(); - genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp())); + genop_1(s, OP_SCLASS, cursp()); push(); - genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD)); + genop_2(s, OP_METHOD, cursp(), idx); pop(); - genop(s, MKOP_AB(OP_METHOD, cursp(), sym)); + genop_2(s, OP_DEF, cursp(), sym); if (val) { - genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym)); + genop_2(s, OP_LOADSYM, cursp(), sym); push(); } } @@ -2875,7 +2842,7 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa); p->irep->plen = 0; - p->scapa = MAXMSYMLEN; + p->scapa = 256; p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa); p->irep->slen = 0; @@ -2971,7 +2938,7 @@ loop_push(codegen_scope *s, enum looptype t) struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo)); p->type = t; - p->pc1 = p->pc2 = p->pc3 = 0; + p->pc0 = p->pc1 = p->pc2 = p->pc3 = 0; p->prev = s->loop; p->ensure_level = s->ensure_level; p->acc = cursp(); @@ -3013,27 +2980,26 @@ loop_break(codegen_scope *s, node *tree) return; } if (n > 0) { - genop_peep(s, MKOP_A(OP_POPERR, n), NOVAL); + genop_1(s, OP_POPERR, n); } if (loop->type == LOOP_NORMAL) { int tmp; if (s->ensure_level > s->loop->ensure_level) { - genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL); + genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level); } if (tree) { - genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL); + gen_move(s, loop->acc, cursp(), 0); } - distcheck(s, s->loop->pc3); - tmp = genop(s, MKOP_sBx(OP_JMP, loop->pc3)); + tmp = genjmp(s, OP_JMP, loop->pc3); loop->pc3 = tmp; } else { if (!tree) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop_1(s, OP_LOADNIL, cursp()); } - genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_BREAK)); + genop_1(s, OP_BREAK, cursp()); } } } @@ -3042,7 +3008,7 @@ static void loop_pop(codegen_scope *s, int val) { if (val) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop_1(s, OP_LOADNIL, cursp()); } dispatch_linked(s, s->loop->pc3); s->loop = s->loop->prev; @@ -3107,3 +3073,56 @@ mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep) mrb_irep_remove_lv(mrb, irep->reps[i]); } } + +#undef OPCODE +#define Z 1 +#define S 3 +#define W 4 +/* instruction sizes */ +uint8_t mrb_insn_size[] = { +#define B 2 +#define BB 3 +#define BBB 4 +#define BS 4 +#define SB 4 +#define OPCODE(_,x) x, +#include "mruby/ops.h" +#undef OPCODE +#undef B +#undef BB +#undef BS +#undef SB +#undef BBB +}; +/* EXT1 instruction sizes */ +uint8_t mrb_insn_size1[] = { +#define B 3 +#define BB 4 +#define BBB 5 +#define BS 5 +#define SB 5 +#define OPCODE(_,x) x, +#include "mruby/ops.h" +#undef OPCODE +#undef B +}; +/* EXT2 instruction sizes */ +uint8_t mrb_insn_size2[] = { +#define B 2 +#define OPCODE(_,x) x, +#include "mruby/ops.h" +#undef OPCODE +#undef BB +#undef BBB +#undef BS +#undef SB +}; +/* EXT3 instruction sizes */ +#define BB 5 +#define BBB 6 +#define BS 4 +#define SB 5 +uint8_t mrb_insn_size3[] = { +#define OPCODE(_,x) x, +#include "mruby/ops.h" +}; diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 7f848b4df..61d94edc9 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -5534,6 +5534,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; } @@ -6648,6 +6649,20 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset) dump_recur(mrb, ((parser_heredoc_info*)tree)->doc, offset+1); break; + case NODE_LITERAL_DELIM: + printf("NODE_LITERAL_DELIM\n"); + break; + + case NODE_SYMBOLS: + printf("NODE_SYMBOLS:\n"); + dump_recur(mrb, tree, offset+1); + break; + + case NODE_WORDS: + printf("NODE_SYMBOLS:\n"); + dump_recur(mrb, tree, offset+1); + break; + default: printf("node type: %d (0x%x)\n", nodetype, (unsigned)nodetype); break; diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c index 5c8e78acd..42a4183b7 100644 --- a/mrbgems/mruby-eval/src/eval.c +++ b/mrbgems/mruby-eval/src/eval.c @@ -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] = 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)) { + mrb_code 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)) { + mrb_code 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); diff --git a/mrbgems/mruby-method/src/method.c b/mrbgems/mruby-method/src/method.c index e445b34c8..600567cac 100644 --- a/mrbgems/mruby-method/src/method.c +++ b/mrbgems/mruby-method/src/method.c @@ -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()); diff --git a/mrbgems/mruby-proc-ext/src/proc.c b/mrbgems/mruby-proc-ext/src/proc.c index b13606f5f..323529dcc 100644 --- a/mrbgems/mruby-proc-ext/src/proc.c +++ b/mrbgems/mruby-proc-ext/src/proc.c @@ -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,13 +139,16 @@ 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) { + if (i < max && irep->lv[i].name) { mrb_ary_push(mrb, a, mrb_symbol_value(irep->lv[i].name)); } mrb_ary_push(mrb, parameters, a); diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index 4cab49094..142d449f4 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -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)); diff --git a/src/class.c b/src/class.c index a9439d7d7..076280f3f 100644 --- a/src/class.c +++ b/src/class.c @@ -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(); diff --git a/src/codedump.c b/src/codedump.c index d79a65a70..22cbc59eb 100644 --- a/src/codedump.c +++ b/src/codedump.c @@ -6,451 +6,503 @@ #include #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+1nlocals; 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, int i) +{ + int32_t line; + + line = mrb_debug_get_line(irep, i); + if (line < 0) { + printf(" "); + } + else { + printf("%5d ", line); + } + + printf("%03d ", 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++) { + pc = irep->iseq; + pcend = pc + irep->ilen; + while (pc < pcend) { + int 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); - break; - case OP_LOADI: - printf("OP_LOADI\tR%d\t%d\t", GETARG_A(c), GETARG_sBx(c)); - print_lv(mrb, irep, c, RA); - 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); - break; - case OP_LOADNIL: - printf("OP_LOADNIL\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_LOADSELF: - printf("OP_LOADSELF\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_LOADT: - printf("OP_LOADT\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_LOADF: - printf("OP_LOADF\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - 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); - 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); - 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); - 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); - 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); - 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); - 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); - 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); - 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); - 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); - 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); - 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); - break; - case OP_JMP: - printf("OP_JMP\t%03d (%d)\n", i+GETARG_sBx(c), GETARG_sBx(c)); - break; - case OP_JMPIF: - printf("OP_JMPIF\tR%d\t%03d (%d)\n", GETARG_A(c), i+GETARG_sBx(c), GETARG_sBx(c)); - break; - case OP_JMPNOT: - printf("OP_JMPNOT\tR%d\t%03d (%d)\n", GETARG_A(c), i+GETARG_sBx(c), GETARG_sBx(c)); - 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)); - 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)); - break; - case OP_CALL: - printf("OP_CALL\tR%d\n", GETARG_A(c)); - break; - case OP_TAILCALL: - printf("OP_TAILCALL\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_SUPER: - printf("OP_SUPER\tR%d\t%d\n", GETARG_A(c), - GETARG_C(c)); - 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); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LOADI, BB): + printf("OP_LOADI\tR%d\t%d\t", a, b); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LOADINEG, BB): + printf("OP_LOADI\tR%d\t-%d\t", a, b); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LOADI__1, B): + printf("OP_LOADI__1\tR%d\t\t", a); + print_lv_a(mrb, irep, a); + break; + 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_ENTER: + 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_LOADNIL, B): + printf("OP_LOADNIL\tR%d\t\t", a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LOADSELF, B): + printf("OP_LOADSELF\tR%d\t\t", a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LOADT, B): + printf("OP_LOADT\tR%d\t\t", a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LOADF, B): + printf("OP_LOADF\tR%d\t\t", a); + print_lv_a(mrb, irep, a); + break; + 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_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_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_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_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_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_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_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_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_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_GETUPVAR, BBB): + printf("OP_GETUPVAR\tR%d\t%d\t%d", a, b, c); + print_lv_a(mrb, irep, a); + break; + 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_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_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_JMP, S): + printf("OP_JMP\t\t%03d\n", a); + break; + CASE(OP_JMPIF, BS): + printf("OP_JMPIF\tR%d\t%03d\t", a, b); + print_lv_a(mrb, irep, a); + break; + CASE(OP_JMPNOT, BS): + printf("OP_JMPNOT\tR%d\t%03d\t", a, b); + print_lv_a(mrb, irep, a); + break; + CASE(OP_JMPNIL, BS): + printf("OP_JMPNIL\tR%d\t%03d\t", a, b); + print_lv_a(mrb, irep, a); + break; + 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", a, + (b>>10)&0x3f, + (b>>9)&0x1, + (b>>4)&0x1f, + (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); - 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); + (a>>18)&0x1f, + (a>>13)&0x1f, + (a>>12)&0x1, + (a>>7)&0x1f, + (a>>2)&0x1f, + (a>>1)&0x1, + a & 0x1); 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_KARG, BB): + printf("OP_KARG\tR(%d)\tK(%d)\n", a, b); 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_KARG2, BB): + printf("OP_KARG2\tR(%d)\tK(%d)\n", a, b); 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_KDICT, B): + printf("OP_KDICt\tR(%d)\n", 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, B): + printf("OP_RETURN\tR%d", 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)); - 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)); - 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)); - 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)); - break; - case OP_MUL: - printf("OP_MUL\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_DIV: - printf("OP_DIV\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_LT: - printf("OP_LT\t\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_LE: - printf("OP_LE\t\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_GT: - printf("OP_GT\t\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_GE: - printf("OP_GE\t\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_EQ: - printf("OP_EQ\t\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); + CASE(OP_RETURN_BLK, B): + printf("OP_RETURN_BLK\tR%d", a); + print_lv_a(mrb, irep, a); break; - - case OP_STOP: - printf("OP_STOP\n"); + CASE(OP_BREAK, B): + printf("OP_BREAK\tR%d", a); + print_lv_a(mrb, irep, a); 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_BLKPUSH, BS): + printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d", a, + (b>>10)&0x3f, + (b>>9)&0x1, + (b>>4)&0x1f, + (b>>0)&0xf); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LAMBDA, BB): + printf("OP_LAMBDA\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]); + break; + CASE(OP_BLOCK, BB): + printf("OP_BLOCK\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]); + break; + CASE(OP_METHOD, BB): + printf("OP_METHOD\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]); + break; + CASE(OP_RANGE_INC, B): + printf("OP_RANGE_INC\tR%d\n", a); + break; + CASE(OP_RANGE_EXC, B): + printf("OP_RANGE_EXC\tR%d\n", a); + break; + CASE(OP_DEF, BB): + printf("OP_DEF\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + CASE(OP_UNDEF, B): + printf("OP_UNDEF\t:%s\n", mrb_sym2name(mrb, irep->syms[a])); + break; + 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_ADD, BB): + printf("OP_ADD\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + 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_SUB, BB): + printf("OP_SUB\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + 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_MUL, BB): + printf("OP_MUL\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + CASE(OP_DIV, BB): + printf("OP_DIV\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + CASE(OP_LT, BB): + printf("OP_LT\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + 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_ARYCAT: - printf("OP_ARYCAT\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c)); - print_lv(mrb, irep, c, RAB); + CASE(OP_ARRAY, BB): + printf("OP_ARRAY\tR%d\t%d\t", a, b); + print_lv_a(mrb, irep, a); 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_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_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_ARYCAT, B): + printf("OP_ARYCAT\tR%d\t", a); + print_lv_a(mrb, irep, a); 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_ARYPUSH, B): + printf("OP_ARYPUSH\tR%d\t", a); + print_lv_a(mrb, irep, a); break; - case OP_STRING: + 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, B): + printf("OP_STRCAT\tR%d\t", a); + 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_HASH, BB): + printf("OP_HASH\tR%d\t%d\t", a, b); + 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_HASHADD, BB): + printf("OP_HASHADD\tR%d\t%d", a, b); + 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_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_EXCEPT, B): + printf("OP_EXCEPT\tR%d\t\t", a); + print_lv_a(mrb, irep, a); break; - case OP_RAISE: - printf("OP_RAISE\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); + CASE(OP_RESCUE, BB): + printf("OP_RESCUE\tR%d\tR%d", a, b); + print_lv_ab(mrb, irep, a, b); break; - case OP_POPERR: - printf("OP_POPERR\t%d\t\t\n", GETARG_A(c)); + CASE(OP_RAISE, B): + printf("OP_RAISE\tR%d\t\t", a); + print_lv_a(mrb, irep, a); break; - case OP_EPOP: - printf("OP_EPOP\t%d\n", GETARG_A(c)); + 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_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_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_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; + 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); diff --git a/src/kernel.c b/src/kernel.c index bbe6e8bb7..155868eaa 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1266,5 +1266,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 */ } diff --git a/src/load.c b/src/load.c index ddf3cdfbf..20878aa56 100644 --- a/src/load.c +++ b/src/load.c @@ -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 { diff --git a/src/proc.c b/src/proc.c index c6e9be433..05b897480 100644 --- a/src/proc.c +++ b/src/proc.c @@ -10,7 +10,7 @@ #include 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); diff --git a/src/vm.c b/src/vm.c index 7a436828a..b50f1ee9f 100644 --- a/src/vm.c +++ b/src/vm.c @@ -333,7 +333,7 @@ ecall(mrb_state *mrb) struct REnv *env; ptrdiff_t cioff; int ai = mrb_gc_arena_save(mrb); - int i = --c->eidx; + uint8_t i = --c->eidx; int nregs; if (i<0) return; @@ -911,18 +911,18 @@ argnum_error(mrb_state *mrb, mrb_int num) #ifndef DIRECT_THREADED -#define INIT_DISPATCH for (;;) { i = BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (GET_OPCODE(i)) { -#define CASE(op) case op: -#define NEXT pc++; break -#define JUMP break +#define INIT_DISPATCH for (;;) { insn = BYTECODE_DECODER(*pc); pc++; CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (insn) { +#define CASE(insn,ops) case insn: pc++; FETCH_ ## ops ();; L_ ## insn ## _BODY: +#define NEXT break +#define JUMP NEXT #define END_DISPATCH }} #else #define INIT_DISPATCH JUMP; return mrb_nil_value(); -#define CASE(op) L_ ## op: -#define NEXT i=BYTECODE_DECODER(*++pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)] -#define JUMP i=BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)] +#define CASE(insn,ops) L_ ## insn: pc++; FETCH_ ## ops (); L_ ## insn ## _BODY: +#define NEXT insn=BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[insn] +#define JUMP NEXT #define END_DISPATCH @@ -958,6 +958,17 @@ mrb_vm_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stac return result; } +static mrb_bool +check_target_class(mrb_state *mrb) +{ + if (!mrb->c->ci->target_class) { + mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, "no target class or module"); + mrb_exc_set(mrb, exc); + return FALSE; + } + return TRUE; +} + MRB_API mrb_value mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc) { @@ -965,33 +976,19 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc) mrb_irep *irep = proc->body.irep; mrb_value *pool = irep->pool; mrb_sym *syms = irep->syms; - mrb_code i; + mrb_code insn; int ai = mrb_gc_arena_save(mrb); struct mrb_jmpbuf *prev_jmp = mrb->jmp; struct mrb_jmpbuf c_jmp; + uint32_t a; + uint16_t b; + uint8_t c; #ifdef DIRECT_THREADED static void *optable[] = { - &&L_OP_NOP, &&L_OP_MOVE, - &&L_OP_LOADL, &&L_OP_LOADI, &&L_OP_LOADSYM, &&L_OP_LOADNIL, - &&L_OP_LOADSELF, &&L_OP_LOADT, &&L_OP_LOADF, - &&L_OP_GETGLOBAL, &&L_OP_SETGLOBAL, &&L_OP_GETSPECIAL, &&L_OP_SETSPECIAL, - &&L_OP_GETIV, &&L_OP_SETIV, &&L_OP_GETCV, &&L_OP_SETCV, - &&L_OP_GETCONST, &&L_OP_SETCONST, &&L_OP_GETMCNST, &&L_OP_SETMCNST, - &&L_OP_GETUPVAR, &&L_OP_SETUPVAR, - &&L_OP_JMP, &&L_OP_JMPIF, &&L_OP_JMPNOT, - &&L_OP_ONERR, &&L_OP_RESCUE, &&L_OP_POPERR, &&L_OP_RAISE, &&L_OP_EPUSH, &&L_OP_EPOP, - &&L_OP_SEND, &&L_OP_SENDB, &&L_OP_FSEND, - &&L_OP_CALL, &&L_OP_SUPER, &&L_OP_ARGARY, &&L_OP_ENTER, - &&L_OP_KARG, &&L_OP_KDICT, &&L_OP_RETURN, &&L_OP_TAILCALL, &&L_OP_BLKPUSH, - &&L_OP_ADD, &&L_OP_ADDI, &&L_OP_SUB, &&L_OP_SUBI, &&L_OP_MUL, &&L_OP_DIV, - &&L_OP_EQ, &&L_OP_LT, &&L_OP_LE, &&L_OP_GT, &&L_OP_GE, - &&L_OP_ARRAY, &&L_OP_ARYCAT, &&L_OP_ARYPUSH, &&L_OP_AREF, &&L_OP_ASET, &&L_OP_APOST, - &&L_OP_STRING, &&L_OP_STRCAT, &&L_OP_HASH, - &&L_OP_LAMBDA, &&L_OP_RANGE, &&L_OP_OCLASS, - &&L_OP_CLASS, &&L_OP_MODULE, &&L_OP_EXEC, - &&L_OP_METHOD, &&L_OP_SCLASS, &&L_OP_TCLASS, - &&L_OP_DEBUG, &&L_OP_STOP, &&L_OP_ERR, +#define OPCODE(x,_) &&L_OP_ ## x, +#include "mruby/ops.h" +#undef OPCODE }; #endif @@ -1013,25 +1010,19 @@ RETRY_TRY_BLOCK: #define regs (mrb->c->stack) INIT_DISPATCH { - CASE(OP_NOP) { + CASE(OP_NOP, Z) { /* do nothing */ NEXT; } - CASE(OP_MOVE) { - /* A B R(A) := R(B) */ - int a = GETARG_A(i); - int b = GETARG_B(i); + CASE(OP_MOVE, BB) { regs[a] = regs[b]; NEXT; } - CASE(OP_LOADL) { - /* A Bx R(A) := Pool(Bx) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); + CASE(OP_LOADL, BB) { #ifdef MRB_WORD_BOXING - mrb_value val = pool[bx]; + mrb_value val = pool[b]; #ifndef MRB_WITHOUT_FLOAT if (mrb_float_p(val)) { val = mrb_float_value(mrb, mrb_float(val)); @@ -1039,125 +1030,110 @@ RETRY_TRY_BLOCK: #endif regs[a] = val; #else - regs[a] = pool[bx]; + regs[a] = pool[b]; #endif NEXT; } - CASE(OP_LOADI) { - /* A sBx R(A) := sBx */ - int a = GETARG_A(i); - mrb_int bx = GETARG_sBx(i); - SET_INT_VALUE(regs[a], bx); + CASE(OP_LOADI, BB) { + SET_INT_VALUE(regs[a], b); + NEXT; + } + + CASE(OP_LOADINEG, BB) { + SET_INT_VALUE(regs[a], -b); + NEXT; + } + + CASE(OP_LOADI__1,B) goto L_LOADI; + 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: + SET_INT_VALUE(regs[a], (mrb_int)insn - (mrb_int)OP_LOADI_0); + NEXT; + } + + CASE(OP_LOADSYM, BB) { + SET_SYM_VALUE(regs[a], syms[b]); NEXT; } - CASE(OP_LOADSYM) { - /* A Bx R(A) := Syms(Bx) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - SET_SYM_VALUE(regs[a], syms[bx]); + CASE(OP_LOADNIL, B) { + SET_NIL_VALUE(regs[a]); NEXT; } - CASE(OP_LOADSELF) { - /* A R(A) := self */ - int a = GETARG_A(i); + CASE(OP_LOADSELF, B) { regs[a] = regs[0]; NEXT; } - CASE(OP_LOADT) { - /* A R(A) := true */ - int a = GETARG_A(i); + CASE(OP_LOADT, B) { SET_TRUE_VALUE(regs[a]); NEXT; } - CASE(OP_LOADF) { - /* A R(A) := false */ - int a = GETARG_A(i); + CASE(OP_LOADF, B) { SET_FALSE_VALUE(regs[a]); NEXT; } - CASE(OP_GETGLOBAL) { - /* A Bx R(A) := getglobal(Syms(Bx)) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_value val = mrb_gv_get(mrb, syms[bx]); + CASE(OP_GETGV, BB) { + mrb_value val = mrb_gv_get(mrb, syms[b]); regs[a] = val; NEXT; } - CASE(OP_SETGLOBAL) { - /* A Bx setglobal(Syms(Bx), R(A)) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_gv_set(mrb, syms[bx], regs[a]); + CASE(OP_SETGV, BB) { + mrb_gv_set(mrb, syms[b], regs[a]); NEXT; } - CASE(OP_GETSPECIAL) { - /* A Bx R(A) := Special[Bx] */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_value val = mrb_vm_special_get(mrb, bx); + CASE(OP_GETSV, BB) { + mrb_value val = mrb_vm_special_get(mrb, b); regs[a] = val; NEXT; } - CASE(OP_SETSPECIAL) { - /* A Bx Special[Bx] := R(A) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_vm_special_set(mrb, bx, regs[a]); + CASE(OP_SETSV, BB) { + mrb_vm_special_set(mrb, b, regs[a]); NEXT; } - CASE(OP_GETIV) { - /* A Bx R(A) := ivget(Bx) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_value val = mrb_vm_iv_get(mrb, syms[bx]); + CASE(OP_GETIV, BB) { + mrb_value val = mrb_vm_iv_get(mrb, syms[b]); regs[a] = val; NEXT; } - CASE(OP_SETIV) { - /* A Bx ivset(Syms(Bx),R(A)) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_vm_iv_set(mrb, syms[bx], regs[a]); + CASE(OP_SETIV, BB) { + mrb_vm_iv_set(mrb, syms[b], regs[a]); NEXT; } - CASE(OP_GETCV) { - /* A Bx R(A) := cvget(Syms(Bx)) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); + CASE(OP_GETCV, BB) { mrb_value val; ERR_PC_SET(mrb, pc); - val = mrb_vm_cv_get(mrb, syms[bx]); + val = mrb_vm_cv_get(mrb, syms[b]); ERR_PC_CLR(mrb); regs[a] = val; NEXT; } - CASE(OP_SETCV) { - /* A Bx cvset(Syms(Bx),R(A)) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_vm_cv_set(mrb, syms[bx], regs[a]); + CASE(OP_SETCV, BB) { + mrb_vm_cv_set(mrb, syms[b], regs[a]); NEXT; } - CASE(OP_GETCONST) { - /* A Bx R(A) := constget(Syms(Bx)) */ + CASE(OP_GETCONST, BB) { mrb_value val; - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_sym sym = syms[bx]; + mrb_sym sym = syms[b]; ERR_PC_SET(mrb, pc); val = mrb_vm_const_get(mrb, sym); @@ -1166,40 +1142,27 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_SETCONST) { - /* A Bx constset(Syms(Bx),R(A)) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_vm_const_set(mrb, syms[bx], regs[a]); + CASE(OP_SETCONST, BB) { + mrb_vm_const_set(mrb, syms[b], regs[a]); NEXT; } - CASE(OP_GETMCNST) { - /* A Bx R(A) := R(A)::Syms(Bx) */ + CASE(OP_GETMCNST, BB) { mrb_value val; - int a = GETARG_A(i); - int bx = GETARG_Bx(i); ERR_PC_SET(mrb, pc); - val = mrb_const_get(mrb, regs[a], syms[bx]); + val = mrb_const_get(mrb, regs[a], syms[b]); ERR_PC_CLR(mrb); regs[a] = val; NEXT; } - CASE(OP_SETMCNST) { - /* A Bx R(A+1)::Syms(Bx) := R(A) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_const_set(mrb, regs[a+1], syms[bx], regs[a]); + CASE(OP_SETMCNST, BB) { + mrb_const_set(mrb, regs[a+1], syms[b], regs[a]); NEXT; } - CASE(OP_GETUPVAR) { - /* A B C R(A) := uvget(B,C) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int c = GETARG_C(i); + CASE(OP_GETUPVAR, BBB) { mrb_value *regs_a = regs + a; struct REnv *e = uvenv(mrb, c); @@ -1212,12 +1175,7 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_SETUPVAR) { - /* A B C uvset(B,C,R(A)) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int c = GETARG_C(i); - + CASE(OP_SETUPVAR, BBB) { struct REnv *e = uvenv(mrb, c); if (e) { @@ -1231,110 +1189,86 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_JMP) { - /* sBx pc+=sBx */ - int sbx = GETARG_sBx(i); - pc += sbx; + CASE(OP_JMP, S) { + pc = irep->iseq+a; JUMP; } - - CASE(OP_JMPIF) { - /* A sBx if R(A) pc+=sBx */ - int a = GETARG_A(i); - int sbx = GETARG_sBx(i); + CASE(OP_JMPIF, BS) { if (mrb_test(regs[a])) { - pc += sbx; + pc = irep->iseq+b; JUMP; } NEXT; } - - CASE(OP_JMPNOT) { - /* A sBx if !R(A) pc+=sBx */ - int a = GETARG_A(i); - int sbx = GETARG_sBx(i); + CASE(OP_JMPNOT, BS) { if (!mrb_test(regs[a])) { - pc += sbx; + pc = irep->iseq+b; + JUMP; + } + NEXT; + } + CASE(OP_JMPNIL, BS) { + if (mrb_nil_p(regs[a])) { + pc = irep->iseq+b; JUMP; } NEXT; } - CASE(OP_ONERR) { - /* sBx pc+=sBx on exception */ - int sbx = GETARG_sBx(i); + CASE(OP_ONERR, S) { if (mrb->c->rsize <= mrb->c->ci->ridx) { if (mrb->c->rsize == 0) mrb->c->rsize = RESCUE_STACK_INIT_SIZE; else mrb->c->rsize *= 2; - mrb->c->rescue = (mrb_code **)mrb_realloc(mrb, mrb->c->rescue, sizeof(mrb_code*) * mrb->c->rsize); + mrb->c->rescue = (uint16_t*)mrb_realloc(mrb, mrb->c->rescue, sizeof(uint16_t) * mrb->c->rsize); } - mrb->c->rescue[mrb->c->ci->ridx++] = pc + sbx; + mrb->c->rescue[mrb->c->ci->ridx++] = a; NEXT; } - CASE(OP_RESCUE) { - /* A B R(A) := exc; clear(exc); R(B) := matched (bool) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int c = GETARG_C(i); - mrb_value exc; - - if (c == 0) { - exc = mrb_obj_value(mrb->exc); - mrb->exc = 0; - } - else { /* continued; exc taken from R(A) */ - exc = regs[a]; - } - if (b != 0) { - mrb_value e = regs[b]; - struct RClass *ec; + CASE(OP_EXCEPT, B) { + mrb_value exc = mrb_obj_value(mrb->exc); + mrb->exc = 0; + regs[a] = exc; + NEXT; + } + CASE(OP_RESCUE, BB) { + mrb_value exc = regs[a]; /* exc on stack */ + mrb_value e = regs[b]; + struct RClass *ec; - switch (mrb_type(e)) { - case MRB_TT_CLASS: - case MRB_TT_MODULE: - break; - default: - { - mrb_value exc; + switch (mrb_type(e)) { + case MRB_TT_CLASS: + case MRB_TT_MODULE: + break; + default: + { + mrb_value exc; - exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, - "class or module required for rescue clause"); - mrb_exc_set(mrb, exc); - goto L_RAISE; - } + exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, + "class or module required for rescue clause"); + mrb_exc_set(mrb, exc); + goto L_RAISE; } - ec = mrb_class_ptr(e); - regs[b] = mrb_bool_value(mrb_obj_is_kind_of(mrb, exc, ec)); - } - if (a != 0 && c == 0) { - regs[a] = exc; } + ec = mrb_class_ptr(e); + regs[b] = mrb_bool_value(mrb_obj_is_kind_of(mrb, exc, ec)); NEXT; } - CASE(OP_POPERR) { - /* A A.times{rescue_pop()} */ - int a = GETARG_A(i); - + CASE(OP_POPERR, B) { mrb->c->ci->ridx -= a; NEXT; } - CASE(OP_RAISE) { - /* A raise(R(A)) */ - int a = GETARG_A(i); - + CASE(OP_RAISE, B) { mrb_exc_set(mrb, regs[a]); goto L_RAISE; } - CASE(OP_EPUSH) { - /* Bx ensure_push(SEQ[Bx]) */ - int bx = GETARG_Bx(i); + CASE(OP_EPUSH, B) { struct RProc *p; - p = mrb_closure_new(mrb, irep->reps[bx]); + p = mrb_closure_new(mrb, irep->reps[a]); /* push ensure_stack */ if (mrb->c->esize <= mrb->c->eidx+1) { if (mrb->c->esize == 0) mrb->c->esize = ENSURE_STACK_INIT_SIZE; @@ -1347,11 +1281,9 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_EPOP) { - /* A A.times{ensure_pop().call} */ - int a = GETARG_A(i); + CASE(OP_EPOP, B) { mrb_callinfo *ci = mrb->c->ci; - int n, epos = ci->epos; + unsigned int n, epos = ci->epos; mrb_value self = regs[0]; struct RClass *target_class = ci->target_class; @@ -1359,9 +1291,8 @@ RETRY_TRY_BLOCK: NEXT; } - if (a > mrb->c->eidx - epos) + if (a > (int)mrb->c->eidx - epos) a = mrb->c->eidx - epos; - pc = pc + 1; for (n=0; nc->ensure[epos+n]; mrb->c->ensure[epos+n] = NULL; @@ -1387,29 +1318,32 @@ RETRY_TRY_BLOCK: JUMP; } - CASE(OP_LOADNIL) { - /* A R(A) := nil */ - int a = GETARG_A(i); + CASE(OP_SENDV, BB) { + c = CALL_MAXARGS; + goto L_SEND; + }; - SET_NIL_VALUE(regs[a]); - NEXT; - } + CASE(OP_SENDVB, BB) { + c = CALL_MAXARGS; + goto L_SENDB; + }; - CASE(OP_SENDB) { - /* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C),&R(A+C+1))*/ - /* fall through */ + CASE(OP_SEND, BBB) + L_SEND: + { + /* push nil after arguments */ + int bidx = (c == CALL_MAXARGS) ? a+2 : a+c+1; + SET_NIL_VALUE(regs[bidx]); + goto L_SENDB; }; - L_SEND: - CASE(OP_SEND) { - /* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C)) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int n = GETARG_C(i); - int argc = (n == CALL_MAXARGS) ? -1 : n; - int bidx = (argc < 0) ? a+2 : a+n+1; + CASE(OP_SENDB, BBB) + L_SENDB: + { + int argc = (c == CALL_MAXARGS) ? -1 : c; + int bidx = (argc < 0) ? a+2 : a+c+1; mrb_method_t m; - struct RClass *c; + struct RClass *cls; mrb_callinfo *ci = mrb->c->ci; mrb_value recv, blk; mrb_sym mid = syms[b]; @@ -1417,26 +1351,20 @@ RETRY_TRY_BLOCK: mrb_assert(bidx < ci->nregs); recv = regs[a]; - if (GET_OPCODE(i) != OP_SENDB) { - SET_NIL_VALUE(regs[bidx]); - blk = regs[bidx]; - } - else { - blk = regs[bidx]; - if (!mrb_nil_p(blk) && mrb_type(blk) != MRB_TT_PROC) { - blk = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc"); - /* The stack might have been reallocated during mrb_convert_type(), - see #3622 */ - regs[bidx] = blk; - } + blk = regs[bidx]; + if (!mrb_nil_p(blk) && mrb_type(blk) != MRB_TT_PROC) { + blk = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc"); + /* The stack might have been reallocated during mrb_convert_type(), + see #3622 */ + regs[bidx] = blk; } - c = mrb_class(mrb, recv); - m = mrb_method_search_vm(mrb, &c, mid); + cls = mrb_class(mrb, recv); + m = mrb_method_search_vm(mrb, &cls, mid); if (MRB_METHOD_UNDEF_P(m)) { mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); - m = mrb_method_search_vm(mrb, &c, missing); + m = mrb_method_search_vm(mrb, &cls, missing); if (MRB_METHOD_UNDEF_P(m) || (missing == mrb->c->ci->mid && mrb_obj_eq(mrb, regs[0], recv))) { - mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, n, regs+a+1); + mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, c, regs+a+1); ERR_PC_SET(mrb, pc); mrb_method_missing(mrb, mid, recv, args); } @@ -1444,7 +1372,7 @@ RETRY_TRY_BLOCK: if (a+2 >= irep->nregs) { mrb_stack_extend(mrb, a+3); } - regs[a+1] = mrb_ary_new_from_values(mrb, n, regs+a+1); + regs[a+1] = mrb_ary_new_from_values(mrb, c, regs+a+1); regs[a+2] = blk; argc = -1; } @@ -1456,17 +1384,17 @@ RETRY_TRY_BLOCK: ci = cipush(mrb); ci->mid = mid; ci->stackent = mrb->c->stack; - ci->target_class = c; + ci->target_class = cls; ci->argc = argc; - ci->pc = pc + 1; + ci->pc = pc; ci->acc = a; /* prepare stack */ mrb->c->stack += a; if (MRB_METHOD_CFUNC_P(m)) { - ci->nregs = (argc < 0) ? 3 : n+2; + ci->nregs = (argc < 0) ? 3 : c+2; if (MRB_METHOD_PROC_P(m)) { struct RProc *p = MRB_METHOD_PROC(m); @@ -1480,12 +1408,10 @@ RETRY_TRY_BLOCK: mrb_gc_arena_shrink(mrb, ai); if (mrb->exc) goto L_RAISE; ci = mrb->c->ci; - if (GET_OPCODE(i) == OP_SENDB) { - if (mrb_type(blk) == MRB_TT_PROC) { - struct RProc *p = mrb_proc_ptr(blk); - if (p && !MRB_PROC_STRICT_P(p) && MRB_PROC_ENV(p) == ci[-1].env) { - p->flags |= MRB_PROC_ORPHAN; - } + if (mrb_type(blk) == MRB_TT_PROC) { + struct RProc *p = mrb_proc_ptr(blk); + if (p && !MRB_PROC_STRICT_P(p) && MRB_PROC_ENV(p) == ci[-1].env) { + p->flags |= MRB_PROC_ORPHAN; } } if (!ci->target_class) { /* return from context modifying method (resume/yield) */ @@ -1521,14 +1447,7 @@ RETRY_TRY_BLOCK: } } - CASE(OP_FSEND) { - /* A B C R(A) := fcall(R(A),Syms(B),R(A+1),... ,R(A+C-1)) */ - /* not implemented yet */ - NEXT; - } - - CASE(OP_CALL) { - /* A R(A) := self.call(frame.argc, frame.argv) */ + CASE(OP_CALL, Z) { mrb_callinfo *ci; mrb_value recv = mrb->c->stack[0]; struct RProc *m = mrb_proc_ptr(recv); @@ -1571,7 +1490,9 @@ RETRY_TRY_BLOCK: irep = m->body.irep; if (!irep) { mrb->c->stack[0] = mrb_nil_value(); - goto L_RETURN; + a = 0; + c = OP_R_NORMAL; + goto L_OP_RETURN_BODY; } pool = irep->pool; syms = irep->syms; @@ -1593,14 +1514,11 @@ RETRY_TRY_BLOCK: } } - CASE(OP_SUPER) { - /* A C R(A) := super(R(A+1),... ,R(A+C+1)) */ - int a = GETARG_A(i); - int n = GETARG_C(i); - int argc = (n == CALL_MAXARGS) ? -1 : n; - int bidx = (argc < 0) ? a+2 : a+n+1; + CASE(OP_SUPER, BB) { + int argc = (b == CALL_MAXARGS) ? -1 : b; + int bidx = (argc < 0) ? a+2 : a+b+1; mrb_method_t m; - struct RClass *c; + struct RClass *cls; mrb_callinfo *ci = mrb->c->ci; mrb_value recv, blk; mrb_sym mid = ci->mid; @@ -1636,17 +1554,17 @@ RETRY_TRY_BLOCK: regs[bidx] = blk; ci = mrb->c->ci; } - c = target_class->super; - m = mrb_method_search_vm(mrb, &c, mid); + cls = target_class->super; + m = mrb_method_search_vm(mrb, &cls, mid); if (MRB_METHOD_UNDEF_P(m)) { mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); if (mid != missing) { - c = mrb_class(mrb, recv); + cls = mrb_class(mrb, recv); } - m = mrb_method_search_vm(mrb, &c, missing); + m = mrb_method_search_vm(mrb, &cls, missing); if (MRB_METHOD_UNDEF_P(m)) { - mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, n, regs+a+1); + mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, b, regs+a+1); ERR_PC_SET(mrb, pc); mrb_method_missing(mrb, mid, recv, args); } @@ -1655,7 +1573,7 @@ RETRY_TRY_BLOCK: if (a+2 >= ci->nregs) { mrb_stack_extend(mrb, a+3); } - regs[a+1] = mrb_ary_new_from_values(mrb, n, regs+a+1); + regs[a+1] = mrb_ary_new_from_values(mrb, b, regs+a+1); regs[a+2] = blk; argc = -1; } @@ -1666,8 +1584,8 @@ RETRY_TRY_BLOCK: ci = cipush(mrb); ci->mid = mid; ci->stackent = mrb->c->stack; - ci->target_class = c; - ci->pc = pc + 1; + ci->target_class = cls; + ci->pc = pc; ci->argc = argc; /* prepare stack */ @@ -1676,7 +1594,7 @@ RETRY_TRY_BLOCK: if (MRB_METHOD_CFUNC_P(m)) { mrb_value v; - ci->nregs = (argc < 0) ? 3 : n+2; + ci->nregs = (argc < 0) ? 3 : b+2; if (MRB_METHOD_PROC_P(m)) { ci->proc = MRB_METHOD_PROC(m); } @@ -1720,14 +1638,11 @@ RETRY_TRY_BLOCK: } } - CASE(OP_ARGARY) { - /* A Bx R(A) := argument array (16=6:1:5:4) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - int m1 = (bx>>10)&0x3f; - int r = (bx>>9)&0x1; - int m2 = (bx>>4)&0x1f; - int lv = (bx>>0)&0xf; + CASE(OP_ARGARY, BS) { + int m1 = (b>>10)&0x3f; + int r = (b>>9)&0x1; + int m2 = (b>>4)&0x1f; + int lv = (b>>0)&0xf; mrb_value *stack; if (mrb->c->ci->mid == 0 || mrb->c->ci->target_class == NULL) { @@ -1778,18 +1693,15 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_ENTER) { - /* Ax arg setup according to flags (23=5:5:1:5:5:1:1) */ - /* number of optional arguments times OP_JMP should follow */ - mrb_aspec ax = GETARG_Ax(i); - int m1 = MRB_ASPEC_REQ(ax); - int o = MRB_ASPEC_OPT(ax); - int r = MRB_ASPEC_REST(ax); - int m2 = MRB_ASPEC_POST(ax); + CASE(OP_ENTER, W) { + int m1 = MRB_ASPEC_REQ(a); + int o = MRB_ASPEC_OPT(a); + int r = MRB_ASPEC_REST(a); + int m2 = MRB_ASPEC_POST(a); /* unused - int k = MRB_ASPEC_KEY(ax); - int kd = MRB_ASPEC_KDICT(ax); - int b = MRB_ASPEC_BLOCK(ax); + int k = MRB_ASPEC_KEY(a); + int kd = MRB_ASPEC_KDICT(a); + int b = MRB_ASPEC_BLOCK(a); */ int argc = mrb->c->ci->argc; mrb_value *argv = regs+1; @@ -1841,9 +1753,8 @@ RETRY_TRY_BLOCK: if (r) { regs[m1+o+1] = mrb_ary_new_capa(mrb, 0); } - if (o == 0 || argc < m1+m2) pc++; - else - pc += argc - m1 - m2 + 1; + if (o > 0 && argc >= m1+m2) + pc += (argc - m1 - m2)*3; } else { int rnum = 0; @@ -1852,8 +1763,11 @@ RETRY_TRY_BLOCK: value_move(®s[1], argv, m1+o); } if (r) { + mrb_value ary; + rnum = argc-m1-o-m2; - regs[m1+o+1] = mrb_ary_new_from_values(mrb, rnum, argv+m1+o); + ary = mrb_ary_new_from_values(mrb, rnum, argv+m1+o); + regs[m1+o+1] = ary; } if (m2) { if (argc-m2 > m1) { @@ -1863,7 +1777,7 @@ RETRY_TRY_BLOCK: if (argv0 == argv) { regs[len+1] = *blk; /* move block */ } - pc += o + 1; + pc += o*3; } mrb->c->ci->argc = len; /* clear local (but non-argument) variables */ @@ -1873,24 +1787,33 @@ RETRY_TRY_BLOCK: JUMP; } - CASE(OP_KARG) { - /* A B C R(A) := kdict[Syms(B)]; if C kdict.rm(Syms(B)) */ - /* if C == 2; raise unless kdict.empty? */ - /* OP_JMP should follow to skip init code */ + CASE(OP_KARG, BB) { + /* not implemented yet */ + NEXT; + } + CASE(OP_KARG2, BB) { + /* not implemented yet */ NEXT; } - CASE(OP_KDICT) { - /* A C R(A) := kdict */ + CASE(OP_KDICT, B) { + /* not implemented yet */ NEXT; } + CASE(OP_BREAK, B) { + c = OP_R_BREAK; + goto L_RETURN; + } + CASE(OP_RETURN_BLK, B) { + c = OP_R_RETURN; + goto L_RETURN; + } + CASE(OP_RETURN, B) + c = OP_R_NORMAL; L_RETURN: - i = MKOP_AB(OP_RETURN, GETARG_A(i), OP_R_NORMAL); - /* fall through */ - CASE(OP_RETURN) { - /* A B return R(A) (B=normal,in-block return/break) */ - mrb_callinfo *ci; + { + mrb_callinfo *ci; #define ecall_adjust() do {\ ptrdiff_t cioff = ci - mrb->c->cibase;\ @@ -1976,7 +1899,7 @@ RETRY_TRY_BLOCK: mrb->c->stack = ci[1].stackent; } mrb_stack_extend(mrb, irep->nregs); - pc = mrb->c->rescue[--ci->ridx]; + pc = irep->iseq+mrb->c->rescue[--ci->ridx]; } else { int acc; @@ -1984,9 +1907,9 @@ RETRY_TRY_BLOCK: struct RProc *dst; ci = mrb->c->ci; - v = regs[GETARG_A(i)]; + v = regs[a]; mrb_gc_protect(mrb, v); - switch (GETARG_B(i)) { + switch (c) { case OP_R_RETURN: /* Fall through to OP_R_NORMAL otherwise */ if (ci->acc >=0 && MRB_PROC_ENV_P(proc) && !MRB_PROC_STRICT_P(proc)) { @@ -2021,8 +1944,7 @@ RETRY_TRY_BLOCK: struct mrb_context *c; if (!mrb->c->prev) { /* toplevel return */ - localjump_error(mrb, LOCALJUMP_ERROR_RETURN); - goto L_RAISE; + goto L_STOP; } if (mrb->c->prev->ci == mrb->c->prev->cibase) { mrb_value exc = mrb_exc_new_str_lit(mrb, E_FIBER_ERROR, "double resume"); @@ -2141,91 +2063,11 @@ RETRY_TRY_BLOCK: JUMP; } - CASE(OP_TAILCALL) { - /* A B C return call(R(A),Syms(B),R(A+1),... ,R(A+C+1)) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int n = GETARG_C(i); - mrb_method_t m; - struct RClass *c; - mrb_callinfo *ci; - mrb_value recv; - mrb_sym mid = syms[b]; - - recv = regs[a]; - c = mrb_class(mrb, recv); - m = mrb_method_search_vm(mrb, &c, mid); - if (MRB_METHOD_UNDEF_P(m)) { - mrb_value sym = mrb_symbol_value(mid); - mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); - m = mrb_method_search_vm(mrb, &c, missing); - if (MRB_METHOD_UNDEF_P(m)) { - mrb_value args; - - if (n == CALL_MAXARGS) { - args = regs[a+1]; - } - else { - args = mrb_ary_new_from_values(mrb, n, regs+a+1); - } - ERR_PC_SET(mrb, pc); - mrb_method_missing(mrb, mid, recv, args); - } - mid = missing; - if (n == CALL_MAXARGS) { - mrb_ary_unshift(mrb, regs[a+1], sym); - } - else { - value_move(regs+a+2, regs+a+1, ++n); - regs[a+1] = sym; - } - } - - /* replace callinfo */ - ci = mrb->c->ci; - ci->mid = mid; - ci->target_class = c; - if (n == CALL_MAXARGS) { - ci->argc = -1; - } - else { - ci->argc = n; - } - - /* move stack */ - value_move(mrb->c->stack, ®s[a], ci->argc+1); - - if (MRB_METHOD_CFUNC_P(m)) { - mrb_value v = MRB_METHOD_CFUNC(m)(mrb, recv); - mrb->c->stack[0] = v; - mrb_gc_arena_restore(mrb, ai); - goto L_RETURN; - } - else { - /* setup environment for calling method */ - struct RProc *p = MRB_METHOD_PROC(m); - irep = p->body.irep; - pool = irep->pool; - syms = irep->syms; - if (ci->argc < 0) { - mrb_stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs); - } - else { - mrb_stack_extend(mrb, irep->nregs); - } - pc = irep->iseq; - } - JUMP; - } - - CASE(OP_BLKPUSH) { - /* A Bx R(A) := block (16=6:1:5:4) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - int m1 = (bx>>10)&0x3f; - int r = (bx>>9)&0x1; - int m2 = (bx>>4)&0x1f; - int lv = (bx>>0)&0xf; + CASE(OP_BLKPUSH, BS) { + int m1 = (b>>10)&0x3f; + int r = (b>>9)&0x1; + int m2 = (b>>4)&0x1f; + int lv = (b>>0)&0xf; mrb_value *stack; if (lv == 0) stack = regs + 1; @@ -2251,10 +2093,7 @@ RETRY_TRY_BLOCK: v1(regs[a]) = v1(regs[a]) op v2(regs[a+1]);\ } while(0) - CASE(OP_ADD) { - /* A B C R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1)*/ - int a = GETARG_A(i); - + CASE(OP_ADD, BB) { /* need to check if op is overridden */ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): @@ -2308,16 +2147,14 @@ RETRY_TRY_BLOCK: regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]); break; default: + c = 1; goto L_SEND; } mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_SUB) { - /* A B C R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1)*/ - int a = GETARG_A(i); - + CASE(OP_SUB, BB) { /* need to check if op is overridden */ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): @@ -2367,15 +2204,13 @@ RETRY_TRY_BLOCK: break; #endif default: + c = 1; goto L_SEND; } NEXT; } - CASE(OP_MUL) { - /* A B C R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1)*/ - int a = GETARG_A(i); - + CASE(OP_MUL, BB) { /* need to check if op is overridden */ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): @@ -2425,14 +2260,13 @@ RETRY_TRY_BLOCK: break; #endif default: + c = 1; goto L_SEND; } NEXT; } - CASE(OP_DIV) { - /* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1)*/ - int a = GETARG_A(i); + CASE(OP_DIV, BB) { #ifndef MRB_WITHOUT_FLOAT double x, y, f; #endif @@ -2465,6 +2299,7 @@ RETRY_TRY_BLOCK: break; #endif default: + c = 1; goto L_SEND; } @@ -2482,16 +2317,13 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_ADDI) { - /* A B C R(A) := R(A)+C (Syms[B]=:+)*/ - int a = GETARG_A(i); - + CASE(OP_ADDI, BBB) { /* need to check if + is overridden */ switch (mrb_type(regs[a])) { case MRB_TT_FIXNUM: { mrb_int x = mrb_fixnum(regs[a]); - mrb_int y = GETARG_C(i); + mrb_int y = (mrb_int)c; mrb_int z; if (mrb_int_add_overflow(x, y, &z)) { @@ -2508,24 +2340,22 @@ RETRY_TRY_BLOCK: #ifdef MRB_WORD_BOXING { mrb_float x = mrb_float(regs[a]); - SET_FLOAT_VALUE(mrb, regs[a], x + GETARG_C(i)); + SET_FLOAT_VALUE(mrb, regs[a], x + c); } #else - mrb_float(regs[a]) += GETARG_C(i); + mrb_float(regs[a]) += c; #endif break; #endif default: - SET_INT_VALUE(regs[a+1], GETARG_C(i)); - i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1); + SET_INT_VALUE(regs[a+1], c); + c = 1; goto L_SEND; } NEXT; } - CASE(OP_SUBI) { - /* A B C R(A) := R(A)-C (Syms[B]=:-)*/ - int a = GETARG_A(i); + CASE(OP_SUBI, BBB) { mrb_value *regs_a = regs + a; /* need to check if + is overridden */ @@ -2533,7 +2363,7 @@ RETRY_TRY_BLOCK: case MRB_TT_FIXNUM: { mrb_int x = mrb_fixnum(regs_a[0]); - mrb_int y = GETARG_C(i); + mrb_int y = (mrb_int)c; mrb_int z; if (mrb_int_sub_overflow(x, y, &z)) { @@ -2553,13 +2383,13 @@ RETRY_TRY_BLOCK: SET_FLOAT_VALUE(mrb, regs[a], x - GETARG_C(i)); } #else - mrb_float(regs_a[0]) -= GETARG_C(i); + mrb_float(regs_a[0]) -= c; #endif break; #endif default: - SET_INT_VALUE(regs_a[1], GETARG_C(i)); - i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1); + SET_INT_VALUE(regs_a[1], c); + c = 1; goto L_SEND; } NEXT; @@ -2576,6 +2406,7 @@ RETRY_TRY_BLOCK: result = OP_CMP_BODY(op,mrb_fixnum,mrb_fixnum);\ break;\ default:\ + c = 1;\ goto L_SEND;\ }\ if (result) {\ @@ -2603,6 +2434,7 @@ RETRY_TRY_BLOCK: result = OP_CMP_BODY(op,mrb_float,mrb_float);\ break;\ default:\ + c = 1;\ goto L_SEND;\ }\ if (result) {\ @@ -2614,9 +2446,7 @@ RETRY_TRY_BLOCK: } while(0) #endif - CASE(OP_EQ) { - /* A B C R(A) := R(A)==R(A+1) (Syms[B]=:==,C=1)*/ - int a = GETARG_A(i); + CASE(OP_EQ, BB) { if (mrb_obj_eq(mrb, regs[a], regs[a+1])) { SET_TRUE_VALUE(regs[a]); } @@ -2626,68 +2456,59 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_LT) { - /* A B C R(A) := R(A)R(A+1) (Syms[B]=:>,C=1)*/ - int a = GETARG_A(i); + CASE(OP_GT, BB) { OP_CMP(>); NEXT; } - CASE(OP_GE) { - /* A B C R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1)*/ - int a = GETARG_A(i); + CASE(OP_GE, BB) { OP_CMP(>=); NEXT; } - CASE(OP_ARRAY) { - /* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int c = GETARG_C(i); + CASE(OP_ARRAY, BB) { + mrb_value v = mrb_ary_new_from_values(mrb, b, ®s[a]); + regs[a] = v; + mrb_gc_arena_restore(mrb, ai); + NEXT; + } + CASE(OP_ARRAY2, BBB) { mrb_value v = mrb_ary_new_from_values(mrb, c, ®s[b]); regs[a] = v; mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_ARYCAT) { - /* A B mrb_ary_concat(R(A),R(B)) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - mrb_value splat = mrb_ary_splat(mrb, regs[b]); + CASE(OP_ARYCAT, B) { + mrb_value splat = mrb_ary_splat(mrb, regs[a+1]); mrb_ary_concat(mrb, regs[a], splat); mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_ARYPUSH) { - /* A B R(A).push(R(B)) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - mrb_ary_push(mrb, regs[a], regs[b]); + CASE(OP_ARYPUSH, B) { + mrb_ary_push(mrb, regs[a], regs[a+1]); NEXT; } - CASE(OP_AREF) { - /* A B C R(A) := R(B)[C] */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int c = GETARG_C(i); + CASE(OP_ARYDUP, B) { + mrb_value ary = regs[a]; + ary = mrb_ary_new_from_values(mrb, RARRAY_LEN(ary), RARRAY_PTR(ary)); + regs[a] = ary; + NEXT; + } + + CASE(OP_AREF, BBB) { mrb_value v = regs[b]; if (!mrb_array_p(v)) { @@ -2705,21 +2526,15 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_ASET) { - /* A B C R(B)[C] := R(A) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int c = GETARG_C(i); + CASE(OP_ASET, BBB) { mrb_ary_set(mrb, regs[b], c, regs[a]); NEXT; } - CASE(OP_APOST) { - /* A B C *R(A),R(A+1)..R(A+C) := R(A)[B..] */ - int a = GETARG_A(i); + CASE(OP_APOST, BBB) { mrb_value v = regs[a]; - int pre = GETARG_B(i); - int post = GETARG_C(i); + int pre = b; + int post = c; struct RArray *ary; int len, idx; @@ -2750,48 +2565,58 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_STRING) { - /* A Bx R(A) := str_new(Lit(Bx)) */ - mrb_int a = GETARG_A(i); - mrb_int bx = GETARG_Bx(i); - mrb_value str = mrb_str_dup(mrb, pool[bx]); + CASE(OP_INTERN, B) { + mrb_sym sym = mrb_intern_str(mrb, regs[a]); + + regs[a] = mrb_symbol_value(sym); + mrb_gc_arena_restore(mrb, ai); + NEXT; + } + + CASE(OP_STRING, BB) { + mrb_value str = mrb_str_dup(mrb, pool[b]); regs[a] = str; mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_STRCAT) { - /* A B R(A).concat(R(B)) */ - mrb_int a = GETARG_A(i); - mrb_int b = GETARG_B(i); + CASE(OP_STRCAT, B) { + mrb_str_concat(mrb, regs[a], regs[a+1]); + NEXT; + } + + CASE(OP_HASH, BB) { + mrb_value hash = mrb_hash_new_capa(mrb, b); + int i; + int lim = a+b*2; - mrb_str_concat(mrb, regs[a], regs[b]); + for (i=a; ireps[b]; if (c & OP_L_CAPTURE) { @@ -2806,19 +2631,38 @@ RETRY_TRY_BLOCK: mrb_gc_arena_restore(mrb, ai); NEXT; } + CASE(OP_BLOCK, BB) { + c = OP_L_BLOCK; + goto L_MAKE_LAMBDA; + } + CASE(OP_METHOD, BB) { + c = OP_L_METHOD; + goto L_MAKE_LAMBDA; + } - CASE(OP_OCLASS) { - /* A R(A) := ::Object */ - regs[GETARG_A(i)] = mrb_obj_value(mrb->object_class); + CASE(OP_RANGE_INC, B) { + mrb_value val = mrb_range_new(mrb, regs[a], regs[a+1], FALSE); + regs[a] = val; + mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_CLASS) { - /* A B R(A) := newclass(R(A),Syms(B),R(A+1)) */ + CASE(OP_RANGE_EXC, B) { + mrb_value val = mrb_range_new(mrb, regs[a], regs[a+1], TRUE); + regs[a] = val; + mrb_gc_arena_restore(mrb, ai); + NEXT; + } + + CASE(OP_OCLASS, B) { + regs[a] = mrb_obj_value(mrb->object_class); + NEXT; + } + + CASE(OP_CLASS, BB) { struct RClass *c = 0, *baseclass; - int a = GETARG_A(i); mrb_value base, super; - mrb_sym id = syms[GETARG_B(i)]; + mrb_sym id = syms[b]; base = regs[a]; super = regs[a+1]; @@ -2832,32 +2676,27 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_MODULE) { - /* A B R(A) := newmodule(R(A),Syms(B)) */ - struct RClass *c = 0, *baseclass; - int a = GETARG_A(i); + CASE(OP_MODULE, BB) { + struct RClass *cls = 0, *baseclass; mrb_value base; - mrb_sym id = syms[GETARG_B(i)]; + mrb_sym id = syms[b]; base = regs[a]; if (mrb_nil_p(base)) { baseclass = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc); base = mrb_obj_value(baseclass); } - c = mrb_vm_define_module(mrb, base, id); - regs[a] = mrb_obj_value(c); + cls = mrb_vm_define_module(mrb, base, id); + regs[a] = mrb_obj_value(cls); mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_EXEC) { - /* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); + CASE(OP_EXEC, BB) { mrb_callinfo *ci; mrb_value recv = regs[a]; struct RProc *p; - mrb_irep *nirep = irep->reps[bx]; + mrb_irep *nirep = irep->reps[b]; /* prepare closure */ p = mrb_proc_new(mrb, nirep); @@ -2868,7 +2707,7 @@ RETRY_TRY_BLOCK: /* prepare call stack */ ci = cipush(mrb); - ci->pc = pc + 1; + ci->pc = pc; ci->acc = a; ci->mid = 0; ci->stackent = mrb->c->stack; @@ -2891,56 +2730,53 @@ RETRY_TRY_BLOCK: JUMP; } - CASE(OP_METHOD) { - /* A B R(A).newmethod(Syms(B),R(A+1)) */ - int a = GETARG_A(i); - struct RClass *c = mrb_class_ptr(regs[a]); + CASE(OP_DEF, BB) { + struct RClass *target = mrb_class_ptr(regs[a]); struct RProc *p = mrb_proc_ptr(regs[a+1]); mrb_method_t m; MRB_METHOD_FROM_PROC(m, p); - mrb_define_method_raw(mrb, c, syms[GETARG_B(i)], m); + mrb_define_method_raw(mrb, target, syms[b], m); mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_SCLASS) { - /* A B R(A) := R(B).singleton_class */ - int a = GETARG_A(i); - int b = GETARG_B(i); - - regs[a] = mrb_singleton_class(mrb, regs[b]); + CASE(OP_SCLASS, B) { + regs[a] = mrb_singleton_class(mrb, regs[a]); mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_TCLASS) { - /* A R(A) := target_class */ - if (!mrb->c->ci->target_class) { - mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, "no target class or module"); - mrb_exc_set(mrb, exc); - goto L_RAISE; - } - regs[GETARG_A(i)] = mrb_obj_value(mrb->c->ci->target_class); + CASE(OP_TCLASS, B) { + if (!check_target_class(mrb)) goto L_RAISE; + regs[a] = mrb_obj_value(mrb->c->ci->target_class); NEXT; } - CASE(OP_RANGE) { - /* A B C R(A) := range_new(R(B),R(B+1),C) */ - int b = GETARG_B(i); - mrb_value val = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i)); - regs[GETARG_A(i)] = val; - mrb_gc_arena_restore(mrb, ai); + CASE(OP_ALIAS, BB) { + struct RClass *target; + + if (!check_target_class(mrb)) goto L_RAISE; + target = mrb->c->ci->target_class; + mrb_alias_method(mrb, target, syms[a], syms[b]); + NEXT; + } + CASE(OP_UNDEF, B) { + struct RClass *target; + + if (!check_target_class(mrb)) goto L_RAISE; + target = mrb->c->ci->target_class; + mrb_undef_method_id(mrb, target, syms[a]); NEXT; } - CASE(OP_DEBUG) { - /* A B C debug print R(A),R(B),R(C) */ + CASE(OP_DEBUG, Z) { + FETCH_BBB(); #ifdef MRB_ENABLE_DEBUG_HOOK mrb->debug_op_hook(mrb, irep, pc, regs); #else #ifndef MRB_DISABLE_STDIO - printf("OP_DEBUG %d %d %d\n", GETARG_A(i), GETARG_B(i), GETARG_C(i)); + printf("OP_DEBUG %d %d %d\n", a, b, c); #else abort(); #endif @@ -2948,7 +2784,48 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_STOP) { + CASE(OP_ERR, B) { + mrb_value msg = mrb_str_dup(mrb, pool[a]); + mrb_value exc; + + exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg); + ERR_PC_SET(mrb, pc); + mrb_exc_set(mrb, exc); + goto L_RAISE; + } + + CASE(OP_EXT1, Z) { + insn = READ_B(); + switch (insn) { +#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _1(); goto L_OP_ ## insn ## _BODY; +#include "mruby/ops.h" +#undef OPCODE + } + pc--; + NEXT; + } + CASE(OP_EXT2, Z) { + insn = READ_B(); + switch (insn) { +#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _2(); goto L_OP_ ## insn ## _BODY; +#include "mruby/ops.h" +#undef OPCODE + } + pc--; + NEXT; + } + CASE(OP_EXT3, Z) { + uint8_t insn = READ_B(); + switch (insn) { +#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _3(); goto L_OP_ ## insn ## _BODY; +#include "mruby/ops.h" +#undef OPCODE + } + pc--; + NEXT; + } + + CASE(OP_STOP, Z) { /* stop VM */ L_STOP: while (mrb->c->eidx > 0) { @@ -2961,26 +2838,9 @@ RETRY_TRY_BLOCK: } return regs[irep->nlocals]; } - - CASE(OP_ERR) { - /* Bx raise RuntimeError with message Lit(Bx) */ - mrb_value msg = mrb_str_dup(mrb, pool[GETARG_Bx(i)]); - mrb_value exc; - - if (GETARG_A(i) == 0) { - exc = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, msg); - } - else { - exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg); - } - ERR_PC_SET(mrb, pc); - mrb_exc_set(mrb, exc); - goto L_RAISE; - } } END_DISPATCH; #undef regs - } MRB_CATCH(&c_jmp) { exc_catched = TRUE; -- cgit v1.2.3 From 8c9e7127845f84fcbb249c45936c97a89ca7a80a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 30 Jul 2018 22:07:31 +0900 Subject: Keyword argument implemented. --- doc/opcode.md | 8 +- include/mruby/hash.h | 27 +- include/mruby/ops.h | 11 +- mrbgems/mruby-compiler/core/codegen.c | 149 +++++-- mrbgems/mruby-compiler/core/node.h | 4 + mrbgems/mruby-compiler/core/parse.y | 493 ++++++++++++++-------- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- mrbgems/mruby-proc-ext/src/proc.c | 10 +- src/codedump.c | 50 ++- src/hash.c | 86 +++- src/kernel.c | 10 +- src/vm.c | 146 +++++-- test/t/syntax.rb | 183 ++++++++ 13 files changed, 887 insertions(+), 292 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/doc/opcode.md b/doc/opcode.md index d904256e5..54d1f0553 100644 --- a/doc/opcode.md +++ b/doc/opcode.md @@ -77,7 +77,7 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed. |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=6:1:5:4) +|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 @@ -85,7 +85,7 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed. |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=6:1:5:4) +|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]=:-) @@ -207,7 +207,7 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed. |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=6:1:5:4) +|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 @@ -215,7 +215,7 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed. |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=6:1:5:4) +|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]=:-) diff --git a/include/mruby/hash.h b/include/mruby/hash.h index 1a870785a..9a3812850 100644 --- a/include/mruby/hash.h +++ b/include/mruby/hash.h @@ -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,16 @@ 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); + /* declaration of struct kh_ht */ /* be careful when you touch the internal */ typedef struct { diff --git a/include/mruby/ops.h b/include/mruby/ops.h index 882ad6f25..9675d6158 100644 --- a/include/mruby/ops.h +++ b/include/mruby/ops.h @@ -61,15 +61,16 @@ 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=6:1:5:4) */ -OPCODE(ENTER, W) /* arg setup according to flags (23=5:5:1:5:5:1:1) */ -OPCODE(KARG, BB) /* R(a) = kdict[Syms(Bx)] # todo */ -OPCODE(KARG2, BB) /* R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo */ +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(KDICT, B) /* R(a) = kdict # 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=6:1:5:4) */ +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]=:-) */ diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 3ba2324fb..070aaac51 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -420,6 +420,9 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep) if (no_peephole(s)) { normal: genop_2(s, OP_MOVE, dst, src); + if (on_eval(s)) { + genop_0(s, OP_NOP); + } return; } else { @@ -453,6 +456,25 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep) } } +static void +gen_return(codegen_scope *s, uint8_t op, uint16_t src) +{ + if (no_peephole(s)) { + genop_1(s, op, src); + } + else { + struct mrb_insn_data data = mrb_last_insn(s); + + if (data.insn == OP_MOVE && src == data.a) { + s->pc = s->lastpc; + genop_1(s, op, data.b); + } + else { + genop_1(s, op, src); + } + } +} + static void gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst, uint16_t idx) { @@ -514,30 +536,28 @@ dispatch_linked(codegen_scope *s, uint16_t pos) #define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0) static void -push_(codegen_scope *s) +push_n_(codegen_scope *s, int n) { - if (s->sp >= 0xffff) { + if (s->sp+n >= 0xffff) { codegen_error(s, "too complex expression"); } - s->sp++; + s->sp+=n; nregs_update; } static void -push_n_(codegen_scope *s, int n) +pop_n_(codegen_scope *s, int n) { - if (s->sp+n >= 0xffff) { - codegen_error(s, "too complex expression"); + if ((int)s->sp-n < 0) { + codegen_error(s, "stack pointer underflow"); } - s->sp+=n; - nregs_update; + s->sp-=n; } -#define push() push_(s) +#define push() push_n_(s,1) #define push_n(n) push_n_(s,n) -#define pop_(s) ((s)->sp--) -#define pop() pop_(s) -#define pop_n(n) (s->sp-=(n)) +#define pop() pop_n_(s,1) +#define pop_n(n) pop_n_(s,n) #define cursp() (s->sp) static inline int @@ -644,8 +664,12 @@ node_len(node *tree) return n; } +#define nint(x) ((int)(intptr_t)(x)) +#define nchar(x) ((char)(intptr_t)(x)) #define nsym(x) ((mrb_sym)(intptr_t)(x)) + #define lv_name(lv) nsym((lv)->car) + static int lv_idx(codegen_scope *s, mrb_sym id) { @@ -694,7 +718,7 @@ for_body(codegen_scope *s, node *tree) /* loop body */ codegen(s, tree->cdr->cdr->car, VAL); pop(); - genop_1(s, OP_RETURN, cursp()); + gen_return(s, OP_RETURN, cursp()); loop_pop(s, NOVAL); scope_finish(s); s = prev; @@ -726,32 +750,44 @@ lambda_body(codegen_scope *s, node *tree, int blk) int ma, oa, ra, pa, ka, kd, ba; int pos, i; node *n, *opt; + node *tail; + /* mandatory arguments */ ma = node_len(tree->car->car); n = tree->car->car; while (n) { n = n->cdr; } + tail = tree->car->cdr->cdr->cdr->cdr; + + /* optional arguments */ oa = node_len(tree->car->cdr->car); + /* rest argument? */ ra = tree->car->cdr->cdr->car ? 1 : 0; + /* mandatory arugments after rest argument */ pa = node_len(tree->car->cdr->cdr->cdr->car); - ka = kd = 0; - ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0; - + /* keyword arguments */ + ka = tail? node_len(tail->cdr->car) : 0; + /* keyword dictionary? */ + kd = tail && tail->cdr->cdr->car? 1 : 0; + /* block argument? */ + ba = tail && tail->cdr->cdr->cdr->car ? 1 : 0; + if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) { codegen_error(s, "too many formal arguments"); } - a = ((mrb_aspec)(ma & 0x1f) << 18) - | ((mrb_aspec)(oa & 0x1f) << 13) - | ((ra & 1) << 12) - | ((pa & 0x1f) << 7) - | ((ka & 0x1f) << 2) - | ((kd & 1)<< 1) - | (ba & 1); - s->ainfo = (((ma+oa) & 0x3f) << 6) /* (12bits = 6:1:5) */ - | ((ra & 1) << 5) - | (pa & 0x1f); + a = MRB_ARGS_REQ(ma) + | MRB_ARGS_OPT(oa) + | (ra? MRB_ARGS_REST() : 0) + | MRB_ARGS_POST(pa) + | MRB_ARGS_KEY(ka, kd) + | (ba? MRB_ARGS_BLOCK() : 0); + s->ainfo = (((ma+oa) & 0x3f) << 7) /* (12bits = 5:1:5:1) */ + | ((ra & 0x1) << 6) + | ((pa & 0x1f) << 1) + | (kd & 0x1); genop_W(s, OP_ENTER, a); + /* generate jump table for optional arguments initializer */ pos = new_label(s); for (i=0; i 0) { dispatch(s, pos+i*3+1); } + + if (tail) { + node *kwds = tail->cdr->car; + int kwrest = 0; + + if (tail->cdr->cdr->car) { + kwrest = 1; + } + mrb_assert(nint(tail->car) == NODE_ARGS_TAIL); + mrb_assert(node_len(tail) == 4); + + while (kwds) { + int jmpif_key_p, jmp_def_set = -1; + node *kwd = kwds->car, *def_arg = kwd->cdr->cdr->car; + mrb_sym kwd_sym = nsym(kwd->cdr->car); + + mrb_assert(nint(kwd->car) == NODE_KW_ARG); + + if (def_arg) { + genop_2(s, OP_KEY_P, cursp(), new_sym(s, kwd_sym)); + jmpif_key_p = genjmp2(s, OP_JMPIF, cursp(), 0, 0); + codegen(s, def_arg, VAL); + pop(); + gen_move(s, lv_idx(s, kwd_sym), cursp(), 0); + jmp_def_set = genjmp(s, OP_JMP, 0); + dispatch(s, jmpif_key_p); + } + genop_2(s, OP_KARG, lv_idx(s, kwd_sym), new_sym(s, kwd_sym)); + if (jmp_def_set != -1) { + dispatch(s, jmp_def_set); + } + i++; + + kwds = kwds->cdr; + } + if (tail->cdr->car && !kwrest) { + genop_0(s, OP_KEYEND); + } + } } codegen(s, tree->cdr->car, VAL); pop(); if (s->pc > 0) { - genop_1(s, OP_RETURN, cursp()); + gen_return(s, OP_RETURN, cursp()); } if (blk) { loop_pop(s, NOVAL); @@ -798,7 +873,7 @@ scope_body(codegen_scope *s, node *tree, int val) } codegen(scope, tree->cdr, VAL); - genop_1(scope, OP_RETURN, scope->sp-1); + gen_return(scope, OP_RETURN, scope->sp-1); if (!s->iseq) { genop_0(scope, OP_STOP); } @@ -810,9 +885,6 @@ scope_body(codegen_scope *s, node *tree, int val) return s->irep->rlen - 1; } -#define nint(x) ((int)(intptr_t)(x)) -#define nchar(x) ((char)(intptr_t)(x)) - static mrb_bool nosplat(node *t) { @@ -1703,11 +1775,18 @@ codegen(codegen_scope *s, node *tree, int val) break; case NODE_HASH: + case NODE_KW_HASH: { int len = 0; mrb_bool update = FALSE; while (tree) { + if (nt == NODE_KW_HASH && + nint(tree->car->car->car) == NODE_KW_REST_ARGS) { + tree = tree->cdr; + continue; + } + codegen(s, tree->car->car, val); codegen(s, tree->car->cdr, val); len++; @@ -2055,10 +2134,10 @@ codegen(codegen_scope *s, node *tree, int val) genop_1(s, OP_LOADNIL, cursp()); } if (s->loop) { - genop_1(s, OP_RETURN_BLK, cursp()); + gen_return(s, OP_RETURN_BLK, cursp()); } else { - genop_1(s, OP_RETURN, cursp()); + gen_return(s, OP_RETURN, cursp()); } if (val) push(); break; @@ -2116,7 +2195,7 @@ codegen(codegen_scope *s, node *tree, int val) else { genop_1(s, OP_LOADNIL, cursp()); } - genop_1(s, OP_RETURN, cursp()); + gen_return(s, OP_RETURN, cursp()); } if (val) push(); break; @@ -2999,7 +3078,7 @@ loop_break(codegen_scope *s, node *tree) if (!tree) { genop_1(s, OP_LOADNIL, cursp()); } - genop_1(s, OP_BREAK, cursp()); + gen_return(s, OP_BREAK, cursp()); } } } diff --git a/mrbgems/mruby-compiler/core/node.h b/mrbgems/mruby-compiler/core/node.h index 9636dd759..af71332e7 100644 --- a/mrbgems/mruby-compiler/core/node.h +++ b/mrbgems/mruby-compiler/core/node.h @@ -46,6 +46,7 @@ enum node_type { NODE_ARRAY, NODE_ZARRAY, NODE_HASH, + NODE_KW_HASH, NODE_RETURN, NODE_YIELD, NODE_LVAR, @@ -73,6 +74,9 @@ enum node_type { NODE_DREGX_ONCE, NODE_LIST, NODE_ARG, + NODE_ARGS_TAIL, + NODE_KW_ARG, + NODE_KW_REST_ARGS, NODE_ARGSCAT, NODE_ARGSPUSH, NODE_SPLAT, diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 61d94edc9..44cb28608 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -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 heredoc words symbols %type call_op call_op2 /* 0:'&.', 1:'.', 2:'::' */ +%type args_tail opt_args_tail f_kwarg f_kw arg_value f_kwrest +%type f_block_kwarg f_block_kw block_args_tail opt_block_args_tail +%type 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,153 @@ f_arglist : '(' f_args rparen } ; -f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg +f_label : tIDENTIFIER tLABEL_TAG + ; + +arg_value : arg + ; + +f_kw : f_label arg_value + { + $$ = 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 +3356,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 +3367,6 @@ blkarg_mark : '&' f_block_arg : blkarg_mark tIDENTIFIER { - local_add_f(p, $2); $$ = $2; } ; @@ -3211,7 +3377,6 @@ opt_f_block_arg : ',' f_block_arg } | none { - local_add_f(p, 0); $$ = 0; } ; @@ -3285,6 +3450,10 @@ assoc : arg tASSOC arg $$ = cons(new_sym(p, new_strsym(p, $1)), $3); } } + | tDSTAR arg_value + { + $$ = cons(cons((node*)NODE_KW_REST_ARGS, 0), $2); + } ; operation : tIDENTIFIER @@ -3450,13 +3619,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 +3638,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 +3677,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 +3726,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 +3751,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 +4188,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 +4534,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 == '=') { @@ -5547,7 +5725,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++; @@ -5897,6 +6075,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 @@ -5908,7 +6128,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: @@ -5968,7 +6188,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: @@ -5976,43 +6197,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"); @@ -6164,7 +6349,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); @@ -6281,7 +6466,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; @@ -6363,11 +6548,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: @@ -6380,7 +6565,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: @@ -6393,7 +6578,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: @@ -6402,7 +6587,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: @@ -6431,7 +6616,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: @@ -6547,43 +6732,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; @@ -6596,44 +6745,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); @@ -6649,18 +6761,35 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset) dump_recur(mrb, ((parser_heredoc_info*)tree)->doc, offset+1); break; - case NODE_LITERAL_DELIM: - printf("NODE_LITERAL_DELIM\n"); + 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_SYMBOLS: - printf("NODE_SYMBOLS:\n"); - dump_recur(mrb, tree, offset+1); + 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_WORDS: - printf("NODE_SYMBOLS:\n"); - dump_recur(mrb, tree, offset+1); + case NODE_KW_REST_ARGS: + printf("NODE_KW_REST_ARGS %s\n", mrb_sym2name(mrb, sym(tree))); break; default: diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 3887091d3..b31dee04c 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -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); } diff --git a/mrbgems/mruby-proc-ext/src/proc.c b/mrbgems/mruby-proc-ext/src/proc.c index 323529dcc..9ce6c1831 100644 --- a/mrbgems/mruby-proc-ext/src/proc.c +++ b/mrbgems/mruby-proc-ext/src/proc.c @@ -149,7 +149,15 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self) a = mrb_ary_new(mrb); mrb_ary_push(mrb, a, sname); if (i < max && irep->lv[i].name) { - mrb_ary_push(mrb, a, mrb_symbol_value(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); } diff --git a/src/codedump.c b/src/codedump.c index 22cbc59eb..dc0e0e548 100644 --- a/src/codedump.c +++ b/src/codedump.c @@ -78,6 +78,16 @@ codedump(mrb_state *mrb, mrb_irep *irep) 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); + 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) { @@ -246,10 +256,11 @@ codedump(mrb_state *mrb, mrb_irep *irep) 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", a, - (b>>10)&0x3f, - (b>>9)&0x1, - (b>>4)&0x1f, + 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; @@ -263,32 +274,39 @@ codedump(mrb_state *mrb, mrb_irep *irep) (a>>1)&0x1, a & 0x1); break; - CASE(OP_KARG, BB): - printf("OP_KARG\tR(%d)\tK(%d)\n", a, b); + 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_KARG2, BB): - printf("OP_KARG2\tR(%d)\tK(%d)\n", a, b); + CASE(OP_KEYEND, Z): + printf("OP_KEYEND\n"); + break; + 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_KDICT, B): - printf("OP_KDICt\tR(%d)\n", a); + printf("OP_KDICT\tR%d\t\t", a); + print_lv_a(mrb, irep, a); break; CASE(OP_RETURN, B): - printf("OP_RETURN\tR%d", a); + printf("OP_RETURN\tR%d\t\t", a); print_lv_a(mrb, irep, a); break; CASE(OP_RETURN_BLK, B): - printf("OP_RETURN_BLK\tR%d", a); + printf("OP_RETURN_BLK\tR%d\t\t", a); print_lv_a(mrb, irep, a); break; CASE(OP_BREAK, B): - printf("OP_BREAK\tR%d", a); + printf("OP_BREAK\tR%d\t\t", a); print_lv_a(mrb, irep, a); break; CASE(OP_BLKPUSH, BS): - printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d", a, - (b>>10)&0x3f, - (b>>9)&0x1, - (b>>4)&0x1f, + 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; diff --git a/src/hash.c b/src/hash.c index db9d1d9c8..0dce81677 100644 --- a/src/hash.c +++ b/src/hash.c @@ -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 */ @@ -904,7 +968,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 */ diff --git a/src/kernel.c b/src/kernel.c index 155868eaa..42e9ca6a4 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -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; diff --git a/src/vm.c b/src/vm.c index b50f1ee9f..8aeb68fc2 100644 --- a/src/vm.c +++ b/src/vm.c @@ -969,6 +969,8 @@ check_target_class(mrb_state *mrb) return TRUE; } +void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self); + MRB_API mrb_value mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc) { @@ -1639,9 +1641,10 @@ RETRY_TRY_BLOCK: } CASE(OP_ARGARY, BS) { - int m1 = (b>>10)&0x3f; - int r = (b>>9)&0x1; - int m2 = (b>>4)&0x1f; + int m1 = (b>>11)&0x3f; + int r = (b>>10)&0x1; + int m2 = (b>>5)&0x1f; + int kd = (b>>4)&0x1; int lv = (b>>0)&0xf; mrb_value *stack; @@ -1657,12 +1660,12 @@ RETRY_TRY_BLOCK: else { struct REnv *e = uvenv(mrb, lv-1); if (!e) goto L_NOSUPER; - if (MRB_ENV_STACK_LEN(e) <= m1+r+m2+1) + if (MRB_ENV_STACK_LEN(e) <= m1+r+m2+kd+1) goto L_NOSUPER; stack = e->stack + 1; } if (r == 0) { - regs[a] = mrb_ary_new_from_values(mrb, m1+m2, stack); + regs[a] = mrb_ary_new_from_values(mrb, m1+m2+kd, stack); } else { mrb_value *pp = NULL; @@ -1675,7 +1678,7 @@ RETRY_TRY_BLOCK: pp = ARY_PTR(ary); len = (int)ARY_LEN(ary); } - regs[a] = mrb_ary_new_capa(mrb, m1+len+m2); + regs[a] = mrb_ary_new_capa(mrb, m1+len+m2+kd); rest = mrb_ary_ptr(regs[a]); if (m1 > 0) { stack_copy(ARY_PTR(rest), stack, m1); @@ -1686,7 +1689,10 @@ RETRY_TRY_BLOCK: if (m2 > 0) { stack_copy(ARY_PTR(rest)+m1+len, stack+m1+1, m2); } - ARY_SET_LEN(rest, m1+len+m2); + if (kd) { + stack_copy(ARY_PTR(rest)+m1+len+m2, stack+m1+m2+1, kd); + } + ARY_SET_LEN(rest, m1+len+m2+kd); } regs[a+1] = stack[m1+r+m2]; mrb_gc_arena_restore(mrb, ai); @@ -1698,74 +1704,114 @@ RETRY_TRY_BLOCK: int o = MRB_ASPEC_OPT(a); int r = MRB_ASPEC_REST(a); int m2 = MRB_ASPEC_POST(a); + int kd = (MRB_ASPEC_KEY(a) > 0 || MRB_ASPEC_KDICT(a))? 1 : 0; /* unused - int k = MRB_ASPEC_KEY(a); - int kd = MRB_ASPEC_KDICT(a); int b = MRB_ASPEC_BLOCK(a); */ int argc = mrb->c->ci->argc; mrb_value *argv = regs+1; - mrb_value *argv0 = argv; - int len = m1 + o + r + m2; + mrb_value * const argv0 = argv; + int const len = m1 + o + r + m2; + int const blk_pos = len + kd + 1; mrb_value *blk = &argv[argc < 0 ? 1 : argc]; + mrb_value kdict; + int kargs = kd; + /* arguments is passed with Array */ if (argc < 0) { struct RArray *ary = mrb_ary_ptr(regs[1]); argv = ARY_PTR(ary); argc = (int)ARY_LEN(ary); mrb_gc_protect(mrb, regs[1]); } + + /* strict argument check */ if (mrb->c->ci->proc && MRB_PROC_STRICT_P(mrb->c->ci->proc)) { - if (argc >= 0) { - if (argc < m1 + m2 || (r == 0 && argc > len)) { + if (argc >= 0 && !(argc <= 1 && kd)) { + if (argc < m1 + m2 + kd || (r == 0 && argc > len + kd)) { argnum_error(mrb, m1+m2); goto L_RAISE; } } } + /* extract first argument array to arguments */ else if (len > 1 && argc == 1 && mrb_array_p(argv[0])) { mrb_gc_protect(mrb, argv[0]); argc = (int)RARRAY_LEN(argv[0]); argv = RARRAY_PTR(argv[0]); } + + if (kd) { + /* check last arguments is hash if method takes keyword arguments */ + if (argc == m1+m2) { + kdict = mrb_hash_new(mrb); + kargs = 0; + } + else { + if (!mrb_hash_p(argv[argc - 1])) { + if (r) { + kdict = mrb_hash_new(mrb); + kargs = 0; + } + else { + mrb_value str = mrb_str_new_lit(mrb, "Excepcted `Hash` as last argument for keyword arguments"); + mrb_exc_set(mrb, mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str)); + goto L_RAISE; + } + } + else { + kdict = argv[argc-1]; + } + mrb_hash_check_kdict(mrb, kdict); + if (MRB_ASPEC_KEY(a) > 0) { + kdict = mrb_hash_dup(mrb, kdict); + } + } + } + + /* no rest arguments */ if (argc < len) { int mlen = m2; if (argc < m1+m2) { - if (m1 < argc) - mlen = argc - m1; - else - mlen = 0; + mlen = m1 < argc ? argc - m1 : 0; } - regs[len+1] = *blk; /* move block */ + regs[blk_pos] = *blk; /* move block */ + if (kd) regs[len + 1] = kdict; + SET_NIL_VALUE(regs[argc+1]); + /* copy mandatory and optional arguments */ if (argv0 != argv) { value_move(®s[1], argv, argc-mlen); /* m1 + o */ } if (argc < m1) { stack_clear(®s[argc+1], m1-argc); } + /* copy post mandatory arguments */ if (mlen) { value_move(®s[len-m2+1], &argv[argc-mlen], mlen); } if (mlen < m2) { stack_clear(®s[len-m2+mlen+1], m2-mlen); } + /* initalize rest arguments with empty Array */ if (r) { regs[m1+o+1] = mrb_ary_new_capa(mrb, 0); } - if (o > 0 && argc >= m1+m2) - pc += (argc - m1 - m2)*3; + /* skip initailizer of passed arguments */ + if (o > 0 && argc-kargs >= m1+m2) + pc += (argc - kargs - m1 - m2)*3; } else { int rnum = 0; if (argv0 != argv) { - regs[len+1] = *blk; /* move block */ + regs[blk_pos] = *blk; /* move block */ + if (kd) regs[len + 1] = kdict; value_move(®s[1], argv, m1+o); } if (r) { mrb_value ary; - rnum = argc-m1-o-m2; + rnum = argc-m1-o-m2-kargs; ary = mrb_ary_new_from_values(mrb, rnum, argv+m1+o); regs[m1+o+1] = ary; } @@ -1775,29 +1821,60 @@ RETRY_TRY_BLOCK: } } if (argv0 == argv) { - regs[len+1] = *blk; /* move block */ + regs[blk_pos] = *blk; /* move block */ + if (kd) regs[len + 1] = kdict; } pc += o*3; } - mrb->c->ci->argc = len; + + /* format arguments for generated code */ + mrb->c->ci->argc = len + kd; + /* clear local (but non-argument) variables */ - if (irep->nlocals-len-2 > 0) { - stack_clear(®s[len+2], irep->nlocals-len-2); + if (irep->nlocals-blk_pos-1 > 0) { + stack_clear(®s[blk_pos+1], irep->nlocals-blk_pos-1); } JUMP; } CASE(OP_KARG, BB) { - /* not implemented yet */ + mrb_value k = mrb_symbol_value(syms[b]); + mrb_value kdict = regs[mrb->c->ci->argc]; + + if (!mrb_hash_key_p(mrb, kdict, k)) { + mrb_value str = mrb_format(mrb, "missing keyword: %S", k); + mrb_exc_set(mrb, mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str)); + goto L_RAISE; + } + regs[a] = mrb_hash_get(mrb, kdict, k); + mrb_hash_delete_key(mrb, kdict, k); NEXT; } - CASE(OP_KARG2, BB) { - /* not implemented yet */ + + CASE(OP_KEY_P, BB) { + mrb_value k = mrb_symbol_value(syms[b]); + mrb_value kdict = regs[mrb->c->ci->argc]; + mrb_bool key_p = mrb_hash_key_p(mrb, kdict, k); + + regs[a] = mrb_bool_value(key_p); + NEXT; + } + + CASE(OP_KEYEND, Z) { + mrb_value kdict = regs[mrb->c->ci->argc]; + + if (mrb_hash_p(kdict) && !mrb_hash_empty_p(mrb, kdict)) { + mrb_value keys = mrb_hash_keys(mrb, kdict); + mrb_value key1 = RARRAY_PTR(keys)[0]; + mrb_value str = mrb_format(mrb, "unknown keyword: %S", key1); + mrb_exc_set(mrb, mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str)); + goto L_RAISE; + } NEXT; } CASE(OP_KDICT, B) { - /* not implemented yet */ + regs[a] = regs[mrb->c->ci->argc]; NEXT; } @@ -2064,9 +2141,10 @@ RETRY_TRY_BLOCK: } CASE(OP_BLKPUSH, BS) { - int m1 = (b>>10)&0x3f; - int r = (b>>9)&0x1; - int m2 = (b>>4)&0x1f; + int m1 = (b>>11)&0x3f; + int r = (b>>10)&0x1; + int m2 = (b>>5)&0x1f; + int kd = (b>>4)&0x1; int lv = (b>>0)&0xf; mrb_value *stack; @@ -2084,7 +2162,7 @@ RETRY_TRY_BLOCK: localjump_error(mrb, LOCALJUMP_ERROR_YIELD); goto L_RAISE; } - regs[a] = stack[m1+r+m2]; + regs[a] = stack[m1+r+m2+kd]; NEXT; } diff --git a/test/t/syntax.rb b/test/t/syntax.rb index 299394557..6392509ec 100644 --- a/test/t/syntax.rb +++ b/test/t/syntax.rb @@ -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,183 @@ 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 [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 -- cgit v1.2.3 From beb6e5c299bb411a7f2a9e355e6eeca3aa785c74 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 31 Jul 2018 17:28:42 +0900 Subject: Bytecode support for `mrdb`. --- include/mruby/irep.h | 9 +++++++++ mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c | 8 +++++--- mrbgems/mruby-compiler/core/codegen.c | 13 +++---------- 3 files changed, 17 insertions(+), 13 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/include/mruby/irep.h b/include/mruby/irep.h index c98d008db..7dcf33735 100644 --- a/include/mruby/irep.h +++ b/include/mruby/irep.h @@ -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 */ diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c index 1b17128fd..05a6f3622 100644 --- a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c +++ b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c @@ -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(*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; diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 070aaac51..b8caba3a0 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -296,15 +296,8 @@ on_eval(codegen_scope *s) return FALSE; } -struct mrb_insn_data { - uint8_t insn; - uint16_t a; - uint16_t b; - uint8_t c; -}; - struct mrb_insn_data -mrb_decode_insn(codegen_scope *s, mrb_code *pc) +mrb_decode_insn(mrb_code *pc) { struct mrb_insn_data data = { 0 }; mrb_code insn = READ_B(); @@ -353,7 +346,7 @@ mrb_decode_insn(codegen_scope *s, mrb_code *pc) return data; } -struct mrb_insn_data +static struct mrb_insn_data mrb_last_insn(codegen_scope *s) { if (s->pc == s->lastpc) { @@ -362,7 +355,7 @@ mrb_last_insn(codegen_scope *s) data.insn = OP_NOP; return data; } - return mrb_decode_insn(s, &s->iseq[s->lastpc]); + return mrb_decode_insn(&s->iseq[s->lastpc]); } static mrb_bool -- cgit v1.2.3 From e3b181586c3f433debc7b5c4b7d45f8b8fe91970 Mon Sep 17 00:00:00 2001 From: Ukrainskiy Sergey Date: Thu, 9 Aug 2018 17:14:00 +0900 Subject: Fix weird behavior of the NODE_NEGATE --- mrbgems/mruby-compiler/core/codegen.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index fec747f0c..ceedb49ad 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2323,12 +2323,11 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_NEGATE: { nt = nint(tree->car); - tree = tree->cdr; switch (nt) { #ifndef MRB_WITHOUT_FLOAT case NODE_FLOAT: if (val) { - char *p = (char*)tree; + char *p = (char*)tree->cdr; mrb_float f = mrb_float_read(p, NULL); int off = new_lit(s, mrb_float_value(s->mrb, -f)); @@ -2340,6 +2339,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_INT: if (val) { + tree = tree->cdr; char *p = (char*)tree->car; int base = nint(tree->cdr->car); mrb_int i; @@ -2373,13 +2373,10 @@ codegen(codegen_scope *s, node *tree, int val) default: if (val) { - int sym = new_msym(s, mrb_intern_lit(s->mrb, "-")); - - genop(s, MKOP_ABx(OP_LOADI, cursp(), 0)); - push(); + int sym = new_msym(s, mrb_intern_lit(s->mrb, "-@")); codegen(s, tree, VAL); - pop(); pop(); - genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2)); + pop(); + genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 0)); } else { codegen(s, tree, NOVAL); -- cgit v1.2.3 From 672110dbe8b116d2ef5594d908e5e2bfe2231a18 Mon Sep 17 00:00:00 2001 From: Ukrainskiy Sergey Date: Thu, 9 Aug 2018 17:57:18 +0900 Subject: Small fix --- mrbgems/mruby-compiler/core/codegen.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index ceedb49ad..471956f92 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2339,9 +2339,8 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_INT: if (val) { - tree = tree->cdr; - char *p = (char*)tree->car; - int base = nint(tree->cdr->car); + char *p = (char*)tree->cdr->car; + int base = nint(tree->cdr->cdr->car); mrb_int i; mrb_code co; mrb_bool overflow; -- cgit v1.2.3 From fbe876b87169c9d5c55e79cc932790297f98a1be Mon Sep 17 00:00:00 2001 From: Ukrainskiy Sergey Date: Fri, 10 Aug 2018 06:44:19 +0900 Subject: Added push() after OP_SEND --- mrbgems/mruby-compiler/core/codegen.c | 1 + 1 file changed, 1 insertion(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 471956f92..12725f4f3 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2376,6 +2376,7 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree, VAL); pop(); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 0)); + push(); } else { codegen(s, tree, NOVAL); -- cgit v1.2.3 From eeb6d5658d9e29ad24f211a3236eb02abcdb136c Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 May 2018 15:19:06 +0900 Subject: New bytecode implementation of mruby VM. --- mrbgems/mruby-compiler/core/codegen.c | 100 ++++++++++++++++++++++++++++++++++ src/vm.c | 16 +++++- 2 files changed, 113 insertions(+), 3 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index b8caba3a0..8e72abda2 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -445,8 +445,108 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep) break; default: goto normal; +======= +struct mrb_insn_data { + uint8_t insn; + uint16_t a; + uint16_t b; + uint8_t c; +}; + +struct mrb_insn_data +mrb_decode_insn(codegen_scope *s, mrb_code *pc) +{ + struct mrb_insn_data data = { 0 }; + mrb_code insn = READ_B(); + uint16_t a = 0; + uint16_t b = 0; + uint8_t c = 0; + + switch (insn) { +#define FETCH_Z() /* empty */ +#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x (); break; +#include "mruby/ops.h" +#undef OPCODE + } + switch (insn) { + case OP_EXT1: + insn = READ_B(); + switch (insn) { +#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); break; +#include "mruby/ops.h" +#undef OPCODE + } + break; + case OP_EXT2: + insn = READ_B(); + switch (insn) { +#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); break; +#include "mruby/ops.h" +#undef OPCODE + } + break; + case OP_EXT3: + insn = READ_B(); + switch (insn) { +#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); break; +#include "mruby/ops.h" +#undef OPCODE + } + break; + default: + break; + } + data.insn = insn; + data.a = a; + data.b = b; + data.c = c; + return data; +} + +struct mrb_insn_data +mrb_last_insn(codegen_scope *s) +{ + if (s->pc == s->lastpc) { + struct mrb_insn_data data; + + data.insn = OP_NOP; + return data; + } + return mrb_decode_insn(s, &s->iseq[s->lastpc]); +} + +static mrb_bool +no_peephole(codegen_scope *s) +{ + return no_optimize(s) || s->lastlabel == s->pc || s->pc == 0 || s->pc == s->lastpc; +} + +static uint16_t +genjmp(codegen_scope *s, mrb_code i, uint16_t pc) +{ + uint16_t pos; + + s->lastpc = s->pc; + gen_B(s, i); + pos = s->pc; + gen_S(s, pc); + return pos; +} + +static uint16_t +genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val) +{ + uint16_t pos; + + if (!no_peephole(s) && !val) { + struct mrb_insn_data data = mrb_last_insn(s); + + if (data.insn == OP_MOVE && data.a == a) { + s->pc = s->lastpc; + a = data.b; } } + return genop(s, i); } static void diff --git a/src/vm.c b/src/vm.c index b8feb52db..d206f9675 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1069,6 +1069,16 @@ RETRY_TRY_BLOCK: NEXT; } + CASE(OP_LOADI, BB) { + SET_INT_VALUE(regs[a], b); + NEXT; + } + + CASE(OP_LOADINEG, BB) { + SET_INT_VALUE(regs[a], -b); + NEXT; + } + CASE(OP_LOADI__1,B) goto L_LOADI; CASE(OP_LOADI_0,B) goto L_LOADI; CASE(OP_LOADI_1,B) goto L_LOADI; @@ -1131,12 +1141,12 @@ RETRY_TRY_BLOCK: } CASE(OP_GETIV, BB) { - regs[a] = mrb_vm_iv_get(mrb, syms[b]); + regs[a] = mrb_iv_get(mrb, regs[0], syms[b]); NEXT; } CASE(OP_SETIV, BB) { - mrb_vm_iv_set(mrb, syms[b], regs[a]); + mrb_iv_set(mrb, regs[0], syms[b], regs[a]); NEXT; } @@ -2470,7 +2480,7 @@ RETRY_TRY_BLOCK: #ifdef MRB_WORD_BOXING { mrb_float x = mrb_float(regs[a]); - SET_FLOAT_VALUE(mrb, regs[a], x - GETARG_C(i)); + SET_FLOAT_VALUE(mrb, regs[a], x - c); } #else mrb_float(regs_a[0]) -= c; -- cgit v1.2.3 From 162243d95cb8f07f98defa5c391b3db40e784576 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 25 Aug 2018 07:40:09 +0900 Subject: Remove `arg_value` from `parse.y`. --- mrbgems/mruby-compiler/core/parse.y | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 44cb28608..28a2b8d5f 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -1179,7 +1179,7 @@ heredoc_end(parser_state *p) %type heredoc words symbols %type call_op call_op2 /* 0:'&.', 1:'.', 2:'::' */ -%type args_tail opt_args_tail f_kwarg f_kw arg_value f_kwrest +%type args_tail opt_args_tail f_kwarg f_kw f_kwrest %type f_block_kwarg f_block_kw block_args_tail opt_block_args_tail %type f_label @@ -3103,11 +3103,9 @@ f_arglist : '(' f_args rparen f_label : tIDENTIFIER tLABEL_TAG ; -arg_value : arg - ; - -f_kw : f_label arg_value +f_kw : f_label arg { + void_expr_error(p, $2); $$ = new_kw_arg(p, $1, $2); } | f_label @@ -3450,8 +3448,9 @@ assoc : arg tASSOC arg $$ = cons(new_sym(p, new_strsym(p, $1)), $3); } } - | tDSTAR arg_value + | tDSTAR arg { + void_expr_error(p, $2); $$ = cons(cons((node*)NODE_KW_REST_ARGS, 0), $2); } ; -- cgit v1.2.3 From e5eb7ef046f5d441bf3930666c6622b0503b7302 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 25 Aug 2018 07:40:46 +0900 Subject: Add `NODE_KW_HASH` support in `mrb_parser_dump()`. --- mrbgems/mruby-compiler/core/parse.y | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 28a2b8d5f..5e6cda236 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -6403,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); -- cgit v1.2.3 From b06dad43fa37ea0edc870202c5d3ad271efacf03 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 25 Aug 2018 09:07:00 +0900 Subject: Remove unused `NODE_*` constants from `node.h`. --- mrbgems/mruby-compiler/core/node.h | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/node.h b/mrbgems/mruby-compiler/core/node.h index af71332e7..219bddab0 100644 --- a/mrbgems/mruby-compiler/core/node.h +++ b/mrbgems/mruby-compiler/core/node.h @@ -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,7 +37,6 @@ enum node_type { NODE_CALL, NODE_SCALL, NODE_FCALL, - NODE_VCALL, NODE_SUPER, NODE_ZSUPER, NODE_ARRAY, @@ -58,8 +54,6 @@ enum node_type { NODE_NTH_REF, NODE_BACK_REF, NODE_MATCH, - NODE_MATCH2, - NODE_MATCH3, NODE_INT, NODE_FLOAT, NODE_NEGATE, @@ -72,13 +66,10 @@ enum node_type { NODE_REGX, NODE_DREGX, NODE_DREGX_ONCE, - NODE_LIST, NODE_ARG, NODE_ARGS_TAIL, NODE_KW_ARG, NODE_KW_REST_ARGS, - NODE_ARGSCAT, - NODE_ARGSPUSH, NODE_SPLAT, NODE_TO_ARY, NODE_SVALUE, @@ -92,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, -- cgit v1.2.3 From 49d1b168221221b7e810f001d88e16ebc94378fd Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 25 Aug 2018 09:10:37 +0900 Subject: Hash splat `**` should not be ignored. Implemented by adding `OP_HASHCAT` that merges hashes. --- include/mruby/ops.h | 1 + mrbgems/mruby-compiler/core/codegen.c | 37 ++++++++++++++++++++++++++--------- src/codedump.c | 6 +++++- src/vm.c | 5 +++++ 4 files changed, 39 insertions(+), 10 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/include/mruby/ops.h b/include/mruby/ops.h index b8fc89d43..f23bb1b0b 100644 --- a/include/mruby/ops.h +++ b/include/mruby/ops.h @@ -94,6 +94,7 @@ 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) */ diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 8e72abda2..bf5cc14b0 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1874,15 +1874,32 @@ codegen(codegen_scope *s, node *tree, int val) mrb_bool update = FALSE; while (tree) { - if (nt == NODE_KW_HASH && - nint(tree->car->car->car) == NODE_KW_REST_ARGS) { - tree = tree->cdr; - continue; + if (nint(tree->car->car->car) == NODE_KW_REST_ARGS) { + if (len > 0) { + pop_n(len*2); + if (!update) { + genop_2(s, OP_HASH, cursp(), len); + } + else { + pop(); + genop_2(s, OP_HASHADD, cursp(), len); + } + push(); + } + codegen(s, tree->car->cdr, VAL); + if (len > 0) { + pop(); pop(); + genop_1(s, OP_HASHCAT, cursp()); + push(); + } + update = TRUE; + len = 0; + } + else { + codegen(s, tree->car->car, VAL); + codegen(s, tree->car->cdr, VAL); + len++; } - - codegen(s, tree->car->car, val); - codegen(s, tree->car->cdr, val); - len++; tree = tree->cdr; if (val && len == 255) { pop_n(len*2); @@ -1905,7 +1922,9 @@ codegen(codegen_scope *s, node *tree, int val) } else { pop(); - genop_2(s, OP_HASHADD, cursp(), len); + if (len > 0) { + genop_2(s, OP_HASHADD, cursp(), len); + } } push(); } diff --git a/src/codedump.c b/src/codedump.c index 842d40bdf..9174ebe3d 100644 --- a/src/codedump.c +++ b/src/codedump.c @@ -416,7 +416,11 @@ codedump(mrb_state *mrb, mrb_irep *irep) print_lv_a(mrb, irep, a); break; CASE(OP_HASHADD, BB): - printf("OP_HASHADD\tR%d\t%d", a, b); + 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; diff --git a/src/vm.c b/src/vm.c index 8332158f7..b47469ebf 100644 --- a/src/vm.c +++ b/src/vm.c @@ -2710,6 +2710,11 @@ RETRY_TRY_BLOCK: mrb_gc_arena_restore(mrb, ai); NEXT; } + CASE(OP_HASHCAT, B) { + mrb_hash_merge(mrb, regs[a], regs[a+1]); + mrb_gc_arena_restore(mrb, ai); + NEXT; + } CASE(OP_LAMBDA, BB) c = OP_L_LAMBDA; -- cgit v1.2.3 From d79dbd92f9104712c6cf41ab3c029dec318a757d Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 25 Aug 2018 09:49:20 +0900 Subject: fixup! New bytecode implementation of mruby VM. --- mrbgems/mruby-compiler/core/codegen.c | 100 ---------------------------------- src/vm.c | 10 ---- 2 files changed, 110 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index bf5cc14b0..075945b3b 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -445,108 +445,8 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep) break; default: goto normal; -======= -struct mrb_insn_data { - uint8_t insn; - uint16_t a; - uint16_t b; - uint8_t c; -}; - -struct mrb_insn_data -mrb_decode_insn(codegen_scope *s, mrb_code *pc) -{ - struct mrb_insn_data data = { 0 }; - mrb_code insn = READ_B(); - uint16_t a = 0; - uint16_t b = 0; - uint8_t c = 0; - - switch (insn) { -#define FETCH_Z() /* empty */ -#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x (); break; -#include "mruby/ops.h" -#undef OPCODE - } - switch (insn) { - case OP_EXT1: - insn = READ_B(); - switch (insn) { -#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); break; -#include "mruby/ops.h" -#undef OPCODE - } - break; - case OP_EXT2: - insn = READ_B(); - switch (insn) { -#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); break; -#include "mruby/ops.h" -#undef OPCODE - } - break; - case OP_EXT3: - insn = READ_B(); - switch (insn) { -#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); break; -#include "mruby/ops.h" -#undef OPCODE - } - break; - default: - break; - } - data.insn = insn; - data.a = a; - data.b = b; - data.c = c; - return data; -} - -struct mrb_insn_data -mrb_last_insn(codegen_scope *s) -{ - if (s->pc == s->lastpc) { - struct mrb_insn_data data; - - data.insn = OP_NOP; - return data; - } - return mrb_decode_insn(s, &s->iseq[s->lastpc]); -} - -static mrb_bool -no_peephole(codegen_scope *s) -{ - return no_optimize(s) || s->lastlabel == s->pc || s->pc == 0 || s->pc == s->lastpc; -} - -static uint16_t -genjmp(codegen_scope *s, mrb_code i, uint16_t pc) -{ - uint16_t pos; - - s->lastpc = s->pc; - gen_B(s, i); - pos = s->pc; - gen_S(s, pc); - return pos; -} - -static uint16_t -genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val) -{ - uint16_t pos; - - if (!no_peephole(s) && !val) { - struct mrb_insn_data data = mrb_last_insn(s); - - if (data.insn == OP_MOVE && data.a == a) { - s->pc = s->lastpc; - a = data.b; } } - return genop(s, i); } static void diff --git a/src/vm.c b/src/vm.c index b47469ebf..d0ea6b3bd 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1069,16 +1069,6 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_LOADI, BB) { - SET_INT_VALUE(regs[a], b); - NEXT; - } - - CASE(OP_LOADINEG, BB) { - SET_INT_VALUE(regs[a], -b); - NEXT; - } - CASE(OP_LOADI__1,B) goto L_LOADI; CASE(OP_LOADI_0,B) goto L_LOADI; CASE(OP_LOADI_1,B) goto L_LOADI; -- cgit v1.2.3 From 471288f37d18e640f98029fabcdcb7ee16b95d93 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 25 Aug 2018 16:58:01 +0900 Subject: Reduce integer casting warnings. --- include/mruby.h | 2 +- mrbgems/mruby-compiler/core/codegen.c | 8 ++++---- mrbgems/mruby-eval/src/eval.c | 6 +++--- src/codedump.c | 6 +++--- src/load.c | 4 ++-- src/vm.c | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/include/mruby.h b/include/mruby.h index 542d7491f..872396899 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -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; diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 075945b3b..a835a563e 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -400,7 +400,7 @@ genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val) } else { gen_B(s, i); - gen_B(s, a); + gen_B(s, (uint8_t)a); pos = s->pc; gen_S(s, pc); } @@ -494,10 +494,10 @@ gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst, uint16_t idx) if (data.b >= 128) goto normal; s->pc = s->lastpc; if (op == OP_ADD) { - genop_3(s, OP_ADDI, dst, idx, data.b); + genop_3(s, OP_ADDI, dst, idx, (uint8_t)data.b); } else { - genop_3(s, OP_SUBI, dst, idx, data.b); + genop_3(s, OP_SUBI, dst, idx, (uint8_t)data.b); } break; default: @@ -2441,7 +2441,7 @@ codegen(codegen_scope *s, node *tree, int val) #endif if (i == -1) genop_1(s, OP_LOADI__1, cursp()); else if (i >= -0xffff) { - genop_2(s, OP_LOADINEG, cursp(), -i); + genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i); } else { int off = new_lit(s, mrb_fixnum_value(i)); diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c index f1e50e83d..b9c87f6d1 100644 --- a/mrbgems/mruby-eval/src/eval.c +++ b/mrbgems/mruby-eval/src/eval.c @@ -154,7 +154,7 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top) if (arg != 0) { /* must replace */ irep->iseq[i] = insn = OP_SETUPVAR; - irep->iseq[i+1] = b; + irep->iseq[i+1] = (mrb_code)b; irep->iseq[i+2] = arg >> 8; irep->iseq[i+3] = arg & 0xff; } @@ -169,7 +169,7 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top) int lev = c+1; mrb_irep *tmp = search_irep(top, bnest, lev, irep); if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) { - mrb_code arg = search_variable(mrb, tmp->lv[b-1].name, bnest); + uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest); if (arg != 0) { /* must replace */ irep->iseq[i] = OP_GETUPVAR; @@ -188,7 +188,7 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top) int lev = c+1; mrb_irep *tmp = search_irep(top, bnest, lev, irep); if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) { - mrb_code arg = search_variable(mrb, tmp->lv[b-1].name, bnest); + uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest); if (arg != 0) { /* must replace */ irep->iseq[i] = OP_SETUPVAR; diff --git a/src/codedump.c b/src/codedump.c index 9174ebe3d..80802778f 100644 --- a/src/codedump.c +++ b/src/codedump.c @@ -48,7 +48,7 @@ print_lv_ab(mrb_state *mrb, mrb_irep *irep, uint16_t a, uint16_t b) #endif static void -print_header(mrb_irep *irep, int i) +print_header(mrb_irep *irep, ptrdiff_t i) { int32_t line; @@ -60,7 +60,7 @@ print_header(mrb_irep *irep, int i) printf("%5d ", line); } - printf("%03d ", i); + printf("%03d ", (int)i); } #define CASE(insn,ops) case insn: FETCH_ ## ops (); L_ ## insn @@ -91,7 +91,7 @@ codedump(mrb_state *mrb, mrb_irep *irep) pc = irep->iseq; pcend = pc + irep->ilen; while (pc < pcend) { - int i; + ptrdiff_t i; uint32_t a; uint16_t b; uint8_t c; diff --git a/src/load.c b/src/load.c index 20878aa56..54b50b14d 100644 --- a/src/load.c +++ b/src/load.c @@ -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); @@ -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))) { diff --git a/src/vm.c b/src/vm.c index d0ea6b3bd..44472e311 100644 --- a/src/vm.c +++ b/src/vm.c @@ -218,7 +218,7 @@ stack_extend_alloc(mrb_state *mrb, int room) } MRB_API void -mrb_stack_extend(mrb_state *mrb, int room) +mrb_stack_extend(mrb_state *mrb, mrb_int room) { if (mrb->c->stack + room >= mrb->c->stend) { stack_extend_alloc(mrb, room); -- cgit v1.2.3 From bc88fc6ed15b9837659071817d93885e4910cba5 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 29 Aug 2018 12:31:48 +0900 Subject: Check iseq buffer size before code emission; fix #4090 The type of `s->pc` is now `uint16_t` that can be overflowed easily. Need more checks. --- mrbgems/mruby-compiler/core/codegen.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index a835a563e..13f5aa053 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -151,11 +151,11 @@ new_label(codegen_scope *s) static void emit_B(codegen_scope *s, uint32_t pc, uint8_t i) { + if (pc >= MAXARG_S || s->icapa >= MAXARG_S) { + codegen_error(s, "too big code block"); + } if (pc >= s->icapa) { s->icapa *= 2; - if (pc >= MAXARG_S) { - codegen_error(s, "too big code block"); - } if (s->icapa > MAXARG_S) { s->icapa = MAXARG_S; } @@ -184,7 +184,8 @@ emit_S(codegen_scope *s, int pc, uint16_t i) static void gen_B(codegen_scope *s, uint8_t i) { - emit_B(s, s->pc++, i); + emit_B(s, s->pc, i); + s->pc++; } static void @@ -248,7 +249,6 @@ genop_2(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b) static void genop_3(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b, uint8_t c) { - s->lastpc = s->pc; genop_2(s, i, a, b); gen_B(s, c); } @@ -256,7 +256,6 @@ genop_3(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b, uint8_t c) static void genop_2S(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b) { - s->lastpc = s->pc; genop_1(s, i, a); gen_S(s, b); } -- cgit v1.2.3 From 75a01af710309e4fc53db285c9018e233c61cb56 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 30 Aug 2018 01:23:17 +0900 Subject: Remove consequent `OP_RETURN` by peephole optimization. --- mrbgems/mruby-compiler/core/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 0d47b236d..835cee817 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -461,7 +461,7 @@ gen_return(codegen_scope *s, uint8_t op, uint16_t src) s->pc = s->lastpc; genop_1(s, op, data.b); } - else { + else if (data.insn != OP_RETURN) { genop_1(s, op, src); } } -- cgit v1.2.3 From 20c0c6330f38c6a1a969a06bc5a3bf56d39f466f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 1 Sep 2018 17:14:54 +0900 Subject: Too much peephole optimization in `gen_call`; fix #4091 It causes trouble for safe navigation operator. --- mrbgems/mruby-compiler/core/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 835cee817..efd20d908 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -979,7 +979,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) codegen(s, tree->car, VAL); /* receiver */ if (safe) { int recv = cursp()-1; - gen_move(s, cursp(), recv, 0); + gen_move(s, cursp(), recv, 1); skip = genjmp2(s, OP_JMPNIL, cursp(), 0, val); } idx = new_sym(s, sym); -- cgit v1.2.3 From a657117e4e5fbde4434661794f80a93dde55d70d Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 1 Sep 2018 17:36:35 +0900 Subject: Avoid warning in MSVC compilation. --- mrbgems/mruby-compiler/core/codegen.c | 6 +++--- mrbgems/mruby-socket/test/sockettest.c | 1 + src/vm.c | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index efd20d908..98b215f6b 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2378,9 +2378,9 @@ codegen(codegen_scope *s, node *tree, int val) #endif { if (i == -1) genop_1(s, OP_LOADI__1, cursp()); - else if (i < 0) genop_2(s, OP_LOADINEG, cursp(), -i); - else if (i < 8) genop_1(s, OP_LOADI_0 + i, cursp()); - else if (i <= 0xffff) genop_2(s, OP_LOADI, cursp(), i); + else if (i < 0) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i); + else if (i < 8) genop_1(s, OP_LOADI_0 + (uint8_t)i, cursp()); + else if (i <= 0xffff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i); else { int off = new_lit(s, mrb_fixnum_value(i)); genop_2(s, OP_LOADL, cursp(), off); diff --git a/mrbgems/mruby-socket/test/sockettest.c b/mrbgems/mruby-socket/test/sockettest.c index 086bc4892..3017c7cc1 100644 --- a/mrbgems/mruby-socket/test/sockettest.c +++ b/mrbgems/mruby-socket/test/sockettest.c @@ -12,6 +12,7 @@ #include #include +#define open _open #define close _close #define unlink _unlink diff --git a/src/vm.c b/src/vm.c index 77d9316d4..70c27da57 100644 --- a/src/vm.c +++ b/src/vm.c @@ -176,7 +176,7 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase, size_t oldsize /** def rec ; $deep =+ 1 ; if $deep > 1000 ; return 0 ; end ; rec ; end */ static void -stack_extend_alloc(mrb_state *mrb, int room) +stack_extend_alloc(mrb_state *mrb, mrb_int room) { mrb_value *oldbase = mrb->c->stbase; mrb_value *newstack; @@ -333,7 +333,7 @@ ecall(mrb_state *mrb) struct REnv *env; ptrdiff_t cioff; int ai = mrb_gc_arena_save(mrb); - uint8_t i = --c->eidx; + uint16_t i = --c->eidx; int nregs; if (i<0) return; -- cgit v1.2.3 From 4cd4c64266e7d9075b09e66c4f7b3546a76120f4 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 6 Sep 2018 14:40:21 +0900 Subject: Need to support multiple `**` splats in argument list; fix #4106 --- mrbgems/mruby-compiler/core/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 98b215f6b..8be9a8ebe 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1786,7 +1786,7 @@ codegen(codegen_scope *s, node *tree, int val) push(); } codegen(s, tree->car->cdr, VAL); - if (len > 0) { + if (len > 0 || update) { pop(); pop(); genop_1(s, OP_HASHCAT, cursp()); push(); -- cgit v1.2.3 From 366848996a6cce8e733246bce6c3f76d797003bb Mon Sep 17 00:00:00 2001 From: dearblue Date: Fri, 7 Sep 2018 00:22:36 +0900 Subject: Clear terminated space --- examples/targets/build_config_android_arm64-v8a.rb | 4 ++-- examples/targets/build_config_android_armeabi.rb | 4 ++-- mrbgems/mruby-array-ext/test/array.rb | 2 +- mrbgems/mruby-compiler/core/codegen.c | 8 ++++---- mrbgems/mruby-random/src/random.c | 2 +- src/array.c | 2 +- src/codedump.c | 2 +- src/gc.c | 2 +- src/numeric.c | 2 +- src/variable.c | 10 +++++----- src/vm.c | 4 ++-- tasks/toolchains/gcc.rake | 2 +- test/t/kernel.rb | 2 +- test/t/syntax.rb | 6 +++--- 14 files changed, 26 insertions(+), 26 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/examples/targets/build_config_android_arm64-v8a.rb b/examples/targets/build_config_android_arm64-v8a.rb index 6188c13ec..70b0f4b97 100644 --- a/examples/targets/build_config_android_arm64-v8a.rb +++ b/examples/targets/build_config_android_arm64-v8a.rb @@ -15,8 +15,8 @@ end # Requires Android NDK r13 or later. MRuby::CrossBuild.new('android-arm64-v8a') do |conf| - params = { - :arch => 'arm64-v8a', + params = { + :arch => 'arm64-v8a', :platform => 'android-24', :toolchain => :clang, } diff --git a/examples/targets/build_config_android_armeabi.rb b/examples/targets/build_config_android_armeabi.rb index b7eb33a92..17330242a 100644 --- a/examples/targets/build_config_android_armeabi.rb +++ b/examples/targets/build_config_android_armeabi.rb @@ -15,8 +15,8 @@ end # Requires Android NDK r13 or later. MRuby::CrossBuild.new('android-armeabi') do |conf| - params = { - :arch => 'armeabi', + params = { + :arch => 'armeabi', :platform => 'android-24', :toolchain => :clang, } diff --git a/mrbgems/mruby-array-ext/test/array.rb b/mrbgems/mruby-array-ext/test/array.rb index 7d810acc2..4f54c65c3 100644 --- a/mrbgems/mruby-array-ext/test/array.rb +++ b/mrbgems/mruby-array-ext/test/array.rb @@ -418,5 +418,5 @@ assert('Array#transpose') do assert_equal([[1], [2], [3]].transpose, [[1,2,3]]) assert_equal([[1,2], [3,4], [5,6]].transpose, [[1,3,5], [2,4,6]]) assert_raise(TypeError) { [1].transpose } - assert_raise(IndexError) { [[1], [2,3,4]].transpose } + assert_raise(IndexError) { [[1], [2,3,4]].transpose } end diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 8be9a8ebe..74504ffd1 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -419,7 +419,7 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep) } else { struct mrb_insn_data data = mrb_last_insn(s); - + switch (data.insn) { case OP_MOVE: if (dst == src) return; /* remove useless MOVE */ @@ -456,7 +456,7 @@ gen_return(codegen_scope *s, uint8_t op, uint16_t src) } else { struct mrb_insn_data data = mrb_last_insn(s); - + if (data.insn == OP_MOVE && src == data.a) { s->pc = s->lastpc; genop_1(s, op, data.b); @@ -764,7 +764,7 @@ lambda_body(codegen_scope *s, node *tree, int blk) kd = tail && tail->cdr->cdr->car? 1 : 0; /* block argument? */ ba = tail && tail->cdr->cdr->cdr->car ? 1 : 0; - + if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) { codegen_error(s, "too many formal arguments"); } @@ -3118,7 +3118,7 @@ generate_code(mrb_state *mrb, parser_state *p, int val) scope->filename_index = p->current_filename_index; MRB_TRY(&scope->jmp) { - mrb->jmp = &scope->jmp; + mrb->jmp = &scope->jmp; /* prepare irep */ codegen(scope, p->tree, val); proc = mrb_proc_new(mrb, scope->irep); diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index b865244cc..5b926a228 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -219,7 +219,7 @@ mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary) mrb_int j; mrb_value *ptr = RARRAY_PTR(ary); mrb_value tmp; - + j = mrb_fixnum(mrb_random_mt_rand(mrb, random, mrb_fixnum_value(RARRAY_LEN(ary)))); diff --git a/src/array.c b/src/array.c index 2152e292d..f0c32bc7f 100644 --- a/src/array.c +++ b/src/array.c @@ -231,7 +231,7 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len) static void ary_shrink_capa(mrb_state *mrb, struct RArray *a) { - + mrb_int capa; if (ARY_EMBED_P(a)) return; diff --git a/src/codedump.c b/src/codedump.c index 454b16b36..30a14f937 100644 --- a/src/codedump.c +++ b/src/codedump.c @@ -516,7 +516,7 @@ codedump(mrb_state *mrb, mrb_irep *irep) #undef OPCODE } break; - + default: printf("OP_unknown (0x%x)\n", ins); break; diff --git a/src/gc.c b/src/gc.c index 9858e45fc..e429603dd 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1559,7 +1559,7 @@ mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, vo mrb->jmp = &c_jmp; gc_each_objects(mrb, &mrb->gc, callback, data); mrb->jmp = prev_jmp; - mrb->gc.iterating = iterating; + mrb->gc.iterating = iterating; } MRB_CATCH(&c_jmp) { mrb->gc.iterating = iterating; mrb->jmp = prev_jmp; diff --git a/src/numeric.c b/src/numeric.c index c3e7d77a3..f7f0318e8 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -433,7 +433,7 @@ flo_shift(mrb_state *mrb, mrb_value x, mrb_int width) val = trunc(val); #else if (val > 0){ - val = floor(val); + val = floor(val); } else { val = ceil(val); } diff --git a/src/variable.c b/src/variable.c index 00bdb4b8d..506b4b63e 100644 --- a/src/variable.c +++ b/src/variable.c @@ -790,7 +790,7 @@ mrb_vm_const_get(mrb_state *mrb, mrb_sym sym) proc = mrb->c->ci->proc; while (proc) { c2 = MRB_PROC_TARGET_CLASS(proc); - if (c2 && iv_get(mrb, c2->iv, sym, &v)) { + if (c2 && iv_get(mrb, c2->iv, sym, &v)) { return v; } proc = proc->upper; @@ -988,25 +988,25 @@ struct csym_arg { struct RClass *c; mrb_sym sym; }; - + static int csym_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) { struct csym_arg *a = (struct csym_arg*)p; struct RClass *c = a->c; - + if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) { a->sym = sym; return 1; /* stop iteration */ } return 0; } - + static mrb_sym find_class_sym(mrb_state *mrb, struct RClass *outer, struct RClass *c) { struct csym_arg arg; - + if (!outer) return 0; if (outer == c) return 0; arg.c = c; diff --git a/src/vm.c b/src/vm.c index 9c4580fb3..14c42984e 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1818,7 +1818,7 @@ RETRY_TRY_BLOCK: } regs[blk_pos] = *blk; /* move block */ if (kd) regs[len + 1] = kdict; - + /* copy mandatory and optional arguments */ if (argv0 != argv) { value_move(®s[1], argv, argc-mlen); /* m1 + o */ @@ -2077,7 +2077,7 @@ RETRY_TRY_BLOCK: break; case OP_R_BREAK: if (MRB_PROC_STRICT_P(proc)) goto NORMAL_RETURN; - if (MRB_PROC_ORPHAN_P(proc)) { + if (MRB_PROC_ORPHAN_P(proc)) { mrb_value exc; L_BREAK_ERROR: diff --git a/tasks/toolchains/gcc.rake b/tasks/toolchains/gcc.rake index fc2e0bff3..e0eb36f26 100644 --- a/tasks/toolchains/gcc.rake +++ b/tasks/toolchains/gcc.rake @@ -55,7 +55,7 @@ MRuby::Toolchain.new(:gcc) do |conf, _params| @header_search_paths end end - + def conf.enable_sanitizer(*opts) fail 'sanitizer already set' if @sanitizer_list diff --git a/test/t/kernel.rb b/test/t/kernel.rb index a730bdb24..74176fbd0 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -157,7 +157,7 @@ assert('Kernel#clone', '15.3.1.3.8') do assert_true a.respond_to?(:test) assert_false b.respond_to?(:test) assert_true c.respond_to?(:test) - + a.freeze d = a.clone assert_true d.frozen? diff --git a/test/t/syntax.rb b/test/t/syntax.rb index c5405aa9c..883cbd1ba 100644 --- a/test/t/syntax.rb +++ b/test/t/syntax.rb @@ -454,15 +454,15 @@ assert('multiline comments work correctly') do =begin this is a comment with nothing after begin and end =end -=begin this is a comment +=begin this is a comment this is a comment with extra after =begin =end =begin this is a comment that has =end with spaces after it -=end +=end =begin this is a comment this is a comment that has extra after =begin and =end with spaces after it -=end +=end line = __LINE__ =begin this is a comment this is a comment that has extra after =begin and =end with tabs after it -- cgit v1.2.3 From d2313aebd6940df8d3fec53c6397bc8c0cde9cff Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 12 Oct 2018 23:26:14 +0900 Subject: Fixed broken stack consistency; fix #4135 --- mrbgems/mruby-compiler/core/codegen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 74504ffd1..4ebd4cd93 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1795,8 +1795,8 @@ codegen(codegen_scope *s, node *tree, int val) len = 0; } else { - codegen(s, tree->car->car, VAL); - codegen(s, tree->car->cdr, VAL); + codegen(s, tree->car->car, val); + codegen(s, tree->car->cdr, val); len++; } tree = tree->cdr; -- cgit v1.2.3 From fdd5ce8fac8f306f71f336f07f0a537b8626e6d6 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 13 Oct 2018 00:31:13 +0900 Subject: Fixed a bug caused by too much optimization; fix #4137 --- mrbgems/mruby-compiler/core/codegen.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 4ebd4cd93..8ab1b9bc3 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1969,9 +1969,9 @@ codegen(codegen_scope *s, node *tree, int val) } } /* copy receiver and arguments */ - gen_move(s, cursp(), base, 0); + gen_move(s, cursp(), base, 1); for (i=0; i= 0) { - gen_move(s, vsp, cursp(), 0); + gen_move(s, vsp, cursp(), 1); } pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val); } @@ -1998,7 +1998,7 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree->cdr->cdr->car, VAL); pop(); if (val && vsp >= 0) { - gen_move(s, vsp, cursp(), 0); + gen_move(s, vsp, cursp(), 1); } if (nint(tree->car->car) == NODE_CALL) { if (callargs == CALL_MAXARGS) { -- cgit v1.2.3 From b37b31208152fdee0cb99e00cffec0b9e57040c6 Mon Sep 17 00:00:00 2001 From: take-cheeze Date: Mon, 29 Oct 2018 13:56:20 +0900 Subject: Rename libmruby stuff to avoid confusion --- Rakefile | 4 ++-- lib/mruby/build.rb | 18 ++++++++++++++++-- lib/mruby/gem.rb | 2 +- mrbgems/mruby-bin-mrbc/mrbgem.rake | 2 +- mrbgems/mruby-bin-mruby-config/mrbgem.rake | 2 +- mrbgems/mruby-compiler/mrbgem.rake | 2 +- mrbgems/mruby-test/mrbgem.rake | 5 +---- mrblib/mrblib.rake | 2 +- src/mruby_core.rake | 4 ++-- tasks/libmruby.rake | 6 +++--- tasks/mrbgems.rake | 2 +- 11 files changed, 30 insertions(+), 19 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/Rakefile b/Rakefile index d2ad9044c..20b6096f5 100644 --- a/Rakefile +++ b/Rakefile @@ -65,7 +65,7 @@ MRuby.each_target do |target| exec = exefile("#{build_dir}/bin/#{bin}") objs = Dir.glob("#{current_dir}/tools/#{bin}/*.{c,cpp,cxx,cc}").map { |f| objfile(f.pathmap("#{current_build_dir}/tools/#{bin}/%n")) } - file exec => objs + [libfile("#{build_dir}/lib/libmruby")] do |t| + file exec => objs + target.libraries do |t| gem_flags = gems.map { |g| g.linker.flags } gem_flags_before_libraries = gems.map { |g| g.linker.flags_before_libraries } gem_flags_after_libraries = gems.map { |g| g.linker.flags_after_libraries } @@ -100,7 +100,7 @@ MRuby.each_target do |target| end depfiles += MRuby.targets.map { |n, t| - [t.libfile("#{t.build_dir}/lib/libmruby")] + t.libraries }.flatten depfiles += MRuby.targets.reject { |n, t| n == 'host' }.map { |n, t| diff --git a/lib/mruby/build.rb b/lib/mruby/build.rb index 047ae13dc..7a0f7a759 100644 --- a/lib/mruby/build.rb +++ b/lib/mruby/build.rb @@ -45,9 +45,11 @@ module MRuby include Rake::DSL include LoadGems attr_accessor :name, :bins, :exts, :file_separator, :build_dir, :gem_clone_dir - attr_reader :libmruby, :gems, :toolchains + attr_reader :libmruby_objs, :gems, :toolchains attr_writer :enable_bintest, :enable_test + alias libmruby libmruby_objs + COMPILERS = %w(cc cxx objc asm) COMMANDS = COMPILERS + %w(linker archiver yacc gperf git exts mrbc) attr_block MRuby::Build::COMMANDS @@ -81,7 +83,7 @@ module MRuby @mrbc = Command::Mrbc.new(self) @bins = [] - @gems, @libmruby = MRuby::Gem::List.new, [] + @gems, @libmruby_objs = MRuby::Gem::List.new, [] @build_mrbtest_lib_only = false @cxx_exception_enabled = false @cxx_exception_disabled = false @@ -327,6 +329,18 @@ EOS puts "================================================" puts end + + def libmruby_static + libfile("#{build_dir}/lib/libmruby") + end + + def libmruby_core_static + libfile("#{build_dir}/lib/libmruby_core") + end + + def libraries + [libmruby_static] + end end # Build class CrossBuild < Build diff --git a/lib/mruby/gem.rb b/lib/mruby/gem.rb index 7e97c34f3..ba4d5d17a 100644 --- a/lib/mruby/gem.rb +++ b/lib/mruby/gem.rb @@ -87,7 +87,7 @@ module MRuby fail "#{name || dir} required to set name, license(s) and author(s)" end - build.libmruby << @objs + build.libmruby_objs << @objs instance_eval(&@build_config_initializer) if @build_config_initializer end diff --git a/mrbgems/mruby-bin-mrbc/mrbgem.rake b/mrbgems/mruby-bin-mrbc/mrbgem.rake index e710b5a49..48b67aedb 100644 --- a/mrbgems/mruby-bin-mrbc/mrbgem.rake +++ b/mrbgems/mruby-bin-mrbc/mrbgem.rake @@ -8,7 +8,7 @@ MRuby::Gem::Specification.new 'mruby-bin-mrbc' do |spec| exec = exefile("#{build.build_dir}/bin/mrbc") mrbc_objs = Dir.glob("#{spec.dir}/tools/mrbc/*.c").map { |f| objfile(f.pathmap("#{spec.build_dir}/tools/mrbc/%n")) }.flatten - file exec => mrbc_objs + [libfile("#{build.build_dir}/lib/libmruby_core")] do |t| + file exec => mrbc_objs + [build.libmruby_core_static] do |t| build.linker.run t.name, t.prerequisites end diff --git a/mrbgems/mruby-bin-mruby-config/mrbgem.rake b/mrbgems/mruby-bin-mruby-config/mrbgem.rake index 32ae2164b..cca7423ac 100644 --- a/mrbgems/mruby-bin-mruby-config/mrbgem.rake +++ b/mrbgems/mruby-bin-mruby-config/mrbgem.rake @@ -20,7 +20,7 @@ MRuby.each_target do @bins << mruby_config make_cfg = "#{build_dir}/lib/libmruby.flags.mak" - file mruby_config_path => [libfile("#{build_dir}/lib/libmruby"), make_cfg] do |t| + file mruby_config_path => [libmruby_static, make_cfg] do |t| FileUtils.copy "#{File.dirname(__FILE__)}/#{mruby_config}", t.name config = Hash[open(make_cfg).read.split("\n").map {|x| a = x.split(/\s*=\s*/, 2); [a[0], a[1].gsub('\\"', '"') ]}] IO.write(t.name, File.open(t.name) {|f| diff --git a/mrbgems/mruby-compiler/mrbgem.rake b/mrbgems/mruby-compiler/mrbgem.rake index e9e0cc2c7..fa191e69b 100644 --- a/mrbgems/mruby-compiler/mrbgem.rake +++ b/mrbgems/mruby-compiler/mrbgem.rake @@ -35,6 +35,6 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec| gperf.run t.name, t.prerequisites.first end - file libfile("#{build.build_dir}/lib/libmruby_core") => core_objs + file build.libmruby_core_static => core_objs build.libmruby << core_objs end diff --git a/mrbgems/mruby-test/mrbgem.rake b/mrbgems/mruby-test/mrbgem.rake index 589fc688a..c9d254bfe 100644 --- a/mrbgems/mruby-test/mrbgem.rake +++ b/mrbgems/mruby-test/mrbgem.rake @@ -16,9 +16,6 @@ MRuby::Gem::Specification.new('mruby-test') do |spec| mlib = clib.ext(exts.object) exec = exefile("#{build.build_dir}/bin/mrbtest") - libmruby = libfile("#{build.build_dir}/lib/libmruby") - libmruby_core = libfile("#{build.build_dir}/lib/libmruby_core") - mrbtest_lib = libfile("#{build_dir}/mrbtest") mrbtest_objs = [] @@ -140,7 +137,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec| end unless build.build_mrbtest_lib_only? - file exec => [driver_obj, mlib, mrbtest_lib, libmruby_core, libmruby] do |t| + file exec => [driver_obj, mlib, mrbtest_lib, build.libmruby_static] do |t| gem_flags = build.gems.map { |g| g.linker.flags } gem_flags_before_libraries = build.gems.map { |g| g.linker.flags_before_libraries } gem_flags_after_libraries = build.gems.map { |g| g.linker.flags_after_libraries } diff --git a/mrblib/mrblib.rake b/mrblib/mrblib.rake index fe4aae1f7..6895d4252 100644 --- a/mrblib/mrblib.rake +++ b/mrblib/mrblib.rake @@ -3,7 +3,7 @@ MRuby.each_target do relative_from_root = File.dirname(__FILE__).relative_path_from(MRUBY_ROOT) current_build_dir = "#{build_dir}/#{relative_from_root}" - self.libmruby << objfile("#{current_build_dir}/mrblib") + self.libmruby_objs << objfile("#{current_build_dir}/mrblib") file objfile("#{current_build_dir}/mrblib") => "#{current_build_dir}/mrblib.c" file "#{current_build_dir}/mrblib.c" => [mrbcfile, __FILE__] + Dir.glob("#{current_dir}/*.rb").sort do |t| diff --git a/src/mruby_core.rake b/src/mruby_core.rake index bb3d7b633..3024c8544 100644 --- a/src/mruby_core.rake +++ b/src/mruby_core.rake @@ -12,9 +12,9 @@ MRuby.each_target do if cxx_exception_enabled? objs += %w(vm error).map { |v| compile_as_cxx "#{current_dir}/#{v}.c", "#{current_build_dir}/#{v}.cxx" } end - self.libmruby << objs + self.libmruby_objs << objs - file libfile("#{build_dir}/lib/libmruby_core") => objs do |t| + file libmruby_core_static => objs do |t| archiver.run t.name, t.prerequisites end end diff --git a/tasks/libmruby.rake b/tasks/libmruby.rake index b6ef29986..ab5a15b4a 100644 --- a/tasks/libmruby.rake +++ b/tasks/libmruby.rake @@ -1,9 +1,9 @@ MRuby.each_target do - file libfile("#{build_dir}/lib/libmruby") => libmruby.flatten do |t| + file libmruby_static => libmruby_objs.flatten do |t| archiver.run t.name, t.prerequisites end - file "#{build_dir}/lib/libmruby.flags.mak" => [__FILE__, libfile("#{build_dir}/lib/libmruby")] do |t| + file "#{build_dir}/lib/libmruby.flags.mak" => [__FILE__, libmruby_static] do |t| FileUtils.mkdir_p File.dirname t.name open(t.name, 'w') do |f| f.puts "MRUBY_CFLAGS = #{cc.all_flags}" @@ -18,7 +18,7 @@ MRuby.each_target do gem_libraries = gems.map { |g| g.linker.libraries } f.puts "MRUBY_LIBS = #{linker.option_library % 'mruby'} #{linker.library_flags(gem_libraries)}" - f.puts "MRUBY_LIBMRUBY_PATH = #{libfile("#{build_dir}/lib/libmruby")}" + f.puts "MRUBY_LIBMRUBY_PATH = #{libmruby_static}" end end task :all => "#{build_dir}/lib/libmruby.flags.mak" diff --git a/tasks/mrbgems.rake b/tasks/mrbgems.rake index e2aeb1514..fb76856e5 100644 --- a/tasks/mrbgems.rake +++ b/tasks/mrbgems.rake @@ -5,7 +5,7 @@ MRuby.each_target do gems.check self # loader all gems - self.libmruby << objfile("#{build_dir}/mrbgems/gem_init") + self.libmruby_objs << objfile("#{build_dir}/mrbgems/gem_init") file objfile("#{build_dir}/mrbgems/gem_init") => ["#{build_dir}/mrbgems/gem_init.c", "#{build_dir}/LEGAL"] file "#{build_dir}/mrbgems/gem_init.c" => [MRUBY_CONFIG, __FILE__] do |t| FileUtils.mkdir_p "#{build_dir}/mrbgems" -- cgit v1.2.3 From 3248de83b6754eecc99d9ab6fdef8bb3575fcd04 Mon Sep 17 00:00:00 2001 From: take-cheeze Date: Mon, 29 Oct 2018 19:17:05 +0900 Subject: Reduce instruction size --- include/mruby/ops.h | 22 ++++++------- include/mruby/symbol.h | 32 ++++++++++++++++++ mrbgems/mruby-compiler/core/codegen.c | 43 ++++++++++++------------ src/symbol.c | 26 +++++++++++++++ src/vm.c | 62 ++++++++++++++++++++++------------- 5 files changed, 130 insertions(+), 55 deletions(-) create mode 100644 include/mruby/symbol.h (limited to 'mrbgems/mruby-compiler') diff --git a/include/mruby/ops.h b/include/mruby/ops.h index f23bb1b0b..7531a5ee2 100644 --- a/include/mruby/ops.h +++ b/include/mruby/ops.h @@ -70,17 +70,17 @@ 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(GE, BB) /* R(a) = R(a)>=R(a+1) (Syms[b]=:>=) */ +OPCODE(ADD, B) /* R(a) = R(a)+R(a+1) */ +OPCODE(ADDI, BB) /* R(a) = R(a)+mrb_int(c) */ +OPCODE(SUB, B) /* R(a) = R(a)-R(a+1) */ +OPCODE(SUBI, BB) /* R(a) = R(a)-C */ +OPCODE(MUL, B) /* R(a) = R(a)*R(a+1) */ +OPCODE(DIV, B) /* R(a) = R(a)/R(a+1) */ +OPCODE(EQ, B) /* R(a) = R(a)==R(a+1) */ +OPCODE(LT, B) /* R(a) = R(a)R(a+1) */ +OPCODE(GE, B) /* R(a) = R(a)>=R(a+1) */ 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)) */ diff --git a/include/mruby/symbol.h b/include/mruby/symbol.h new file mode 100644 index 000000000..595caeefd --- /dev/null +++ b/include/mruby/symbol.h @@ -0,0 +1,32 @@ +/* +** mruby/symbol.h - symbol utilities +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_SYMBOL_H +#define MRUBY_SYMBOL_H + +#include "common.h" + +/** + * Symbol utilities + */ +MRB_BEGIN_DECL + +typedef enum mrb_reserved_symbol { + mrb_sym_add = 1, // + + mrb_sym_sub = 2, // - + mrb_sym_mul = 3, // * + mrb_sym_div = 4, // / + mrb_sym_eq = 5, // == + mrb_sym_lt = 6, // < + mrb_sym_le = 7, // <= + mrb_sym_gt = 8, // > + mrb_sym_ge = 9, // >= + mrb_sym_method_missing = 10, // method_missing +} mrb_reserved_symbol; + +MRB_END_DECL + +#endif /* MRUBY_SYMBOL_H */ diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 8ab1b9bc3..759e7267e 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -468,11 +468,11 @@ gen_return(codegen_scope *s, uint8_t op, uint16_t src) } static void -gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst, uint16_t idx) +gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst) { if (no_peephole(s)) { normal: - genop_2(s, op, dst, idx); + genop_1(s, op, dst); return; } else { @@ -493,10 +493,10 @@ gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst, uint16_t idx) if (data.b >= 128) goto normal; s->pc = s->lastpc; if (op == OP_ADD) { - genop_3(s, OP_ADDI, dst, idx, (uint8_t)data.b); + genop_2(s, OP_ADDI, dst, (uint8_t)data.b); } else { - genop_3(s, OP_SUBI, dst, idx, (uint8_t)data.b); + genop_2(s, OP_SUBI, dst, (uint8_t)data.b); } break; default: @@ -982,6 +982,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) gen_move(s, cursp(), recv, 1); skip = genjmp2(s, OP_JMPNIL, cursp(), 0, val); } + // TODO: don't new when unused idx = new_sym(s, sym); tree = tree->cdr->cdr->car; if (tree) { @@ -1017,31 +1018,31 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen); if (!noop && symlen == 1 && symname[0] == '+' && n == 1) { - gen_addsub(s, OP_ADD, cursp(), idx); + gen_addsub(s, OP_ADD, cursp()); } else if (!noop && symlen == 1 && symname[0] == '-' && n == 1) { - gen_addsub(s, OP_SUB, cursp(), idx); + gen_addsub(s, OP_SUB, cursp()); } else if (!noop && symlen == 1 && symname[0] == '*' && n == 1) { - genop_2(s, OP_MUL, cursp(), idx); + genop_1(s, OP_MUL, cursp()); } else if (!noop && symlen == 1 && symname[0] == '/' && n == 1) { - genop_2(s, OP_DIV, cursp(), idx); + genop_1(s, OP_DIV, cursp()); } else if (!noop && symlen == 1 && symname[0] == '<' && n == 1) { - genop_2(s, OP_LT, cursp(), idx); + genop_1(s, OP_LT, cursp()); } else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=' && n == 1) { - genop_2(s, OP_LE, cursp(), idx); + genop_1(s, OP_LE, cursp()); } else if (!noop && symlen == 1 && symname[0] == '>' && n == 1) { - genop_2(s, OP_GT, cursp(), idx); + genop_1(s, OP_GT, cursp()); } else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=' && n == 1) { - genop_2(s, OP_GE, cursp(), idx); + genop_1(s, OP_GE, cursp()); } else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=' && n == 1) { - genop_2(s, OP_EQ, cursp(), idx); + genop_1(s, OP_EQ, cursp()); } else { if (sendv) { @@ -2025,28 +2026,28 @@ codegen(codegen_scope *s, node *tree, int val) idx = new_sym(s, sym); if (len == 1 && name[0] == '+') { - gen_addsub(s, OP_ADD, cursp(), idx); + gen_addsub(s, OP_ADD, cursp()); } else if (len == 1 && name[0] == '-') { - gen_addsub(s, OP_SUB, cursp(), idx); + gen_addsub(s, OP_SUB, cursp()); } else if (len == 1 && name[0] == '*') { - genop_2(s, OP_MUL, cursp(), idx); + genop_1(s, OP_MUL, cursp()); } else if (len == 1 && name[0] == '/') { - genop_2(s, OP_DIV, cursp(), idx); + genop_1(s, OP_DIV, cursp()); } else if (len == 1 && name[0] == '<') { - genop_2(s, OP_LT, cursp(), idx); + genop_1(s, OP_LT, cursp()); } else if (len == 2 && name[0] == '<' && name[1] == '=') { - genop_2(s, OP_LE, cursp(), idx); + genop_1(s, OP_LE, cursp()); } else if (len == 1 && name[0] == '>') { - genop_2(s, OP_GT, cursp(), idx); + genop_1(s, OP_GT, cursp()); } else if (len == 2 && name[0] == '>' && name[1] == '=') { - genop_2(s, OP_GE, cursp(), idx); + genop_1(s, OP_GE, cursp()); } else { genop_3(s, OP_SEND, cursp(), idx, 1); diff --git a/src/symbol.c b/src/symbol.c index 6b4c7200c..f7dbc1be1 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -11,6 +11,7 @@ #include #include #include +#include /* ------------------------------------------------------ */ typedef struct symbol_name { @@ -170,10 +171,35 @@ mrb_free_symtbl(mrb_state *mrb) kh_destroy(n2s, mrb, mrb->name2sym); } +struct reserved_symbol_t { + mrb_reserved_symbol sym; + char const *str; +}; + +static struct reserved_symbol_t reserved_symbols[] = { + { mrb_sym_add, "+" }, + { mrb_sym_sub, "-" }, + { mrb_sym_mul, "*" }, + { mrb_sym_div, "/" }, + { mrb_sym_eq, "==" }, + { mrb_sym_lt, "<" }, + { mrb_sym_le, "<=" }, + { mrb_sym_gt, ">" }, + { mrb_sym_ge, ">=" }, + { mrb_sym_method_missing, "method_missing" }, + { 0, NULL }, +}; + void mrb_init_symtbl(mrb_state *mrb) { + int i; mrb->name2sym = kh_init(n2s, mrb); + + for (i = 0; reserved_symbols[i].sym != 0; ++i) { + mrb_sym s = mrb_intern_static(mrb, reserved_symbols[i].str, strlen(reserved_symbols[i].str)); + mrb_assert(s == reserved_symbols[i].sym); + } } /********************************************************************** diff --git a/src/vm.c b/src/vm.c index 067dd90f7..9792c3fbd 100644 --- a/src/vm.c +++ b/src/vm.c @@ -21,6 +21,7 @@ #include #include "value_array.h" #include +#include #ifdef MRB_DISABLE_STDIO #if defined(__cplusplus) @@ -1009,6 +1010,7 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc) uint32_t a; uint16_t b; uint8_t c; + mrb_sym mid; #ifdef DIRECT_THREADED static void *optable[] = { @@ -1386,9 +1388,18 @@ RETRY_TRY_BLOCK: SET_NIL_VALUE(regs[bidx]); goto L_SENDB; }; + L_SEND_CONSTSYM: + { + /* push nil after arguments */ + int bidx = (c == CALL_MAXARGS) ? a+2 : a+c+1; + SET_NIL_VALUE(regs[bidx]); + goto L_SENDB_CONSTSYM; + }; CASE(OP_SENDB, BBB) L_SENDB: + mid = syms[b]; + L_SENDB_CONSTSYM: { int argc = (c == CALL_MAXARGS) ? -1 : c; int bidx = (argc < 0) ? a+2 : a+c+1; @@ -1396,7 +1407,6 @@ RETRY_TRY_BLOCK: struct RClass *cls; mrb_callinfo *ci = mrb->c->ci; mrb_value recv, blk; - mrb_sym mid = syms[b]; mrb_assert(bidx < irep->nregs); @@ -2204,7 +2214,7 @@ RETRY_TRY_BLOCK: v1(regs[a]) = v1(regs[a]) op v2(regs[a+1]);\ } while(0) - CASE(OP_ADD, BB) { + CASE(OP_ADD, B) { /* need to check if op is overridden */ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): @@ -2259,13 +2269,14 @@ RETRY_TRY_BLOCK: break; default: c = 1; - goto L_SEND; + mid = mrb_sym_add; + goto L_SEND_CONSTSYM; } mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_SUB, BB) { + CASE(OP_SUB, B) { /* need to check if op is overridden */ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): @@ -2316,12 +2327,13 @@ RETRY_TRY_BLOCK: #endif default: c = 1; - goto L_SEND; + mid = mrb_sym_sub; + goto L_SEND_CONSTSYM; } NEXT; } - CASE(OP_MUL, BB) { + CASE(OP_MUL, B) { /* need to check if op is overridden */ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): @@ -2372,12 +2384,13 @@ RETRY_TRY_BLOCK: #endif default: c = 1; - goto L_SEND; + mid = mrb_sym_mul; + goto L_SEND_CONSTSYM; } NEXT; } - CASE(OP_DIV, BB) { + CASE(OP_DIV, B) { #ifndef MRB_WITHOUT_FLOAT double x, y, f; #endif @@ -2411,7 +2424,8 @@ RETRY_TRY_BLOCK: #endif default: c = 1; - goto L_SEND; + mid = mrb_sym_div; + goto L_SEND_CONSTSYM; } #ifndef MRB_WITHOUT_FLOAT @@ -2509,7 +2523,7 @@ RETRY_TRY_BLOCK: #define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1])) #ifdef MRB_WITHOUT_FLOAT -#define OP_CMP(op) do {\ +#define OP_CMP(op, sym) do {\ int result;\ /* need to check if - is overridden */\ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\ @@ -2518,7 +2532,8 @@ RETRY_TRY_BLOCK: break;\ default:\ c = 1;\ - goto L_SEND;\ + mid = mrb_sym_ ## sym;\ + goto L_SEND_CONSTSYM;\ }\ if (result) {\ SET_TRUE_VALUE(regs[a]);\ @@ -2528,7 +2543,7 @@ RETRY_TRY_BLOCK: }\ } while(0) #else -#define OP_CMP(op) do {\ +#define OP_CMP(op, sym) do {\ int result;\ /* need to check if - is overridden */\ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\ @@ -2546,7 +2561,8 @@ RETRY_TRY_BLOCK: break;\ default:\ c = 1;\ - goto L_SEND;\ + mid = mrb_sym_ ## sym;\ + goto L_SEND_CONSTSYM;\ }\ if (result) {\ SET_TRUE_VALUE(regs[a]);\ @@ -2557,33 +2573,33 @@ RETRY_TRY_BLOCK: } while(0) #endif - CASE(OP_EQ, BB) { + CASE(OP_EQ, B) { if (mrb_obj_eq(mrb, regs[a], regs[a+1])) { SET_TRUE_VALUE(regs[a]); } else { - OP_CMP(==); + OP_CMP(==, eq); } NEXT; } - CASE(OP_LT, BB) { - OP_CMP(<); + CASE(OP_LT, B) { + OP_CMP(<, gt); NEXT; } - CASE(OP_LE, BB) { - OP_CMP(<=); + CASE(OP_LE, B) { + OP_CMP(<=, ge); NEXT; } - CASE(OP_GT, BB) { - OP_CMP(>); + CASE(OP_GT, B) { + OP_CMP(>, lt); NEXT; } - CASE(OP_GE, BB) { - OP_CMP(>=); + CASE(OP_GE, B) { + OP_CMP(>=, le); NEXT; } -- cgit v1.2.3 From 6a6586ca84c6a9a691c9968320eed5e60e824b3c Mon Sep 17 00:00:00 2001 From: take-cheeze Date: Mon, 29 Oct 2018 19:40:33 +0900 Subject: Reduce unnecessary symbol table entry --- include/mruby/symbol.h | 7 +++++++ mrbgems/mruby-compiler/core/codegen.c | 10 +++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/include/mruby/symbol.h b/include/mruby/symbol.h index f11346830..b0feccc51 100644 --- a/include/mruby/symbol.h +++ b/include/mruby/symbol.h @@ -16,6 +16,7 @@ MRB_BEGIN_DECL typedef enum mrb_reserved_symbol { mrb_sym_null = 0, // NULL symbol + mrb_sym_add = 1, // + mrb_sym_sub = 2, // - mrb_sym_mul = 3, // * @@ -25,9 +26,15 @@ typedef enum mrb_reserved_symbol { mrb_sym_le = 7, // <= mrb_sym_gt = 8, // > mrb_sym_ge = 9, // >= + mrb_sym_method_missing = 10, // method_missing } mrb_reserved_symbol; +static inline mrb_bool +mrb_symbol_constsym_send_p(mrb_sym sym) { + return mrb_sym_add <= sym && sym <= mrb_sym_ge; +} + MRB_END_DECL #endif /* MRUBY_SYMBOL_H */ diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 759e7267e..22ac51239 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -18,6 +18,7 @@ #include #include #include +#include #ifndef MRB_CODEGEN_LEVEL_MAX #define MRB_CODEGEN_LEVEL_MAX 1024 @@ -982,8 +983,9 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) gen_move(s, cursp(), recv, 1); skip = genjmp2(s, OP_JMPNIL, cursp(), 0, val); } - // TODO: don't new when unused - idx = new_sym(s, sym); + if (!mrb_symbol_constsym_send_p(sym)) { + idx = new_sym(s, sym); + } tree = tree->cdr->cdr->car; if (tree) { n = gen_values(s, tree->car, VAL, sp?1:0); @@ -2024,7 +2026,9 @@ codegen(codegen_scope *s, node *tree, int val) push(); pop(); pop(); pop(); - idx = new_sym(s, sym); + if (!mrb_symbol_constsym_send_p(sym)) { + idx = new_sym(s, sym); + } if (len == 1 && name[0] == '+') { gen_addsub(s, OP_ADD, cursp()); } -- cgit v1.2.3 From d9e253255218b04fd54a55980c4d8b6d61b1697c Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 2 Nov 2018 22:58:12 +0900 Subject: Remove reserved symbols for now. It should be done by planned embedded symbols. --- include/mruby/symbol.h | 40 -------------------------- mrbgems/mruby-compiler/core/codegen.c | 12 +++----- src/symbol.c | 26 ----------------- src/vm.c | 53 +++++++++++++++++------------------ 4 files changed, 30 insertions(+), 101 deletions(-) delete mode 100644 include/mruby/symbol.h (limited to 'mrbgems/mruby-compiler') diff --git a/include/mruby/symbol.h b/include/mruby/symbol.h deleted file mode 100644 index b0feccc51..000000000 --- a/include/mruby/symbol.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -** mruby/symbol.h - symbol utilities -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_SYMBOL_H -#define MRUBY_SYMBOL_H - -#include "common.h" - -/** - * Symbol utilities - */ -MRB_BEGIN_DECL - -typedef enum mrb_reserved_symbol { - mrb_sym_null = 0, // NULL symbol - - mrb_sym_add = 1, // + - mrb_sym_sub = 2, // - - mrb_sym_mul = 3, // * - mrb_sym_div = 4, // / - mrb_sym_eq = 5, // == - mrb_sym_lt = 6, // < - mrb_sym_le = 7, // <= - mrb_sym_gt = 8, // > - mrb_sym_ge = 9, // >= - - mrb_sym_method_missing = 10, // method_missing -} mrb_reserved_symbol; - -static inline mrb_bool -mrb_symbol_constsym_send_p(mrb_sym sym) { - return mrb_sym_add <= sym && sym <= mrb_sym_ge; -} - -MRB_END_DECL - -#endif /* MRUBY_SYMBOL_H */ diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 22ac51239..22ad3253b 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -18,7 +18,6 @@ #include #include #include -#include #ifndef MRB_CODEGEN_LEVEL_MAX #define MRB_CODEGEN_LEVEL_MAX 1024 @@ -974,7 +973,7 @@ static void gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) { mrb_sym sym = name ? name : nsym(tree->cdr->car); - int idx, skip = 0; + int skip = 0; int n = 0, noop = 0, sendv = 0, blk = 0; codegen(s, tree->car, VAL); /* receiver */ @@ -983,9 +982,6 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) gen_move(s, cursp(), recv, 1); skip = genjmp2(s, OP_JMPNIL, cursp(), 0, val); } - if (!mrb_symbol_constsym_send_p(sym)) { - idx = new_sym(s, sym); - } tree = tree->cdr->cdr->car; if (tree) { n = gen_values(s, tree->car, VAL, sp?1:0); @@ -1047,6 +1043,8 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) genop_1(s, OP_EQ, cursp()); } else { + int idx = new_sym(s, sym); + if (sendv) { genop_2(s, blk ? OP_SENDVB : OP_SENDV, cursp(), idx); } @@ -2026,9 +2024,6 @@ codegen(codegen_scope *s, node *tree, int val) push(); pop(); pop(); pop(); - if (!mrb_symbol_constsym_send_p(sym)) { - idx = new_sym(s, sym); - } if (len == 1 && name[0] == '+') { gen_addsub(s, OP_ADD, cursp()); } @@ -2054,6 +2049,7 @@ codegen(codegen_scope *s, node *tree, int val) genop_1(s, OP_GE, cursp()); } else { + idx = new_sym(s, sym); genop_3(s, OP_SEND, cursp(), idx, 1); } if (callargs < 0) { diff --git a/src/symbol.c b/src/symbol.c index 8ec300e20..6b4c7200c 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -11,7 +11,6 @@ #include #include #include -#include /* ------------------------------------------------------ */ typedef struct symbol_name { @@ -171,35 +170,10 @@ mrb_free_symtbl(mrb_state *mrb) kh_destroy(n2s, mrb, mrb->name2sym); } -struct reserved_symbol_t { - mrb_reserved_symbol sym; - char const *str; -}; - -static struct reserved_symbol_t reserved_symbols[] = { - { mrb_sym_add, "+" }, - { mrb_sym_sub, "-" }, - { mrb_sym_mul, "*" }, - { mrb_sym_div, "/" }, - { mrb_sym_eq, "==" }, - { mrb_sym_lt, "<" }, - { mrb_sym_le, "<=" }, - { mrb_sym_gt, ">" }, - { mrb_sym_ge, ">=" }, - { mrb_sym_method_missing, "method_missing" }, - { mrb_sym_null, NULL }, -}; - void mrb_init_symtbl(mrb_state *mrb) { - int i; mrb->name2sym = kh_init(n2s, mrb); - - for (i = 0; reserved_symbols[i].sym != mrb_sym_null; ++i) { - mrb_sym s = mrb_intern_static(mrb, reserved_symbols[i].str, strlen(reserved_symbols[i].str)); - mrb_assert(s == reserved_symbols[i].sym); - } } /********************************************************************** diff --git a/src/vm.c b/src/vm.c index 627eb9325..9844d3e60 100644 --- a/src/vm.c +++ b/src/vm.c @@ -21,7 +21,6 @@ #include #include "value_array.h" #include -#include #ifdef MRB_DISABLE_STDIO #if defined(__cplusplus) @@ -1388,18 +1387,18 @@ RETRY_TRY_BLOCK: SET_NIL_VALUE(regs[bidx]); goto L_SENDB; }; - L_SEND_CONSTSYM: + L_SEND_SYM: { /* push nil after arguments */ int bidx = (c == CALL_MAXARGS) ? a+2 : a+c+1; SET_NIL_VALUE(regs[bidx]); - goto L_SENDB_CONSTSYM; + goto L_SENDB_SYM; }; CASE(OP_SENDB, BBB) L_SENDB: mid = syms[b]; - L_SENDB_CONSTSYM: + L_SENDB_SYM: { int argc = (c == CALL_MAXARGS) ? -1 : c; int bidx = (argc < 0) ? a+2 : a+c+1; @@ -2269,8 +2268,8 @@ RETRY_TRY_BLOCK: break; default: c = 1; - mid = mrb_sym_add; - goto L_SEND_CONSTSYM; + mid = mrb_intern_lit(mrb, "+"); + goto L_SEND_SYM; } mrb_gc_arena_restore(mrb, ai); NEXT; @@ -2327,8 +2326,8 @@ RETRY_TRY_BLOCK: #endif default: c = 1; - mid = mrb_sym_sub; - goto L_SEND_CONSTSYM; + mid = mrb_intern_lit(mrb, "-"); + goto L_SEND_SYM; } NEXT; } @@ -2384,8 +2383,8 @@ RETRY_TRY_BLOCK: #endif default: c = 1; - mid = mrb_sym_mul; - goto L_SEND_CONSTSYM; + mid = mrb_intern_lit(mrb, "*"); + goto L_SEND_SYM; } NEXT; } @@ -2424,8 +2423,8 @@ RETRY_TRY_BLOCK: #endif default: c = 1; - mid = mrb_sym_div; - goto L_SEND_CONSTSYM; + mid = mrb_intern_lit(mrb, "/"); + goto L_SEND_SYM; } #ifndef MRB_WITHOUT_FLOAT @@ -2475,8 +2474,8 @@ RETRY_TRY_BLOCK: default: SET_INT_VALUE(regs[a+1], b); c = 1; - mid = mrb_sym_add; - goto L_SEND_CONSTSYM; + mid = mrb_intern_lit(mrb, "+"); + goto L_SEND_SYM; } NEXT; } @@ -2516,8 +2515,8 @@ RETRY_TRY_BLOCK: default: SET_INT_VALUE(regs_a[1], b); c = 1; - mid = mrb_sym_sub; - goto L_SEND_CONSTSYM; + mid = mrb_intern_lit(mrb, "-"); + goto L_SEND_SYM; } NEXT; } @@ -2525,7 +2524,7 @@ RETRY_TRY_BLOCK: #define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1])) #ifdef MRB_WITHOUT_FLOAT -#define OP_CMP(op, sym) do {\ +#define OP_CMP(op) do {\ int result;\ /* need to check if - is overridden */\ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\ @@ -2534,8 +2533,8 @@ RETRY_TRY_BLOCK: break;\ default:\ c = 1;\ - mid = mrb_sym_ ## sym;\ - goto L_SEND_CONSTSYM;\ + mid = mrb_intern_lit(mrb, # op);\ + goto L_SEND_SYM;\ }\ if (result) {\ SET_TRUE_VALUE(regs[a]);\ @@ -2545,7 +2544,7 @@ RETRY_TRY_BLOCK: }\ } while(0) #else -#define OP_CMP(op, sym) do {\ +#define OP_CMP(op) do {\ int result;\ /* need to check if - is overridden */\ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\ @@ -2563,8 +2562,8 @@ RETRY_TRY_BLOCK: break;\ default:\ c = 1;\ - mid = mrb_sym_ ## sym;\ - goto L_SEND_CONSTSYM;\ + mid = mrb_intern_lit(mrb, # op);\ + goto L_SEND_SYM;\ }\ if (result) {\ SET_TRUE_VALUE(regs[a]);\ @@ -2580,28 +2579,28 @@ RETRY_TRY_BLOCK: SET_TRUE_VALUE(regs[a]); } else { - OP_CMP(==, eq); + OP_CMP(==); } NEXT; } CASE(OP_LT, B) { - OP_CMP(<, lt); + OP_CMP(<); NEXT; } CASE(OP_LE, B) { - OP_CMP(<=, le); + OP_CMP(<=); NEXT; } CASE(OP_GT, B) { - OP_CMP(>, gt); + OP_CMP(>); NEXT; } CASE(OP_GE, B) { - OP_CMP(>=, ge); + OP_CMP(>=); NEXT; } -- cgit v1.2.3 From 61f49690e43cea3df6ebbdf424cf6777826056b0 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 15 Nov 2018 20:15:10 +0900 Subject: Remove `filename`&`lines` from `mrb_irep` struct. This patch slightly reduce memory consumption (2% for my test). --- include/mruby/debug.h | 5 +- include/mruby/irep.h | 3 - mrbgems/mruby-compiler/core/codegen.c | 38 +++-------- src/debug.c | 32 ++++----- src/dump.c | 125 +--------------------------------- src/load.c | 10 +-- src/state.c | 5 -- 7 files changed, 30 insertions(+), 188 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/include/mruby/debug.h b/include/mruby/debug.h index d1de34882..f0a40dfcf 100644 --- a/include/mruby/debug.h +++ b/include/mruby/debug.h @@ -55,10 +55,11 @@ MRB_API const char *mrb_debug_get_filename(mrb_irep *irep, ptrdiff_t pc); */ MRB_API int32_t mrb_debug_get_line(mrb_irep *irep, ptrdiff_t pc); +MRB_API mrb_irep_debug_info *mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep); MRB_API mrb_irep_debug_info_file *mrb_debug_info_append_file( - mrb_state *mrb, mrb_irep *irep, + mrb_state *mrb, mrb_irep_debug_info *info, + const char *filename, uint16_t *lines, uint32_t start_pos, uint32_t end_pos); -MRB_API mrb_irep_debug_info *mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep); MRB_API void mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d); MRB_END_DECL diff --git a/include/mruby/irep.h b/include/mruby/irep.h index 76bafb25c..78cbc2b74 100644 --- a/include/mruby/irep.h +++ b/include/mruby/irep.h @@ -39,9 +39,6 @@ typedef struct mrb_irep { struct mrb_locals *lv; /* debug info */ - mrb_bool own_filename; - const char *filename; - uint16_t *lines; struct mrb_irep_debug_info* debug_info; uint16_t ilen, plen, slen, rlen; diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 22ad3253b..dbd3b8ecf 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -124,15 +124,6 @@ codegen_palloc(codegen_scope *s, size_t len) return p; } -static void* -codegen_malloc(codegen_scope *s, size_t len) -{ - void *p = mrb_malloc_simple(s->mrb, len); - - if (!p) codegen_error(s, "mrb_malloc"); - return p; -} - static void* codegen_realloc(codegen_scope *s, void *p, size_t len) { @@ -162,7 +153,6 @@ emit_B(codegen_scope *s, uint32_t pc, uint8_t i) s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa); if (s->lines) { s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->icapa); - s->irep->lines = s->lines; } } if (s->lines) { @@ -1371,8 +1361,10 @@ codegen(codegen_scope *s, node *tree, int val) codegen_error(s, "too complex expression"); } if (s->irep && s->filename_index != tree->filename_index) { - s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index); - mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc); + const char *filename = mrb_parser_get_filename(s->parser, s->filename_index); + + mrb_debug_info_append_file(s->mrb, s->irep->debug_info, + filename, s->lines, s->debug_start_pos, s->pc); s->debug_start_pos = s->pc; s->filename_index = tree->filename_index; s->filename = mrb_parser_get_filename(s->parser, tree->filename_index); @@ -2965,8 +2957,6 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) p->debug_start_pos = 0; if (p->filename) { mrb_debug_info_alloc(mrb, p->irep); - p->irep->filename = p->filename; - p->irep->lines = p->lines; } else { p->irep->debug_info = NULL; @@ -2984,34 +2974,22 @@ scope_finish(codegen_scope *s) { mrb_state *mrb = s->mrb; mrb_irep *irep = s->irep; - size_t fname_len; - char *fname; irep->flags = 0; if (s->iseq) { irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc); irep->ilen = s->pc; - if (s->lines) { - irep->lines = (uint16_t *)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->pc); - } - else { - irep->lines = 0; - } } irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen); irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen); irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen); if (s->filename) { - irep->filename = mrb_parser_get_filename(s->parser, s->filename_index); - mrb_debug_info_append_file(mrb, irep, s->debug_start_pos, s->pc); + const char *filename = mrb_parser_get_filename(s->parser, s->filename_index); - fname_len = strlen(s->filename); - fname = (char*)codegen_malloc(s, fname_len + 1); - memcpy(fname, s->filename, fname_len); - fname[fname_len] = '\0'; - irep->filename = fname; - irep->own_filename = TRUE; + mrb_debug_info_append_file(s->mrb, s->irep->debug_info, + filename, s->lines, s->debug_start_pos, s->pc); } + mrb_free(s->mrb, s->lines); irep->nlocals = s->nlocals; irep->nregs = s->nregs; diff --git a/src/debug.c b/src/debug.c index e55f11d4f..207065d9e 100644 --- a/src/debug.c +++ b/src/debug.c @@ -55,7 +55,7 @@ mrb_debug_get_filename(mrb_irep *irep, ptrdiff_t pc) { if (irep && pc >= 0 && pc < irep->ilen) { mrb_irep_debug_info_file* f = NULL; - if (!irep->debug_info) { return irep->filename; } + if (!irep->debug_info) return NULL; else if ((f = get_file(irep->debug_info, (uint32_t)pc))) { return f->filename; } @@ -69,7 +69,7 @@ mrb_debug_get_line(mrb_irep *irep, ptrdiff_t pc) if (irep && pc >= 0 && pc < irep->ilen) { mrb_irep_debug_info_file* f = NULL; if (!irep->debug_info) { - return irep->lines? irep->lines[pc] : -1; + return -1; } else if ((f = get_file(irep->debug_info, (uint32_t)pc))) { switch (f->line_type) { @@ -122,24 +122,22 @@ mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep) } MRB_API mrb_irep_debug_info_file* -mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep, +mrb_debug_info_append_file(mrb_state *mrb, mrb_irep_debug_info *info, + const char *filename, uint16_t *lines, uint32_t start_pos, uint32_t end_pos) { - mrb_irep_debug_info *info; mrb_irep_debug_info_file *ret; uint32_t file_pc_count; size_t fn_len; mrb_int len; uint32_t i; - if (!irep->debug_info) { return NULL; } + if (!info) { return NULL; } - mrb_assert(irep->filename); - mrb_assert(irep->lines); + mrb_assert(filename); + mrb_assert(lines); - info = irep->debug_info; - - if (info->flen > 0 && strcmp(irep->filename, info->files[info->flen - 1]->filename) == 0) { + if (info->flen > 0 && strcmp(filename, info->files[info->flen - 1]->filename) == 0) { return NULL; } @@ -156,12 +154,12 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep, ret->start_pos = start_pos; info->pc_count = end_pos; - fn_len = strlen(irep->filename); - ret->filename_sym = mrb_intern(mrb, irep->filename, fn_len); + fn_len = strlen(filename); + ret->filename_sym = mrb_intern(mrb, filename, fn_len); len = 0; ret->filename = mrb_sym2name_len(mrb, ret->filename_sym, &len); - ret->line_type = select_line_type(irep->lines + start_pos, end_pos - start_pos); + ret->line_type = select_line_type(lines + start_pos, end_pos - start_pos); ret->lines.ptr = NULL; switch (ret->line_type) { @@ -169,7 +167,7 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep, ret->line_entry_count = file_pc_count; ret->lines.ary = (uint16_t*)mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count); for (i = 0; i < file_pc_count; ++i) { - ret->lines.ary[i] = irep->lines[start_pos + i]; + ret->lines.ary[i] = lines[start_pos + i]; } break; @@ -179,18 +177,18 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep, ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1); ret->line_entry_count = 0; for (i = 0; i < file_pc_count; ++i) { - if (irep->lines[start_pos + i] == prev_line) { continue; } + if (lines[start_pos + i] == prev_line) { continue; } ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_realloc( mrb, ret->lines.flat_map, sizeof(mrb_irep_debug_info_line) * (ret->line_entry_count + 1)); m.start_pos = start_pos + i; - m.line = irep->lines[start_pos + i]; + m.line = lines[start_pos + i]; ret->lines.flat_map[ret->line_entry_count] = m; /* update */ ++ret->line_entry_count; - prev_line = irep->lines[start_pos + i]; + prev_line = lines[start_pos + i]; } } break; diff --git a/src/dump.c b/src/dump.c index e41dd83ed..6ce9c4eb9 100644 --- a/src/dump.c +++ b/src/dump.c @@ -353,118 +353,6 @@ write_section_irep(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, size_t *len_p, return MRB_DUMP_OK; } -static int -write_section_lineno_header(mrb_state *mrb, size_t section_size, uint8_t *bin) -{ - struct rite_section_lineno_header *header = (struct rite_section_lineno_header*)bin; - - memcpy(header->section_ident, RITE_SECTION_LINENO_IDENT, sizeof(header->section_ident)); - uint32_to_bin((uint32_t)section_size, header->section_size); - - return MRB_DUMP_OK; -} - -static size_t -get_lineno_record_size(mrb_state *mrb, mrb_irep *irep) -{ - size_t size = 0; - - size += sizeof(uint32_t); /* record size */ - size += sizeof(uint16_t); /* filename size */ - if (irep->filename) { - size += strlen(irep->filename); /* filename */ - } - size += sizeof(uint32_t); /* niseq */ - if (irep->lines) { - size += sizeof(uint16_t) * irep->ilen; /* lineno */ - } - - return size; -} - -static size_t -write_lineno_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) -{ - uint8_t *cur = bin; - int iseq_no; - size_t filename_len; - ptrdiff_t diff; - - cur += sizeof(uint32_t); /* record size */ - - if (irep->filename) { - filename_len = strlen(irep->filename); - } - else { - filename_len = 0; - } - mrb_assert_int_fit(size_t, filename_len, uint16_t, UINT16_MAX); - cur += uint16_to_bin((uint16_t)filename_len, cur); /* filename size */ - - if (filename_len) { - memcpy(cur, irep->filename, filename_len); - cur += filename_len; /* filename */ - } - - if (irep->lines) { - mrb_assert_int_fit(size_t, irep->ilen, uint32_t, UINT32_MAX); - cur += uint32_to_bin((uint32_t)(irep->ilen), cur); /* niseq */ - for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) { - cur += uint16_to_bin(irep->lines[iseq_no], cur); /* opcode */ - } - } - else { - cur += uint32_to_bin(0, cur); /* niseq */ - } - - diff = cur - bin; - mrb_assert_int_fit(ptrdiff_t, diff, uint32_t, UINT32_MAX); - - uint32_to_bin((uint32_t)diff, bin); /* record size */ - - mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); - return (size_t)diff; -} - -static size_t -write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) -{ - size_t rlen, size = 0; - int i; - - rlen = write_lineno_record_1(mrb, irep, bin); - bin += rlen; - size += rlen; - for (i=0; irlen; i++) { - rlen = write_lineno_record(mrb, irep, bin); - bin += rlen; - size += rlen; - } - return size; -} - -static int -write_section_lineno(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) -{ - size_t section_size = 0; - size_t rlen = 0; /* size of irep record */ - uint8_t *cur = bin; - - if (mrb == NULL || bin == NULL) { - return MRB_DUMP_INVALID_ARGUMENT; - } - - cur += sizeof(struct rite_section_lineno_header); - section_size += sizeof(struct rite_section_lineno_header); - - rlen = write_lineno_record(mrb, irep, cur); - section_size += rlen; - - write_section_lineno_header(mrb, section_size, bin); - - return MRB_DUMP_OK; -} - static size_t get_debug_record_size(mrb_state *mrb, mrb_irep *irep) { @@ -911,10 +799,6 @@ dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t * section_lineno_size += get_debug_record_size(mrb, irep); } - else { - section_lineno_size += sizeof(struct rite_section_lineno_header); - section_lineno_size += get_lineno_record_size(mrb, irep); - } } if (lv_defined) { @@ -942,12 +826,9 @@ dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t * if (flags & DUMP_DEBUG_INFO) { if (debug_info_defined) { result = write_section_debug(mrb, irep, cur, filenames, filenames_len); - } - else { - result = write_section_lineno(mrb, irep, cur); - } - if (result != MRB_DUMP_OK) { - goto error_exit; + if (result != MRB_DUMP_OK) { + goto error_exit; + } } cur += section_lineno_size; } diff --git a/src/load.c b/src/load.c index 70f5406eb..559fff1d4 100644 --- a/src/load.c +++ b/src/load.c @@ -215,12 +215,11 @@ read_section_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags) return read_irep_record(mrb, bin, &len, flags); } +/* ignore lineno record */ static int read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *len) { size_t i, fname_len, niseq; - char *fname; - uint16_t *lines; *len = 0; bin += sizeof(uint32_t); /* record size */ @@ -228,9 +227,6 @@ read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t fname_len = bin_to_uint16(bin); bin += sizeof(uint16_t); *len += sizeof(uint16_t); - fname = (char *)mrb_malloc(mrb, fname_len + 1); - memcpy(fname, bin, fname_len); - fname[fname_len] = '\0'; bin += fname_len; *len += fname_len; @@ -241,15 +237,11 @@ read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t if (SIZE_ERROR_MUL(niseq, sizeof(uint16_t))) { return MRB_DUMP_GENERAL_FAILURE; } - lines = (uint16_t *)mrb_malloc(mrb, niseq * sizeof(uint16_t)); for (i = 0; i < niseq; i++) { - lines[i] = bin_to_uint16(bin); bin += sizeof(uint16_t); /* niseq */ *len += sizeof(uint16_t); } - irep->filename = fname; - irep->lines = lines; return MRB_DUMP_OK; } diff --git a/src/state.c b/src/state.c index 18d104555..5583a77e5 100644 --- a/src/state.c +++ b/src/state.c @@ -168,10 +168,6 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep) } mrb_free(mrb, irep->reps); mrb_free(mrb, irep->lv); - if (irep->own_filename) { - mrb_free(mrb, (void *)irep->filename); - } - mrb_free(mrb, irep->lines); mrb_debug_info_free(mrb, irep->debug_info); mrb_free(mrb, irep); } @@ -273,7 +269,6 @@ mrb_add_irep(mrb_state *mrb) irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep)); *irep = mrb_irep_zero; irep->refcnt = 1; - irep->own_filename = FALSE; return irep; } -- cgit v1.2.3 From 7e3e8d8ed5d9d12e7d3b0d616bf9b770f07e0d4f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 15 Nov 2018 23:26:37 +0900 Subject: Shrink file name table size to `uint16_t`; ref #4138 --- include/mruby/compile.h | 4 ++-- mrbgems/mruby-compiler/core/parse.y | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/include/mruby/compile.h b/include/mruby/compile.h index a85460415..63ec8aca1 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -158,8 +158,8 @@ struct mrb_parser_state { struct mrb_parser_message warn_buffer[10]; mrb_sym* filename_table; - size_t filename_table_length; - int current_filename_index; + uint16_t filename_table_length; + uint16_t current_filename_index; struct mrb_jmpbuf* jmp; }; diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 5e6cda236..1c06be839 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -5900,7 +5900,11 @@ mrb_parser_set_filename(struct mrb_parser_state *p, const char *f) } } - p->current_filename_index = (int)p->filename_table_length++; + if (p->filename_table_length == UINT16_MAX) { + yyerror(p, "too many files to compile"); + return; + } + p->current_filename_index = p->filename_table_length++; new_table = (mrb_sym*)parser_palloc(p, sizeof(mrb_sym) * p->filename_table_length); if (p->filename_table) { @@ -5912,7 +5916,7 @@ mrb_parser_set_filename(struct mrb_parser_state *p, const char *f) MRB_API char const* mrb_parser_get_filename(struct mrb_parser_state* p, uint16_t idx) { - if (idx >= p->filename_table_length) { return NULL; } + if (idx >= p->filename_table_length) return NULL; else { return mrb_sym2name_len(p->mrb, p->filename_table[idx], NULL); } -- cgit v1.2.3 From 418ad65db40200058a023b57682f4a3853fd63bc Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 15 Nov 2018 23:29:55 +0900 Subject: Fixed a bug in continuous read of target files; ref #4138 Line number information in a compiled file was wrong. --- mrbgems/mruby-compiler/core/codegen.c | 5 ++++- mrbgems/mruby-compiler/core/parse.y | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index dbd3b8ecf..ba7d8cf63 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -156,7 +156,10 @@ emit_B(codegen_scope *s, uint32_t pc, uint8_t i) } } if (s->lines) { - s->lines[pc] = s->lineno; + if (s->lineno > 0 || pc == 0) + s->lines[pc] = s->lineno; + else + s->lines[pc] = s->lines[pc-1]; } s->iseq[pc] = i; } diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 1c06be839..ac8724377 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -133,6 +133,10 @@ cons_gen(parser_state *p, node *car, node *cdr) c->cdr = cdr; c->lineno = p->lineno; c->filename_index = p->current_filename_index; + /* beginning of next partial file; need to point the previous file */ + if (p->lineno == 0 && p->current_filename_index > 0) { + c->filename_index-- ; + } return c; } #define cons(a,b) cons_gen(p,(a),(b)) -- cgit v1.2.3 From 423f872c846d63056ba75f067201ba9c221231d1 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 19 Nov 2018 15:26:19 +0900 Subject: Need to keep rooms for empty splat; fix #4166 --- mrbgems/mruby-compiler/core/parse.y | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index ac8724377..3a9da3d36 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -2482,6 +2482,7 @@ f_margs : f_marg_list } | f_marg_list ',' tSTAR { + local_add_f(p, 0); $$ = list3($1, (node*)-1, 0); } | f_marg_list ',' tSTAR ',' f_marg_list @@ -2498,11 +2499,16 @@ f_margs : f_marg_list } | tSTAR { + local_add_f(p, 0); $$ = list3(0, (node*)-1, 0); } - | tSTAR ',' f_marg_list + | tSTAR ',' { - $$ = list3(0, (node*)-1, $3); + local_add_f(p, 0); + } + f_marg_list + { + $$ = list3(0, (node*)-1, $4); } ; -- cgit v1.2.3 From f1eeaad84a1b1183c6e5128be0a4efeec6da5e8e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 20 Nov 2018 09:35:38 +0900 Subject: Stop special treating of `\r` in the lexer; fix #4132 --- mrbgems/mruby-compiler/core/parse.y | 8 -------- 1 file changed, 8 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 3a9da3d36..e489dd934 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3710,14 +3710,6 @@ nextc(parser_state *p) if (c >= 0) { p->column++; } - if (c == '\r') { - c = nextc(p); - if (c != '\n') { - pushback(p, c); - return '\r'; - } - return c; - } return c; eof: -- cgit v1.2.3 From ec19c34a209e05156cdce8d317234bc62489148f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 20 Nov 2018 10:39:34 +0900 Subject: Fixed a bug in `mirb` heredoc handling; fix #3989 --- include/mruby/compile.h | 1 - mrbgems/mruby-bin-mirb/tools/mirb/mirb.c | 4 ---- mrbgems/mruby-compiler/core/parse.y | 1 - 3 files changed, 6 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/include/mruby/compile.h b/include/mruby/compile.h index 63ec8aca1..fd735be88 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -143,7 +143,6 @@ struct mrb_parser_state { mrb_ast_node *heredocs_from_nextline; mrb_ast_node *parsing_heredoc; mrb_ast_node *lex_strterm_before_heredoc; - mrb_bool heredoc_end_now:1; /* for mirb */ void *ylval; diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c index 1880f22f7..19f533acd 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c @@ -126,10 +126,6 @@ is_code_block_open(struct mrb_parser_state *parser) /* check for heredoc */ if (parser->parsing_heredoc != NULL) return TRUE; - if (parser->heredoc_end_now) { - parser->heredoc_end_now = FALSE; - return FALSE; - } /* check for unterminated string */ if (parser->lex_strterm) return TRUE; diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index e489dd934..70b9d0fc4 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -1078,7 +1078,6 @@ heredoc_end(parser_state *p) end_strterm(p); p->lex_strterm = p->lex_strterm_before_heredoc; p->lex_strterm_before_heredoc = NULL; - p->heredoc_end_now = TRUE; } else { /* next heredoc */ -- cgit v1.2.3 From e6b72b2121b981c504f902723b3c1531be001c02 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 25 Nov 2018 07:30:32 +0900 Subject: Remove redundant rules from `parse.y`. --- mrbgems/mruby-compiler/core/parse.y | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 70b9d0fc4..1485fb086 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -1171,7 +1171,7 @@ heredoc_end(parser_state *p) %type command_args aref_args opt_block_arg block_arg var_ref var_lhs %type command_asgn command_rhs mrhs superclass block_call block_command %type f_block_optarg f_block_opt -%type f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs +%type f_arglist f_args f_arg f_arg_item f_optarg f_margs %type assoc_list assocs assoc undef_list backref for_var %type block_param opt_block_param block_param_def f_opt %type bv_decls opt_bv_decl bvar f_larglist lambda_body @@ -2447,44 +2447,24 @@ for_var : lhs | mlhs ; -f_marg : f_norm_arg - { - $$ = new_arg(p, $1); - } - | tLPAREN f_margs rparen - { - $$ = new_masgn(p, $2, 0); - } - ; - -f_marg_list : f_marg - { - $$ = list1($1); - } - | f_marg_list ',' f_marg - { - $$ = push($1, $3); - } - ; - -f_margs : f_marg_list +f_margs : f_arg { $$ = list3($1,0,0); } - | f_marg_list ',' tSTAR f_norm_arg + | f_arg ',' tSTAR f_norm_arg { $$ = list3($1, new_arg(p, $4), 0); } - | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list + | f_arg ',' tSTAR f_norm_arg ',' f_arg { $$ = list3($1, new_arg(p, $4), $6); } - | f_marg_list ',' tSTAR + | f_arg ',' tSTAR { local_add_f(p, 0); $$ = list3($1, (node*)-1, 0); } - | f_marg_list ',' tSTAR ',' f_marg_list + | f_arg ',' tSTAR ',' f_arg { $$ = list3($1, (node*)-1, $5); } @@ -2492,7 +2472,7 @@ f_margs : f_marg_list { $$ = list3(0, new_arg(p, $2), 0); } - | tSTAR f_norm_arg ',' f_marg_list + | tSTAR f_norm_arg ',' f_arg { $$ = list3(0, new_arg(p, $2), $4); } @@ -2505,7 +2485,7 @@ f_margs : f_marg_list { local_add_f(p, 0); } - f_marg_list + f_arg { $$ = list3(0, (node*)-1, $4); } -- cgit v1.2.3 From 762f682b80460929d9c69b1957bcb2aad108ec93 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 25 Nov 2018 09:01:14 +0900 Subject: Allow destructuring in formal arguments. e.g. ``` def m(a,(b,c),d); p [a,b,c,d]; end m(1,[2,3],4) # => [1,2,3,4] ``` mruby limitation: Destructured arguments (`b` and `c` in above example) cannot be accessed from the default expression of optional arguments and keyword arguments, since actual assignment is done after the evaluation of those default expressions. Thus: ``` def f(a,(b,c),d=b) p [a,b,c,d] end f(1,[2,3]) ``` raises `NoMethodError` for `b` in mruby. --- mrbgems/mruby-compiler/core/codegen.c | 40 +++++++++++++++++++++++++++++------ mrbgems/mruby-compiler/core/parse.y | 31 +++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 8 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index ba7d8cf63..b3659863b 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -734,15 +734,13 @@ lambda_body(codegen_scope *s, node *tree, int blk) mrb_aspec a; int ma, oa, ra, pa, ka, kd, ba; int pos, i; - node *n, *opt; + node *opt; + node *margs, *pargs; node *tail; /* mandatory arguments */ ma = node_len(tree->car->car); - n = tree->car->car; - while (n) { - n = n->cdr; - } + margs = tree->car->car; tail = tree->car->cdr->cdr->cdr->cdr; /* optional arguments */ @@ -751,6 +749,7 @@ lambda_body(codegen_scope *s, node *tree, int blk) ra = tree->car->cdr->cdr->car ? 1 : 0; /* mandatory arugments after rest argument */ pa = node_len(tree->car->cdr->cdr->cdr->car); + pargs = tree->car->cdr->cdr->cdr->car; /* keyword arguments */ ka = tail? node_len(tail->cdr->car) : 0; /* keyword dictionary? */ @@ -798,6 +797,7 @@ lambda_body(codegen_scope *s, node *tree, int blk) dispatch(s, pos+i*3+1); } + /* keyword arguments */ if (tail) { node *kwds = tail->cdr->car; int kwrest = 0; @@ -836,7 +836,34 @@ lambda_body(codegen_scope *s, node *tree, int blk) genop_0(s, OP_KEYEND); } } + + /* argument destructuring */ + if (margs) { + node *n = margs; + + pos = 1; + while (n) { + if (nint(n->car->car) == NODE_MASGN) { + gen_vmassignment(s, n->car->cdr->car, pos, NOVAL); + } + pos++; + n = n->cdr; + } + } + if (pargs) { + node *n = margs; + + pos = ma+oa+ra+1; + while (n) { + if (nint(n->car->car) == NODE_MASGN) { + gen_vmassignment(s, n->car->cdr->car, pos, NOVAL); + } + pos++; + n = n->cdr; + } + } } + codegen(s, tree->cdr->car, VAL); pop(); if (s->pc > 0) { @@ -1066,6 +1093,7 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val) idx = new_sym(s, nsym(tree)); genop_2(s, OP_SETGV, sp, idx); break; + case NODE_ARG: case NODE_LVAR: idx = lv_idx(s, nsym(tree)); if (idx > 0) { @@ -1173,7 +1201,7 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) pop_n(post+1); genop_3(s, OP_APOST, cursp(), n, post); n = 1; - if (t->car) { /* rest */ + if (t->car && t->car != (node*)-1) { /* rest */ gen_assignment(s, t->car, cursp(), NOVAL); } if (t->cdr && t->cdr->car) { diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 1485fb086..d143344c3 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -682,6 +682,25 @@ new_arg(parser_state *p, mrb_sym sym) return cons((node*)NODE_ARG, nsym(sym)); } +static void +local_add_margs(parser_state *p, node *n) +{ + while (n) { + if (n->car->car == (node*)NODE_MASGN) { + node *t = n->car->cdr->cdr; + + n->car->cdr->cdr = NULL; + while (t) { + local_add_f(p, sym(t->car)); + t = t->cdr; + } + local_add_margs(p, n->car->cdr->car->car); + local_add_margs(p, n->car->cdr->car->cdr->cdr->car); + } + n = n->cdr; + } +} + /* (m o r m2 tail) */ /* m: (a b c) */ /* o: ((a . e1) (b . e2)) */ @@ -693,6 +712,8 @@ new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2, node *tail { node *n; + local_add_margs(p, m); + local_add_margs(p, m2); n = cons(m2, tail); n = cons(nsym(rest), n); n = cons(opt, n); @@ -3275,9 +3296,15 @@ f_arg_item : f_norm_arg { $$ = new_arg(p, $1); } - | tLPAREN f_margs rparen + | tLPAREN + { + $$ = local_switch(p); + } + f_margs rparen { - $$ = new_masgn(p, $2, 0); + $$ = new_masgn(p, $3, p->locals->car); + local_resume(p, $2); + local_add_f(p, 0); } ; -- cgit v1.2.3 From 94b73b14402af26a844a98d22a87cce7d8f58ea0 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 21 Dec 2018 09:35:10 +0900 Subject: Add `NULL` pointer check before `void_expr_error()`; fix #4192 --- mrbgems/mruby-compiler/core/parse.y | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index d143344c3..0e67e5881 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3664,8 +3664,10 @@ void_expr_error(parser_state *p, node *n) break; case NODE_AND: case NODE_OR: - void_expr_error(p, n->cdr->car); - void_expr_error(p, n->cdr->cdr); + if (n->cdr) { + void_expr_error(p, n->cdr->car); + void_expr_error(p, n->cdr->cdr); + } break; case NODE_BEGIN: if (n->cdr) { -- cgit v1.2.3 From b04506cdcc4e389c9e157cefe6c3ad9e6afab7ca Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 31 Dec 2018 12:50:13 +0900 Subject: Should not check non-node value to `void_expr_error`; fix #4203 This is also a reason for #4192 as well. --- mrbgems/mruby-compiler/core/parse.y | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 0e67e5881..6a2defa8f 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -795,6 +795,13 @@ new_masgn(parser_state *p, node *a, node *b) return cons((node*)NODE_MASGN, cons(a, b)); } +/* (:masgn mlhs mrhs) no check */ +static node* +new_masgn_param(parser_state *p, node *a, node *b) +{ + return cons((node*)NODE_MASGN, cons(a, b)); +} + /* (:asgn lhs rhs) */ static node* new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b) @@ -3302,7 +3309,7 @@ f_arg_item : f_norm_arg } f_margs rparen { - $$ = new_masgn(p, $3, p->locals->car); + $$ = new_masgn_param(p, $3, p->locals->car); local_resume(p, $2); local_add_f(p, 0); } -- cgit v1.2.3 From c8f904b7f5f53482293815822cebe7d5ac4247c1 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Sun, 6 Jan 2019 23:05:13 +0900 Subject: Fix 0.0 and -0.0 handling. Fix the following issue: Good: $ bin/mruby -e 'p(-0.0)' #=> "-0" Bad: $ bin/mruby -e 'a=0.0; p(-0.0)' #=> "0" --- mrbgems/mruby-compiler/core/codegen.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index b3659863b..a17272ba7 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -566,9 +567,12 @@ new_lit(codegen_scope *s, mrb_value val) #ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: for (i=0; iirep->plen; i++) { + mrb_float f1, f2; pv = &s->irep->pool[i]; if (mrb_type(*pv) != MRB_TT_FLOAT) continue; - if (mrb_float(*pv) == mrb_float(val)) return i; + f1 = mrb_float(*pv); + f2 = mrb_float(val); + if (f1 == f2 && !signbit(f1) == !signbit(f2)) return i; } break; #endif -- cgit v1.2.3 From abbc50143364dd84111573e594d24f6ace256eeb Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Mon, 28 Jan 2019 21:29:55 +0900 Subject: `class`/`module` expression with empty body should return `nil` Before: p(class A end) #=> A p(class << self; end) #=> #> p(module B end) #=> B After/Ruby: p(class A end) #=> nil p(class << self; end) #=> nil p(module B end) #=> nil --- mrbgems/mruby-compiler/core/codegen.c | 19 ++++++++++++++----- test/t/class.rb | 5 +++++ test/t/module.rb | 9 +++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index a17272ba7..cc46f835f 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2806,7 +2806,10 @@ codegen(codegen_scope *s, node *tree, int val) idx = new_sym(s, nsym(tree->car->cdr)); genop_2(s, OP_CLASS, cursp(), idx); body = tree->cdr->cdr->car; - if (!(nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL)) { + if (nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL) { + genop_1(s, OP_LOADNIL, cursp()); + } + else { idx = scope_body(s, body, val); genop_2(s, OP_EXEC, cursp(), idx); } @@ -2834,8 +2837,11 @@ codegen(codegen_scope *s, node *tree, int val) pop(); idx = new_sym(s, nsym(tree->car->cdr)); genop_2(s, OP_MODULE, cursp(), idx); - if (!(nint(tree->cdr->car->cdr->car) == NODE_BEGIN && - tree->cdr->car->cdr->cdr == NULL)) { + if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN && + tree->cdr->car->cdr->cdr == NULL) { + genop_1(s, OP_LOADNIL, cursp()); + } + else { idx = scope_body(s, tree->cdr->car, val); genop_2(s, OP_EXEC, cursp(), idx); } @@ -2852,8 +2858,11 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree->car, VAL); pop(); genop_1(s, OP_SCLASS, cursp()); - if (!(nint(tree->cdr->car->cdr->car) == NODE_BEGIN && - tree->cdr->car->cdr->cdr == NULL)) { + if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN && + tree->cdr->car->cdr->cdr == NULL) { + genop_1(s, OP_LOADNIL, cursp()); + } + else { idx = scope_body(s, tree->cdr->car, val); genop_2(s, OP_EXEC, cursp(), idx); } diff --git a/test/t/class.rb b/test/t/class.rb index f37a891a4..6a0a3225c 100644 --- a/test/t/class.rb +++ b/test/t/class.rb @@ -236,6 +236,11 @@ assert('class to return the last value') do assert_equal(m, :m) end +assert('class to return nil if body is empty') do + assert_nil(class C end) + assert_nil(class << self; end) +end + assert('raise when superclass is not a class') do module FirstModule; end assert_raise(TypeError, 'should raise TypeError') do diff --git a/test/t/module.rb b/test/t/module.rb index 78cb5d07f..f01245e88 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -708,6 +708,15 @@ assert('module with non-class/module outer raises TypeError') do assert_raise(TypeError) { module []::M2 end } end +assert('module to return the last value') do + m = module M; :m end + assert_equal(m, :m) +end + +assert('module to return nil if body is empty') do + assert_nil(module M end) +end + assert('get constant of parent module in singleton class; issue #3568') do actual = module GetConstantInSingletonTest EXPECTED = "value" -- cgit v1.2.3 From bdc9de875f5545d4dbf8136dbfb576a0caacf7e3 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 7 Feb 2019 22:44:36 +0900 Subject: Add `OP_ENTER` to blocks without parameters; fix #4175 So that `lambda{}.call(1)` raises `ArgumentError` as CRuby does. Also, fixed junk assignment for `lambda{|;a|p a}.call{}`. --- mrbgems/mruby-compiler/core/codegen.c | 5 ++++- mrbgems/mruby-compiler/core/parse.y | 33 +++++++++++++++++++++++++-------- 2 files changed, 29 insertions(+), 9 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index cc46f835f..48bf06461 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -734,7 +734,10 @@ lambda_body(codegen_scope *s, node *tree, int blk) lp->pc0 = new_label(s); } tree = tree->cdr; - if (tree->car) { + if (tree->car == NULL) { + genop_W(s, OP_ENTER, 0); + } + else { mrb_aspec a; int ma, oa, ra, pa, ka, kd, ba; int pos, i; diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 6a2defa8f..1b2d64b25 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -283,6 +283,20 @@ local_add(parser_state *p, mrb_sym sym) } } +static void +local_add_blk(parser_state *p, mrb_sym blk) +{ + /* allocate register for block */ + local_add_f(p, blk ? blk : mrb_intern_lit(p->mrb, "&")); +} + +static void +local_add_kw(parser_state *p, mrb_sym kwd) +{ + /* allocate register for keywords hash */ + local_add_f(p, kwd ? kwd : mrb_intern_lit(p->mrb, "**")); +} + static node* locals_node(parser_state *p) { @@ -726,13 +740,11 @@ 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, "**")); + local_add_kw(p, (kwrest && kwrest->cdr)? sym(kwrest->cdr) : 0); } - /* allocate register for block */ - local_add_f(p, blk? blk : mrb_intern_lit(p->mrb, "&")); + local_add_blk(p, blk); // allocate register for keywords arguments // order is for Proc#parameters @@ -2567,9 +2579,9 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail { $$ = new_args(p, $1, 0, $3, 0, $4); } - | f_arg ',' + | f_arg ',' opt_block_args_tail { - $$ = new_args(p, $1, 0, 0, 0, 0); + $$ = new_args(p, $1, 0, 0, 0, $3); } | f_arg ',' f_rest_arg ',' f_arg opt_block_args_tail { @@ -2610,19 +2622,24 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail ; opt_block_param : none - | block_param_def { + local_add_blk(p, 0); + $$ = 0; + } + | block_param_def + { p->cmd_start = TRUE; $$ = $1; } ; -block_param_def : '|' opt_bv_decl '|' +block_param_def : '|' {local_add_blk(p, 0);} opt_bv_decl '|' { $$ = 0; } | tOROP { + local_add_blk(p, 0); $$ = 0; } | '|' block_param opt_bv_decl '|' -- cgit v1.2.3 From c6e2d91536acfb05803323c42eccef1811e7bf23 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Mon, 11 Feb 2019 21:09:40 +0900 Subject: Small refactoring in `codegen.c` --- mrbgems/mruby-compiler/core/codegen.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 48bf06461..bfc08cd94 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2357,13 +2357,9 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_BACK_REF: if (val) { - char buf[3]; - int sym; + char buf[] = {'$', nchar(tree)}; + int sym = new_sym(s, mrb_intern(s->mrb, buf, sizeof(buf))); - buf[0] = '$'; - buf[1] = nchar(tree); - buf[2] = 0; - sym = new_sym(s, mrb_intern_cstr(s->mrb, buf)); genop_2(s, OP_GETGV, cursp(), sym); push(); } -- cgit v1.2.3 From 4ccc3f15259c9857255c5af9f35e56c742aca2c3 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 13 Feb 2019 07:28:33 +0900 Subject: Use key argument register for `OP_KEY_P` to reduce register use. --- mrbgems/mruby-compiler/core/codegen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index bfc08cd94..a2d790e32 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -823,8 +823,8 @@ lambda_body(codegen_scope *s, node *tree, int blk) mrb_assert(nint(kwd->car) == NODE_KW_ARG); if (def_arg) { - genop_2(s, OP_KEY_P, cursp(), new_sym(s, kwd_sym)); - jmpif_key_p = genjmp2(s, OP_JMPIF, cursp(), 0, 0); + genop_2(s, OP_KEY_P, lv_idx(s, kwd_sym), new_sym(s, kwd_sym)); + jmpif_key_p = genjmp2(s, OP_JMPIF, lv_idx(s, kwd_sym), 0, 0); codegen(s, def_arg, VAL); pop(); gen_move(s, lv_idx(s, kwd_sym), cursp(), 0); -- cgit v1.2.3 From 289462508980b5231f812f8a34229ad8cdb33ca9 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Wed, 27 Feb 2019 20:21:40 +0900 Subject: Use `yywarning()` instead of `yywarning_s()` for `MRB_WITHOUT_FLOAT` --- mrbgems/mruby-compiler/core/parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 1b2d64b25..82aa346d0 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -5167,7 +5167,7 @@ parser_yylex(parser_state *p) tokfix(p); if (is_float) { #ifdef MRB_WITHOUT_FLOAT - yywarning_s(p, "floating point numbers are not supported", tok(p)); + yywarning(p, "floating point numbers are not supported"); pylval.nd = new_int(p, "0", 10); return tINTEGER; #else -- cgit v1.2.3 From c11bd075f78e1f9d4b9a18401ce3292809433038 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Wed, 27 Feb 2019 20:27:29 +0900 Subject: Remove unnecessary backticks; ref #2858 --- mrbgems/mruby-compiler/core/parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 1b2d64b25..1efc0ea9d 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -4568,7 +4568,7 @@ parser_yylex(parser_state *p) } pushback(p, c); if (IS_SPCARG(c)) { - yywarning(p, "`**' interpreted as argument prefix"); + yywarning(p, "'**' interpreted as argument prefix"); c = tDSTAR; } else if (IS_BEG()) { -- cgit v1.2.3 From cece0163895c9f62b6b7ffb8724acba1217bf9ab Mon Sep 17 00:00:00 2001 From: dearblue Date: Wed, 27 Feb 2019 20:18:50 +0900 Subject: Concatenate string literals --- mrbgems/mruby-compiler/core/parse.y | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 82aa346d0..09088f3c3 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -852,6 +852,12 @@ new_dstr(parser_state *p, node *a) return cons((node*)NODE_DSTR, a); } +static node* +concat_string(parser_state *p, node *a, node *b) +{ + return new_dstr(p, list2(a, b)); +} + /* (:str . (s . len)) */ static node* new_xstr(parser_state *p, const char *s, int len) @@ -1200,7 +1206,7 @@ heredoc_end(parser_state *p) %token tNTH_REF tBACK_REF %token tREGEXP_END -%type singleton string string_rep string_interp xstring regexp +%type singleton string string_fragment string_rep string_interp xstring regexp %type literal numeric cpath symbol %type top_compstmt top_stmts top_stmt %type bodystmt compstmt stmts stmt expr arg primary command command_call method_call @@ -2852,7 +2858,14 @@ literal : numeric | symbols ; -string : tCHAR +string : string_fragment + | string string_fragment + { + $$ = concat_string(p, $1, $2); + } + ; + +string_fragment : tCHAR | tSTRING | tSTRING_BEG tSTRING { @@ -3478,7 +3491,7 @@ assoc : arg tASSOC arg void_expr_error(p, $3); $$ = cons(new_sym(p, $1), $3); } - | string tLABEL_TAG arg + | string_fragment tLABEL_TAG arg { void_expr_error(p, $3); if ($1->car == (node*)NODE_DSTR) { -- cgit v1.2.3 From 9913643ed8a6d778bc90a932e30e6113e8b3f9e3 Mon Sep 17 00:00:00 2001 From: dearblue Date: Wed, 27 Feb 2019 21:42:37 +0900 Subject: Compositing `NODE_STR` and `NODE_STR` --- mrbgems/mruby-compiler/core/parse.y | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 09088f3c3..e80af7d6d 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -855,6 +855,21 @@ new_dstr(parser_state *p, node *a) static node* concat_string(parser_state *p, node *a, node *b) { + if ((enum node_type)(intptr_t)a->car == NODE_STR) { + if ((enum node_type)(intptr_t)b->car == NODE_STR) { + /* a == NODE_STR && b == NODE_STR */ + size_t newlen = (size_t)a->cdr->cdr + (size_t)b->cdr->cdr; + char *str = (char*)mrb_pool_realloc(p->pool, a->cdr->car, (size_t)a->cdr->cdr + 1, newlen + 1); + memcpy(str + (size_t)a->cdr->cdr, b->cdr->car, (size_t)b->cdr->cdr); + str[newlen] = '\0'; + a->cdr->car = (node*)str; + a->cdr->cdr = (node*)newlen; + cons_free(b->cdr); + cons_free(b); + return a; + } + } + return new_dstr(p, list2(a, b)); } -- cgit v1.2.3 From 477e5285e86afb5f33e74747a54201718a249489 Mon Sep 17 00:00:00 2001 From: dearblue Date: Wed, 27 Feb 2019 21:46:07 +0900 Subject: Replacement to function for `NODE_STR` cheking --- mrbgems/mruby-compiler/core/parse.y | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index e80af7d6d..2771ddeed 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -852,11 +852,17 @@ new_dstr(parser_state *p, node *a) return cons((node*)NODE_DSTR, a); } +static int +string_node_p(node *n) +{ + return (int)((enum node_type)(intptr_t)n->car == NODE_STR); +} + static node* concat_string(parser_state *p, node *a, node *b) { - if ((enum node_type)(intptr_t)a->car == NODE_STR) { - if ((enum node_type)(intptr_t)b->car == NODE_STR) { + if (string_node_p(a)) { + if (string_node_p(b)) { /* a == NODE_STR && b == NODE_STR */ size_t newlen = (size_t)a->cdr->cdr + (size_t)b->cdr->cdr; char *str = (char*)mrb_pool_realloc(p->pool, a->cdr->car, (size_t)a->cdr->cdr + 1, newlen + 1); -- cgit v1.2.3 From 25957421bcea8070a796428c4dc6638142ffbb56 Mon Sep 17 00:00:00 2001 From: dearblue Date: Wed, 27 Feb 2019 21:49:41 +0900 Subject: Replacement to function for composite two string nodes --- mrbgems/mruby-compiler/core/parse.y | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 2771ddeed..ea292c3b9 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -858,19 +858,26 @@ string_node_p(node *n) return (int)((enum node_type)(intptr_t)n->car == NODE_STR); } +static node* +composite_string_node(parser_state *p, node *a, node *b) +{ + size_t newlen = (size_t)a->cdr + (size_t)b->cdr; + char *str = (char*)mrb_pool_realloc(p->pool, a->car, (size_t)a->cdr + 1, newlen + 1); + memcpy(str + (size_t)a->cdr, b->car, (size_t)b->cdr); + str[newlen] = '\0'; + a->car = (node*)str; + a->cdr = (node*)newlen; + cons_free(b); + return a; +} + static node* concat_string(parser_state *p, node *a, node *b) { if (string_node_p(a)) { if (string_node_p(b)) { /* a == NODE_STR && b == NODE_STR */ - size_t newlen = (size_t)a->cdr->cdr + (size_t)b->cdr->cdr; - char *str = (char*)mrb_pool_realloc(p->pool, a->cdr->car, (size_t)a->cdr->cdr + 1, newlen + 1); - memcpy(str + (size_t)a->cdr->cdr, b->cdr->car, (size_t)b->cdr->cdr); - str[newlen] = '\0'; - a->cdr->car = (node*)str; - a->cdr->cdr = (node*)newlen; - cons_free(b->cdr); + composite_string_node(p, a->cdr, b->cdr); cons_free(b); return a; } -- cgit v1.2.3 From 8ead6da9132e57f2b8e47e4dfb793aa1b90e5daa Mon Sep 17 00:00:00 2001 From: dearblue Date: Wed, 27 Feb 2019 20:21:35 +0900 Subject: Compositing `NODE_STR` and `NODE_DSTR` --- mrbgems/mruby-compiler/core/parse.y | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index ea292c3b9..4c884fa92 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -881,6 +881,17 @@ concat_string(parser_state *p, node *a, node *b) cons_free(b); return a; } + else { + /* a == NODE_STR && b == NODE_DSTR */ + + if (string_node_p(b->cdr->car)) { + /* a == NODE_STR && b->[NODE_STR, ...] */ + composite_string_node(p, a->cdr, b->cdr->car->cdr); + cons_free(b->cdr->car); + b->cdr->car = a; + return b; + } + } } return new_dstr(p, list2(a, b)); -- cgit v1.2.3 From 4d2bb3cb47b3628eb140d1d28f79f29887cf6262 Mon Sep 17 00:00:00 2001 From: dearblue Date: Wed, 27 Feb 2019 20:22:24 +0900 Subject: Compositing `NODE_DSTR` and `NODE_STR` --- mrbgems/mruby-compiler/core/parse.y | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 4c884fa92..fed8cfbbc 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -893,6 +893,21 @@ concat_string(parser_state *p, node *a, node *b) } } } + else if (string_node_p(b)) { + /* a == NODE_DSTR && b == NODE_STR */ + + node *c; + for (c = a; c->cdr != NULL; c = c->cdr) ; + if (string_node_p(c->car)) { + /* a->[..., NODE_STR] && b == NODE_STR */ + composite_string_node(p, c->car->cdr, b->cdr); + cons_free(b); + return a; + } + + push(a, b); + return a; + } return new_dstr(p, list2(a, b)); } -- cgit v1.2.3 From e871a1538d2c84c56d102656d393ecf630f4deef Mon Sep 17 00:00:00 2001 From: dearblue Date: Wed, 27 Feb 2019 20:22:55 +0900 Subject: Compositing `NODE_DSTR` and `NODE_DSTR` --- mrbgems/mruby-compiler/core/parse.y | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index fed8cfbbc..57eb03cc6 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -908,6 +908,27 @@ concat_string(parser_state *p, node *a, node *b) push(a, b); return a; } + else { + /* a == NODE_DSTR && b == NODE_DSTR */ + + node *c, *d; + for (c = a; c->cdr != NULL; c = c->cdr) ; + if (string_node_p(c->car) && string_node_p(b->cdr->car)) { + /* a->[..., NODE_STR] && b->[NODE_STR, ...] */ + d = b->cdr; + cons_free(b); + composite_string_node(p, c->car->cdr, d->car->cdr); + cons_free(d->car); + c->cdr = d->cdr; + cons_free(d); + return a; + } + else { + c->cdr = b->cdr; + cons_free(b); + return a; + } + } return new_dstr(p, list2(a, b)); } -- cgit v1.2.3 From 8c04ba2222e277f55ffc131480bc6e58ec73c1dc Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Thu, 28 Feb 2019 19:54:45 +0900 Subject: Add `warning: ` prefix to parser warning message --- mrbgems/mruby-compiler/core/parse.y | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index e281a5a6d..0aabc2f34 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3708,10 +3708,10 @@ yywarn(parser_state *p, const char *s) if (! p->capture_errors) { #ifndef MRB_DISABLE_STDIO if (p->filename) { - fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s); + fprintf(stderr, "%s:%d:%d: warning: %s\n", p->filename, p->lineno, p->column, s); } else { - fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s); + fprintf(stderr, "line %d:%d: warning: %s\n", p->lineno, p->column, s); } #endif } -- cgit v1.2.3 From a5a6b51126875e578ef1834c8af06141934df7dd Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 25 Mar 2019 21:06:54 +0900 Subject: Use uppercase version of `ctype` macros e.g. `ISSPACE`; fix #4338 --- mrbgems/mruby-bin-mirb/tools/mirb/mirb.c | 22 +++++++++++----------- mrbgems/mruby-compiler/core/parse.y | 12 ++++++------ mrbgems/mruby-pack/src/pack.c | 6 +++--- src/string.c | 6 +++--- 4 files changed, 23 insertions(+), 23 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c index 9519d88bb..17b2ca16c 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c @@ -6,6 +6,15 @@ ** immediately. It's a REPL... */ +#include +#include +#include +#include +#include +#include +#include +#include + #include #include #include @@ -49,15 +58,6 @@ #define SIGJMP_BUF jmp_buf #endif -#include -#include -#include -#include -#include -#include -#include -#include - #ifdef ENABLE_READLINE static const char history_file_name[] = ".mirb_history"; @@ -373,7 +373,7 @@ check_keyword(const char *buf, const char *word) size_t len = strlen(word); /* skip preceding spaces */ - while (*p && isspace((unsigned char)*p)) { + while (*p && ISSPACE(*p)) { p++; } /* check keyword */ @@ -383,7 +383,7 @@ check_keyword(const char *buf, const char *word) p += len; /* skip trailing spaces */ while (*p) { - if (!isspace((unsigned char)*p)) return 0; + if (!ISSPACE(*p)) return 0; p++; } return 1; diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 0aabc2f34..90f01e3a8 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -4888,10 +4888,10 @@ parser_yylex(parser_state *p) } newtok(p); /* need support UTF-8 if configured */ - if ((isalnum(c) || c == '_')) { + if ((ISALNUM(c) || c == '_')) { int c2 = nextc(p); pushback(p, c2); - if ((isalnum(c2) || c2 == '_')) { + if ((ISALNUM(c2) || c2 == '_')) { goto ternary; } } @@ -5459,7 +5459,7 @@ parser_yylex(parser_state *p) } else { term = nextc(p); - if (isalnum(term)) { + if (ISALNUM(term)) { yyerror(p, "unknown type of %string"); return 0; } @@ -5603,7 +5603,7 @@ parser_yylex(parser_state *p) do { tokadd(p, c); c = nextc(p); - } while (c >= 0 && isdigit(c)); + } while (c >= 0 && ISDIGIT(c)); pushback(p, c); if (last_state == EXPR_FNAME) goto gvar; tokfix(p); @@ -5645,7 +5645,7 @@ parser_yylex(parser_state *p) } return 0; } - else if (isdigit(c)) { + else if (ISDIGIT(c)) { if (p->tidx == 1) { yyerror_i(p, "'@%c' is not allowed as an instance variable name", c); } @@ -5802,7 +5802,7 @@ parser_yylex(parser_state *p) mrb_sym ident = intern_cstr(tok(p)); pylval.id = ident; - if (last_state != EXPR_DOT && islower(tok(p)[0]) && local_var_p(p, ident)) { + if (last_state != EXPR_DOT && ISLOWER(tok(p)[0]) && local_var_p(p, ident)) { p->lstate = EXPR_END; } } diff --git a/mrbgems/mruby-pack/src/pack.c b/mrbgems/mruby-pack/src/pack.c index 2e68f35ed..ac29fdbf3 100644 --- a/mrbgems/mruby-pack/src/pack.c +++ b/mrbgems/mruby-pack/src/pack.c @@ -627,7 +627,7 @@ unpack_a(mrb_state *mrb, const void *src, int slen, mrb_value ary, long count, u } } else if (!(flags & PACK_FLAG_a)) { /* "A" */ - while (copylen > 0 && (sptr[copylen - 1] == '\0' || isspace(sptr[copylen - 1]))) { + while (copylen > 0 && (sptr[copylen - 1] == '\0' || ISSPACE(sptr[copylen - 1]))) { copylen--; } } @@ -1072,9 +1072,9 @@ alias: /* read suffix [0-9*_!<>] */ while (tmpl->idx < tlen) { ch = tptr[tmpl->idx++]; - if (isdigit(ch)) { + if (ISDIGIT(ch)) { count = ch - '0'; - while (tmpl->idx < tlen && isdigit(tptr[tmpl->idx])) { + while (tmpl->idx < tlen && ISDIGIT(tptr[tmpl->idx])) { count = count * 10 + (tptr[tmpl->idx++] - '0'); if (count < 0) { mrb_raise(mrb, E_RUNTIME_ERROR, "too big template length"); diff --git a/src/string.c b/src/string.c index 19962fb30..8efea84ab 100644 --- a/src/string.c +++ b/src/string.c @@ -2844,7 +2844,7 @@ mrb_float_read(const char *string, char **endPtr) */ p = string; - while (isspace(*p)) { + while (ISSPACE(*p)) { p += 1; } if (*p == '-') { @@ -2867,7 +2867,7 @@ mrb_float_read(const char *string, char **endPtr) for (mantSize = 0; ; mantSize += 1) { c = *p; - if (!isdigit(c)) { + if (!ISDIGIT(c)) { if ((c != '.') || (decPt >= 0)) { break; } @@ -2952,7 +2952,7 @@ mrb_float_read(const char *string, char **endPtr) } expSign = FALSE; } - while (isdigit(*p)) { + while (ISDIGIT(*p)) { exp = exp * 10 + (*p - '0'); if (exp > 19999) { exp = 19999; -- cgit v1.2.3 From 2871d0cdc5e5ef952d27187b5488888bbd18c5b0 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 1 Apr 2019 14:13:06 +0900 Subject: Avoid keeping pointers from `mrb_sym2name_len()`; fix #4342 The addresses for packed inline symbols reference `mrb->symbuf` that could be overridden by the later call of `mrb_sym2name_len`. Since file names in call stack information are kept as symbols, keeping the address in the C structures could cause problems like #4342. This changes small incompatible changes in function prototypes: * `mrb_parser_get_filename`: return value changed to `mrb_sym`. * `mrb_debug_get_filename`: add `mrb_state*` as a first argument. * `mrb_debug_get_line`: ditto. I believe above functions are almost internal, and no third-party mrbgem use them. --- include/mruby/compile.h | 4 ++-- include/mruby/debug.h | 5 ++--- mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c | 16 ++++++++------- mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c | 2 +- mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c | 6 +++--- mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c | 4 ++-- mrbgems/mruby-compiler/core/codegen.c | 25 +++++++++++++----------- mrbgems/mruby-compiler/core/parse.y | 20 ++++++++++--------- mrbgems/mruby-proc-ext/src/proc.c | 8 ++++---- src/backtrace.c | 4 ++-- src/class.c | 14 +++---------- src/codedump.c | 14 ++++++------- src/debug.c | 15 +++++++------- src/error.c | 4 ++-- src/load.c | 3 --- src/symbol.c | 9 ++++++++- 16 files changed, 77 insertions(+), 76 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/include/mruby/compile.h b/include/mruby/compile.h index fd735be88..f19d9b0b3 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -118,7 +118,7 @@ struct mrb_parser_state { FILE *f; #endif mrbc_context *cxt; - char const *filename; + mrb_sym filename_sym; int lineno; int column; @@ -168,7 +168,7 @@ MRB_API void mrb_parser_free(struct mrb_parser_state*); MRB_API void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*); MRB_API void mrb_parser_set_filename(struct mrb_parser_state*, char const*); -MRB_API char const* mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx); +MRB_API mrb_sym mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx); /* utility functions */ #ifndef MRB_DISABLE_STDIO diff --git a/include/mruby/debug.h b/include/mruby/debug.h index f0a40dfcf..e08c47cfc 100644 --- a/include/mruby/debug.h +++ b/include/mruby/debug.h @@ -26,7 +26,6 @@ typedef struct mrb_irep_debug_info_line { typedef struct mrb_irep_debug_info_file { uint32_t start_pos; - const char *filename; mrb_sym filename_sym; uint32_t line_entry_count; mrb_debug_line_type line_type; @@ -47,13 +46,13 @@ typedef struct mrb_irep_debug_info { * get line from irep's debug info and program counter * @return returns NULL if not found */ -MRB_API const char *mrb_debug_get_filename(mrb_irep *irep, ptrdiff_t pc); +MRB_API const char *mrb_debug_get_filename(mrb_state *mrb, mrb_irep *irep, ptrdiff_t pc); /* * get line from irep's debug info and program counter * @return returns -1 if not found */ -MRB_API int32_t mrb_debug_get_line(mrb_irep *irep, ptrdiff_t pc); +MRB_API int32_t mrb_debug_get_line(mrb_state *mrb, mrb_irep *irep, ptrdiff_t pc); MRB_API mrb_irep_debug_info *mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep); MRB_API mrb_irep_debug_info_file *mrb_debug_info_append_file( diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c b/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c index d3ccf08ae..513db4ded 100644 --- a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c +++ b/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c @@ -84,7 +84,7 @@ free_breakpoint(mrb_state *mrb, mrb_debug_breakpoint *bp) } static uint16_t -check_file_lineno(struct mrb_irep *irep, const char *file, uint16_t lineno) +check_file_lineno(mrb_state *mrb, struct mrb_irep *irep, const char *file, uint16_t lineno) { mrb_irep_debug_info_file *info_file; uint16_t result = 0; @@ -93,8 +93,10 @@ check_file_lineno(struct mrb_irep *irep, const char *file, uint16_t lineno) uint16_t i; for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { + const char *filename; info_file = irep->debug_info->files[f_idx]; - if (!strcmp(info_file->filename, file)) { + filename = mrb_sym2name_len(mrb, info_file->filename_sym, NULL); + if (!strcmp(filename, file)) { result = MRB_DEBUG_BP_FILE_OK; fix_lineno = check_lineno(info_file, lineno); @@ -103,7 +105,7 @@ check_file_lineno(struct mrb_irep *irep, const char *file, uint16_t lineno) } } for (i=0; i < irep->rlen; ++i) { - result |= check_file_lineno(irep->reps[i], file, lineno); + result |= check_file_lineno(mrb, irep->reps[i], file, lineno); if (result == (MRB_DEBUG_BP_FILE_OK | MRB_DEBUG_BP_LINENO_OK)) { return result; } @@ -185,7 +187,7 @@ mrb_debug_set_break_line(mrb_state *mrb, mrb_debug_context *dbg, const char *fil } /* file and lineno check (line type mrb_debug_line_ary only.) */ - result = check_file_lineno(dbg->root_irep, file, lineno); + result = check_file_lineno(mrb, dbg->root_irep, file, lineno); if (result == 0) { return MRB_DEBUG_BREAK_INVALID_FILE; } @@ -426,10 +428,10 @@ mrb_debug_disable_break_all(mrb_state *mrb, mrb_debug_context *dbg) } static mrb_bool -check_start_pc_for_line(mrb_irep *irep, mrb_code *pc, uint16_t line) +check_start_pc_for_line(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, uint16_t line) { if (pc > irep->iseq) { - if (line == mrb_debug_get_line(irep, pc - irep->iseq - 1)) { + if (line == mrb_debug_get_line(mrb, irep, pc - irep->iseq - 1)) { return FALSE; } } @@ -447,7 +449,7 @@ mrb_debug_check_breakpoint_line(mrb_state *mrb, mrb_debug_context *dbg, const ch return MRB_DEBUG_INVALID_ARGUMENT; } - if (!check_start_pc_for_line(dbg->irep, dbg->pc, line)) { + if (!check_start_pc_for_line(mrb, dbg->irep, dbg->pc, line)) { return MRB_DEBUG_OK; } diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c b/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c index 21fe64127..66ddfa783 100644 --- a/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c +++ b/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c @@ -181,7 +181,7 @@ mrb_debug_get_source(mrb_state *mrb, mrdb_state *mrdb, const char *srcpath, cons else srcname = filename; search_path[0] = srcpath; - search_path[1] = dirname(mrb, mrb_debug_get_filename(mrdb->dbg->irep, 0)); + search_path[1] = dirname(mrb, mrb_debug_get_filename(mrb, mrdb->dbg->irep, 0)); search_path[2] = "."; for (i = 0; i < 3; i++) { diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c b/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c index 8e5901754..bc9937e94 100644 --- a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c +++ b/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c @@ -242,7 +242,7 @@ info_break_select(mrb_state *mrb, mrdb_state *mrdb) } mrb_debug_bptype -parse_breakcommand(mrdb_state *mrdb, const char **file, uint32_t *line, char **cname, char **method) +parse_breakcommand(mrb_state *mrb, mrdb_state *mrdb, const char **file, uint32_t *line, char **cname, char **method) { mrb_debug_context *dbg = mrdb->dbg; char *args; @@ -274,7 +274,7 @@ parse_breakcommand(mrdb_state *mrdb, const char **file, uint32_t *line, char **c STRTOUL(l, body); if (l <= 65535) { *line = l; - *file = (body == args)? mrb_debug_get_filename(dbg->irep, dbg->pc - dbg->irep->iseq): args; + *file = (body == args)? mrb_debug_get_filename(mrb, dbg->irep, dbg->pc - dbg->irep->iseq): args; } else { puts(BREAK_ERR_MSG_RANGEOVER); @@ -332,7 +332,7 @@ dbgcmd_break(mrb_state *mrb, mrdb_state *mrdb) char *method = NULL; int32_t ret; - type = parse_breakcommand(mrdb, &file, &line, &cname, &method); + type = parse_breakcommand(mrb, mrdb, &file, &line, &cname, &method); switch (type) { case MRB_DEBUG_BPTYPE_LINE: ret = mrb_debug_set_break_line(mrb, dbg, file, line); diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c index 5256ac5e3..003406172 100644 --- a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c +++ b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c @@ -569,8 +569,8 @@ mrb_code_fetch_hook(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *reg dbg->xphase = DBG_PHASE_RUNNING; } - file = mrb_debug_get_filename(irep, pc - irep->iseq); - line = mrb_debug_get_line(irep, pc - irep->iseq); + file = mrb_debug_get_filename(mrb, irep, pc - irep->iseq); + line = mrb_debug_get_line(mrb, irep, pc - irep->iseq); switch (dbg->xm) { case DBG_STEP: diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index a2d790e32..927cc3a0f 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -62,7 +62,7 @@ typedef struct scope { struct loopinfo *loop; int ensure_level; - char const *filename; + mrb_sym filename_sym; uint16_t lineno; mrb_code *iseq; @@ -106,8 +106,9 @@ codegen_error(codegen_scope *s, const char *message) s = tmp; } #ifndef MRB_DISABLE_STDIO - if (s->filename && s->lineno) { - fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message); + if (s->filename_sym && s->lineno) { + const char *filename = mrb_sym2name_len(s->mrb, s->filename_sym, NULL); + fprintf(stderr, "codegen error:%s:%d: %s\n", filename, s->lineno, message); } else { fprintf(stderr, "codegen error: %s\n", message); @@ -1399,13 +1400,14 @@ codegen(codegen_scope *s, node *tree, int val) codegen_error(s, "too complex expression"); } if (s->irep && s->filename_index != tree->filename_index) { - const char *filename = mrb_parser_get_filename(s->parser, s->filename_index); + mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index); + const char *filename = mrb_sym2name_len(s->mrb, fname, NULL); mrb_debug_info_append_file(s->mrb, s->irep->debug_info, filename, s->lines, s->debug_start_pos, s->pc); s->debug_start_pos = s->pc; s->filename_index = tree->filename_index; - s->filename = mrb_parser_get_filename(s->parser, tree->filename_index); + s->filename_sym = mrb_parser_get_filename(s->parser, tree->filename_index); } nt = nint(tree->car); @@ -2990,15 +2992,15 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) } p->ai = mrb_gc_arena_save(mrb); - p->filename = prev->filename; - if (p->filename) { + p->filename_sym = prev->filename_sym; + if (p->filename_sym) { p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa); } p->lineno = prev->lineno; /* debug setting */ p->debug_start_pos = 0; - if (p->filename) { + if (p->filename_sym) { mrb_debug_info_alloc(mrb, p->irep); } else { @@ -3026,8 +3028,9 @@ scope_finish(codegen_scope *s) irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen); irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen); irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen); - if (s->filename) { - const char *filename = mrb_parser_get_filename(s->parser, s->filename_index); + if (s->filename_sym) { + mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index); + const char *filename = mrb_sym2name_len(s->mrb, fname, NULL); mrb_debug_info_append_file(s->mrb, s->irep->debug_info, filename, s->lines, s->debug_start_pos, s->pc); @@ -3136,7 +3139,7 @@ generate_code(mrb_state *mrb, parser_state *p, int val) } scope->mrb = mrb; scope->parser = p; - scope->filename = p->filename; + scope->filename_sym = p->filename_sym; scope->filename_index = p->current_filename_index; MRB_TRY(&scope->jmp) { diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 90f01e3a8..88d9ea4ee 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3162,7 +3162,7 @@ var_ref : variable } | keyword__FILE__ { - const char *fn = p->filename; + const char *fn = mrb_sym2name_len(p->mrb, p->filename_sym, NULL); if (!fn) { fn = "(null)"; } @@ -3671,8 +3671,9 @@ yyerror(parser_state *p, const char *s) if (! p->capture_errors) { #ifndef MRB_DISABLE_STDIO - if (p->filename) { - fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s); + if (p->filename_sym) { + const char *filename = mrb_sym2name_len(p->mrb, p->filename_sym, NULL); + fprintf(stderr, "%s:%d:%d: %s\n", filename, p->lineno, p->column, s); } else { fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s); @@ -3707,8 +3708,9 @@ yywarn(parser_state *p, const char *s) if (! p->capture_errors) { #ifndef MRB_DISABLE_STDIO - if (p->filename) { - fprintf(stderr, "%s:%d:%d: warning: %s\n", p->filename, p->lineno, p->column, s); + if (p->filename_sym) { + const char *filename = mrb_sym2name_len(p->mrb, p->filename_sym, NULL); + fprintf(stderr, "%s:%d:%d: warning: %s\n", filename, p->lineno, p->column, s); } else { fprintf(stderr, "line %d:%d: warning: %s\n", p->lineno, p->column, s); @@ -6012,7 +6014,7 @@ mrb_parser_set_filename(struct mrb_parser_state *p, const char *f) mrb_sym* new_table; sym = mrb_intern_cstr(p->mrb, f); - p->filename = mrb_sym2name_len(p->mrb, sym, NULL); + p->filename_sym = sym; p->lineno = (p->filename_table_length > 0)? 0 : 1; for (i = 0; i < p->filename_table_length; ++i) { @@ -6036,11 +6038,11 @@ mrb_parser_set_filename(struct mrb_parser_state *p, const char *f) p->filename_table[p->filename_table_length - 1] = sym; } -MRB_API char const* +MRB_API mrb_sym mrb_parser_get_filename(struct mrb_parser_state* p, uint16_t idx) { - if (idx >= p->filename_table_length) return NULL; + if (idx >= p->filename_table_length) return 0; else { - return mrb_sym2name_len(p->mrb, p->filename_table[idx], NULL); + return p->filename_table[idx]; } } diff --git a/mrbgems/mruby-proc-ext/src/proc.c b/mrbgems/mruby-proc-ext/src/proc.c index 4b85c245d..17884e3c6 100644 --- a/mrbgems/mruby-proc-ext/src/proc.c +++ b/mrbgems/mruby-proc-ext/src/proc.c @@ -25,8 +25,8 @@ mrb_proc_source_location(mrb_state *mrb, mrb_value self) int32_t line; const char *filename; - filename = mrb_debug_get_filename(irep, 0); - line = mrb_debug_get_line(irep, 0); + filename = mrb_debug_get_filename(mrb, irep, 0); + line = mrb_debug_get_line(mrb, irep, 0); return (!filename && line == -1)? mrb_nil_value() : mrb_assoc_new(mrb, mrb_str_new_cstr(mrb, filename), mrb_fixnum_value(line)); @@ -46,11 +46,11 @@ mrb_proc_inspect(mrb_state *mrb, mrb_value self) int32_t line; mrb_str_cat_lit(mrb, str, "@"); - filename = mrb_debug_get_filename(irep, 0); + filename = mrb_debug_get_filename(mrb, irep, 0); mrb_str_cat_cstr(mrb, str, filename ? filename : "-"); mrb_str_cat_lit(mrb, str, ":"); - line = mrb_debug_get_line(irep, 0); + line = mrb_debug_get_line(mrb, irep, 0); if (line != -1) { str = mrb_format(mrb, "%S:%S", str, mrb_fixnum_value(line)); } diff --git a/src/backtrace.c b/src/backtrace.c index efca2562f..e4f5a3064 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -58,10 +58,10 @@ each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, mrb_code *pc0, each_backtrace_fu pc = pc0; } - loc.lineno = mrb_debug_get_line(irep, pc - irep->iseq); + loc.lineno = mrb_debug_get_line(mrb, irep, pc - irep->iseq); if (loc.lineno == -1) continue; - loc.filename = mrb_debug_get_filename(irep, pc - irep->iseq); + loc.filename = mrb_debug_get_filename(mrb, irep, pc - irep->iseq); if (!loc.filename) { loc.filename = "(unknown)"; } diff --git a/src/class.c b/src/class.c index 3354617bb..5c5ee9d17 100644 --- a/src/class.c +++ b/src/class.c @@ -484,15 +484,11 @@ mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t MRB_API void mrb_notimplement(mrb_state *mrb) { - const char *str; - mrb_int len; mrb_callinfo *ci = mrb->c->ci; if (ci->mid) { - str = mrb_sym2name_len(mrb, ci->mid, &len); - mrb_raisef(mrb, E_NOTIMP_ERROR, - "%S() function is unimplemented on this machine", - mrb_str_new_static(mrb, str, (size_t)len)); + mrb_value str = mrb_sym2str(mrb, ci->mid); + mrb_raisef(mrb, E_NOTIMP_ERROR, "%S() function is unimplemented on this machine", str); } } @@ -1686,11 +1682,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) } else if (mrb_symbol_p(path)) { /* toplevel class/module */ - const char *str; - mrb_int len; - - str = mrb_sym2name_len(mrb, mrb_symbol(path), &len); - return mrb_str_new(mrb, str, len); + return mrb_sym2str(mrb, mrb_symbol(path)); } return mrb_str_dup(mrb, path); } diff --git a/src/codedump.c b/src/codedump.c index c9c3b25ef..5bffefddb 100644 --- a/src/codedump.c +++ b/src/codedump.c @@ -48,11 +48,11 @@ print_lv_ab(mrb_state *mrb, mrb_irep *irep, uint16_t a, uint16_t b) } static void -print_header(mrb_irep *irep, ptrdiff_t i) +print_header(mrb_state *mrb, mrb_irep *irep, ptrdiff_t i) { int32_t line; - line = mrb_debug_get_line(irep, i); + line = mrb_debug_get_line(mrb, irep, i); if (line < 0) { printf(" "); } @@ -99,12 +99,12 @@ codedump(mrb_state *mrb, mrb_irep *irep) ai = mrb_gc_arena_save(mrb); i = pc - irep->iseq; - next_file = mrb_debug_get_filename(irep, i); + next_file = mrb_debug_get_filename(mrb, irep, i); if (next_file && file != next_file) { printf("file: %s\n", next_file); file = next_file; } - print_header(irep, i); + print_header(mrb, irep, i); ins = READ_B(); switch (ins) { CASE(OP_NOP, Z): @@ -491,7 +491,7 @@ codedump(mrb_state *mrb, mrb_irep *irep) CASE(OP_EXT1, Z): ins = READ_B(); printf("OP_EXT1\n"); - print_header(irep, pc-irep->iseq-2); + print_header(mrb, 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" @@ -501,7 +501,7 @@ codedump(mrb_state *mrb, mrb_irep *irep) CASE(OP_EXT2, Z): ins = READ_B(); printf("OP_EXT2\n"); - print_header(irep, pc-irep->iseq-2); + print_header(mrb, 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" @@ -511,7 +511,7 @@ codedump(mrb_state *mrb, mrb_irep *irep) CASE(OP_EXT3, Z): ins = READ_B(); printf("OP_EXT3\n"); - print_header(irep, pc-irep->iseq-2); + print_header(mrb, 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" diff --git a/src/debug.c b/src/debug.c index 2949131e4..0dc02a1e3 100644 --- a/src/debug.c +++ b/src/debug.c @@ -51,20 +51,20 @@ select_line_type(const uint16_t *lines, size_t lines_len) } MRB_API char const* -mrb_debug_get_filename(mrb_irep *irep, ptrdiff_t pc) +mrb_debug_get_filename(mrb_state *mrb, mrb_irep *irep, ptrdiff_t pc) { if (irep && pc >= 0 && pc < irep->ilen) { mrb_irep_debug_info_file* f = NULL; if (!irep->debug_info) return NULL; else if ((f = get_file(irep->debug_info, (uint32_t)pc))) { - return f->filename; + return mrb_sym2name_len(mrb, f->filename_sym, NULL); } } return NULL; } MRB_API int32_t -mrb_debug_get_line(mrb_irep *irep, ptrdiff_t pc) +mrb_debug_get_line(mrb_state *mrb, mrb_irep *irep, ptrdiff_t pc) { if (irep && pc >= 0 && pc < irep->ilen) { mrb_irep_debug_info_file* f = NULL; @@ -129,7 +129,6 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep_debug_info *d, mrb_irep_debug_info_file *f; uint32_t file_pc_count; size_t fn_len; - mrb_int len; uint32_t i; if (!d) return NULL; @@ -138,8 +137,10 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep_debug_info *d, mrb_assert(filename); mrb_assert(lines); - if (d->flen > 0 && strcmp(filename, d->files[d->flen - 1]->filename) == 0) { - return NULL; + if (d->flen > 0) { + const char *fn = mrb_sym2name_len(mrb, d->files[d->flen - 1]->filename_sym, NULL); + if (strcmp(filename, fn) == 0) + return NULL; } f = (mrb_irep_debug_info_file*)mrb_malloc(mrb, sizeof(*f)); @@ -156,8 +157,6 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep_debug_info *d, fn_len = strlen(filename); f->filename_sym = mrb_intern(mrb, filename, fn_len); - len = 0; - f->filename = mrb_sym2name_len(mrb, f->filename_sym, &len); f->line_type = select_line_type(lines + start_pos, end_pos - start_pos); f->lines.ptr = NULL; diff --git a/src/error.c b/src/error.c index 50d1ab6f9..e69812dda 100644 --- a/src/error.c +++ b/src/error.c @@ -208,8 +208,8 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc) if (err && ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) { mrb_irep *irep = ci->proc->body.irep; - int32_t const line = mrb_debug_get_line(irep, err - irep->iseq); - char const* file = mrb_debug_get_filename(irep, err - irep->iseq); + int32_t const line = mrb_debug_get_line(mrb, irep, err - irep->iseq); + char const* file = mrb_debug_get_filename(mrb, irep, err - irep->iseq); if (line != -1 && file) { mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "file"), mrb_str_new_cstr(mrb, file)); mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "line"), mrb_fixnum_value(line)); diff --git a/src/load.c b/src/load.c index 55e0845f3..ab0346750 100644 --- a/src/load.c +++ b/src/load.c @@ -317,7 +317,6 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t * for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { mrb_irep_debug_info_file *file; uint16_t filename_idx; - mrb_int len; file = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*file)); irep->debug_info->files[f_idx] = file; @@ -330,8 +329,6 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t * bin += sizeof(uint16_t); mrb_assert(filename_idx < filenames_len); file->filename_sym = filenames[filename_idx]; - len = 0; - file->filename = mrb_sym2name_len(mrb, file->filename_sym, &len); file->line_entry_count = bin_to_uint32(bin); bin += sizeof(uint32_t); diff --git a/src/symbol.c b/src/symbol.c index 8ca03344c..96ca9dd17 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -520,7 +520,14 @@ mrb_sym2name(mrb_state *mrb, mrb_sym sym) return name; } else { - mrb_value str = mrb_str_dump(mrb, mrb_str_new_static(mrb, name, len)); + mrb_value str; + if (sym&1) { /* inline symbol */ + str = mrb_str_new(mrb, name, len); + } + else { + str = mrb_str_new_static(mrb, name, len); + } + str = mrb_str_dump(mrb, str); return RSTRING_PTR(str); } } -- cgit v1.2.3 From ec1688807ef301483321919778b2ccb578822767 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 8 Apr 2019 19:04:56 +0900 Subject: Avoid using `snprintf` when `MRB_DISABLE_STDIO` is set; fix #4173 --- mrbgems/mruby-compiler/core/parse.y | 90 ++++++++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 22 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 88d9ea4ee..f6c77859a 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -220,6 +220,25 @@ parser_strdup(parser_state *p, const char *s) #undef strdup #define strdup(s) parser_strdup(p, s) +static void +itoa(short i, char *s) +{ + char *p = s; + char *t = s; + + while (i > 0) { + *p++ = (i % 10)+'0'; + i /= 10; + } + if (p == s) *p++ = '0'; + *p = 0; + p--; /* point the last char */ + while (t < p) { + char c = *t; + *t++ = *p; + *p-- = c; + } +} /* xxx ----------------------------- */ static node* @@ -3172,7 +3191,7 @@ var_ref : variable { char buf[16]; - snprintf(buf, sizeof(buf), "%d", p->lineno); + itoa(p->lineno, buf); $$ = new_int(p, buf, 10); } | keyword__ENCODING__ @@ -3692,11 +3711,12 @@ yyerror(parser_state *p, const char *s) } static void -yyerror_i(parser_state *p, const char *fmt, int i) +yyerror_c(parser_state *p, const char *msg, char c) { char buf[256]; - snprintf(buf, sizeof(buf), fmt, i); + strcpy(buf, msg); + strcat(buf, &c); yyerror(p, buf); } @@ -3735,11 +3755,13 @@ yywarning(parser_state *p, const char *s) } static void -yywarning_s(parser_state *p, const char *fmt, const char *s) +yywarning_s(parser_state *p, const char *msg, const char *s) { char buf[256]; - snprintf(buf, sizeof(buf), fmt, s); + strcpy(buf, msg); + strcat(buf, ": "); + strcat(buf, s); yywarning(p, buf); } @@ -3751,10 +3773,10 @@ backref_error(parser_state *p, node *n) c = intn(n->car); if (c == NODE_NTH_REF) { - yyerror_i(p, "can't set variable $%" MRB_PRId, intn(n->cdr)); + yyerror_c(p, "can't set variable $", (char)intn(n->cdr)+'0'); } else if (c == NODE_BACK_REF) { - yyerror_i(p, "can't set variable $%c", intn(n->cdr)); + yyerror_c(p, "can't set variable $", (char)intn(n->cdr)); } else { mrb_bug(p->mrb, "Internal error in backref_error() : n=>car == %S", mrb_fixnum_value(c)); @@ -4298,7 +4320,15 @@ parse_string(parser_state *p) } if (c < 0) { char buf[256]; - snprintf(buf, sizeof(buf), "can't find heredoc delimiter \"%s\" anywhere before EOF", hinf->term); + const char s1[] = "can't find heredoc delimiter \""; + const char s2[] = "\" anywhere before EOF"; + + if (sizeof(s1)+sizeof(s2)+strlen(hinf->term)+1 >= sizeof(buf)) { + yyerror(p, "can't find heredoc delimiter anywhere before EOF"); + } + strcpy(buf, s1); + strcat(buf, hinf->term); + strcat(buf, s2); yyerror(p, buf); return 0; } @@ -4449,9 +4479,14 @@ parse_string(parser_state *p) pushback(p, re_opt); if (toklen(p)) { char msg[128]; + + strcpy(msg, "unknown regexp option"); tokfix(p); - snprintf(msg, sizeof(msg), "unknown regexp option%s - %s", - toklen(p) > 1 ? "s" : "", tok(p)); + if (toklen(p) > 1) { + strcat(msg, "s"); + } + strcat(msg, " - "); + strcat(msg, tok(p)); yyerror(p, msg); } if (f != 0) { @@ -4879,7 +4914,10 @@ parser_yylex(parser_state *p) } if (c2) { char buf[256]; - snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2); + char cc = (char)c2; + + strcpy(buf, "invalid character syntax; use ?\\"); + strcat(buf, &cc); yyerror(p, buf); } } @@ -5252,7 +5290,7 @@ parser_yylex(parser_state *p) pushback(p, c); if (nondigit) { trailing_uc: - yyerror_i(p, "trailing '%c' in number", nondigit); + yyerror_c(p, "trailing non digit in number: ", (char)nondigit); } tokfix(p); if (is_float) { @@ -5267,10 +5305,10 @@ parser_yylex(parser_state *p) errno = 0; d = mrb_float_read(tok(p), &endp); if (d == 0 && endp == tok(p)) { - yywarning_s(p, "corrupted float value %s", tok(p)); + yywarning_s(p, "corrupted float value", tok(p)); } else if (errno == ERANGE) { - yywarning_s(p, "float %s out of range", tok(p)); + yywarning_s(p, "float out of range", tok(p)); errno = 0; } pylval.nd = new_float(p, tok(p)); @@ -5612,7 +5650,7 @@ parser_yylex(parser_state *p) { unsigned long n = strtoul(tok(p), NULL, 10); if (n > INT_MAX) { - yyerror_i(p, "capture group index must be <= %d", INT_MAX); + yyerror(p, "capture group index must be <= " MRB_STRINGIZE(INT_MAX)); return 0; } pylval.nd = new_nth_ref(p, (int)n); @@ -5649,10 +5687,10 @@ parser_yylex(parser_state *p) } else if (ISDIGIT(c)) { if (p->tidx == 1) { - yyerror_i(p, "'@%c' is not allowed as an instance variable name", c); + yyerror_c(p, "wrong instance variable name: @", c); } else { - yyerror_i(p, "'@@%c' is not allowed as a class variable name", c); + yyerror_c(p, "wrong class variable name: @@", c); } return 0; } @@ -5668,7 +5706,14 @@ parser_yylex(parser_state *p) default: if (!identchar(c)) { - yyerror_i(p, "Invalid char '\\x%02X' in expression", c); + char buf[36]; + const char s[] = "Invalid char in expression: 0x"; + + strcpy(buf, s); + buf[sizeof(s)] = (c & 0xff00) >> 8; + buf[sizeof(s)+1] = (c & 0xff); + buf[sizeof(s)+2] = 0; + yyerror(p, buf); goto retry; } @@ -6097,11 +6142,12 @@ mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c) if (c) c->parser_nerr = p->nerr; if (p->capture_errors) { char buf[256]; - int n; - n = snprintf(buf, sizeof(buf), "line %d: %s\n", - p->error_buffer[0].lineno, p->error_buffer[0].message); - mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n)); + strcpy(buf, "line "); + itoa(p->error_buffer[0].lineno, buf+5); + strcat(buf, ": "); + strcat(buf, p->error_buffer[0].message); + mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, strlen(buf))); mrb_parser_free(p); return mrb_undef_value(); } -- cgit v1.2.3 From d529501cbfd2331c530ca37efa7295d9e627af97 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 10 Apr 2019 05:55:40 +0900 Subject: Rename `itoa` to `dump_int` to avoid name crash; ref #4173 --- mrbgems/mruby-compiler/core/parse.y | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index f6c77859a..cb62ec3f2 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -221,7 +221,7 @@ parser_strdup(parser_state *p, const char *s) #define strdup(s) parser_strdup(p, s) static void -itoa(short i, char *s) +dump_int(short i, char *s) { char *p = s; char *t = s; @@ -239,6 +239,7 @@ itoa(short i, char *s) *p-- = c; } } + /* xxx ----------------------------- */ static node* @@ -3191,7 +3192,7 @@ var_ref : variable { char buf[16]; - itoa(p->lineno, buf); + dump_int(p->lineno, buf); $$ = new_int(p, buf, 10); } | keyword__ENCODING__ @@ -6144,7 +6145,7 @@ mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c) char buf[256]; strcpy(buf, "line "); - itoa(p->error_buffer[0].lineno, buf+5); + dump_int(p->error_buffer[0].lineno, buf+5); strcat(buf, ": "); strcat(buf, p->error_buffer[0].message); mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, strlen(buf))); -- cgit v1.2.3 From 57e617620a4fa8b144dd87e94dc22ae2acd87679 Mon Sep 17 00:00:00 2001 From: Clayton Smith Date: Thu, 11 Apr 2019 20:07:43 -0400 Subject: Fix buffer overflows in parser. --- mrbgems/mruby-compiler/core/parse.y | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index cb62ec3f2..ca4c90770 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3716,8 +3716,9 @@ yyerror_c(parser_state *p, const char *msg, char c) { char buf[256]; - strcpy(buf, msg); - strcat(buf, &c); + strncpy(buf, msg, sizeof(buf) - 2); + buf[sizeof(buf) - 2] = '\0'; + strncat(buf, &c, 1); yyerror(p, buf); } @@ -3760,9 +3761,10 @@ yywarning_s(parser_state *p, const char *msg, const char *s) { char buf[256]; - strcpy(buf, msg); - strcat(buf, ": "); - strcat(buf, s); + strncpy(buf, msg, sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; + strncat(buf, ": ", sizeof(buf) - strlen(buf) - 1); + strncat(buf, s, sizeof(buf) - strlen(buf) - 1); yywarning(p, buf); } @@ -4326,11 +4328,12 @@ parse_string(parser_state *p) if (sizeof(s1)+sizeof(s2)+strlen(hinf->term)+1 >= sizeof(buf)) { yyerror(p, "can't find heredoc delimiter anywhere before EOF"); + } else { + strcpy(buf, s1); + strcat(buf, hinf->term); + strcat(buf, s2); + yyerror(p, buf); } - strcpy(buf, s1); - strcat(buf, hinf->term); - strcat(buf, s2); - yyerror(p, buf); return 0; } pylval.nd = new_str(p, tok(p), toklen(p)); @@ -4487,7 +4490,7 @@ parse_string(parser_state *p) strcat(msg, "s"); } strcat(msg, " - "); - strcat(msg, tok(p)); + strncat(msg, tok(p), sizeof(msg) - strlen(msg) - 1); yyerror(p, msg); } if (f != 0) { @@ -4918,7 +4921,7 @@ parser_yylex(parser_state *p) char cc = (char)c2; strcpy(buf, "invalid character syntax; use ?\\"); - strcat(buf, &cc); + strncat(buf, &cc, 1); yyerror(p, buf); } } @@ -6147,7 +6150,7 @@ mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c) strcpy(buf, "line "); dump_int(p->error_buffer[0].lineno, buf+5); strcat(buf, ": "); - strcat(buf, p->error_buffer[0].message); + strncat(buf, p->error_buffer[0].message, sizeof(buf) - strlen(buf) - 1); mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, strlen(buf))); mrb_parser_free(p); return mrb_undef_value(); -- cgit v1.2.3 From 00545fc51d33a9c71d610cc8da5e779cf29487af Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 12 Apr 2019 22:52:26 +0900 Subject: The number of local variables should be less than 1024; fix #4370 The `env` stores stack length in a 10 bit field. See `MRB_ENV_STACK_LEN()` macro. --- mrbgems/mruby-compiler/core/codegen.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 927cc3a0f..4bb81f415 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -3020,6 +3020,9 @@ scope_finish(codegen_scope *s) mrb_state *mrb = s->mrb; mrb_irep *irep = s->irep; + if (s->nlocals >= 0x3ff) { + codegen_error(s, "too many local variables"); + } irep->flags = 0; if (s->iseq) { irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc); -- cgit v1.2.3 From befdf59e610b43e7043b83074a2cc34070ae4e5f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 12 Apr 2019 22:54:25 +0900 Subject: Deallocate `s->lines` in `codegen_error`; ref #4370 --- mrbgems/mruby-compiler/core/codegen.c | 1 + 1 file changed, 1 insertion(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 4bb81f415..b6d35f363 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -102,6 +102,7 @@ codegen_error(codegen_scope *s, const char *message) while (s->prev) { codegen_scope *tmp = s->prev; mrb_free(s->mrb, s->iseq); + mrb_free(s->mrb, s->lines); mrb_pool_close(s->mpool); s = tmp; } -- cgit v1.2.3 From c2fa935fee31c201ba4b07e72690e78a3094cf68 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 14 Apr 2019 16:11:21 +0900 Subject: Fix hexdigits convertion --- mrbgems/mruby-compiler/core/parse.y | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index ca4c90770..f6b883b9e 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -5712,10 +5712,11 @@ parser_yylex(parser_state *p) if (!identchar(c)) { char buf[36]; const char s[] = "Invalid char in expression: 0x"; + const char hexdigits[] = "0123456789ABCDEF"; strcpy(buf, s); - buf[sizeof(s)] = (c & 0xff00) >> 8; - buf[sizeof(s)+1] = (c & 0xff); + buf[sizeof(s)] = hexdigits[(c & 0xf0) >> 4]; + buf[sizeof(s)+1] = hexdigits[(c & 0x0f)]; buf[sizeof(s)+2] = 0; yyerror(p, buf); goto retry; -- cgit v1.2.3 From dac0f3f5e85d067b15c44a933b151acefb2d5598 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 14 Apr 2019 16:16:05 +0900 Subject: Fix string index for appending `sizeof(string-literal)` is included `'\0'` character --- mrbgems/mruby-compiler/core/parse.y | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index f6b883b9e..7838b6dfb 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -5715,9 +5715,9 @@ parser_yylex(parser_state *p) const char hexdigits[] = "0123456789ABCDEF"; strcpy(buf, s); - buf[sizeof(s)] = hexdigits[(c & 0xf0) >> 4]; - buf[sizeof(s)+1] = hexdigits[(c & 0x0f)]; - buf[sizeof(s)+2] = 0; + buf[sizeof(s)-1] = hexdigits[(c & 0xf0) >> 4]; + buf[sizeof(s)] = hexdigits[(c & 0x0f)]; + buf[sizeof(s)+1] = 0; yyerror(p, buf); goto retry; } -- cgit v1.2.3 From 3f3e4754d931004838278c1483e047a3635ebeb0 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 14 Apr 2019 15:58:11 +0900 Subject: Fix leaked function symbols - `free_heap()` in src/gc.c - `symhash()` in src/symbol.c - `no_optimize()` in mrbgems/mruby-compiler/core/codegen.c --- mrbgems/mruby-compiler/core/codegen.c | 3 +-- src/gc.c | 2 +- src/symbol.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index b6d35f363..ed8fc3150 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -273,8 +273,7 @@ genop_W(codegen_scope *s, mrb_code i, uint32_t a) #define NOVAL 0 #define VAL 1 -//static -mrb_bool +static mrb_bool no_optimize(codegen_scope *s) { if (s && s->parser && s->parser->no_optimize) diff --git a/src/gc.c b/src/gc.c index ec52787e8..d07335eca 100644 --- a/src/gc.c +++ b/src/gc.c @@ -396,7 +396,7 @@ mrb_gc_init(mrb_state *mrb, mrb_gc *gc) static void obj_free(mrb_state *mrb, struct RBasic *obj, int end); -void +static void free_heap(mrb_state *mrb, mrb_gc *gc) { mrb_heap_page *page = gc->heaps; diff --git a/src/symbol.c b/src/symbol.c index 96ca9dd17..b26f2b1fd 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -91,7 +91,7 @@ sym_inline_unpack(mrb_sym sym, char *buf, mrb_int *lenp) } #endif -uint8_t +static uint8_t symhash(const char *key, size_t len) { uint32_t hash, i; -- cgit v1.2.3 From f5d5caaf82f68f5146594050d833cc1ceda6c72b Mon Sep 17 00:00:00 2001 From: dearblue Date: Fri, 3 May 2019 11:36:31 +0900 Subject: Clean duplicate code Removed duplicates in the code entered for "Concatenate string literal". --- mrbgems/mruby-compiler/core/parse.y | 55 ++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 28 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 7838b6dfb..b7d47118f 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -913,40 +913,39 @@ concat_string(parser_state *p, node *a, node *b) } } } - else if (string_node_p(b)) { - /* a == NODE_DSTR && b == NODE_STR */ - - node *c; + else { + node *c; /* last node of a */ for (c = a; c->cdr != NULL; c = c->cdr) ; - if (string_node_p(c->car)) { - /* a->[..., NODE_STR] && b == NODE_STR */ - composite_string_node(p, c->car->cdr, b->cdr); - cons_free(b); - return a; - } - push(a, b); - return a; - } - else { - /* a == NODE_DSTR && b == NODE_DSTR */ + if (string_node_p(b)) { + /* a == NODE_DSTR && b == NODE_STR */ + if (string_node_p(c->car)) { + /* a->[..., NODE_STR] && b == NODE_STR */ + composite_string_node(p, c->car->cdr, b->cdr); + cons_free(b); + return a; + } - node *c, *d; - for (c = a; c->cdr != NULL; c = c->cdr) ; - if (string_node_p(c->car) && string_node_p(b->cdr->car)) { - /* a->[..., NODE_STR] && b->[NODE_STR, ...] */ - d = b->cdr; - cons_free(b); - composite_string_node(p, c->car->cdr, d->car->cdr); - cons_free(d->car); - c->cdr = d->cdr; - cons_free(d); + push(a, b); return a; } else { - c->cdr = b->cdr; - cons_free(b); - return a; + /* a == NODE_DSTR && b == NODE_DSTR */ + if (string_node_p(c->car) && string_node_p(b->cdr->car)) { + /* a->[..., NODE_STR] && b->[NODE_STR, ...] */ + node *d = b->cdr; + cons_free(b); + composite_string_node(p, c->car->cdr, d->car->cdr); + cons_free(d->car); + c->cdr = d->cdr; + cons_free(d); + return a; + } + else { + c->cdr = b->cdr; + cons_free(b); + return a; + } } } -- cgit v1.2.3 From 8808219e6d51673e6fa582819703e6e5912439b0 Mon Sep 17 00:00:00 2001 From: Ukrainskiy Sergey Date: Thu, 9 Aug 2018 17:09:02 +0900 Subject: Initial suffix support --- include/mrbconf.h | 3 + mrbgems/default.gembox | 6 ++ mrbgems/mruby-compiler/core/parse.y | 148 +++++++++++++++++++++++++++--- mrbgems/mruby-complex/mrbgem.rake | 5 + mrbgems/mruby-complex/mrblib/complex.rb | 95 +++++++++++++++++++ mrbgems/mruby-complex/test/complex.rb | 3 + mrbgems/mruby-rational/mrbgem.rake | 5 + mrbgems/mruby-rational/mrblib/rational.rb | 46 ++++++++++ mrbgems/mruby-rational/test/rational.rb | 3 + 9 files changed, 301 insertions(+), 13 deletions(-) create mode 100644 mrbgems/mruby-complex/mrbgem.rake create mode 100644 mrbgems/mruby-complex/mrblib/complex.rb create mode 100644 mrbgems/mruby-complex/test/complex.rb create mode 100644 mrbgems/mruby-rational/mrbgem.rake create mode 100644 mrbgems/mruby-rational/mrblib/rational.rb create mode 100644 mrbgems/mruby-rational/test/rational.rb (limited to 'mrbgems/mruby-compiler') diff --git a/include/mrbconf.h b/include/mrbconf.h index 6b0b9e37e..ee816e322 100644 --- a/include/mrbconf.h +++ b/include/mrbconf.h @@ -63,6 +63,9 @@ # endif #endif +#define MRB_COMPLEX_NUMBERS +#define MRB_RATIONAL_NUMBERS + /* define on big endian machines; used by MRB_NAN_BOXING, etc. */ #ifndef MRB_ENDIAN_BIG # if (defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN) || \ diff --git a/mrbgems/default.gembox b/mrbgems/default.gembox index 23e65fcee..501aee146 100644 --- a/mrbgems/default.gembox +++ b/mrbgems/default.gembox @@ -68,6 +68,12 @@ MRuby::GemBox.new do |conf| # Use Enumerator::Lazy class (require mruby-enumerator) conf.gem :core => "mruby-enum-lazy" + # Use Complex class + #conf.gem :core => "mruby-complex" + + # Use Rational class + #conf.gem :core => "mruby-rational" + # Use toplevel object (main) methods extension conf.gem :core => "mruby-toplevel-ext" diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index b7d47118f..b18906ed3 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -76,6 +76,24 @@ typedef unsigned int stack_type; #define nint(x) ((node*)(intptr_t)(x)) #define intn(x) ((int)(intptr_t)(x)) +#if defined(MRB_COMPLEX_NUMBERS) || defined(MRB_RATIONAL_NUMBERS) + #define MRB_SUFFIX_SUPPORT + + #ifdef MRB_RATIONAL_NUMBERS + #define NUM_SUFFIX_R (1<<0) + #else + #define NUM_SUFFIX_R 0 + #endif + + #ifdef MRB_COMPLEX_NUMBERS + #define NUM_SUFFIX_I (1<<1) + #else + #define NUM_SUFFIX_I 0 + #endif + + #define NUM_SUFFIX_ALL (NUM_SUFFIX_R | NUM_SUFFIX_I) +#endif + static inline mrb_sym intern_cstr_gen(parser_state *p, const char *s) { @@ -842,19 +860,62 @@ new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b) return list4((node*)NODE_OP_ASGN, a, nsym(op), b); } +#ifdef MRB_COMPLEX_NUMBERS +static node* +new_imaginary(parser_state *p, node *imaginary); +#endif + +#ifdef MRB_RATIONAL_NUMBERS +static node* +new_rational(parser_state *p, node *rational) +{ + return new_call(p, new_const(p, intern_cstr("Rational")), intern_cstr("new"), list1(list1(rational)), 1); +} +#endif + /* (:int . i) */ static node* -new_int(parser_state *p, const char *s, int base) +new_int(parser_state *p, const char *s, int base, int suffix) { - return list3((node*)NODE_INT, (node*)strdup(s), nint(base)); + node* result = list3((node*)NODE_INT, (node*)strdup(s), nint(base)); +#ifdef MRB_RATIONAL_NUMBERS + if (suffix & NUM_SUFFIX_R) { + result = new_rational(p, result); + } +#endif +#ifdef MRB_COMPLEX_NUMBERS + if (suffix & NUM_SUFFIX_I) { + result = new_imaginary(p, result); + } +#endif + return result; } #ifndef MRB_WITHOUT_FLOAT /* (:float . i) */ static node* -new_float(parser_state *p, const char *s) +new_float(parser_state *p, const char *s, int suffix) +{ + node* result = cons((node*)NODE_FLOAT, (node*)strdup(s)); +#ifdef MRB_RATIONAL_NUMBERS + if (suffix & NUM_SUFFIX_R) { + result = new_rational(p, result); + } +#endif +#ifdef MRB_COMPLEX_NUMBERS + if (suffix & NUM_SUFFIX_I) { + result = new_imaginary(p, result); + } +#endif + return result; +} +#endif + +#ifdef MRB_COMPLEX_NUMBERS +static node* +new_imaginary(parser_state *p, node *imaginary) { - return cons((node*)NODE_FLOAT, (node*)strdup(s)); + return new_call(p, new_const(p, intern_cstr("Complex")), intern_cstr("new"), list1(list2(new_int(p, "0", 10, 0), imaginary)), 1); } #endif @@ -3192,7 +3253,7 @@ var_ref : variable char buf[16]; dump_int(p->lineno, buf); - $$ = new_int(p, buf, 10); + $$ = new_int(p, buf, 10, 0); } | keyword__ENCODING__ { @@ -4520,6 +4581,45 @@ parse_string(parser_state *p) return tSTRING; } +#ifdef MRB_SUFFIX_SUPPORT +static int +number_literal_suffix(parser_state *p, int mask) +{ + int c, result = 0; + node *list = 0; + int column = p->column; + + while ((c = nextc(p)) != -1) { + list = push(list, (node*)(intptr_t)c); + + if ((mask & NUM_SUFFIX_I) && c == 'i') { + result |= (mask & NUM_SUFFIX_I); + mask &= ~NUM_SUFFIX_I; + /* r after i, rational of complex is disallowed */ + mask &= ~NUM_SUFFIX_R; + continue; + } + if ((mask & NUM_SUFFIX_R) && c == 'r') { + result |= (mask & NUM_SUFFIX_R); + mask &= ~NUM_SUFFIX_R; + continue; + } + if (!ISASCII(c) || ISALPHA(c) || c == '_') { + p->column = column; + if (p->pb) { + p->pb = append((node*)list, p->pb); + } + else { + p->pb = list; + } + return 0; + } + pushback(p, c); + break; + } + return result; +} +#endif static int heredoc_identifier(parser_state *p) @@ -5094,6 +5194,7 @@ parser_yylex(parser_state *p) case '5': case '6': case '7': case '8': case '9': { int is_float, seen_point, seen_e, nondigit; + int suffix; is_float = seen_point = seen_e = nondigit = 0; p->lstate = EXPR_ENDARG; @@ -5127,7 +5228,10 @@ parser_yylex(parser_state *p) no_digits(); } else if (nondigit) goto trailing_uc; - pylval.nd = new_int(p, tok(p), 16); + #ifdef MRB_SUFFIX_SUPPORT + suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); + #endif + pylval.nd = new_int(p, tok(p), 16, suffix); return tINTEGER; } if (c == 'b' || c == 'B') { @@ -5151,7 +5255,10 @@ parser_yylex(parser_state *p) no_digits(); } else if (nondigit) goto trailing_uc; - pylval.nd = new_int(p, tok(p), 2); + #ifdef MRB_SUFFIX_SUPPORT + suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); + #endif + pylval.nd = new_int(p, tok(p), 2, suffix); return tINTEGER; } if (c == 'd' || c == 'D') { @@ -5175,7 +5282,10 @@ parser_yylex(parser_state *p) no_digits(); } else if (nondigit) goto trailing_uc; - pylval.nd = new_int(p, tok(p), 10); + #ifdef MRB_SUFFIX_SUPPORT + suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); + #endif + pylval.nd = new_int(p, tok(p), 10, suffix); return tINTEGER; } if (c == '_') { @@ -5208,7 +5318,10 @@ parser_yylex(parser_state *p) pushback(p, c); tokfix(p); if (nondigit) goto trailing_uc; - pylval.nd = new_int(p, tok(p), 8); + #ifdef MRB_SUFFIX_SUPPORT + suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); + #endif + pylval.nd = new_int(p, tok(p), 8, suffix); return tINTEGER; } if (nondigit) { @@ -5225,7 +5338,10 @@ parser_yylex(parser_state *p) } else { pushback(p, c); - pylval.nd = new_int(p, "0", 10); + #ifdef MRB_SUFFIX_SUPPORT + suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); + #endif + pylval.nd = new_int(p, "0", 10, suffix); return tINTEGER; } } @@ -5299,7 +5415,7 @@ parser_yylex(parser_state *p) if (is_float) { #ifdef MRB_WITHOUT_FLOAT yywarning(p, "floating point numbers are not supported"); - pylval.nd = new_int(p, "0", 10); + pylval.nd = new_int(p, "0", 10, 0); return tINTEGER; #else double d; @@ -5314,11 +5430,17 @@ parser_yylex(parser_state *p) yywarning_s(p, "float out of range", tok(p)); errno = 0; } - pylval.nd = new_float(p, tok(p)); + #ifdef MRB_SUFFIX_SUPPORT + suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); + #endif + pylval.nd = new_float(p, tok(p), suffix); return tFLOAT; #endif } - pylval.nd = new_int(p, tok(p), 10); + #ifdef MRB_SUFFIX_SUPPORT + suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); + #endif + pylval.nd = new_int(p, tok(p), 10, suffix); return tINTEGER; } diff --git a/mrbgems/mruby-complex/mrbgem.rake b/mrbgems/mruby-complex/mrbgem.rake new file mode 100644 index 000000000..f8f04d0b8 --- /dev/null +++ b/mrbgems/mruby-complex/mrbgem.rake @@ -0,0 +1,5 @@ +MRuby::Gem::Specification.new('mruby-complex') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'Complex class' +end diff --git a/mrbgems/mruby-complex/mrblib/complex.rb b/mrbgems/mruby-complex/mrblib/complex.rb new file mode 100644 index 000000000..0815c9a71 --- /dev/null +++ b/mrbgems/mruby-complex/mrblib/complex.rb @@ -0,0 +1,95 @@ +class Complex < Numeric + def initialize(real = 0, imaginary = 0) + @real = real + @imaginary = imaginary + end + + def inspect + "(#{to_s})" + end + + def to_s + "#{real}#{'+'}#{imaginary}i" + end + + def +@ + Complex.new(real, imaginary) + end + + def -@ + Complex.new(-real, -imaginary) + end + + def +(rhs) + if rhs.is_a? Complex + Complex.new(real + rhs.real, imaginary + rhs.imaginary) + elsif rhs.is_a? Numeric + Complex.new(real + rhs, imaginary) + end + end + + def -(rhs) + if rhs.is_a? Complex + Complex.new(real - rhs.real, imaginary - rhs.imaginary) + elsif rhs.is_a? Numeric + Complex.new(real - rhs, imaginary) + end + end + + def *(rhs) + if rhs.is_a? Complex + Complex.new(real * rhs.real - imaginary * rhs.imaginary, real * rhs.imaginary + rhs.real * imaginary) + elsif rhs.is_a? Numeric + Complex.new(real * rhs, imaginary * rhs) + end + end + + def /(rhs) + if rhs.is_a? Complex + div = rhs.real * rhs.real + rhs.imaginary * rhs.imaginary + Complex.new((real * rhs.real + imaginary * rhs.imaginary) / div, (rhs.real * imaginary - real * rhs.imaginary) / div) + elsif rhs.is_a? Numeric + Complex.new(real / rhs, imaginary / rhs) + end + end + + attr_reader :real, :imaginary +end + +def Complex(real = 0, imaginary = 0) + Complex.new(real, imaginary) +end + +module ForwardOperatorToComplex + def __forward_operator_to_complex(op, &b) + original_operator_name = "__original_operator_#{op}_complex" + alias_method original_operator_name, op + define_method op do |rhs| + if rhs.is_a? Complex + Complex.new(self).send(op, rhs) + else + send(original_operator_name, rhs) + end + end + end + + def __forward_operators_to_complex + __forward_operator_to_complex :+ + __forward_operator_to_complex :- + __forward_operator_to_complex :* + __forward_operator_to_complex :/ + + singleton_class.undef_method :__forward_operator_to_complex + singleton_class.undef_method :__forward_operators_to_complex + end +end + +class Fixnum + extend ForwardOperatorToComplex + __forward_operators_to_complex +end + +class Float + extend ForwardOperatorToComplex + __forward_operators_to_complex +end \ No newline at end of file diff --git a/mrbgems/mruby-complex/test/complex.rb b/mrbgems/mruby-complex/test/complex.rb new file mode 100644 index 000000000..890dd4ff1 --- /dev/null +++ b/mrbgems/mruby-complex/test/complex.rb @@ -0,0 +1,3 @@ +assert 'Complex' do + assert_equal Complex, 0i.class +end \ No newline at end of file diff --git a/mrbgems/mruby-rational/mrbgem.rake b/mrbgems/mruby-rational/mrbgem.rake new file mode 100644 index 000000000..4b540dec4 --- /dev/null +++ b/mrbgems/mruby-rational/mrbgem.rake @@ -0,0 +1,5 @@ +MRuby::Gem::Specification.new('mruby-rational') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'Rational class' +end diff --git a/mrbgems/mruby-rational/mrblib/rational.rb b/mrbgems/mruby-rational/mrblib/rational.rb new file mode 100644 index 000000000..457c0488a --- /dev/null +++ b/mrbgems/mruby-rational/mrblib/rational.rb @@ -0,0 +1,46 @@ +class Rational < Numeric + def initialize(numerator = 0, denominator = 1) + @numerator = numerator + @denominator = denominator + end + + attr_reader :numerator, :denominator +end + +def Rational(numerator = 0, denominator = 1) + Rational.new(numerator, denominator) +end + +module ForwardOperatorToRational + def __forward_operator_to_rational(op, &b) + original_operator_name = "__original_operator_#{op}_rational" + alias_method original_operator_name, op + define_method op do |rhs| + if rhs.is_a? Rational + Rational.new(self).send(op, rhs) + else + send(original_operator_name, rhs) + end + end + end + + def __forward_operators_to_rational + __forward_operator_to_rational :+ + __forward_operator_to_rational :- + __forward_operator_to_rational :* + __forward_operator_to_rational :/ + + singleton_class.undef_method :__forward_operator_to_rational + singleton_class.undef_method :__forward_operators_to_rational + end +end + +class Fixnum + extend ForwardOperatorToRational + __forward_operators_to_rational +end + +class Float + extend ForwardOperatorToRational + __forward_operators_to_rational +end \ No newline at end of file diff --git a/mrbgems/mruby-rational/test/rational.rb b/mrbgems/mruby-rational/test/rational.rb new file mode 100644 index 000000000..6f20a6cd4 --- /dev/null +++ b/mrbgems/mruby-rational/test/rational.rb @@ -0,0 +1,3 @@ +assert 'Rational' do + assert_equal Rational, 0r.class +end \ No newline at end of file -- cgit v1.2.3 From 79c3335e8d22ec76340b3028a7bbc658d631b17c Mon Sep 17 00:00:00 2001 From: Ukrainskiy Sergey Date: Sun, 9 Sep 2018 11:55:21 +0900 Subject: Small refactoring --- mrbgems/mruby-compiler/core/parse.y | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index b18906ed3..2c5e0c991 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -862,14 +862,17 @@ new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b) #ifdef MRB_COMPLEX_NUMBERS static node* -new_imaginary(parser_state *p, node *imaginary); +new_imaginary(parser_state *p, node *imaginary) +{ + return new_call(p, new_const(p, intern_cstr("Kernel")), intern_cstr("Complex"), list1(list2(list3((node*)NODE_INT, (node*)strdup("0"), nint(10)), imaginary)), 1); +} #endif #ifdef MRB_RATIONAL_NUMBERS static node* new_rational(parser_state *p, node *rational) { - return new_call(p, new_const(p, intern_cstr("Rational")), intern_cstr("new"), list1(list1(rational)), 1); + return new_call(p, new_const(p, intern_cstr("Kernel")), intern_cstr("Rational"), list1(list1(rational)), 1); } #endif @@ -911,14 +914,6 @@ new_float(parser_state *p, const char *s, int suffix) } #endif -#ifdef MRB_COMPLEX_NUMBERS -static node* -new_imaginary(parser_state *p, node *imaginary) -{ - return new_call(p, new_const(p, intern_cstr("Complex")), intern_cstr("new"), list1(list2(new_int(p, "0", 10, 0), imaginary)), 1); -} -#endif - /* (:str . (s . len)) */ static node* new_str(parser_state *p, const char *s, size_t len) -- cgit v1.2.3 From 31bfc5586615a759b3c415ec8550ee67827bd296 Mon Sep 17 00:00:00 2001 From: Ukrainskiy Sergey Date: Sat, 22 Sep 2018 17:23:03 +0900 Subject: Fix --- mrbgems/mruby-compiler/core/parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 2c5e0c991..3ad11f406 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -5189,7 +5189,7 @@ parser_yylex(parser_state *p) case '5': case '6': case '7': case '8': case '9': { int is_float, seen_point, seen_e, nondigit; - int suffix; + int suffix = 0; is_float = seen_point = seen_e = nondigit = 0; p->lstate = EXPR_ENDARG; -- cgit v1.2.3 From 9b604abc8300d378bb32fb0e88d6f0831ed7e0d9 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 16 May 2019 11:46:37 +0900 Subject: Enable `YYSTACK_USE_ALLOCA`. It used heap allocated memory for the parser stack, but there's possibility of parser termination by exceptions. In that case, the parser stack memory is leaked. We were afraid of stack consumption, but parser stack size is only 4KB, so we don't have to worry about it (at least for the parser). --- mrbgems/mruby-compiler/core/parse.y | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 3ad11f406..37d4d1bf1 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -10,13 +10,7 @@ # define YYDEBUG 1 #endif #define YYERROR_VERBOSE 1 -/* - * Force yacc to use our memory management. This is a little evil because - * the macros assume that "parser_state *p" is in scope - */ -#define YYMALLOC(n) mrb_malloc(p->mrb, (n)) -#define YYFREE(o) mrb_free(p->mrb, (o)) -#define YYSTACK_USE_ALLOCA 0 +#define YYSTACK_USE_ALLOCA 1 #include #include -- cgit v1.2.3 From d895c5fe5aa8e65f7e98b79494602a0f0d442a30 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 15 Jun 2019 10:02:49 +0900 Subject: Fixed wrong behavior on `..` at the beginning of the line. --- mrbgems/mruby-compiler/core/parse.y | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 37d4d1bf1..baa69b556 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -4758,8 +4758,7 @@ parser_yylex(parser_state *p) space_seen = 1; break; case '.': - if ((c = nextc(p)) != '.') { - pushback(p, c); + if (!peek(p, '.')) { pushback(p, '.'); goto retry; } -- cgit v1.2.3 From 4124047ccec9c299002902750fcb4b6534bbbdca Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 15 Jun 2019 10:04:47 +0900 Subject: Support `&.` at the beginning of the line. --- mrbgems/mruby-compiler/core/parse.y | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index baa69b556..ff4016d8b 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -4762,6 +4762,15 @@ parser_yylex(parser_state *p) pushback(p, '.'); goto retry; } + pushback(p, c); + goto normal_newline; + case '&': + if (peek(p, '.')) { + pushback(p, '&'); + goto retry; + } + pushback(p, c); + goto normal_newline; case -1: /* EOF */ case -2: /* end of a file */ goto normal_newline; -- cgit v1.2.3 From 4296c77e29b67e72399dde8295dd6fa4a10cc321 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 15 Jun 2019 12:52:57 +0900 Subject: Allow newlines and comments between method calls. --- mrbgems/mruby-compiler/core/parse.y | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index ff4016d8b..6ab91ce91 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -4757,6 +4757,14 @@ parser_yylex(parser_state *p) case '\13': /* '\v' */ space_seen = 1; break; + case '#': /* comment as a whitespace */ + pushback(p, '#'); + goto retry; + case '\n': /* consecutive newlines */ + p->lineno++; + p->column = 0; + pushback(p, '\n'); + goto retry; case '.': if (!peek(p, '.')) { pushback(p, '.'); -- cgit v1.2.3 From 0fba50082642fa4a6e0468f4e41192de095258f4 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 15 Jun 2019 12:58:30 +0900 Subject: Fixed indentation in parse.y --- mrbgems/mruby-compiler/core/parse.y | 106 ++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 53 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 6ab91ce91..96a9453b6 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -4729,68 +4729,68 @@ parser_yylex(parser_state *p) /* fall through */ case -2: /* end of a file */ case '\n': - maybe_heredoc: + maybe_heredoc: heredoc_treat_nextline(p); - switch (p->lstate) { - case EXPR_BEG: - case EXPR_FNAME: - case EXPR_DOT: - case EXPR_CLASS: - case EXPR_VALUE: - p->lineno++; - p->column = 0; - if (p->parsing_heredoc != NULL) { - if (p->lex_strterm) { - return parse_string(p); - } - } - goto retry; - default: - break; - } - if (p->parsing_heredoc != NULL) { - return '\n'; - } - while ((c = nextc(p))) { - switch (c) { - case ' ': case '\t': case '\f': case '\r': - case '\13': /* '\v' */ - space_seen = 1; - break; - case '#': /* comment as a whitespace */ - pushback(p, '#'); - goto retry; - case '\n': /* consecutive newlines */ + switch (p->lstate) { + case EXPR_BEG: + case EXPR_FNAME: + case EXPR_DOT: + case EXPR_CLASS: + case EXPR_VALUE: p->lineno++; p->column = 0; - pushback(p, '\n'); + if (p->parsing_heredoc != NULL) { + if (p->lex_strterm) { + return parse_string(p); + } + } goto retry; - case '.': - if (!peek(p, '.')) { - pushback(p, '.'); + default: + break; + } + if (p->parsing_heredoc != NULL) { + return '\n'; + } + while ((c = nextc(p))) { + switch (c) { + case ' ': case '\t': case '\f': case '\r': + case '\13': /* '\v' */ + space_seen = 1; + break; + case '#': /* comment as a whitespace */ + pushback(p, '#'); goto retry; - } - pushback(p, c); - goto normal_newline; - case '&': - if (peek(p, '.')) { - pushback(p, '&'); + case '\n': /* consecutive newlines */ + p->lineno++; + p->column = 0; + pushback(p, '\n'); goto retry; + case '.': + if (!peek(p, '.')) { + pushback(p, '.'); + goto retry; + } + pushback(p, c); + goto normal_newline; + case '&': + if (peek(p, '.')) { + pushback(p, '&'); + goto retry; + } + pushback(p, c); + goto normal_newline; + case -1: /* EOF */ + case -2: /* end of a file */ + goto normal_newline; + default: + pushback(p, c); + goto normal_newline; } - pushback(p, c); - goto normal_newline; - case -1: /* EOF */ - case -2: /* end of a file */ - goto normal_newline; - default: - pushback(p, c); - goto normal_newline; } - } normal_newline: - p->cmd_start = TRUE; - p->lstate = EXPR_BEG; - return '\n'; + p->cmd_start = TRUE; + p->lstate = EXPR_BEG; + return '\n'; case '*': if ((c = nextc(p)) == '*') { -- cgit v1.2.3 From acad9567c16317a86d7e246d6093a43d3a58c758 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Mon, 15 Jul 2019 23:03:41 +0900 Subject: Unify type of line number to `uint16_t` --- include/mruby/compile.h | 6 +++--- mrbgems/mruby-compiler/core/parse.y | 2 +- mrbgems/mruby-eval/src/eval.c | 2 +- src/backtrace.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/include/mruby/compile.h b/include/mruby/compile.h index 8f8f2ebd7..3b25ff526 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -24,7 +24,7 @@ typedef struct mrbc_context { mrb_sym *syms; int slen; char *filename; - short lineno; + uint16_t lineno; int (*partial_hook)(struct mrb_parser_state*); void *partial_data; struct RClass *target_class; @@ -67,7 +67,7 @@ enum mrb_lex_state_enum { /* saved error message */ struct mrb_parser_message { - int lineno; + uint16_t lineno; int column; char* message; }; @@ -119,7 +119,7 @@ struct mrb_parser_state { #endif mrbc_context *cxt; mrb_sym filename_sym; - int lineno; + uint16_t lineno; int column; enum mrb_lex_state_enum lstate; diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 96a9453b6..ac59a8b0b 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -233,7 +233,7 @@ parser_strdup(parser_state *p, const char *s) #define strdup(s) parser_strdup(p, s) static void -dump_int(short i, char *s) +dump_int(uint16_t i, char *s) { char *p = s; char *t = s; diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c index a3b211ba2..30534aaec 100644 --- a/mrbgems/mruby-eval/src/eval.c +++ b/mrbgems/mruby-eval/src/eval.c @@ -235,7 +235,7 @@ create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding, } cxt = mrbc_context_new(mrb); - cxt->lineno = (short)line; + cxt->lineno = (uint16_t)line; mrbc_filename(mrb, cxt, file ? file : "(eval)"); cxt->capture_errors = TRUE; diff --git a/src/backtrace.c b/src/backtrace.c index e4f5a3064..991a67d00 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -16,7 +16,7 @@ #include struct backtrace_location { - int lineno; + int32_t lineno; mrb_sym method_id; const char *filename; }; -- cgit v1.2.3