cmpl_parse.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. package otto
  2. import (
  3. "fmt"
  4. "github.com/robertkrimen/otto/ast"
  5. "github.com/robertkrimen/otto/file"
  6. "github.com/robertkrimen/otto/token"
  7. )
  8. var (
  9. trueLiteral = &nodeLiteral{value: boolValue(true)}
  10. falseLiteral = &nodeLiteral{value: boolValue(false)}
  11. nullLiteral = &nodeLiteral{value: nullValue}
  12. emptyStatement = &nodeEmptyStatement{}
  13. )
  14. func (cmpl *compiler) parseExpression(expr ast.Expression) nodeExpression {
  15. if expr == nil {
  16. return nil
  17. }
  18. switch expr := expr.(type) {
  19. case *ast.ArrayLiteral:
  20. out := &nodeArrayLiteral{
  21. value: make([]nodeExpression, len(expr.Value)),
  22. }
  23. for i, value := range expr.Value {
  24. out.value[i] = cmpl.parseExpression(value)
  25. }
  26. return out
  27. case *ast.AssignExpression:
  28. return &nodeAssignExpression{
  29. operator: expr.Operator,
  30. left: cmpl.parseExpression(expr.Left),
  31. right: cmpl.parseExpression(expr.Right),
  32. }
  33. case *ast.BinaryExpression:
  34. return &nodeBinaryExpression{
  35. operator: expr.Operator,
  36. left: cmpl.parseExpression(expr.Left),
  37. right: cmpl.parseExpression(expr.Right),
  38. comparison: expr.Comparison,
  39. }
  40. case *ast.BooleanLiteral:
  41. if expr.Value {
  42. return trueLiteral
  43. }
  44. return falseLiteral
  45. case *ast.BracketExpression:
  46. return &nodeBracketExpression{
  47. idx: expr.Left.Idx0(),
  48. left: cmpl.parseExpression(expr.Left),
  49. member: cmpl.parseExpression(expr.Member),
  50. }
  51. case *ast.CallExpression:
  52. out := &nodeCallExpression{
  53. callee: cmpl.parseExpression(expr.Callee),
  54. argumentList: make([]nodeExpression, len(expr.ArgumentList)),
  55. }
  56. for i, value := range expr.ArgumentList {
  57. out.argumentList[i] = cmpl.parseExpression(value)
  58. }
  59. return out
  60. case *ast.ConditionalExpression:
  61. return &nodeConditionalExpression{
  62. test: cmpl.parseExpression(expr.Test),
  63. consequent: cmpl.parseExpression(expr.Consequent),
  64. alternate: cmpl.parseExpression(expr.Alternate),
  65. }
  66. case *ast.DotExpression:
  67. return &nodeDotExpression{
  68. idx: expr.Left.Idx0(),
  69. left: cmpl.parseExpression(expr.Left),
  70. identifier: expr.Identifier.Name,
  71. }
  72. case *ast.EmptyExpression:
  73. return nil
  74. case *ast.FunctionLiteral:
  75. name := ""
  76. if expr.Name != nil {
  77. name = expr.Name.Name
  78. }
  79. out := &nodeFunctionLiteral{
  80. name: name,
  81. body: cmpl.parseStatement(expr.Body),
  82. source: expr.Source,
  83. file: cmpl.file,
  84. }
  85. if expr.ParameterList != nil {
  86. list := expr.ParameterList.List
  87. out.parameterList = make([]string, len(list))
  88. for i, value := range list {
  89. out.parameterList[i] = value.Name
  90. }
  91. }
  92. for _, value := range expr.DeclarationList {
  93. switch value := value.(type) {
  94. case *ast.FunctionDeclaration:
  95. out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*nodeFunctionLiteral))
  96. case *ast.VariableDeclaration:
  97. for _, value := range value.List {
  98. out.varList = append(out.varList, value.Name)
  99. }
  100. default:
  101. panic(fmt.Sprintf("parse expression unknown function declaration type %T", value))
  102. }
  103. }
  104. return out
  105. case *ast.Identifier:
  106. return &nodeIdentifier{
  107. idx: expr.Idx,
  108. name: expr.Name,
  109. }
  110. case *ast.NewExpression:
  111. out := &nodeNewExpression{
  112. callee: cmpl.parseExpression(expr.Callee),
  113. argumentList: make([]nodeExpression, len(expr.ArgumentList)),
  114. }
  115. for i, value := range expr.ArgumentList {
  116. out.argumentList[i] = cmpl.parseExpression(value)
  117. }
  118. return out
  119. case *ast.NullLiteral:
  120. return nullLiteral
  121. case *ast.NumberLiteral:
  122. return &nodeLiteral{
  123. value: toValue(expr.Value),
  124. }
  125. case *ast.ObjectLiteral:
  126. out := &nodeObjectLiteral{
  127. value: make([]nodeProperty, len(expr.Value)),
  128. }
  129. for i, value := range expr.Value {
  130. out.value[i] = nodeProperty{
  131. key: value.Key,
  132. kind: value.Kind,
  133. value: cmpl.parseExpression(value.Value),
  134. }
  135. }
  136. return out
  137. case *ast.RegExpLiteral:
  138. return &nodeRegExpLiteral{
  139. flags: expr.Flags,
  140. pattern: expr.Pattern,
  141. }
  142. case *ast.SequenceExpression:
  143. out := &nodeSequenceExpression{
  144. sequence: make([]nodeExpression, len(expr.Sequence)),
  145. }
  146. for i, value := range expr.Sequence {
  147. out.sequence[i] = cmpl.parseExpression(value)
  148. }
  149. return out
  150. case *ast.StringLiteral:
  151. return &nodeLiteral{
  152. value: stringValue(expr.Value),
  153. }
  154. case *ast.ThisExpression:
  155. return &nodeThisExpression{}
  156. case *ast.UnaryExpression:
  157. return &nodeUnaryExpression{
  158. operator: expr.Operator,
  159. operand: cmpl.parseExpression(expr.Operand),
  160. postfix: expr.Postfix,
  161. }
  162. case *ast.VariableExpression:
  163. return &nodeVariableExpression{
  164. idx: expr.Idx0(),
  165. name: expr.Name,
  166. initializer: cmpl.parseExpression(expr.Initializer),
  167. }
  168. default:
  169. panic(fmt.Errorf("parse expression unknown node type %T", expr))
  170. }
  171. }
  172. func (cmpl *compiler) parseStatement(stmt ast.Statement) nodeStatement {
  173. if stmt == nil {
  174. return nil
  175. }
  176. switch stmt := stmt.(type) {
  177. case *ast.BlockStatement:
  178. out := &nodeBlockStatement{
  179. list: make([]nodeStatement, len(stmt.List)),
  180. }
  181. for i, value := range stmt.List {
  182. out.list[i] = cmpl.parseStatement(value)
  183. }
  184. return out
  185. case *ast.BranchStatement:
  186. out := &nodeBranchStatement{
  187. branch: stmt.Token,
  188. }
  189. if stmt.Label != nil {
  190. out.label = stmt.Label.Name
  191. }
  192. return out
  193. case *ast.DebuggerStatement:
  194. return &nodeDebuggerStatement{}
  195. case *ast.DoWhileStatement:
  196. out := &nodeDoWhileStatement{
  197. test: cmpl.parseExpression(stmt.Test),
  198. }
  199. body := cmpl.parseStatement(stmt.Body)
  200. if block, ok := body.(*nodeBlockStatement); ok {
  201. out.body = block.list
  202. } else {
  203. out.body = append(out.body, body)
  204. }
  205. return out
  206. case *ast.EmptyStatement:
  207. return emptyStatement
  208. case *ast.ExpressionStatement:
  209. return &nodeExpressionStatement{
  210. expression: cmpl.parseExpression(stmt.Expression),
  211. }
  212. case *ast.ForInStatement:
  213. out := &nodeForInStatement{
  214. into: cmpl.parseExpression(stmt.Into),
  215. source: cmpl.parseExpression(stmt.Source),
  216. }
  217. body := cmpl.parseStatement(stmt.Body)
  218. if block, ok := body.(*nodeBlockStatement); ok {
  219. out.body = block.list
  220. } else {
  221. out.body = append(out.body, body)
  222. }
  223. return out
  224. case *ast.ForStatement:
  225. out := &nodeForStatement{
  226. initializer: cmpl.parseExpression(stmt.Initializer),
  227. update: cmpl.parseExpression(stmt.Update),
  228. test: cmpl.parseExpression(stmt.Test),
  229. }
  230. body := cmpl.parseStatement(stmt.Body)
  231. if block, ok := body.(*nodeBlockStatement); ok {
  232. out.body = block.list
  233. } else {
  234. out.body = append(out.body, body)
  235. }
  236. return out
  237. case *ast.FunctionStatement:
  238. return emptyStatement
  239. case *ast.IfStatement:
  240. return &nodeIfStatement{
  241. test: cmpl.parseExpression(stmt.Test),
  242. consequent: cmpl.parseStatement(stmt.Consequent),
  243. alternate: cmpl.parseStatement(stmt.Alternate),
  244. }
  245. case *ast.LabelledStatement:
  246. return &nodeLabelledStatement{
  247. label: stmt.Label.Name,
  248. statement: cmpl.parseStatement(stmt.Statement),
  249. }
  250. case *ast.ReturnStatement:
  251. return &nodeReturnStatement{
  252. argument: cmpl.parseExpression(stmt.Argument),
  253. }
  254. case *ast.SwitchStatement:
  255. out := &nodeSwitchStatement{
  256. discriminant: cmpl.parseExpression(stmt.Discriminant),
  257. defaultIdx: stmt.Default,
  258. body: make([]*nodeCaseStatement, len(stmt.Body)),
  259. }
  260. for i, clause := range stmt.Body {
  261. out.body[i] = &nodeCaseStatement{
  262. test: cmpl.parseExpression(clause.Test),
  263. consequent: make([]nodeStatement, len(clause.Consequent)),
  264. }
  265. for j, value := range clause.Consequent {
  266. out.body[i].consequent[j] = cmpl.parseStatement(value)
  267. }
  268. }
  269. return out
  270. case *ast.ThrowStatement:
  271. return &nodeThrowStatement{
  272. argument: cmpl.parseExpression(stmt.Argument),
  273. }
  274. case *ast.TryStatement:
  275. out := &nodeTryStatement{
  276. body: cmpl.parseStatement(stmt.Body),
  277. finally: cmpl.parseStatement(stmt.Finally),
  278. }
  279. if stmt.Catch != nil {
  280. out.catch = &nodeCatchStatement{
  281. parameter: stmt.Catch.Parameter.Name,
  282. body: cmpl.parseStatement(stmt.Catch.Body),
  283. }
  284. }
  285. return out
  286. case *ast.VariableStatement:
  287. out := &nodeVariableStatement{
  288. list: make([]nodeExpression, len(stmt.List)),
  289. }
  290. for i, value := range stmt.List {
  291. out.list[i] = cmpl.parseExpression(value)
  292. }
  293. return out
  294. case *ast.WhileStatement:
  295. out := &nodeWhileStatement{
  296. test: cmpl.parseExpression(stmt.Test),
  297. }
  298. body := cmpl.parseStatement(stmt.Body)
  299. if block, ok := body.(*nodeBlockStatement); ok {
  300. out.body = block.list
  301. } else {
  302. out.body = append(out.body, body)
  303. }
  304. return out
  305. case *ast.WithStatement:
  306. return &nodeWithStatement{
  307. object: cmpl.parseExpression(stmt.Object),
  308. body: cmpl.parseStatement(stmt.Body),
  309. }
  310. default:
  311. panic(fmt.Sprintf("parse statement: unknown type %T", stmt))
  312. }
  313. }
  314. func cmplParse(in *ast.Program) *nodeProgram {
  315. cmpl := compiler{
  316. program: in,
  317. }
  318. if cmpl.program != nil {
  319. cmpl.file = cmpl.program.File
  320. }
  321. return cmpl.parse()
  322. }
  323. func (cmpl *compiler) parse() *nodeProgram {
  324. out := &nodeProgram{
  325. body: make([]nodeStatement, len(cmpl.program.Body)),
  326. file: cmpl.program.File,
  327. }
  328. for i, value := range cmpl.program.Body {
  329. out.body[i] = cmpl.parseStatement(value)
  330. }
  331. for _, value := range cmpl.program.DeclarationList {
  332. switch value := value.(type) {
  333. case *ast.FunctionDeclaration:
  334. out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*nodeFunctionLiteral))
  335. case *ast.VariableDeclaration:
  336. for _, value := range value.List {
  337. out.varList = append(out.varList, value.Name)
  338. }
  339. default:
  340. panic(fmt.Sprintf("Here be dragons: cmpl.parseProgram.DeclarationList(%T)", value))
  341. }
  342. }
  343. return out
  344. }
  345. type nodeProgram struct {
  346. file *file.File
  347. body []nodeStatement
  348. varList []string
  349. functionList []*nodeFunctionLiteral
  350. }
  351. type node interface{}
  352. type (
  353. nodeExpression interface {
  354. node
  355. expressionNode()
  356. }
  357. nodeArrayLiteral struct {
  358. value []nodeExpression
  359. }
  360. nodeAssignExpression struct {
  361. left nodeExpression
  362. right nodeExpression
  363. operator token.Token
  364. }
  365. nodeBinaryExpression struct {
  366. left nodeExpression
  367. right nodeExpression
  368. operator token.Token
  369. comparison bool
  370. }
  371. nodeBracketExpression struct {
  372. left nodeExpression
  373. member nodeExpression
  374. idx file.Idx
  375. }
  376. nodeCallExpression struct {
  377. callee nodeExpression
  378. argumentList []nodeExpression
  379. }
  380. nodeConditionalExpression struct {
  381. test nodeExpression
  382. consequent nodeExpression
  383. alternate nodeExpression
  384. }
  385. nodeDotExpression struct {
  386. left nodeExpression
  387. identifier string
  388. idx file.Idx
  389. }
  390. nodeFunctionLiteral struct {
  391. body nodeStatement
  392. file *file.File
  393. name string
  394. source string
  395. parameterList []string
  396. varList []string
  397. functionList []*nodeFunctionLiteral
  398. }
  399. nodeIdentifier struct {
  400. name string
  401. idx file.Idx
  402. }
  403. nodeLiteral struct {
  404. value Value
  405. }
  406. nodeNewExpression struct {
  407. callee nodeExpression
  408. argumentList []nodeExpression
  409. }
  410. nodeObjectLiteral struct {
  411. value []nodeProperty
  412. }
  413. nodeProperty struct {
  414. value nodeExpression
  415. key string
  416. kind string
  417. }
  418. nodeRegExpLiteral struct {
  419. flags string
  420. pattern string // Value?
  421. }
  422. nodeSequenceExpression struct {
  423. sequence []nodeExpression
  424. }
  425. nodeThisExpression struct{}
  426. nodeUnaryExpression struct {
  427. operand nodeExpression
  428. operator token.Token
  429. postfix bool
  430. }
  431. nodeVariableExpression struct {
  432. initializer nodeExpression
  433. name string
  434. idx file.Idx
  435. }
  436. )
  437. type (
  438. nodeStatement interface {
  439. node
  440. statementNode()
  441. }
  442. nodeBlockStatement struct {
  443. list []nodeStatement
  444. }
  445. nodeBranchStatement struct {
  446. label string
  447. branch token.Token
  448. }
  449. nodeCaseStatement struct {
  450. test nodeExpression
  451. consequent []nodeStatement
  452. }
  453. nodeCatchStatement struct {
  454. body nodeStatement
  455. parameter string
  456. }
  457. nodeDebuggerStatement struct{}
  458. nodeDoWhileStatement struct {
  459. test nodeExpression
  460. body []nodeStatement
  461. }
  462. nodeEmptyStatement struct{}
  463. nodeExpressionStatement struct {
  464. expression nodeExpression
  465. }
  466. nodeForInStatement struct {
  467. into nodeExpression
  468. source nodeExpression
  469. body []nodeStatement
  470. }
  471. nodeForStatement struct {
  472. initializer nodeExpression
  473. update nodeExpression
  474. test nodeExpression
  475. body []nodeStatement
  476. }
  477. nodeIfStatement struct {
  478. test nodeExpression
  479. consequent nodeStatement
  480. alternate nodeStatement
  481. }
  482. nodeLabelledStatement struct {
  483. statement nodeStatement
  484. label string
  485. }
  486. nodeReturnStatement struct {
  487. argument nodeExpression
  488. }
  489. nodeSwitchStatement struct {
  490. discriminant nodeExpression
  491. body []*nodeCaseStatement
  492. defaultIdx int
  493. }
  494. nodeThrowStatement struct {
  495. argument nodeExpression
  496. }
  497. nodeTryStatement struct {
  498. body nodeStatement
  499. catch *nodeCatchStatement
  500. finally nodeStatement
  501. }
  502. nodeVariableStatement struct {
  503. list []nodeExpression
  504. }
  505. nodeWhileStatement struct {
  506. test nodeExpression
  507. body []nodeStatement
  508. }
  509. nodeWithStatement struct {
  510. object nodeExpression
  511. body nodeStatement
  512. }
  513. )
  514. // expressionNode.
  515. func (*nodeArrayLiteral) expressionNode() {}
  516. func (*nodeAssignExpression) expressionNode() {}
  517. func (*nodeBinaryExpression) expressionNode() {}
  518. func (*nodeBracketExpression) expressionNode() {}
  519. func (*nodeCallExpression) expressionNode() {}
  520. func (*nodeConditionalExpression) expressionNode() {}
  521. func (*nodeDotExpression) expressionNode() {}
  522. func (*nodeFunctionLiteral) expressionNode() {}
  523. func (*nodeIdentifier) expressionNode() {}
  524. func (*nodeLiteral) expressionNode() {}
  525. func (*nodeNewExpression) expressionNode() {}
  526. func (*nodeObjectLiteral) expressionNode() {}
  527. func (*nodeRegExpLiteral) expressionNode() {}
  528. func (*nodeSequenceExpression) expressionNode() {}
  529. func (*nodeThisExpression) expressionNode() {}
  530. func (*nodeUnaryExpression) expressionNode() {}
  531. func (*nodeVariableExpression) expressionNode() {}
  532. // statementNode
  533. func (*nodeBlockStatement) statementNode() {}
  534. func (*nodeBranchStatement) statementNode() {}
  535. func (*nodeCaseStatement) statementNode() {}
  536. func (*nodeCatchStatement) statementNode() {}
  537. func (*nodeDebuggerStatement) statementNode() {}
  538. func (*nodeDoWhileStatement) statementNode() {}
  539. func (*nodeEmptyStatement) statementNode() {}
  540. func (*nodeExpressionStatement) statementNode() {}
  541. func (*nodeForInStatement) statementNode() {}
  542. func (*nodeForStatement) statementNode() {}
  543. func (*nodeIfStatement) statementNode() {}
  544. func (*nodeLabelledStatement) statementNode() {}
  545. func (*nodeReturnStatement) statementNode() {}
  546. func (*nodeSwitchStatement) statementNode() {}
  547. func (*nodeThrowStatement) statementNode() {}
  548. func (*nodeTryStatement) statementNode() {}
  549. func (*nodeVariableStatement) statementNode() {}
  550. func (*nodeWhileStatement) statementNode() {}
  551. func (*nodeWithStatement) statementNode() {}