vm.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  1. package zygo
  2. import (
  3. "errors"
  4. "fmt"
  5. )
  6. type Instruction interface {
  7. InstrString() string
  8. Execute(env *Zlisp) error
  9. }
  10. type JumpInstr struct {
  11. addpc int
  12. where string
  13. }
  14. var OutOfBounds error = errors.New("jump out of bounds")
  15. func (j JumpInstr) InstrString() string {
  16. return fmt.Sprintf("jump %d %s", j.addpc, j.where)
  17. }
  18. func (j JumpInstr) Execute(env *Zlisp) error {
  19. newpc := env.pc + j.addpc
  20. if newpc < 0 || newpc > env.CurrentFunctionSize() {
  21. return OutOfBounds
  22. }
  23. env.pc = newpc
  24. return nil
  25. }
  26. type GotoInstr struct {
  27. location int
  28. }
  29. func (g GotoInstr) InstrString() string {
  30. return fmt.Sprintf("goto %d", g.location)
  31. }
  32. func (g GotoInstr) Execute(env *Zlisp) error {
  33. if g.location < 0 || g.location > env.CurrentFunctionSize() {
  34. return OutOfBounds
  35. }
  36. env.pc = g.location
  37. return nil
  38. }
  39. type BranchInstr struct {
  40. direction bool
  41. location int
  42. }
  43. func (b BranchInstr) InstrString() string {
  44. var format string
  45. if b.direction {
  46. format = "br %d"
  47. } else {
  48. format = "brn %d"
  49. }
  50. return fmt.Sprintf(format, b.location)
  51. }
  52. func (b BranchInstr) Execute(env *Zlisp) error {
  53. expr, err := env.datastack.PopExpr()
  54. if err != nil {
  55. return err
  56. }
  57. if b.direction == IsTruthy(expr) {
  58. return JumpInstr{addpc: b.location}.Execute(env)
  59. }
  60. env.pc++
  61. return nil
  62. }
  63. type PushInstr struct {
  64. expr Sexp
  65. }
  66. func (p PushInstr) InstrString() string {
  67. return "push " + p.expr.SexpString(nil)
  68. }
  69. func (p PushInstr) Execute(env *Zlisp) error {
  70. env.datastack.PushExpr(p.expr)
  71. env.pc++
  72. return nil
  73. }
  74. type PopInstr int
  75. func (p PopInstr) InstrString() string {
  76. return "pop"
  77. }
  78. func (p PopInstr) Execute(env *Zlisp) error {
  79. _, err := env.datastack.PopExpr()
  80. env.pc++
  81. return err
  82. }
  83. type DupInstr int
  84. func (d DupInstr) InstrString() string {
  85. return "dup"
  86. }
  87. func (d DupInstr) Execute(env *Zlisp) error {
  88. expr, err := env.datastack.GetExpr(0)
  89. if err != nil {
  90. return err
  91. }
  92. env.datastack.PushExpr(expr)
  93. env.pc++
  94. return nil
  95. }
  96. type EnvToStackInstr struct {
  97. sym *SexpSymbol
  98. }
  99. func (g EnvToStackInstr) InstrString() string {
  100. return fmt.Sprintf("envToStack %s", g.sym.name)
  101. }
  102. func (g EnvToStackInstr) Execute(env *Zlisp) error {
  103. //VPrintf("in EnvToStackInstr\n")
  104. //defer VPrintf("leaving EnvToStackInstr env.pc =%v\n", env.pc)
  105. macxpr, isMacro := env.macros[g.sym.number]
  106. if isMacro {
  107. if macxpr.orig != nil {
  108. return fmt.Errorf("'%s' is a macro, with definition: %s\n", g.sym.name, macxpr.orig.SexpString(nil))
  109. }
  110. return fmt.Errorf("'%s' is a builtin macro.\n", g.sym.name)
  111. }
  112. var expr Sexp
  113. var err error
  114. expr, err, _ = env.LexicalLookupSymbol(g.sym, nil)
  115. if err != nil {
  116. return err
  117. }
  118. env.datastack.PushExpr(expr)
  119. env.pc++
  120. return nil
  121. }
  122. type PopStackPutEnvInstr struct {
  123. sym *SexpSymbol
  124. }
  125. func (p PopStackPutEnvInstr) InstrString() string {
  126. return fmt.Sprintf("popStackPutEnv %s", p.sym.name)
  127. }
  128. func (p PopStackPutEnvInstr) Execute(env *Zlisp) error {
  129. expr, err := env.datastack.PopExpr()
  130. if err != nil {
  131. return err
  132. }
  133. env.pc++
  134. return env.LexicalBindSymbol(p.sym, expr)
  135. }
  136. // Update takes top of datastack and
  137. // assigns it to sym when sym is found
  138. // already in the current scope or
  139. // up the stack. Used
  140. // to implement (set v 10) when v is
  141. // not in the local scope.
  142. //
  143. type UpdateInstr struct {
  144. sym *SexpSymbol
  145. }
  146. func (p UpdateInstr) InstrString() string {
  147. return fmt.Sprintf("putup %s", p.sym.name)
  148. }
  149. func (p UpdateInstr) Execute(env *Zlisp) error {
  150. expr, err := env.datastack.PopExpr()
  151. if err != nil {
  152. return err
  153. }
  154. env.pc++
  155. if p.sym.isSigil {
  156. Q("UpdateInstr: ignoring sigil symbol '%s'", p.sym.SexpString(nil))
  157. return nil
  158. }
  159. if p.sym.isDot {
  160. Q("UpdateInstr: dot symbol '%s' being updated with dotGetSetHelper()",
  161. p.sym.SexpString(nil))
  162. _, err := dotGetSetHelper(env, p.sym.name, &expr)
  163. return err
  164. }
  165. // if found up the stack, we will (set) expr
  166. _, err, _ = env.LexicalLookupSymbol(p.sym, &expr)
  167. if err != nil {
  168. // not found up the stack, so treat like (def)
  169. // instead of (set)
  170. return env.LexicalBindSymbol(p.sym, expr)
  171. }
  172. //return scope.UpdateSymbolInScope(p.sym, expr) // LexicalLookupSymbol now takes a setVal pointer which does this automatically
  173. return err
  174. }
  175. type CallInstr struct {
  176. sym *SexpSymbol
  177. nargs int
  178. }
  179. func (c CallInstr) InstrString() string {
  180. return fmt.Sprintf("call %s %d", c.sym.name, c.nargs)
  181. }
  182. func (c CallInstr) Execute(env *Zlisp) error {
  183. f, ok := env.builtins[c.sym.number]
  184. if ok {
  185. _, err := env.CallUserFunction(f, c.sym.name, c.nargs)
  186. return err
  187. }
  188. var funcobj, indirectFuncName Sexp
  189. var err error
  190. funcobj, err, _ = env.LexicalLookupSymbol(c.sym, nil)
  191. if err != nil {
  192. return err
  193. }
  194. //P("\n in CallInstr, after looking up c.sym='%s', got funcobj='%v'. datastack is:\n", c.sym.name, funcobj.SexpString(nil))
  195. //env.datastack.PrintStack()
  196. switch f := funcobj.(type) {
  197. case *SexpSymbol:
  198. // is it a dot-symbol call?
  199. //P("\n in CallInstr, found symbol\n")
  200. if c.sym.isDot {
  201. //P("\n in CallInstr, found symbol, c.sym.isDot is true\n")
  202. dotSymRef, dotLookupErr := dotGetSetHelper(env, c.sym.name, nil)
  203. // cannot error out yet, we might be assigning to a new field,
  204. // not already set.
  205. if dotLookupErr != nil {
  206. return dotLookupErr
  207. }
  208. // are we a value request (no further args), or a fuction/method call?
  209. //P("\n in CallInstr, found dot-symbol\n")
  210. // now always be a function call here, allowing zero-argument calls.
  211. indirectFuncName = dotSymRef
  212. } else {
  213. // not isDot
  214. // allow symbols to refer to dot-symbols, that then we call
  215. indirectFuncName, err = dotGetSetHelper(env, f.name, nil)
  216. if err != nil {
  217. return fmt.Errorf("'%s' refers to symbol '%s', but '%s' could not be resolved: '%s'.",
  218. c.sym.name, f.name, f.name, err)
  219. }
  220. // allow symbols to refer to functions that we then call
  221. /*
  222. indirectFuncName, err, _ = env.LexicalLookupSymbol(f, nil)
  223. if err != nil {
  224. return fmt.Errorf("'%s' refers to symbol '%s', but '%s' could not be resolved: '%s'.",
  225. c.sym.name, f.name, f.name, err)
  226. }
  227. */
  228. //P("\n in CallInstr, found symbol, c.sym.isDot is false. f of type %T/val = %v. indirectFuncName = '%v'\n", f, f.SexpString(nil), indirectFuncName.SexpString(nil))
  229. }
  230. //P("in CallInstr, reached switch on indirectFuncName.(type)")
  231. switch g := indirectFuncName.(type) {
  232. case *SexpFunction:
  233. if !g.user {
  234. return env.CallFunction(g, c.nargs)
  235. }
  236. _, err := env.CallUserFunction(g, f.name, c.nargs)
  237. return err
  238. default:
  239. if err != nil {
  240. return fmt.Errorf("symbol '%s' refers to '%s' which does not refer to a function.", c.sym.name, f.name)
  241. }
  242. }
  243. case *SexpFunction:
  244. if !f.user {
  245. return env.CallFunction(f, c.nargs)
  246. }
  247. _, err := env.CallUserFunction(f, c.sym.name, c.nargs)
  248. return err
  249. case *RegisteredType:
  250. if f.Constructor == nil {
  251. env.pc++
  252. res, err := baseConstruct(env, f, c.nargs)
  253. if err != nil {
  254. return err
  255. }
  256. env.datastack.PushExpr(res)
  257. return nil
  258. }
  259. //P("call instruction for RegisteredType!")
  260. _, err := env.CallUserFunction(f.Constructor, c.sym.name, c.nargs)
  261. return err
  262. }
  263. return fmt.Errorf("%s is not a function", c.sym.name)
  264. }
  265. type DispatchInstr struct {
  266. nargs int
  267. }
  268. func (d DispatchInstr) InstrString() string {
  269. return fmt.Sprintf("dispatch %d", d.nargs)
  270. }
  271. func (d DispatchInstr) Execute(env *Zlisp) error {
  272. funcobj, err := env.datastack.PopExpr()
  273. if err != nil {
  274. return err
  275. }
  276. switch f := funcobj.(type) {
  277. case *SexpFunction:
  278. if !f.user {
  279. return env.CallFunction(f, d.nargs)
  280. }
  281. _, err := env.CallUserFunction(f, f.name, d.nargs)
  282. return err
  283. }
  284. // allow ([] int64) to express slice of int64.
  285. switch arr := funcobj.(type) {
  286. case *SexpArray:
  287. if len(arr.Val) == 0 {
  288. _, err := env.CallUserFunction(sxSliceOf, funcobj.SexpString(nil), d.nargs)
  289. return err
  290. }
  291. // call along with the array as an argument so we know the size of the
  292. // array / matrix / tensor to make. The 2nd argument will be the dimension array.
  293. env.datastack.PushExpr(arr)
  294. _, err := env.CallUserFunction(sxArrayOf, funcobj.SexpString(nil), d.nargs+1)
  295. return err
  296. }
  297. return fmt.Errorf("unbalanced parenthesis in the input? : not a function on top of datastack: '%T/%#v'", funcobj, funcobj)
  298. }
  299. type ReturnInstr struct {
  300. err error
  301. }
  302. func (r ReturnInstr) Execute(env *Zlisp) error {
  303. if r.err != nil {
  304. return r.err
  305. }
  306. return env.ReturnFromFunction()
  307. }
  308. func (r ReturnInstr) InstrString() string {
  309. if r.err == nil {
  310. return "ret"
  311. }
  312. return "ret \"" + r.err.Error() + "\""
  313. }
  314. type AddScopeInstr struct {
  315. Name string
  316. }
  317. func (a AddScopeInstr) InstrString() string {
  318. return "add scope " + a.Name
  319. }
  320. func (a AddScopeInstr) Execute(env *Zlisp) error {
  321. sc := env.NewNamedScope(fmt.Sprintf("scope Name: '%s'",
  322. a.Name))
  323. env.linearstack.Push(sc)
  324. env.pc++
  325. return nil
  326. }
  327. type AddFuncScopeInstr struct {
  328. Name string
  329. Helper *AddFuncScopeHelper // we need a pointer we can update later once we know MyFunction
  330. }
  331. type AddFuncScopeHelper struct {
  332. MyFunction *SexpFunction
  333. }
  334. func (a AddFuncScopeInstr) InstrString() string {
  335. return "add func scope " + a.Name
  336. }
  337. func (a AddFuncScopeInstr) Execute(env *Zlisp) error {
  338. sc := env.NewNamedScope(fmt.Sprintf("%s at pc=%v",
  339. env.curfunc.name, env.pc))
  340. sc.IsFunction = true
  341. sc.MyFunction = a.Helper.MyFunction
  342. env.linearstack.Push(sc)
  343. env.pc++
  344. return nil
  345. }
  346. type RemoveScopeInstr struct{}
  347. func (a RemoveScopeInstr) InstrString() string {
  348. return "rem runtime scope"
  349. }
  350. func (a RemoveScopeInstr) Execute(env *Zlisp) error {
  351. env.pc++
  352. return env.linearstack.PopScope()
  353. }
  354. type ExplodeInstr int
  355. func (e ExplodeInstr) InstrString() string {
  356. return "explode"
  357. }
  358. func (e ExplodeInstr) Execute(env *Zlisp) error {
  359. expr, err := env.datastack.PopExpr()
  360. if err != nil {
  361. return err
  362. }
  363. arr, err := ListToArray(expr)
  364. if err != nil {
  365. return err
  366. }
  367. for _, val := range arr {
  368. env.datastack.PushExpr(val)
  369. }
  370. env.pc++
  371. return nil
  372. }
  373. type SquashInstr int
  374. func (s SquashInstr) InstrString() string {
  375. return "squash"
  376. }
  377. func (s SquashInstr) Execute(env *Zlisp) error {
  378. var list Sexp = SexpNull
  379. for {
  380. expr, err := env.datastack.PopExpr()
  381. if err != nil {
  382. return err
  383. }
  384. if expr == SexpMarker {
  385. break
  386. }
  387. list = Cons(expr, list)
  388. }
  389. env.datastack.PushExpr(list)
  390. env.pc++
  391. return nil
  392. }
  393. // bind these symbols to the SexpPair list found at
  394. // datastack top.
  395. type BindlistInstr struct {
  396. syms []*SexpSymbol
  397. }
  398. func (b BindlistInstr) InstrString() string {
  399. joined := ""
  400. for _, s := range b.syms {
  401. joined += s.name + " "
  402. }
  403. return fmt.Sprintf("bindlist %s", joined)
  404. }
  405. func (b BindlistInstr) Execute(env *Zlisp) error {
  406. expr, err := env.datastack.PopExpr()
  407. if err != nil {
  408. return err
  409. }
  410. arr, err := ListToArray(expr)
  411. if err != nil {
  412. return err
  413. }
  414. nsym := len(b.syms)
  415. narr := len(arr)
  416. if narr < nsym {
  417. return fmt.Errorf("bindlist failing: %d targets but only %d sources", nsym, narr)
  418. }
  419. for i, bindThisSym := range b.syms {
  420. env.LexicalBindSymbol(bindThisSym, arr[i])
  421. }
  422. env.pc++
  423. return nil
  424. }
  425. type VectorizeInstr int
  426. func (s VectorizeInstr) InstrString() string {
  427. return fmt.Sprintf("vectorize %v", int(s))
  428. }
  429. func (s VectorizeInstr) Execute(env *Zlisp) error {
  430. vec := make([]Sexp, 0)
  431. env.pc++
  432. for {
  433. expr, err := env.datastack.PopExpr()
  434. if err != nil {
  435. return err
  436. }
  437. if expr == SexpMarker {
  438. break
  439. }
  440. vec = append([]Sexp{expr}, vec...)
  441. }
  442. env.datastack.PushExpr(&SexpArray{Val: vec, Env: env})
  443. return nil
  444. }
  445. type HashizeInstr struct {
  446. HashLen int
  447. TypeName string
  448. }
  449. func (s HashizeInstr) InstrString() string {
  450. return "hashize"
  451. }
  452. func (s HashizeInstr) Execute(env *Zlisp) error {
  453. a := make([]Sexp, 0)
  454. for {
  455. expr, err := env.datastack.PopExpr()
  456. if err != nil {
  457. return err
  458. }
  459. if expr == SexpMarker {
  460. break
  461. }
  462. a = append(a, expr)
  463. }
  464. hash, err := MakeHash(a, s.TypeName, env)
  465. if err != nil {
  466. return err
  467. }
  468. env.datastack.PushExpr(hash)
  469. env.pc++
  470. return nil
  471. }
  472. type LabelInstr struct {
  473. label string
  474. }
  475. func (s LabelInstr) InstrString() string {
  476. return fmt.Sprintf("label %s", s.label)
  477. }
  478. func (s LabelInstr) Execute(env *Zlisp) error {
  479. env.pc++
  480. return nil
  481. }
  482. type BreakInstr struct {
  483. loop *Loop
  484. pos int
  485. }
  486. func (s BreakInstr) InstrString() string {
  487. if s.pos == 0 {
  488. return fmt.Sprintf("break %s", s.loop.stmtname.name)
  489. }
  490. return fmt.Sprintf("break %s (loop is at %d)", s.loop.stmtname.name, s.pos)
  491. }
  492. func (s *BreakInstr) Execute(env *Zlisp) error {
  493. if s.pos == 0 {
  494. pos, err := env.FindLoop(s.loop)
  495. if err != nil {
  496. return err
  497. }
  498. s.pos = pos
  499. }
  500. env.pc = s.pos + s.loop.breakOffset
  501. return nil
  502. }
  503. type ContinueInstr struct {
  504. loop *Loop
  505. pos int
  506. }
  507. func (s ContinueInstr) InstrString() string {
  508. if s.pos == 0 {
  509. return fmt.Sprintf("continue %s", s.loop.stmtname.name)
  510. }
  511. return fmt.Sprintf("continue %s (loop is at pos %d)", s.loop.stmtname.name, s.pos)
  512. }
  513. func (s *ContinueInstr) Execute(env *Zlisp) error {
  514. //VPrintf("\n executing ContinueInstr with loop: '%#v'\n", s.loop)
  515. if s.pos == 0 {
  516. pos, err := env.FindLoop(s.loop)
  517. if err != nil {
  518. return err
  519. }
  520. s.pos = pos
  521. }
  522. env.pc = s.pos + s.loop.continueOffset
  523. //VPrintf("\n more detail ContinueInstr pos=%d, setting pc = %d\n", s.pos, env.pc)
  524. return nil
  525. }
  526. type LoopStartInstr struct {
  527. loop *Loop
  528. }
  529. func (s LoopStartInstr) InstrString() string {
  530. return fmt.Sprintf("loopstart %s", s.loop.stmtname.name)
  531. }
  532. func (s LoopStartInstr) Execute(env *Zlisp) error {
  533. env.pc++
  534. return nil
  535. }
  536. // stack cleanup discipline instructions let us
  537. // ensure the stack gets reset to a previous
  538. // known good level. The sym designates
  539. // how far down to clean up, in a unique and
  540. // distinguishable gensym-ed manner.
  541. // create a stack mark
  542. type PushStackmarkInstr struct {
  543. sym *SexpSymbol
  544. }
  545. func (s PushStackmarkInstr) InstrString() string {
  546. return fmt.Sprintf("push-stack-mark %s", s.sym.name)
  547. }
  548. func (s PushStackmarkInstr) Execute(env *Zlisp) error {
  549. env.datastack.PushExpr(&SexpStackmark{sym: s.sym})
  550. env.pc++
  551. return nil
  552. }
  553. // cleanup until our stackmark, but leave it in place
  554. type PopUntilStackmarkInstr struct {
  555. sym *SexpSymbol
  556. }
  557. func (s PopUntilStackmarkInstr) InstrString() string {
  558. return fmt.Sprintf("pop-until-stack-mark %s", s.sym.name)
  559. }
  560. func (s PopUntilStackmarkInstr) Execute(env *Zlisp) error {
  561. env.pc++
  562. toploop:
  563. for {
  564. expr, err := env.datastack.PopExpr()
  565. if err != nil {
  566. P("alert: did not find SexpStackmark '%s'", s.sym.name)
  567. return err
  568. }
  569. switch m := expr.(type) {
  570. case *SexpStackmark:
  571. if m.sym.number == s.sym.number {
  572. env.datastack.PushExpr(m)
  573. break toploop
  574. }
  575. }
  576. }
  577. return nil
  578. }
  579. // erase everything up-to-and-including our mark
  580. type ClearStackmarkInstr struct {
  581. sym *SexpSymbol
  582. }
  583. func (s ClearStackmarkInstr) InstrString() string {
  584. return fmt.Sprintf("clear-stack-mark %s", s.sym.name)
  585. }
  586. func (s ClearStackmarkInstr) Execute(env *Zlisp) error {
  587. toploop:
  588. for {
  589. expr, err := env.datastack.PopExpr()
  590. if err != nil {
  591. return err
  592. }
  593. switch m := expr.(type) {
  594. case *SexpStackmark:
  595. if m.sym.number == s.sym.number {
  596. break toploop
  597. }
  598. }
  599. }
  600. env.pc++
  601. return nil
  602. }
  603. type DebugInstr struct {
  604. diagnostic string
  605. }
  606. func (g DebugInstr) InstrString() string {
  607. return fmt.Sprintf("debug %s", g.diagnostic)
  608. }
  609. func (g DebugInstr) Execute(env *Zlisp) error {
  610. switch g.diagnostic {
  611. case "showScopes":
  612. err := env.ShowStackStackAndScopeStack()
  613. if err != nil {
  614. return err
  615. }
  616. default:
  617. panic(fmt.Errorf("unknown diagnostic %v", g.diagnostic))
  618. }
  619. env.pc++
  620. return nil
  621. }
  622. // when a defn or fn executes, capture the creation env.
  623. type CreateClosureInstr struct {
  624. sfun *SexpFunction
  625. }
  626. func (a CreateClosureInstr) InstrString() string {
  627. return "create closure " + a.sfun.SexpString(nil)
  628. }
  629. func (a CreateClosureInstr) Execute(env *Zlisp) error {
  630. env.pc++
  631. cls := NewClosing(a.sfun.name, env)
  632. myInvok := a.sfun.Copy()
  633. myInvok.SetClosing(cls)
  634. if env.curfunc != nil {
  635. a.sfun.parent = env.curfunc
  636. myInvok.parent = env.curfunc
  637. //P("myInvok is copy of a.sfun '%s' with parent = %s", a.sfun.name, myInvok.parent.name)
  638. }
  639. ps8 := NewPrintStateWithIndent(8)
  640. shown, err := myInvok.ShowClosing(env, ps8, fmt.Sprintf("closedOverScopes of '%s'", myInvok.name))
  641. _ = shown
  642. if err != nil {
  643. return err
  644. }
  645. //VPrintf("+++ CreateClosure: assign to '%s' the stack:\n\n%s\n\n", myInvok.SexpString(nil), shown)
  646. top := cls.TopScope()
  647. //VPrintf("222 CreateClosure: top of NewClosing Scope has addr %p and is\n", top)
  648. top.Show(env, ps8, fmt.Sprintf("top of NewClosing at %p", top))
  649. env.datastack.PushExpr(myInvok)
  650. return nil
  651. }
  652. type AssignInstr struct {
  653. }
  654. func (a AssignInstr) InstrString() string {
  655. return "assign stack top to stack top -1"
  656. }
  657. func (a AssignInstr) Execute(env *Zlisp) error {
  658. env.pc++
  659. rhs, err := env.datastack.PopExpr()
  660. if err != nil {
  661. return err
  662. }
  663. lhs, err := env.datastack.PopExpr()
  664. if err != nil {
  665. return err
  666. }
  667. switch x := lhs.(type) {
  668. case *SexpSymbol:
  669. return env.LexicalBindSymbol(x, rhs)
  670. case Selector:
  671. Q("AssignInstr: I see lhs is Selector")
  672. err := x.AssignToSelection(env, rhs)
  673. return err
  674. case *SexpArray:
  675. switch rhsArray := rhs.(type) {
  676. case *SexpArray:
  677. //Q("AssignInstr: lhs is SexpArray '%v', *and* rhs is SexpArray ='%v'",
  678. // x.SexpString(nil), rhsArray.SexpString(nil))
  679. nRhs := len(rhsArray.Val)
  680. nLhs := len(x.Val)
  681. if nRhs != nLhs {
  682. return fmt.Errorf("assignment count mismatch %v != %v", nLhs, nRhs)
  683. }
  684. for i := range x.Val {
  685. switch sym := x.Val[i].(type) {
  686. case *SexpSymbol:
  687. err = env.LexicalBindSymbol(sym, rhsArray.Val[i])
  688. if err != nil {
  689. return err
  690. }
  691. default:
  692. return fmt.Errorf("assignment error: left-hand-side element %v needs to be a symbol but"+
  693. " we found %T", i, x.Val[i])
  694. }
  695. }
  696. return nil
  697. default:
  698. return fmt.Errorf("AssignInstr: don't know how to assign rhs %T `%v` to lhs %T `%v`",
  699. rhs, rhs.SexpString(nil), lhs, lhs.SexpString(nil))
  700. }
  701. }
  702. return fmt.Errorf("AssignInstr: don't know how to assign to lhs %T", lhs)
  703. }
  704. // PopScopeTransferToDataStackInstr is used to wrap up a package
  705. // and put it on the data stack as a value.
  706. type PopScopeTransferToDataStackInstr struct {
  707. PackageName string
  708. }
  709. func (a PopScopeTransferToDataStackInstr) InstrString() string {
  710. return "pop scope transfer to data stack as package " + a.PackageName
  711. }
  712. func (a PopScopeTransferToDataStackInstr) Execute(env *Zlisp) error {
  713. env.pc++
  714. stackClone := env.linearstack.Clone()
  715. stackClone.IsPackage = true // always/only used for packages.
  716. stackClone.PackageName = a.PackageName
  717. //P("PopScopeTransferToDataStackInstr: scope is '%v'", stackClone.SexpString(nil))
  718. env.linearstack.PopScope()
  719. env.datastack.PushExpr(stackClone)
  720. return nil
  721. }
  722. type PrepareCallInstr struct {
  723. sym *SexpSymbol
  724. nargs int
  725. }
  726. func (c PrepareCallInstr) InstrString() string {
  727. return fmt.Sprintf("pre-call %s %d", c.sym.name, c.nargs)
  728. }
  729. func (c PrepareCallInstr) Execute(env *Zlisp) error {
  730. if err := c.execute(env); err != nil {
  731. return err
  732. }
  733. env.pc++
  734. return nil
  735. }
  736. func (c PrepareCallInstr) execute(env *Zlisp) error {
  737. _, ok := env.builtins[c.sym.number]
  738. if ok {
  739. return nil
  740. }
  741. var funcobj, indirectFuncName Sexp
  742. var err error
  743. funcobj, err, _ = env.LexicalLookupSymbol(c.sym, nil)
  744. if err != nil {
  745. return err
  746. }
  747. switch f := funcobj.(type) {
  748. case *SexpSymbol:
  749. if c.sym.isDot {
  750. dotSymRef, dotLookupErr := dotGetSetHelper(env, c.sym.name, nil)
  751. if dotLookupErr != nil {
  752. return dotLookupErr
  753. }
  754. indirectFuncName = dotSymRef
  755. } else {
  756. indirectFuncName, err = dotGetSetHelper(env, f.name, nil)
  757. if err != nil {
  758. return fmt.Errorf("'%s' refers to symbol '%s', but '%s' could not be resolved: '%s'.",
  759. c.sym.name, f.name, f.name, err)
  760. }
  761. }
  762. switch g := indirectFuncName.(type) {
  763. case *SexpFunction:
  764. if !g.user && g.varargs {
  765. return env.wrangleOptargs(g.nargs, c.nargs)
  766. }
  767. return nil
  768. }
  769. case *SexpFunction:
  770. if !f.user && f.varargs {
  771. return env.wrangleOptargs(f.nargs, c.nargs)
  772. }
  773. }
  774. return nil
  775. }