1/*
2 * Copyright (c) 2022-2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http:// www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16const { NapiLog } = require('./NapiLog');
17const { NodeTools } = require('./NodeTools');
18const { Parser } = require('./parser');
19const { DataType } = require('./NodeTools');
20
21class Generator {
22  constructor() {
23    this.parser = new Parser();
24  }
25
26  hcsToAst(fn) {
27    return this.parser.parse(fn);
28  }
29
30  DATA_NODES_NOT_INHERIT = 0;
31  CLASS_NODES_COPY = 1;
32  CLASS_NODES_REFERENCE = 2;
33  CLASS_NODES_DELETION = 3;
34  CLASS_NODES_TEMPLETE = 4;
35  DATA_NODES_INHERIT = 5;
36
37  astToObjConfigNodeType(nodeType, obj, node) {
38    if (
39      nodeType === this.DATA_NODES_INHERIT ||
40      nodeType === this.CLASS_NODES_COPY ||
41      nodeType === this.CLASS_NODES_REFERENCE
42    ) {
43      obj.ref_ = node.refNodePath_;
44    } else if (
45      nodeType !== this.DATA_NODES_NOT_INHERIT &&
46      nodeType !== this.CLASS_NODES_DELETION &&
47      nodeType !== this.CLASS_NODES_TEMPLETE
48    ) {
49      NapiLog.logError('unknow node type');
50    }
51  }
52
53  astToObjConfigNode(ret, child, node) {
54    ret.value_ = [];
55    child = node.child_;
56    while (child !== undefined) {
57      ret.value_.push(this.astToObj(child, ret));
58      child = child.next_;
59    }
60    ret.nodeType_ = node.nodeType_;
61    ret.isOpen_ = true;
62    ret.nodeWidth_ = 132;
63    this.astToObjConfigNodeType(node.nodeType_, ret, node);
64  }
65
66  astToObj(node, parent) {
67    let child;
68    let ret = new Object();
69    ret.type_ = node.type_;
70    ret.name_ = node.name_;
71    ret.lineno_ = node.lineno_;
72    ret.parent_ = parent;
73    ret.nodeWidth_ = 132;
74    switch (node.type_) {
75      case DataType.INT8:
76      case DataType.INT16:
77      case DataType.INT32:
78      case DataType.INT64:
79        ret.value_ = node.integerValue_;
80        ret.jinzhi_ = node.jinzhi_;
81        break;
82      case DataType.STRING:
83        ret.value_ = node.stringValue_;
84        break;
85      case DataType.NODE:
86        this.astToObjConfigNode(ret, child, node);
87        break;
88      case DataType.ATTR:
89        ret.value_ = this.astToObj(node.child_, ret);
90        break;
91      case DataType.ARRAY:
92        ret.value_ = [];
93        child = node.child_;
94        while (child !== undefined) {
95          ret.value_.push(this.astToObj(child, ret));
96          child = child.next_;
97        }
98        ret.arraySize_ = node.arraySize_;
99        ret.arrayType_ = node.arrayType_;
100        break;
101      case DataType.REFERENCE:
102        ret.value_ = node.stringValue_;
103        break;
104      case DataType.DELETE:
105        ret.value_ = null;
106        break;
107      case DataType.BOOL:
108        if (node.integerValue_ === 0) {
109          ret.value_ = false;
110        }
111        else {
112          ret.value_ = true;
113        }
114        break;
115      default:
116        NapiLog.logError('unknow type');
117        break;
118    }
119    return ret;
120  }
121
122  mergeObj(files) {
123    let objList = [];
124    for (let i in files) {
125      objList.push(files[i]);
126    }
127    let err = true;
128    for (let i in objList) {
129      err = err && NodeTools.redefineCheck(objList[i]);
130    }
131    if (!err) {
132      return false;
133    }
134    objList.push(objList.shift());
135    let ret = {
136      type_: DataType.NODE,
137      name_: 'root',
138      value_: [],
139    };
140    for (let i in objList) {
141      NodeTools.merge(ret, objList[i]);
142    }
143    return ret;
144  }
145
146  expandObj(node) {
147    NodeTools.nodeExpand(node);
148    NodeTools.inheritExpand(node);
149    NodeTools.nodeNestCheck(node);
150    return node;
151  }
152
153  makeSpace(deep) {
154    let ret = '';
155    for (let i = 0; i < deep; i++) ret += '    ';
156    return ret;
157  }
158
159  makeHcs(fn, node) {
160    let body = this.objToHcs(node, 0);
161    let head = '';
162
163    let fpath = fn.substring(0, fn.lastIndexOf('\\') + 1);
164    for (let i in this.parser.astList[fn].include) {
165      head +=
166        '#include "./' +
167        this.parser.astList[fn].include[i].substring(fpath.length) +
168        '"\n';
169    }
170    return head + body;
171  }
172
173  objToHcsConfigNode(node, deep) {
174    let ret = '';
175    if (node.nodeType_ === this.DATA_NODES_NOT_INHERIT) {
176      ret = this.makeSpace(deep) + node.name_ + ' {\n';
177    } else if (node.nodeType_ === this.CLASS_NODES_COPY) {
178      ret = this.makeSpace(deep) + node.name_ + ' : ' + node.ref_ + ' {\n';
179    } else if (node.nodeType_ === this.CLASS_NODES_REFERENCE) {
180      ret = this.makeSpace(deep) + node.name_ + ' : &' + node.ref_ + ' {\n';
181    } else if (node.nodeType_ === this.CLASS_NODES_DELETION) {
182      ret = this.makeSpace(deep) + node.name_ + ' : delete {\n';
183    } else if (node.nodeType_ === this.CLASS_NODES_TEMPLETE) {
184      ret = this.makeSpace(deep) + 'template ' + node.name_ + ' {\n';
185    } else if (node.nodeType_ === this.DATA_NODES_INHERIT) {
186      ret = this.makeSpace(deep) + node.name_ + ' :: ' + node.ref_ + ' {\n';
187    } else {
188      NapiLog.logError('unknow node type');
189    }
190
191    for (let i in node.value_) {
192      ret += this.objToHcs(node.value_[i], deep + 1);
193    }
194    ret += this.makeSpace(deep) + '}\n';
195    return ret;
196  }
197
198  objToHcs(node, deep) {
199    let ret = '';
200    switch (node.type_) {
201      case DataType.INT8:
202      case DataType.INT16:
203      case DataType.INT32:
204      case DataType.INT64:
205        ret = NodeTools.jinZhi10ToX(node.value_, node.jinzhi_);
206        break;
207      case DataType.STRING:
208        ret = '"' + node.value_ + '"';
209        break;
210      case DataType.NODE:
211        ret += this.objToHcsConfigNode(node, deep);
212        break;
213      case DataType.ATTR:
214        ret = this.makeSpace(deep) + node.name_ + ' = ';
215        ret += this.objToHcs(node.value_, 0);
216        ret += ';\n';
217        break;
218      case DataType.ARRAY:
219        ret = '[';
220        for (let i in node.value_) {
221          let ss = this.objToHcs(node.value_[i], 0);
222          if (i > 0) {
223            ret += ', ';
224          }
225          ret += ss;
226        }
227        ret += ']';
228        break;
229      case DataType.REFERENCE:
230        ret = '&' + node.value_;
231        break;
232      case DataType.DELETE:
233        ret = 'delete';
234        break;
235      case DataType.BOOL:
236        if (node.value_) {
237          ret = 'true';
238        }
239        else {
240          ret = 'false';
241        }
242        break;
243      default:
244        NapiLog.logError('unknow' + node.type_);
245        break;
246    }
247    return ret;
248  }
249}
250
251Generator.pInstance_ = null;
252Generator.gi = function () {
253  if (Generator.pInstance_ === null) {
254    Generator.pInstance_ = new Generator();
255  }
256  return Generator.pInstance_;
257};
258
259module.exports = {
260  Generator,
261};
262