--- esJ.py- 2016-09-07 00:00:00.000000000 +0900 +++ esJ.py 2016-09-08 00:00:00.000000000 +0900 @@ -281,13 +281,106 @@ def es_split(s): return lst +def get_call_inf(info): + return info.get('call_stk')[-1] + +def get_env(info): + return get_call_inf(info).get('env') + +def do_set(e, val, info): + (k, v) = e[:2] + if k == 'name': + get_env(info)[v] = val + return val + if k == 'arr': + idx = e[2] + i = int( do_expr(idx, info) ) + arr = get_arr_with_chk(v, i, info) + if arr is None: + err_exit("not found arr '{}'".format(name)) + arr[i] = val + return val + + warn_no_sup('do_set', 'k', k) + +def do_op1(v, a, info): + a = do_expr(a, info) + if v == '-': + return -a + + warn_no_sup('do_op1', 'v', v) + +def do_op2(v, a, b, info): + b = do_expr(b, info) + if v == '=': + return do_set(a, b, info) + + a = do_expr(a, info) + if v == '+': + return a + b + if v == '-': + return a - b + if v == '*': + return a * b + if v == '/': + return a / b + + warn_no_sup('do_op2', 'v', v) + +def do_op(v, args, info): + term = len(args) + if term == 1: + return do_op1(v, args[0], info) + if term == 2: + return do_op2(v, args[0], args[1], info) + + warn_no_sup('do_op', 'term', term) + +def get_arr_with_chk(name, i, info): + arr = get_env(info).get(name) + if arr is not None and i >= len(arr): + err_exit('over acc {}[{}]'.format(name, i)) + return arr + +def do_arr(name, idx, info): + i = int( do_expr(idx, info) ) + arr = get_arr_with_chk(name, i, info) + if arr is not None: + return arr[i] + get_env(info)[name] = [ None ] * i # new + return None + def do_expr(expr, info): + if info.get('verb') >= 2: + print('expr={}'.format(expr)) (k, v) = expr[:2] if k == 'kwd' and v == 'return': r = do_expr( expr[2], info ) - info.get('call_stk')[-1]['ret'] = r - return r - return 123 # !!! + get_call_inf(info)['ret'] = r + return None + if k == 'num': + return float(v) + if k == 'str': + return expr[2] + if k == 'name': + return get_env(info).get(v) + if k == 'br_s': + e = expr[2][0] + return do_expr(e, info) + if k == 'op': + return do_op( v, expr[2:], info ) + if k == 'arr': + return do_arr( v, expr[2], info ) + if k == 'fcall': + (_, _, args) = expr[2] + args = [ do_expr(e, info) for e in args if e != [ 'etc', ',' ] ] + return do_fcall(v, args, info) + + if k in [ 'type', 'fproto', 'etc' ]: # do nothing !!! + return None + + warn_no_sup('do_expr', 'k', k) + return None def do_blk(blk, info): (_, _, lst) = blk # [ 'br_s', '{', lst ] @@ -295,9 +388,12 @@ def do_blk(blk, info): for expr in lst: do_expr(expr, info) if 'ret' in call_inf: - return call_inf.get('ret') + return def do_fcall(name, args, info): + if info.get('verb') >= 1: + print('do_fcall() name={} args={}'.format(name, args)) + lst = info.get('lst') f = lambda (k, nm): k == 'fdef' and nm == name @@ -306,8 +402,8 @@ def do_fcall(name, args, info): err_exit("not found fdef '{}'".format(name)) (args_info, ret_type, body) = fdef[2:] - - names = [ e[1] for e in args_info if e[0] == 'name' ] + (_, _, args_lst) = 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') @@ -316,6 +412,12 @@ def do_fcall(name, args, info): call_inf = call_stk.pop() return call_inf.get('ret', None) +def warn_no_sup(f, t, v): + warn("{}() not support {}='{}'".format(f, t, v)) + +def warn(msg): + print('Warn {}'.format(msg)) + def err_exit(msg, rcode=1): print('Err {}'.format(msg)) sys.exit(rcode) @@ -323,16 +425,24 @@ def err_exit(msg, rcode=1): if __name__ == "__main__": rcode = 0 if len(sys.argv) <= 1: - print('usage: {} file'.format(sys.argv[0])) + print('usage: {} [-v -vv] file'.format(sys.argv[0])) else: - with open(sys.argv[1], 'r') as f: + verb = 0 + argv = sys.argv[:] + for (i, opt) in enumerate( [ '-v', '-vv' ] ): + if opt in argv: + argv.remove(opt) + verb = i + 1 + with open(argv[1], 'r') as f: s = f.read() lst = es_split(s) - print yaml.dump(lst) + if verb >= 1: + print yaml.dump(lst) - argv = sys.argv[1:] + argv = argv[1:] args = [ len(argv), argv ] - info = { 'lst' : lst, 'call_stk' : [] } + info = { 'lst' : lst, 'call_stk' : [], 'verb' : verb } rcode = do_fcall( 'main', args, info ) + rcode = int(rcode) sys.exit(rcode) # EOF