compiler.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. package compiler
  2. import (
  3. "kumachan/checker"
  4. "kumachan/loader"
  5. "kumachan/runtime/common"
  6. "kumachan/transformer/node"
  7. )
  8. type Code struct {
  9. InstSeq [] common.Instruction
  10. SourceMap [] *node.Node
  11. }
  12. func CodeFrom(inst common.Instruction, info checker.ExprInfo) Code {
  13. return Code {
  14. InstSeq: [] common.Instruction { inst },
  15. SourceMap: [] *node.Node { &(info.ErrorPoint.Node) },
  16. }
  17. }
  18. type CodeBuffer struct {
  19. Code *Code
  20. }
  21. func MakeCodeBuffer() CodeBuffer {
  22. var code = &Code {
  23. InstSeq: make([] common.Instruction, 0),
  24. SourceMap: make([] *node.Node, 0),
  25. }
  26. return CodeBuffer { code }
  27. }
  28. func (buf CodeBuffer) Write(code Code) {
  29. var base = &(buf.Code.InstSeq)
  30. var base_size = uint(len(buf.Code.InstSeq))
  31. for _, inst := range code.InstSeq {
  32. if inst.OpCode == common.JIF || inst.OpCode == common.JMP {
  33. var dest_addr = (uint(inst.Arg1) + base_size)
  34. ValidateDestAddr(dest_addr)
  35. *base = append(*base, common.Instruction {
  36. OpCode: inst.OpCode,
  37. Arg0: inst.Arg0,
  38. Arg1: common.Long(dest_addr),
  39. })
  40. } else {
  41. *base = append(*base, inst)
  42. }
  43. }
  44. buf.Code.SourceMap = append(buf.Code.SourceMap, code.SourceMap...)
  45. }
  46. func (buf CodeBuffer) Collect() Code {
  47. var code = buf.Code
  48. buf.Code = nil
  49. return *code
  50. }
  51. type Context struct {
  52. GlobalRefs *([] GlobalRef)
  53. LocalScope *Scope
  54. }
  55. func (ctx Context) MakeClosure() Context {
  56. var refs = make([] GlobalRef, 0)
  57. return Context {
  58. GlobalRefs: &refs,
  59. LocalScope: MakeClosureScope(ctx.LocalScope),
  60. }
  61. }
  62. func (ctx Context) AppendDataRef(v common.DataValue) uint {
  63. var refs = ctx.GlobalRefs
  64. var index = uint(len(*refs))
  65. *refs = append(*refs, RefData { v })
  66. return index
  67. }
  68. func (ctx Context) AppendFunRef(ref checker.RefFunction) uint {
  69. var refs = ctx.GlobalRefs
  70. var index = uint(len(*refs))
  71. *refs = append(*refs, RefFun(ref))
  72. return index
  73. }
  74. func (ctx Context) AppendConstRef(ref checker.RefConstant) uint {
  75. var refs = ctx.GlobalRefs
  76. var index = uint(len(*refs))
  77. *refs = append(*refs, RefConst(ref))
  78. return index
  79. }
  80. func (ctx Context) AppendClosureRef(f *common.Function) uint {
  81. var refs = ctx.GlobalRefs
  82. var index = uint(len(*refs))
  83. *refs = append(*refs, RefClosure { f })
  84. return index
  85. }
  86. type GlobalRef interface { GlobalRef() }
  87. func (impl RefData) GlobalRef() {}
  88. type RefData struct { common.DataValue }
  89. func (impl RefFun) GlobalRef() {}
  90. type RefFun checker.RefFunction
  91. func (impl RefConst) GlobalRef() {}
  92. type RefConst checker.RefConstant
  93. func (impl RefClosure) GlobalRef() {}
  94. type RefClosure struct { *common.Function }
  95. type DataInteger checker.IntLiteral
  96. func (d DataInteger) ToValue() common.Value {
  97. return d.Value
  98. }
  99. type DataSmallInteger checker.SmallIntLiteral
  100. func (d DataSmallInteger) ToValue() common.Value {
  101. return d.Value
  102. }
  103. type DataFloat checker.FloatLiteral
  104. func (d DataFloat) ToValue() common.Value {
  105. return d.Value
  106. }
  107. type DataString struct { Value [] rune }
  108. func (d DataString) ToValue() common.Value {
  109. return d.Value
  110. }
  111. type DataStringFormatter checker.StringFormatter
  112. func (d DataStringFormatter) ToValue() common.Value {
  113. var f = func(args []common.Value) []rune {
  114. var buf = make([]rune, 0)
  115. for i, seg := range d.Segments {
  116. buf = append(buf, seg...)
  117. if uint(i) < d.Arity {
  118. var runes = args[i].([]rune)
  119. buf = append(buf, runes...)
  120. }
  121. }
  122. return buf
  123. }
  124. return common.NativeFunctionValue(common.AdaptNativeFunction(f))
  125. }
  126. type Scope struct {
  127. Bindings [] Binding
  128. BindingMap map[string] uint
  129. BindingPeek *uint
  130. }
  131. type Binding struct {
  132. Name string
  133. Used bool
  134. }
  135. func MakeClosureScope(outer *Scope) *Scope {
  136. var bindings = make([] Binding, 0)
  137. for i, e := range outer.Bindings {
  138. bindings[i] = Binding {
  139. Name: e.Name,
  140. Used: false,
  141. }
  142. }
  143. var binding_map = make(map[string] uint)
  144. for k, v := range outer.BindingMap {
  145. binding_map[k] = v
  146. }
  147. var peek = uint(0)
  148. return &Scope {
  149. Bindings: bindings,
  150. BindingMap: binding_map,
  151. BindingPeek: &peek,
  152. }
  153. }
  154. func MakeBranchScope(outer *Scope) *Scope {
  155. var bindings = make([] Binding, 0)
  156. copy(bindings, outer.Bindings)
  157. var binding_map = make(map[string] uint)
  158. for k, v := range outer.BindingMap {
  159. binding_map[k] = v
  160. }
  161. return &Scope {
  162. Bindings: bindings,
  163. BindingMap: binding_map,
  164. BindingPeek: outer.BindingPeek,
  165. }
  166. }
  167. func (scope *Scope) AddBinding(name string) uint {
  168. var _, exists = scope.BindingMap[name]
  169. if exists { panic("duplicate binding") }
  170. var list = &(scope.Bindings)
  171. var offset = uint(len(*list))
  172. *list = append(*list, Binding {
  173. Name: name,
  174. Used: false,
  175. })
  176. scope.BindingMap[name] = offset
  177. *(scope.BindingPeek) += 1
  178. return offset
  179. }
  180. func Compile(expr checker.Expr, ctx Context) Code {
  181. switch v := expr.Value.(type) {
  182. case checker.UnitValue:
  183. var inst_nil = common.Instruction { OpCode: common.NIL }
  184. return CodeFrom(inst_nil, expr.Info)
  185. case checker.IntLiteral:
  186. var index = ctx.AppendDataRef(DataInteger(v))
  187. return CodeFrom(InstGlobalRef(index), expr.Info)
  188. case checker.SmallIntLiteral:
  189. var index = ctx.AppendDataRef(DataSmallInteger(v))
  190. return CodeFrom(InstGlobalRef(index), expr.Info)
  191. case checker.FloatLiteral:
  192. var index = ctx.AppendDataRef(DataFloat(v))
  193. return CodeFrom(InstGlobalRef(index), expr.Info)
  194. case checker.StringLiteral:
  195. var index = ctx.AppendDataRef(DataString { v.Value })
  196. return CodeFrom(InstGlobalRef(index), expr.Info)
  197. case checker.StringFormatter:
  198. var index = ctx.AppendDataRef(DataStringFormatter(v))
  199. return CodeFrom(InstGlobalRef(index), expr.Info)
  200. case checker.RefFunction:
  201. var index = ctx.AppendFunRef(v)
  202. return CodeFrom(InstGlobalRef(index), expr.Info)
  203. case checker.RefConstant:
  204. var index = ctx.AppendConstRef(v)
  205. return CodeFrom(InstGlobalRef(index), expr.Info)
  206. case checker.RefLocal:
  207. var offset, exists = ctx.LocalScope.BindingMap[v.Name]
  208. if !exists { panic("binding " + v.Name + " does not exist") }
  209. ctx.LocalScope.Bindings[offset].Used = true
  210. return CodeFrom(InstLocalRef(offset), expr.Info)
  211. case checker.Array:
  212. var buf = MakeCodeBuffer()
  213. var inst_array = InstArray(uint(len(v.Items)))
  214. buf.Write(CodeFrom(inst_array, expr.Info))
  215. for _, item := range v.Items {
  216. var item_code = Compile(item, ctx)
  217. buf.Write(item_code)
  218. var inst_append = common.Instruction {
  219. OpCode: common.APPEND,
  220. }
  221. buf.Write(CodeFrom(inst_append, item.Info))
  222. }
  223. return buf.Collect()
  224. case checker.Product:
  225. var buf = MakeCodeBuffer()
  226. for _, element := range v.Values {
  227. var element_code = Compile(element, ctx)
  228. buf.Write(element_code)
  229. }
  230. var inst_prod = InstProduct(uint(len(v.Values)))
  231. buf.Write(CodeFrom(inst_prod, expr.Info))
  232. return buf.Collect()
  233. case checker.Get:
  234. var buf = MakeCodeBuffer()
  235. var base_code = Compile(v.Product, ctx)
  236. buf.Write(base_code)
  237. var inst_get = InstGet(v.Index)
  238. buf.Write(CodeFrom(inst_get, expr.Info))
  239. return buf.Collect()
  240. case checker.Set:
  241. var buf = MakeCodeBuffer()
  242. var base_code = Compile(v.Product, ctx)
  243. buf.Write(base_code)
  244. var new_value_code = Compile(v.NewValue, ctx)
  245. buf.Write(new_value_code)
  246. var inst_set = InstSet(v.Index)
  247. buf.Write(CodeFrom(inst_set, expr.Info))
  248. return buf.Collect()
  249. case checker.Lambda:
  250. return CompileClosure(v, expr.Info, false, "", ctx)
  251. case checker.Block:
  252. // TODO: collect info of all unused bindings
  253. var buf = MakeCodeBuffer()
  254. for _, b := range v.Bindings {
  255. switch p := b.Pattern.Concrete.(type) {
  256. case checker.TrivialPattern:
  257. var offset uint
  258. var val_code Code
  259. if b.Recursive {
  260. offset = ctx.LocalScope.AddBinding(p.ValueName)
  261. var lambda, ok = b.Value.Value.(checker.Lambda)
  262. if !ok { panic("something went wrong") }
  263. var info = b.Value.Info
  264. var name = p.ValueName
  265. val_code = CompileClosure(lambda, info, true, name, ctx)
  266. } else {
  267. val_code = Compile(b.Value, ctx)
  268. offset = ctx.LocalScope.AddBinding(p.ValueName)
  269. }
  270. var bind_inst = InstAddBinding(offset)
  271. buf.Write(val_code)
  272. buf.Write(CodeFrom(bind_inst, b.Value.Info))
  273. case checker.TuplePattern:
  274. var val_code = Compile(b.Value, ctx)
  275. buf.Write(val_code)
  276. var info = b.Value.Info
  277. BindPatternItems(p.Items, ctx.LocalScope, buf, info)
  278. case checker.BundlePattern:
  279. var val_code = Compile(b.Value, ctx)
  280. buf.Write(val_code)
  281. var info = b.Value.Info
  282. BindPatternItems(p.Items, ctx.LocalScope, buf, info)
  283. default:
  284. panic("impossible branch")
  285. }
  286. }
  287. var ret_code = Compile(v.Returned, ctx)
  288. buf.Write(ret_code)
  289. return buf.Collect()
  290. case checker.Call:
  291. var buf = MakeCodeBuffer()
  292. var arg_code = Compile(v.Argument, ctx)
  293. var f_code = Compile(v.Function, ctx)
  294. buf.Write(arg_code)
  295. buf.Write(f_code)
  296. var inst_call = common.Instruction {
  297. OpCode:common.CALL,
  298. }
  299. buf.Write(CodeFrom(inst_call, expr.Info))
  300. return buf.Collect()
  301. default:
  302. panic("unknown expression kind")
  303. }
  304. }
  305. func CompileClosure (
  306. lambda checker.Lambda,
  307. info checker.ExprInfo,
  308. recursive bool,
  309. rec_name string,
  310. ctx Context,
  311. ) Code {
  312. // TODO: collect info of all unused parameters
  313. var inner_ctx = ctx.MakeClosure()
  314. var inner_scope = inner_ctx.LocalScope
  315. var inner_buf = MakeCodeBuffer()
  316. switch p := lambda.Input.Concrete.(type) {
  317. case checker.TrivialPattern:
  318. var offset = inner_scope.AddBinding(p.ValueName)
  319. var bind_inst = InstAddBinding(offset)
  320. inner_buf.Write(CodeFrom(bind_inst, info))
  321. case checker.TuplePattern:
  322. BindPatternItems(p.Items, inner_scope, inner_buf, info)
  323. case checker.BundlePattern:
  324. BindPatternItems(p.Items, inner_scope, inner_buf, info)
  325. default:
  326. panic("impossible branch")
  327. }
  328. var body_code = Compile(lambda.Output, inner_ctx)
  329. inner_buf.Write(body_code)
  330. var base_reserved_size = *inner_scope.BindingPeek
  331. if base_reserved_size >= common.LocalSlotMaxSize {
  332. panic("maximum quantity of local bindings exceeded")
  333. }
  334. var outer_bindings_size = uint(len(ctx.LocalScope.Bindings))
  335. var base_context_size = uint(0)
  336. var context_offset_map = make(map[uint] uint)
  337. var context_outer_offsets = make([] uint, 0)
  338. var rec_used bool
  339. var rec_outer_offset uint
  340. for i := uint(0); i < outer_bindings_size; i += 1 {
  341. var b = inner_scope.Bindings[i]
  342. if b.Used {
  343. if recursive && b.Name == rec_name {
  344. rec_used = true
  345. rec_outer_offset = i
  346. continue
  347. }
  348. var offset = base_context_size
  349. base_context_size += 1
  350. context_offset_map[i] = offset
  351. context_outer_offsets = append(context_outer_offsets, i)
  352. }
  353. }
  354. if recursive {
  355. base_context_size += 1
  356. if rec_used {
  357. context_offset_map[rec_outer_offset] = base_context_size
  358. }
  359. }
  360. if base_context_size >= common.ClosureMaxSize {
  361. panic("maximum closure size exceeded")
  362. }
  363. var raw_inner_code = inner_buf.Collect()
  364. var inst_seq_len = len(raw_inner_code.InstSeq)
  365. var final_inst_seq = make([] common.Instruction, inst_seq_len)
  366. for i, inst := range raw_inner_code.InstSeq {
  367. if inst.OpCode == common.LOAD {
  368. var offset = inst.GetOffset()
  369. var new_offset uint
  370. if offset < outer_bindings_size {
  371. new_offset = context_offset_map[offset]
  372. } else {
  373. new_offset = offset - outer_bindings_size + base_context_size
  374. }
  375. final_inst_seq[i] = common.Instruction {
  376. OpCode: common.LOAD,
  377. Arg0: 0,
  378. Arg1: common.Long(new_offset),
  379. }
  380. } else {
  381. final_inst_seq[i] = inst
  382. }
  383. }
  384. var final_inner_code = Code {
  385. InstSeq: final_inst_seq,
  386. SourceMap: raw_inner_code.SourceMap,
  387. }
  388. var f = &common.Function {
  389. IsNative: false,
  390. Code: final_inner_code.InstSeq,
  391. BaseSize: common.FrameBaseSize {
  392. Context: common.Short(base_context_size),
  393. Reserved: common.Long(base_reserved_size),
  394. },
  395. Info: common.FuncInfo {
  396. Name: loader.NewSymbol("", "(closure)"),
  397. DeclPoint: info.ErrorPoint,
  398. SourceMap: final_inner_code.SourceMap,
  399. },
  400. }
  401. var index = ctx.AppendClosureRef(f)
  402. var outer_buf = MakeCodeBuffer()
  403. outer_buf.Write(CodeFrom(InstGlobalRef(index), info))
  404. for _, outer_offset := range context_outer_offsets {
  405. var capture_inst = InstLocalRef(outer_offset)
  406. outer_buf.Write(CodeFrom(capture_inst, info))
  407. }
  408. var prod_inst = InstProduct(uint(len(context_outer_offsets)))
  409. outer_buf.Write(CodeFrom(prod_inst, info))
  410. var rec_flag common.Short
  411. if recursive {
  412. rec_flag = 1
  413. } else {
  414. rec_flag = 0
  415. }
  416. var ctx_inst = common.Instruction {
  417. OpCode: common.CTX,
  418. Arg0: rec_flag,
  419. Arg1: 0,
  420. }
  421. outer_buf.Write(CodeFrom(ctx_inst, info))
  422. return outer_buf.Collect()
  423. }
  424. // TODO: CompileFunction
  425. func BindPatternItems (
  426. items [] checker.PatternItem,
  427. scope *Scope,
  428. buf CodeBuffer,
  429. info checker.ExprInfo,
  430. ) {
  431. for _, item := range items {
  432. var inst_get = InstGet(item.Index)
  433. var offset = scope.AddBinding(item.Name)
  434. var inst_bind = InstAddBinding(offset)
  435. buf.Write(CodeFrom(inst_get, info))
  436. buf.Write(CodeFrom(inst_bind, info))
  437. }
  438. }
  439. func InstGlobalRef(index uint) common.Instruction {
  440. ValidateGlobalIndex(index)
  441. var a0, a1 = common.GlobalIndex(index)
  442. return common.Instruction {
  443. OpCode: common.GLOBAL,
  444. Arg0: a0,
  445. Arg1: a1,
  446. }
  447. }
  448. func InstLocalRef(offset uint) common.Instruction {
  449. ValidateLocalOffset(offset)
  450. return common.Instruction {
  451. OpCode: common.LOAD,
  452. Arg0: 0,
  453. Arg1: common.Long(offset),
  454. }
  455. }
  456. func InstAddBinding(offset uint) common.Instruction {
  457. ValidateLocalOffset(offset)
  458. return common.Instruction {
  459. OpCode: common.STORE,
  460. Arg0: 0,
  461. Arg1: common.Long(offset),
  462. }
  463. }
  464. func InstGet(index uint) common.Instruction {
  465. ValidateProductIndex(index)
  466. return common.Instruction {
  467. OpCode: common.GET,
  468. Arg0: common.Short(index),
  469. Arg1: 0,
  470. }
  471. }
  472. func InstSet(index uint) common.Instruction {
  473. ValidateProductIndex(index)
  474. return common.Instruction {
  475. OpCode: common.SET,
  476. Arg0: common.Short(index),
  477. Arg1: 0,
  478. }
  479. }
  480. func InstProduct(size uint) common.Instruction {
  481. ValidateProductSize(size)
  482. return common.Instruction {
  483. OpCode: common.PROD,
  484. Arg0: common.Short(size),
  485. Arg1: 0,
  486. }
  487. }
  488. func InstArray(size uint) common.Instruction {
  489. ValidateArraySize(size)
  490. var a0, a1 = common.ArraySize(size)
  491. return common.Instruction {
  492. OpCode: common.ARRAY,
  493. Arg0: a0,
  494. Arg1: a1,
  495. }
  496. }
  497. func ValidateGlobalIndex(index uint) {
  498. if index >= common.GlobalSlotMaxSize {
  499. panic("global value index exceeded maximum slot capacity")
  500. }
  501. }
  502. func ValidateLocalOffset(offset uint) {
  503. if offset >= common.LocalSlotMaxSize {
  504. panic("local binding offset exceeded maximum slot capacity")
  505. }
  506. }
  507. func ValidateDestAddr(addr uint) {
  508. if addr >= common.FunCodeMaxLength {
  509. panic("destination address exceeded limitation")
  510. }
  511. }
  512. func ValidateProductIndex(index uint) {
  513. if index >= common.ProductMaxSize {
  514. panic("value index exceeded maximum capacity of product type")
  515. }
  516. }
  517. func ValidateProductSize(size uint) {
  518. if size > common.ProductMaxSize {
  519. panic("given size exceeded maximum capacity of product type")
  520. }
  521. }
  522. func ValidateArraySize(size uint) {
  523. if size > common.ArrayMaxSize {
  524. panic("given size exceeded maximum capacity of array literal")
  525. }
  526. }