builtin_special.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. package eval
  2. // Builtin special forms. Special forms behave mostly like ordinary commands -
  3. // they are valid commands syntactically, and can take part in pipelines - but
  4. // they have special rules for the evaluation of their arguments and can affect
  5. // the compilation phase (whereas ordinary commands can only affect the
  6. // evaluation phase).
  7. //
  8. // For example, the "and" special form evaluates its arguments from left to
  9. // right, and stops as soon as one booleanly false value is obtained: the
  10. // command "and $false (fail haha)" does not produce an exception.
  11. //
  12. // As another example, the "del" special form removes a variable, affecting the
  13. // compiler.
  14. //
  15. // Flow control structures are also implemented as special forms in elvish, with
  16. // closures functioning as code blocks.
  17. import (
  18. "os"
  19. "path/filepath"
  20. "strings"
  21. "src.elv.sh/pkg/diag"
  22. "src.elv.sh/pkg/eval/vals"
  23. "src.elv.sh/pkg/eval/vars"
  24. "src.elv.sh/pkg/parse"
  25. "src.elv.sh/pkg/parse/cmpd"
  26. )
  27. type compileBuiltin func(*compiler, *parse.Form) effectOp
  28. var builtinSpecials map[string]compileBuiltin
  29. // IsBuiltinSpecial is the set of all names of builtin special forms. It is
  30. // intended for external consumption, e.g. the syntax highlighter.
  31. var IsBuiltinSpecial = map[string]bool{}
  32. // NoSuchModule encodes an error where a module spec cannot be resolved.
  33. type NoSuchModule struct{ spec string }
  34. // Error implements the error interface.
  35. func (err NoSuchModule) Error() string { return "no such module: " + err.spec }
  36. func init() {
  37. // Needed to avoid initialization loop
  38. builtinSpecials = map[string]compileBuiltin{
  39. "var": compileVar,
  40. "set": compileSet,
  41. "tmp": compileTmp,
  42. "del": compileDel,
  43. "fn": compileFn,
  44. "use": compileUse,
  45. "and": compileAnd,
  46. "or": compileOr,
  47. "coalesce": compileCoalesce,
  48. "if": compileIf,
  49. "while": compileWhile,
  50. "for": compileFor,
  51. "try": compileTry,
  52. "pragma": compilePragma,
  53. }
  54. for name := range builtinSpecials {
  55. IsBuiltinSpecial[name] = true
  56. }
  57. }
  58. // VarForm = 'var' { VariablePrimary } [ '=' { Compound } ]
  59. func compileVar(cp *compiler, fn *parse.Form) effectOp {
  60. lhsArgs, rhs := compileLHSRHS(cp, fn)
  61. lhs := cp.parseCompoundLValues(lhsArgs, newLValue)
  62. if rhs == nil {
  63. // Just create new variables, nothing extra to do at runtime.
  64. return nopOp{}
  65. }
  66. return &assignOp{fn.Range(), lhs, rhs, false}
  67. }
  68. // SetForm = 'set' { LHS } '=' { Compound }
  69. func compileSet(cp *compiler, fn *parse.Form) effectOp {
  70. lhs, rhs := compileSetArgs(cp, fn)
  71. return &assignOp{fn.Range(), lhs, rhs, false}
  72. }
  73. // TmpForm = 'tmp' { LHS } '=' { Compound }
  74. func compileTmp(cp *compiler, fn *parse.Form) effectOp {
  75. if len(cp.scopes) <= 1 {
  76. cp.errorpf(fn, "tmp may only be used inside a function")
  77. }
  78. lhs, rhs := compileSetArgs(cp, fn)
  79. return &assignOp{fn.Range(), lhs, rhs, true}
  80. }
  81. func compileSetArgs(cp *compiler, fn *parse.Form) (lvaluesGroup, valuesOp) {
  82. lhsArgs, rhs := compileLHSRHS(cp, fn)
  83. if rhs == nil {
  84. cp.errorpf(diag.PointRanging(fn.Range().To), "need = and right-hand-side")
  85. }
  86. lhs := cp.parseCompoundLValues(lhsArgs, setLValue)
  87. return lhs, rhs
  88. }
  89. func compileLHSRHS(cp *compiler, fn *parse.Form) ([]*parse.Compound, valuesOp) {
  90. for i, cn := range fn.Args {
  91. if parse.SourceText(cn) == "=" {
  92. lhs := fn.Args[:i]
  93. if i == len(fn.Args)-1 {
  94. return lhs, nopValuesOp{diag.PointRanging(fn.Range().To)}
  95. }
  96. return lhs, seqValuesOp{
  97. diag.MixedRanging(fn.Args[i+1], fn.Args[len(fn.Args)-1]),
  98. cp.compoundOps(fn.Args[i+1:])}
  99. }
  100. }
  101. return fn.Args, nil
  102. }
  103. const delArgMsg = "arguments to del must be variable or variable elements"
  104. // DelForm = 'del' { LHS }
  105. func compileDel(cp *compiler, fn *parse.Form) effectOp {
  106. var ops []effectOp
  107. for _, cn := range fn.Args {
  108. if len(cn.Indexings) != 1 {
  109. cp.errorpf(cn, delArgMsg)
  110. continue
  111. }
  112. head, indices := cn.Indexings[0].Head, cn.Indexings[0].Indices
  113. if head.Type == parse.Variable {
  114. cp.errorpf(cn, "arguments to del must drop $")
  115. } else if !parse.ValidLHSVariable(head, false) {
  116. cp.errorpf(cn, delArgMsg)
  117. }
  118. qname := head.Value
  119. var f effectOp
  120. ref := resolveVarRef(cp, qname, nil)
  121. if ref == nil {
  122. cp.errorpf(cn, "no variable $%s", head.Value)
  123. continue
  124. }
  125. if len(indices) == 0 {
  126. if ref.scope == envScope {
  127. f = delEnvVarOp{fn.Range(), ref.subNames[0]}
  128. } else if ref.scope == localScope && len(ref.subNames) == 0 {
  129. f = delLocalVarOp{ref.index}
  130. cp.thisScope().infos[ref.index].deleted = true
  131. } else {
  132. cp.errorpf(cn, "only variables in the local scope or E: can be deleted")
  133. continue
  134. }
  135. } else {
  136. f = newDelElementOp(ref, head.Range().From, head.Range().To, cp.arrayOps(indices))
  137. }
  138. ops = append(ops, f)
  139. }
  140. return seqOp{ops}
  141. }
  142. type delLocalVarOp struct{ index int }
  143. func (op delLocalVarOp) exec(fm *Frame) Exception {
  144. fm.local.slots[op.index] = nil
  145. return nil
  146. }
  147. type delEnvVarOp struct {
  148. diag.Ranging
  149. name string
  150. }
  151. func (op delEnvVarOp) exec(fm *Frame) Exception {
  152. return fm.errorp(op, os.Unsetenv(op.name))
  153. }
  154. func newDelElementOp(ref *varRef, begin, headEnd int, indexOps []valuesOp) effectOp {
  155. ends := make([]int, len(indexOps)+1)
  156. ends[0] = headEnd
  157. for i, op := range indexOps {
  158. ends[i+1] = op.Range().To
  159. }
  160. return &delElemOp{ref, indexOps, begin, ends}
  161. }
  162. type delElemOp struct {
  163. ref *varRef
  164. indexOps []valuesOp
  165. begin int
  166. ends []int
  167. }
  168. func (op *delElemOp) Range() diag.Ranging {
  169. return diag.Ranging{From: op.begin, To: op.ends[0]}
  170. }
  171. func (op *delElemOp) exec(fm *Frame) Exception {
  172. var indices []any
  173. for _, indexOp := range op.indexOps {
  174. indexValues, exc := indexOp.exec(fm)
  175. if exc != nil {
  176. return exc
  177. }
  178. if len(indexValues) != 1 {
  179. return fm.errorpf(indexOp, "index must evaluate to a single value in argument to del")
  180. }
  181. indices = append(indices, indexValues[0])
  182. }
  183. err := vars.DelElement(deref(fm, op.ref), indices)
  184. if err != nil {
  185. if level := vars.ElementErrorLevel(err); level >= 0 {
  186. return fm.errorp(diag.Ranging{From: op.begin, To: op.ends[level]}, err)
  187. }
  188. return fm.errorp(op, err)
  189. }
  190. return nil
  191. }
  192. // FnForm = 'fn' StringPrimary LambdaPrimary
  193. //
  194. // fn f { foobar } is a shorthand for set '&'f = { foobar }.
  195. func compileFn(cp *compiler, fn *parse.Form) effectOp {
  196. args := cp.walkArgs(fn)
  197. nameNode := args.next()
  198. name := stringLiteralOrError(cp, nameNode, "function name")
  199. bodyNode := args.nextMustLambda("function body")
  200. args.mustEnd()
  201. // Define the variable before compiling the body, so that the body may refer
  202. // to the function itself.
  203. index := cp.thisScope().add(name + FnSuffix)
  204. op := cp.lambda(bodyNode)
  205. return fnOp{nameNode.Range(), index, op}
  206. }
  207. type fnOp struct {
  208. keywordRange diag.Ranging
  209. varIndex int
  210. lambdaOp valuesOp
  211. }
  212. func (op fnOp) exec(fm *Frame) Exception {
  213. // Initialize the function variable with the builtin nop function. This step
  214. // allows the definition of recursive functions; the actual function will
  215. // never be called.
  216. fm.local.slots[op.varIndex].Set(NewGoFn("<shouldn't be called>", nop))
  217. values, exc := op.lambdaOp.exec(fm)
  218. if exc != nil {
  219. return exc
  220. }
  221. c := values[0].(*Closure)
  222. c.op = fnWrap{c.op}
  223. return fm.errorp(op.keywordRange, fm.local.slots[op.varIndex].Set(c))
  224. }
  225. type fnWrap struct{ effectOp }
  226. func (op fnWrap) Range() diag.Ranging { return op.effectOp.(diag.Ranger).Range() }
  227. func (op fnWrap) exec(fm *Frame) Exception {
  228. exc := op.effectOp.exec(fm)
  229. if exc != nil && exc.Reason() != Return {
  230. // rethrow
  231. return exc
  232. }
  233. return nil
  234. }
  235. // UseForm = 'use' StringPrimary
  236. func compileUse(cp *compiler, fn *parse.Form) effectOp {
  237. var name, spec string
  238. switch len(fn.Args) {
  239. case 0:
  240. end := fn.Head.Range().To
  241. cp.errorpf(diag.PointRanging(end), "lack module name")
  242. case 1:
  243. spec = stringLiteralOrError(cp, fn.Args[0], "module spec")
  244. // Use the last path component as the name; for instance, if path =
  245. // "a/b/c/d", name is "d". If path doesn't have slashes, name = path.
  246. name = spec[strings.LastIndexByte(spec, '/')+1:]
  247. case 2:
  248. // TODO(xiaq): Allow using variable as module path
  249. spec = stringLiteralOrError(cp, fn.Args[0], "module spec")
  250. name = stringLiteralOrError(cp, fn.Args[1], "module name")
  251. default: // > 2
  252. cp.errorpf(diag.MixedRanging(fn.Args[2], fn.Args[len(fn.Args)-1]),
  253. "superfluous argument(s)")
  254. }
  255. return useOp{fn.Range(), cp.thisScope().add(name + NsSuffix), spec}
  256. }
  257. type useOp struct {
  258. diag.Ranging
  259. varIndex int
  260. spec string
  261. }
  262. func (op useOp) exec(fm *Frame) Exception {
  263. ns, err := use(fm, op.spec, op)
  264. if err != nil {
  265. return fm.errorp(op, err)
  266. }
  267. fm.local.slots[op.varIndex].Set(ns)
  268. return nil
  269. }
  270. // TODO: Add support for module specs relative to a package/workspace.
  271. // See https://github.com/elves/elvish/issues/1421.
  272. func use(fm *Frame, spec string, r diag.Ranger) (*Ns, error) {
  273. // Handle relative imports. Note that this deliberately does not support Windows backslash as a
  274. // path separator because module specs are meant to be platform independent. If necessary, we
  275. // translate a module spec to an appropriate path for the platform.
  276. if strings.HasPrefix(spec, "./") || strings.HasPrefix(spec, "../") {
  277. var dir string
  278. if fm.srcMeta.IsFile {
  279. dir = filepath.Dir(fm.srcMeta.Name)
  280. } else {
  281. var err error
  282. dir, err = os.Getwd()
  283. if err != nil {
  284. return nil, err
  285. }
  286. }
  287. path := filepath.Clean(dir + "/" + spec)
  288. return useFromFile(fm, spec, path, r)
  289. }
  290. // Handle imports of pre-defined modules like `builtin` and `str`.
  291. if ns, ok := fm.Evaler.modules[spec]; ok {
  292. return ns, nil
  293. }
  294. if code, ok := fm.Evaler.BundledModules[spec]; ok {
  295. return evalModule(fm, spec,
  296. parse.Source{Name: "[bundled " + spec + "]", Code: code}, r)
  297. }
  298. // Handle imports relative to the Elvish module search directories.
  299. //
  300. // TODO: For non-relative imports, use the spec (instead of the full path)
  301. // as the module key instead to avoid searching every time.
  302. for _, dir := range fm.Evaler.LibDirs {
  303. ns, err := useFromFile(fm, spec, filepath.Join(dir, spec), r)
  304. if _, isNoSuchModule := err.(NoSuchModule); isNoSuchModule {
  305. continue
  306. }
  307. return ns, err
  308. }
  309. // Sadly, we couldn't resolve the module spec.
  310. return nil, NoSuchModule{spec}
  311. }
  312. // TODO: Make access to fm.Evaler.modules concurrency-safe.
  313. func useFromFile(fm *Frame, spec, path string, r diag.Ranger) (*Ns, error) {
  314. if ns, ok := fm.Evaler.modules[path]; ok {
  315. return ns, nil
  316. }
  317. _, err := os.Stat(path + ".so")
  318. if err != nil {
  319. code, err := readFileUTF8(path + ".elv")
  320. if err != nil {
  321. if os.IsNotExist(err) {
  322. return nil, NoSuchModule{spec}
  323. }
  324. return nil, err
  325. }
  326. src := parse.Source{Name: path + ".elv", Code: code, IsFile: true}
  327. return evalModule(fm, path, src, r)
  328. }
  329. plug, err := pluginOpen(path + ".so")
  330. if err != nil {
  331. return nil, NoSuchModule{spec}
  332. }
  333. sym, err := plug.Lookup("Ns")
  334. if err != nil {
  335. return nil, err
  336. }
  337. ns, ok := sym.(**Ns)
  338. if !ok {
  339. return nil, NoSuchModule{spec}
  340. }
  341. fm.Evaler.modules[path] = *ns
  342. return *ns, nil
  343. }
  344. // TODO: Make access to fm.Evaler.modules concurrency-safe.
  345. func evalModule(fm *Frame, key string, src parse.Source, r diag.Ranger) (*Ns, error) {
  346. ns, exec, err := fm.PrepareEval(src, r, new(Ns))
  347. if err != nil {
  348. return nil, err
  349. }
  350. // Installs the namespace before executing. This prevent circular use'es
  351. // from resulting in an infinite recursion.
  352. fm.Evaler.modules[key] = ns
  353. err = exec()
  354. if err != nil {
  355. // Unload the namespace.
  356. delete(fm.Evaler.modules, key)
  357. return nil, err
  358. }
  359. return ns, nil
  360. }
  361. // compileAnd compiles the "and" special form.
  362. //
  363. // The and special form evaluates arguments until a false-ish values is found
  364. // and outputs it; the remaining arguments are not evaluated. If there are no
  365. // false-ish values, the last value is output. If there are no arguments, it
  366. // outputs $true, as if there is a hidden $true before actual arguments.
  367. func compileAnd(cp *compiler, fn *parse.Form) effectOp {
  368. return &andOrOp{fn.Range(), cp.compoundOps(fn.Args), true, false}
  369. }
  370. // compileOr compiles the "or" special form.
  371. //
  372. // The or special form evaluates arguments until a true-ish values is found and
  373. // outputs it; the remaining arguments are not evaluated. If there are no
  374. // true-ish values, the last value is output. If there are no arguments, it
  375. // outputs $false, as if there is a hidden $false before actual arguments.
  376. func compileOr(cp *compiler, fn *parse.Form) effectOp {
  377. return &andOrOp{fn.Range(), cp.compoundOps(fn.Args), false, true}
  378. }
  379. type andOrOp struct {
  380. diag.Ranging
  381. argOps []valuesOp
  382. init bool
  383. stopAt bool
  384. }
  385. func (op *andOrOp) exec(fm *Frame) Exception {
  386. var lastValue any = vals.Bool(op.init)
  387. out := fm.ValueOutput()
  388. for _, argOp := range op.argOps {
  389. values, exc := argOp.exec(fm)
  390. if exc != nil {
  391. return exc
  392. }
  393. for _, value := range values {
  394. if vals.Bool(value) == op.stopAt {
  395. return fm.errorp(op, out.Put(value))
  396. }
  397. lastValue = value
  398. }
  399. }
  400. return fm.errorp(op, out.Put(lastValue))
  401. }
  402. // Compiles the "coalesce" special form, which is like "or", but evaluates until
  403. // a non-nil value is found.
  404. func compileCoalesce(cp *compiler, fn *parse.Form) effectOp {
  405. return &coalesceOp{fn.Range(), cp.compoundOps(fn.Args)}
  406. }
  407. type coalesceOp struct {
  408. diag.Ranging
  409. argOps []valuesOp
  410. }
  411. func (op *coalesceOp) exec(fm *Frame) Exception {
  412. out := fm.ValueOutput()
  413. for _, argOp := range op.argOps {
  414. values, exc := argOp.exec(fm)
  415. if exc != nil {
  416. return exc
  417. }
  418. for _, value := range values {
  419. if value != nil {
  420. return fm.errorp(op, out.Put(value))
  421. }
  422. }
  423. }
  424. return fm.errorp(op, out.Put(nil))
  425. }
  426. func compileIf(cp *compiler, fn *parse.Form) effectOp {
  427. args := cp.walkArgs(fn)
  428. var condNodes []*parse.Compound
  429. var bodyNodes []*parse.Primary
  430. condLeader := "if"
  431. for {
  432. condNodes = append(condNodes, args.next())
  433. bodyNodes = append(bodyNodes, args.nextMustThunk(condLeader))
  434. if !args.nextIs("elif") {
  435. break
  436. }
  437. condLeader = "elif"
  438. }
  439. elseNode := args.nextMustThunkIfAfter("else")
  440. args.mustEnd()
  441. condOps := cp.compoundOps(condNodes)
  442. bodyOps := cp.primaryOps(bodyNodes)
  443. var elseOp valuesOp
  444. if elseNode != nil {
  445. elseOp = cp.primaryOp(elseNode)
  446. }
  447. return &ifOp{fn.Range(), condOps, bodyOps, elseOp}
  448. }
  449. type ifOp struct {
  450. diag.Ranging
  451. condOps []valuesOp
  452. bodyOps []valuesOp
  453. elseOp valuesOp
  454. }
  455. func (op *ifOp) exec(fm *Frame) Exception {
  456. bodies := make([]Callable, len(op.bodyOps))
  457. for i, bodyOp := range op.bodyOps {
  458. bodies[i] = execLambdaOp(fm, bodyOp)
  459. }
  460. elseFn := execLambdaOp(fm, op.elseOp)
  461. for i, condOp := range op.condOps {
  462. condValues, exc := condOp.exec(fm.Fork("if cond"))
  463. if exc != nil {
  464. return exc
  465. }
  466. if allTrue(condValues) {
  467. return fm.errorp(op, bodies[i].Call(fm.Fork("if body"), NoArgs, NoOpts))
  468. }
  469. }
  470. if op.elseOp != nil {
  471. return fm.errorp(op, elseFn.Call(fm.Fork("if else"), NoArgs, NoOpts))
  472. }
  473. return nil
  474. }
  475. func compileWhile(cp *compiler, fn *parse.Form) effectOp {
  476. args := cp.walkArgs(fn)
  477. condNode := args.next()
  478. bodyNode := args.nextMustThunk("while body")
  479. elseNode := args.nextMustThunkIfAfter("else")
  480. args.mustEnd()
  481. condOp := cp.compoundOp(condNode)
  482. bodyOp := cp.primaryOp(bodyNode)
  483. var elseOp valuesOp
  484. if elseNode != nil {
  485. elseOp = cp.primaryOp(elseNode)
  486. }
  487. return &whileOp{fn.Range(), condOp, bodyOp, elseOp}
  488. }
  489. type whileOp struct {
  490. diag.Ranging
  491. condOp, bodyOp, elseOp valuesOp
  492. }
  493. func (op *whileOp) exec(fm *Frame) Exception {
  494. body := execLambdaOp(fm, op.bodyOp)
  495. elseBody := execLambdaOp(fm, op.elseOp)
  496. iterated := false
  497. for {
  498. condValues, exc := op.condOp.exec(fm.Fork("while cond"))
  499. if exc != nil {
  500. return exc
  501. }
  502. if !allTrue(condValues) {
  503. break
  504. }
  505. iterated = true
  506. err := body.Call(fm.Fork("while"), NoArgs, NoOpts)
  507. if err != nil {
  508. exc := err.(Exception)
  509. if exc.Reason() == Continue {
  510. // Do nothing
  511. } else if exc.Reason() == Break {
  512. break
  513. } else {
  514. return exc
  515. }
  516. }
  517. }
  518. if op.elseOp != nil && !iterated {
  519. return fm.errorp(op, elseBody.Call(fm.Fork("while else"), NoArgs, NoOpts))
  520. }
  521. return nil
  522. }
  523. func compileFor(cp *compiler, fn *parse.Form) effectOp {
  524. args := cp.walkArgs(fn)
  525. varNode := args.next()
  526. iterNode := args.next()
  527. bodyNode := args.nextMustThunk("for body")
  528. elseNode := args.nextMustThunkIfAfter("else")
  529. args.mustEnd()
  530. lvalue := cp.compileOneLValue(varNode, setLValue|newLValue)
  531. iterOp := cp.compoundOp(iterNode)
  532. bodyOp := cp.primaryOp(bodyNode)
  533. var elseOp valuesOp
  534. if elseNode != nil {
  535. elseOp = cp.primaryOp(elseNode)
  536. }
  537. return &forOp{fn.Range(), lvalue, iterOp, bodyOp, elseOp}
  538. }
  539. type forOp struct {
  540. diag.Ranging
  541. lvalue lvalue
  542. iterOp valuesOp
  543. bodyOp valuesOp
  544. elseOp valuesOp
  545. }
  546. func (op *forOp) exec(fm *Frame) Exception {
  547. variable, err := derefLValue(fm, op.lvalue)
  548. if err != nil {
  549. return fm.errorp(op.lvalue, err)
  550. }
  551. iterable, err := evalForValue(fm, op.iterOp, "value being iterated")
  552. if err != nil {
  553. return fm.errorp(op, err)
  554. }
  555. body := execLambdaOp(fm, op.bodyOp)
  556. elseBody := execLambdaOp(fm, op.elseOp)
  557. iterated := false
  558. var errElement error
  559. errIterate := vals.Iterate(iterable, func(v any) bool {
  560. iterated = true
  561. err := variable.Set(v)
  562. if err != nil {
  563. errElement = err
  564. return false
  565. }
  566. err = body.Call(fm.Fork("for"), NoArgs, NoOpts)
  567. if err != nil {
  568. exc := err.(Exception)
  569. if exc.Reason() == Continue {
  570. // do nothing
  571. } else if exc.Reason() == Break {
  572. return false
  573. } else {
  574. errElement = err
  575. return false
  576. }
  577. }
  578. return true
  579. })
  580. if errIterate != nil {
  581. return fm.errorp(op, errIterate)
  582. }
  583. if errElement != nil {
  584. return fm.errorp(op, errElement)
  585. }
  586. if !iterated && elseBody != nil {
  587. return fm.errorp(op, elseBody.Call(fm.Fork("for else"), NoArgs, NoOpts))
  588. }
  589. return nil
  590. }
  591. func compileTry(cp *compiler, fn *parse.Form) effectOp {
  592. logger.Println("compiling try")
  593. args := cp.walkArgs(fn)
  594. bodyNode := args.nextMustThunk("try body")
  595. logger.Printf("body is %q", parse.SourceText(bodyNode))
  596. var catchVarNode *parse.Compound
  597. var catchNode *parse.Primary
  598. if args.peekIs("except") {
  599. cp.deprecate(args.peek(),
  600. `"except" is deprecated; use "catch" instead`, 18)
  601. }
  602. if args.nextIs("except") || args.nextIs("catch") {
  603. // Parse an optional lvalue into exceptVarNode.
  604. n := args.peek()
  605. if _, ok := cmpd.StringLiteral(n); ok {
  606. catchVarNode = n
  607. args.next()
  608. }
  609. catchNode = args.nextMustThunk("catch body")
  610. }
  611. elseNode := args.nextMustThunkIfAfter("else")
  612. finallyNode := args.nextMustThunkIfAfter("finally")
  613. args.mustEnd()
  614. if catchNode == nil && finallyNode == nil {
  615. cp.errorpf(fn, "try must be followed by a catch block or a finally block")
  616. }
  617. var catchVar lvalue
  618. var bodyOp, catchOp, elseOp, finallyOp valuesOp
  619. bodyOp = cp.primaryOp(bodyNode)
  620. if catchVarNode != nil {
  621. catchVar = cp.compileOneLValue(catchVarNode, setLValue|newLValue)
  622. }
  623. if catchNode != nil {
  624. catchOp = cp.primaryOp(catchNode)
  625. }
  626. if elseNode != nil {
  627. elseOp = cp.primaryOp(elseNode)
  628. }
  629. if finallyNode != nil {
  630. finallyOp = cp.primaryOp(finallyNode)
  631. }
  632. return &tryOp{fn.Range(), bodyOp, catchVar, catchOp, elseOp, finallyOp}
  633. }
  634. type tryOp struct {
  635. diag.Ranging
  636. bodyOp valuesOp
  637. catchVar lvalue
  638. catchOp valuesOp
  639. elseOp valuesOp
  640. finallyOp valuesOp
  641. }
  642. func (op *tryOp) exec(fm *Frame) Exception {
  643. body := execLambdaOp(fm, op.bodyOp)
  644. var exceptVar vars.Var
  645. if op.catchVar.ref != nil {
  646. var err error
  647. exceptVar, err = derefLValue(fm, op.catchVar)
  648. if err != nil {
  649. return fm.errorp(op, err)
  650. }
  651. }
  652. catch := execLambdaOp(fm, op.catchOp)
  653. elseFn := execLambdaOp(fm, op.elseOp)
  654. finally := execLambdaOp(fm, op.finallyOp)
  655. err := body.Call(fm.Fork("try body"), NoArgs, NoOpts)
  656. if err != nil {
  657. if catch != nil {
  658. if exceptVar != nil {
  659. err := exceptVar.Set(err.(Exception))
  660. if err != nil {
  661. return fm.errorp(op.catchVar, err)
  662. }
  663. }
  664. err = catch.Call(fm.Fork("try catch"), NoArgs, NoOpts)
  665. }
  666. } else {
  667. if elseFn != nil {
  668. err = elseFn.Call(fm.Fork("try else"), NoArgs, NoOpts)
  669. }
  670. }
  671. if finally != nil {
  672. errFinally := finally.Call(fm.Fork("try finally"), NoArgs, NoOpts)
  673. if errFinally != nil {
  674. // TODO: If err is not nil, this discards err. Use something similar
  675. // to pipeline exception to expose both.
  676. return fm.errorp(op, errFinally)
  677. }
  678. }
  679. return fm.errorp(op, err)
  680. }
  681. // PragmaForm = 'pragma' 'fallback-resolver' '=' { Compound }
  682. func compilePragma(cp *compiler, fn *parse.Form) effectOp {
  683. args := cp.walkArgs(fn)
  684. nameNode := args.next()
  685. name := stringLiteralOrError(cp, nameNode, "pragma name")
  686. eqNode := args.next()
  687. eq := stringLiteralOrError(cp, eqNode, "literal =")
  688. if eq != "=" {
  689. cp.errorpf(eqNode, "must be literal =")
  690. }
  691. valueNode := args.next()
  692. args.mustEnd()
  693. switch name {
  694. case "unknown-command":
  695. value := stringLiteralOrError(cp, valueNode, "value for unknown-command")
  696. switch value {
  697. case "disallow":
  698. cp.currentPragma().unknownCommandIsExternal = false
  699. case "external":
  700. cp.currentPragma().unknownCommandIsExternal = true
  701. default:
  702. cp.errorpf(valueNode,
  703. "invalid value for unknown-command: %s", parse.Quote(value))
  704. }
  705. default:
  706. cp.errorpf(nameNode, "unknown pragma %s", parse.Quote(name))
  707. }
  708. return nopOp{}
  709. }
  710. func (cp *compiler) compileOneLValue(n *parse.Compound, f lvalueFlag) lvalue {
  711. if len(n.Indexings) != 1 {
  712. cp.errorpf(n, "must be valid lvalue")
  713. }
  714. lvalues := cp.parseIndexingLValue(n.Indexings[0], f)
  715. if lvalues.rest != -1 {
  716. cp.errorpf(lvalues.lvalues[lvalues.rest], "rest variable not allowed")
  717. }
  718. if len(lvalues.lvalues) != 1 {
  719. cp.errorpf(n, "must be exactly one lvalue")
  720. }
  721. return lvalues.lvalues[0]
  722. }
  723. // Executes a valuesOp that is known to yield a lambda and returns the lambda.
  724. // Returns nil if op is nil.
  725. func execLambdaOp(fm *Frame, op valuesOp) Callable {
  726. if op == nil {
  727. return nil
  728. }
  729. values, exc := op.exec(fm)
  730. if exc != nil {
  731. panic("must not be erroneous")
  732. }
  733. return values[0].(Callable)
  734. }