• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2024 Huawei Device Co., Ltd.
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14require_relative 'types'
15
16module ESChecker
17    UNMANGLE = {"#__NaN" => "NaN", "#__null" => "null", "#__Inf" => "Infinity", "#__NegInf" => "-Infinity", "#__undefined" => "undefined"}
18    class ValueDumper
19        def initialize(conf)
20            @name = 0
21            @conf = conf
22        end
23
24        def parse_type(str)
25            ESChecker::Types::Parser.new(str).run
26        end
27
28        def unmangle(x)
29            toh = Proc.new { |i, off|
30                ((i >> (off * 8)) % 256).to_s(16).rjust(2, '0')
31            }
32            if x.kind_of? Array
33                x.map { |e| unmangle e }
34            elsif x.kind_of? Hash
35                case x["__kind"]
36                when "str"
37                    res = x["data"].map { |c| "\\u#{toh.(c, 1)}#{toh.(c, 0)}" }.join
38                    "\"#{res}\""
39                when "num"
40                    "Double.bitCastFromLong(#{x["data"]} as long) /* #{x["dbg"]} */"
41                when "bigint"
42                    "#{x["data"]}n"
43                else
44                    raise "unknown kind for #{x}"
45                end
46            elsif x.kind_of? String
47                old = x
48                x = UNMANGLE[x] || x
49                if x != old
50                    x
51                else
52                    x.inspect
53                end
54            elsif x.kind_of?(Float)
55                hex = [x].pack('G').split('').map { |ds| ds[0] }.map { |a| sprintf("%02x", a.ord) }.join()
56                "Double.bitCastFromLong(0x#{hex}) /* #{x} */"
57            else
58                UNMANGLE[x] || x
59            end
60        end
61
62        def get_array_type_from(x)
63            match = /^\s*(Array|Iterable)<(?<elem>.*)>\s*$/.match(x)
64            if match
65                match[:elem]
66            else
67                nil
68            end
69        end
70
71        def dump_value(buf, rb_obj, exp_type)
72            case exp_type[:kind]
73            when :array, :iterable
74                buf << "Array.of<" << ESChecker::Types::dump(exp_type[:el]) << ">("
75                rb_obj.each_with_index { |v, i|
76                    if i != 0
77                        buf << ", "
78                    end
79                    dump_value(buf, v, exp_type[:el])
80                }
81                buf << ")"
82            when :tuple
83                buf << "["
84                rb_obj.zip(exp_type[:els]).each_with_index { |v, i|
85                    if i != 0
86                        buf << ", "
87                    end
88                    dump_value buf, v[0], v[1]
89                }
90                buf << "] as " << ESChecker::Types::dump(exp_type)
91            when :trivial
92                buf << "#{rb_obj} as #{exp_type[:str]}"
93            else
94                raise "unknown type kind #{exp_type.kind}"
95            end
96        end
97
98        def dump(rb_obj, is_self: false)
99            typ = if is_self
100                ESChecker::Types::detect(rb_obj, dflt: @conf.self_type)
101            else
102                ESChecker::Types::detect(rb_obj, dflt: @conf.ret_type)
103            end
104            rb_obj = unmangle(rb_obj)
105            @buf = String.new
106            dump_value(@buf, rb_obj, typ)
107            r = @buf
108            @buf = String.new
109            r
110        end
111    end
112end
113