node.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. package node
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strings"
  6. "kumachan/parser/scanner"
  7. "kumachan/parser/syntax"
  8. )
  9. type Node struct {
  10. Point scanner.Point
  11. Span scanner.Span
  12. UID uint64
  13. }
  14. type NodeInfo struct {
  15. Type reflect.Type
  16. Children map[syntax.Id] NodeChildInfo
  17. Strings map[syntax.Id] NodeChildInfo
  18. Lists map[syntax.Id] NodeListInfo
  19. Options map[syntax.Id] NodeChildInfo
  20. First int
  21. Last int
  22. }
  23. type NodeChildInfo struct {
  24. FieldIndex int
  25. DivePath [] syntax.Id
  26. Optional bool
  27. Fallback syntax.Id
  28. }
  29. type NodeListInfo struct {
  30. NodeChildInfo
  31. ItemId syntax.Id
  32. TailId syntax.Id
  33. }
  34. var __NodeRegistry = []interface{} {
  35. // Root
  36. Module {},
  37. // Command
  38. VariousCommand {},
  39. Import {},
  40. Identifier {},
  41. DeclConst {},
  42. VariousConstValue {},
  43. Do {},
  44. DeclFunction {},
  45. DeclType {},
  46. VariousBody {},
  47. NativeRef {},
  48. DeclType {},
  49. VariousTypeValue {},
  50. NativeType {},
  51. BoxedType {},
  52. UnionType {},
  53. // Type
  54. VariousType {},
  55. TypeRef {},
  56. TypeLiteral {},
  57. VariousRepr {},
  58. ReprTuple {},
  59. ReprBundle {},
  60. Field {},
  61. ReprFunc {},
  62. // Expression
  63. Expr {},
  64. Call {},
  65. VariousTerm {},
  66. Pipeline {},
  67. PipeOperator {},
  68. // Term
  69. Cast {},
  70. Switch {},
  71. Branch {},
  72. If {},
  73. Lambda {},
  74. VariousPattern {},
  75. PatternTrivial {},
  76. PatternTuple {},
  77. PatternBundle {},
  78. Array {},
  79. Tuple {},
  80. Bundle {},
  81. FieldValue {},
  82. Update {},
  83. Member {},
  84. Get {},
  85. Block {},
  86. Binding {},
  87. Infix {},
  88. Text {},
  89. Ref {},
  90. VariousLiteral {},
  91. IntegerLiteral {},
  92. FloatLiteral {},
  93. StringLiteral {},
  94. }
  95. var __NodeInfoMap = map[syntax.Id] NodeInfo {}
  96. var __Initialized = false
  97. func __Initialize() {
  98. var get_field_tag = func(f reflect.StructField) (string, string) {
  99. var kinds = []string {
  100. "use",
  101. "part", "part_opt", "content",
  102. "option",
  103. "list", "list_more", "list_rec",
  104. }
  105. for _, kind := range kinds {
  106. var value, exists = f.Tag.Lookup(kind)
  107. if exists {
  108. return kind, value
  109. }
  110. }
  111. return "", ""
  112. }
  113. var get_part_id = func(part string) syntax.Id {
  114. var part_id, exists = syntax.Name2Id[part]
  115. if !exists {
  116. panic(fmt.Sprintf("syntax part `%v` does not exist", part))
  117. }
  118. return part_id
  119. }
  120. var get_parts_id = func(parts []string) []syntax.Id {
  121. var mapped = make([]syntax.Id, len(parts))
  122. for i, part := range parts {
  123. mapped[i] = get_part_id(part)
  124. }
  125. return mapped
  126. }
  127. var get_dive_info = func(tag_value string) (syntax.Id, []syntax.Id) {
  128. var path = strings.Split(tag_value, ".")
  129. if len(path) == 1 && path[0] == "" {
  130. return (syntax.Id)(-1), []syntax.Id {}
  131. } else {
  132. return get_part_id(path[0]), get_parts_id(path)
  133. }
  134. }
  135. for _, node := range __NodeRegistry {
  136. var T = reflect.TypeOf(node)
  137. if T.Kind() != reflect.Struct {
  138. panic("invalid node")
  139. }
  140. var f_node, exists = T.FieldByName("Node")
  141. if !exists {
  142. panic("invalid node")
  143. }
  144. var node_part_name = f_node.Tag.Get("part")
  145. var node_id = get_part_id(node_part_name)
  146. var info = NodeInfo {
  147. Type: T,
  148. Children: make(map[syntax.Id] NodeChildInfo),
  149. Strings: make(map[syntax.Id] NodeChildInfo),
  150. Lists: make(map[syntax.Id] NodeListInfo),
  151. Options: make(map[syntax.Id] NodeChildInfo),
  152. First: -1,
  153. Last: -1,
  154. }
  155. for i := 0; i < T.NumField(); i += 1 {
  156. var f = T.Field(i)
  157. if f.Name == "Node" {
  158. continue
  159. }
  160. var kind, value = get_field_tag(f)
  161. if kind == "use" {
  162. if value == "first" {
  163. info.First = i
  164. } else if value == "last" {
  165. info.Last = i
  166. } else {
  167. panic(fmt.Sprintf("invalid directive `use:'%v'`", value))
  168. }
  169. continue
  170. }
  171. var part_id, dive_path = get_dive_info(value)
  172. var fallback = f.Tag.Get("fallback")
  173. var fallback_id syntax.Id = -1
  174. if fallback != "" {
  175. fallback_id = get_part_id(fallback)
  176. }
  177. switch kind {
  178. // case "use": already handled above
  179. case "part":
  180. info.Children[part_id] = NodeChildInfo {
  181. FieldIndex: i,
  182. DivePath: dive_path,
  183. Fallback: fallback_id,
  184. }
  185. case "part_opt":
  186. info.Children[part_id] = NodeChildInfo {
  187. FieldIndex: i,
  188. DivePath: dive_path,
  189. Optional: true,
  190. Fallback: fallback_id,
  191. }
  192. case "content":
  193. info.Strings[part_id] = NodeChildInfo {
  194. FieldIndex: i,
  195. DivePath: dive_path,
  196. Fallback: fallback_id,
  197. }
  198. case "option":
  199. info.Options[part_id] = NodeChildInfo {
  200. FieldIndex: i,
  201. DivePath: dive_path,
  202. Optional: true,
  203. }
  204. case "list":
  205. var list_name string
  206. if len(dive_path) > 0 {
  207. list_name = syntax.Id2Name[dive_path[len(dive_path)-1]]
  208. } else {
  209. list_name = syntax.Id2Name[part_id]
  210. }
  211. var t = strings.TrimSuffix(list_name, "list")
  212. var item = strings.TrimSuffix(t, "_")
  213. var tail = list_name + "_tail"
  214. var item_id = get_part_id(item)
  215. var tail_id = get_part_id(tail)
  216. info.Lists[part_id] = NodeListInfo {
  217. NodeChildInfo: NodeChildInfo {
  218. FieldIndex: i,
  219. DivePath: dive_path,
  220. Optional: true,
  221. Fallback: fallback_id,
  222. },
  223. ItemId: item_id,
  224. TailId: tail_id,
  225. }
  226. case "list_more":
  227. var item = f.Tag.Get("item")
  228. if item == "" {
  229. panic("`item` tag should be specified when using list_more")
  230. }
  231. var item_id = get_part_id(item)
  232. var tail string
  233. if strings.HasSuffix(item, "ch") || strings.HasSuffix(item, "x") {
  234. tail = "more_" + item + "es"
  235. } else {
  236. tail = "more_" + item + "s"
  237. }
  238. var tail_id = get_part_id(tail)
  239. info.Lists[part_id] = NodeListInfo {
  240. NodeChildInfo: NodeChildInfo {
  241. FieldIndex: i,
  242. DivePath: dive_path,
  243. Optional: true,
  244. Fallback: fallback_id,
  245. },
  246. ItemId: item_id,
  247. TailId: tail_id,
  248. }
  249. case "list_rec":
  250. var tail_id syntax.Id
  251. if len(dive_path) > 0 {
  252. tail_id = dive_path[len(dive_path)-1]
  253. } else {
  254. tail_id = part_id
  255. }
  256. var list_name = syntax.Id2Name[tail_id]
  257. var item string
  258. if strings.HasSuffix(list_name, "ches") {
  259. item = strings.TrimSuffix(list_name, "es")
  260. } else {
  261. item = strings.TrimSuffix(list_name, "s")
  262. }
  263. var item_id = get_part_id(item)
  264. info.Lists[part_id] = NodeListInfo{
  265. NodeChildInfo: NodeChildInfo{
  266. FieldIndex: i,
  267. DivePath: dive_path,
  268. Optional: true,
  269. Fallback: fallback_id,
  270. },
  271. ItemId: item_id,
  272. TailId: tail_id,
  273. }
  274. default:
  275. // no tag found, do nothing
  276. }
  277. }
  278. __NodeInfoMap[node_id] = info
  279. }
  280. __Initialized = true
  281. }
  282. func GetNodeInfoById (part_id syntax.Id) NodeInfo {
  283. if !__Initialized {
  284. __Initialize()
  285. }
  286. var info, exists = __NodeInfoMap[part_id]
  287. if !exists {
  288. panic(fmt.Sprintf (
  289. "node info of part `%v` does not exist",
  290. syntax.Id2Name[part_id],
  291. ))
  292. } else {
  293. return info
  294. }
  295. }
  296. func GetNodeInfo (part string) NodeInfo {
  297. var part_id, exists = syntax.Name2Id[part]
  298. if !exists {
  299. panic("part " + part + " does not exist")
  300. } else {
  301. return GetNodeInfoById(part_id)
  302. }
  303. }