--- esj.py- 2016-09-15 01:00:00.000000000 +0900 +++ esj.py 2016-09-15 23:00:00.000000000 +0900 @@ -356,9 +356,6 @@ def es_split(s): def get_call_inf(info): return info.get('call_stk')[-1] -def get_env(info, g=False): - return info.get('genv') if g else get_call_inf(info).get('env') - def get_flags(info): return info.get('flags') @@ -369,30 +366,34 @@ def was_flags(info, f): flags.remove(f) return ret -def is_exist(name, info, g=None): - if g is not None: - return name in get_env(info, g) - return is_exist(name, info, g=False) or is_exist(name, info, g=True) +def find_env(name, info, genv=None): + rstk = [ inf for inf in reversed( info.get('call_stk') ) ] + i = next( ( i for (i, inf) in enumerate(rstk) if inf.get('name') ), 0 ) + for inf in rstk[:i+1]: + env = inf.get('env') + if name in env: + return env + if genv is None: + genv = info.get('genv') + return genv if name in genv else None def get_val(name, info): - if is_exist(name, info, g=False): - return get_env(info).get(name) - if is_exist(name, info, g=True): - return get_env(info, g=True).get(name) + env = find_env(name, info) + if env: + return env.get(name) err_not_found(name) def set_val(name, val, info): - if is_exist(name, info, g=False): - get_env(info)[name] = val - return val - if is_exist(name, info, g=True): - get_env(info, g=True)[name] = val + env = find_env(name, info) + if env: + env[name] = val return val err_not_found(name) def new_val(name, val, info): - if not is_exist(name, info, g=False): - get_env(info)[name] = val + env = get_call_inf(info).get('env') + if name not in env: + env[name] = val return val err_exit("alredy exist '{}'".format(name)) @@ -565,7 +566,7 @@ def do_expr(expr, info): e = expr[2][0] return do_expr(e, info) if v == '{': - do_blk(expr, info) + do_blk(None, {}, expr, info) return None if k == 'op': return do_op( v, expr[2:], info ) @@ -585,16 +586,19 @@ def do_expr(expr, info): warn_no_sup('do_expr', '[k, v]', [k, v]) return None -def do_blk(blk, info): +def do_blk(name, env, blk, info): + call_stk = info.get('call_stk') + call_stk.append( { 'name' : name, 'env' : env } ) (_, _, lst) = blk # [ 'br_s', '{', lst ] call_inf = get_call_inf(info) for expr in lst: do_expr(expr, info) if 'ret' in info: - return + break flags = get_flags(info) if 'break' in flags or 'continue' in flags: - return + break + call_stk.pop() def get_sys_func(name): try: @@ -612,7 +616,8 @@ def do_fcall(name, args, info): f = lambda (k, nm): k == 'fdef' and nm == name fdef = next( ( e for e in lst if f( e[:2] ) ), None ) if fdef is None: - func = get_val(name, info) if is_exist(name, info) else get_sys_func(name) + env = find_env(name, info) + func = env.get(name) if env else get_sys_func(name) if func: return func(*args) err_not_found("fdef '{}'".format(name)) @@ -622,10 +627,7 @@ def do_fcall(name, args, info): names = [ e[1] for e in args_lst if e[0] == 'name' ] env = dict( zip(names, args) ) - call_stk = info.get('call_stk') - call_stk.append( { 'name' : name, 'env' : env } ) - do_blk(body, info) - call_inf = call_stk.pop() + do_blk(name, env, body, info) was_flags(info, 'break') was_flags(info, 'continue') @@ -634,12 +636,9 @@ def do_fcall(name, args, info): def do_global(lst, verb): genv = {} - inf = { 'name' : None, 'env' : genv } - call_stk = [ inf ] - info = { 'lst' : lst, 'call_stk' : call_stk, 'genv' : genv, 'flags' : [], 'verb' : verb } + info = { 'lst' : lst, 'call_stk' : [], 'genv' : genv, 'flags' : [], 'verb' : verb } blk = [ 'br_s', '{', lst ] - do_expr(blk, info) - info.get('call_stk').pop() + do_blk(None, genv, blk, info) return info def warn_no_sup(f, t, v):