OILS / builtin / func_reflect.py View on Github | oilshell.org

119 lines, 68 significant
1#!/usr/bin/env python2
2"""
3func_reflect.py - Functions for reflecting on Oils code - OSH or YSH.
4"""
5from __future__ import print_function
6
7from _devbuild.gen.runtime_asdl import (scope_e)
8from _devbuild.gen.syntax_asdl import source
9from _devbuild.gen.value_asdl import (value, value_t)
10
11from core import alloc
12from core import error
13from core import main_loop
14from core import state
15from core import vm
16from frontend import reader
17from frontend import typed_args
18from mycpp.mylib import log
19from ysh import expr_eval
20
21from typing import TYPE_CHECKING
22if TYPE_CHECKING:
23 from frontend import parse_lib
24 from display import ui
25
26_ = log
27
28
29class Shvar_get(vm._Callable):
30 """Look up with dynamic scope."""
31
32 def __init__(self, mem):
33 # type: (state.Mem) -> None
34 vm._Callable.__init__(self)
35 self.mem = mem
36
37 def Call(self, rd):
38 # type: (typed_args.Reader) -> value_t
39 name = rd.PosStr()
40 rd.Done()
41 return state.DynamicGetVar(self.mem, name, scope_e.Dynamic)
42
43
44class GetVar(vm._Callable):
45 """Look up normal scoping rules."""
46
47 def __init__(self, mem):
48 # type: (state.Mem) -> None
49 vm._Callable.__init__(self)
50 self.mem = mem
51
52 def Call(self, rd):
53 # type: (typed_args.Reader) -> value_t
54 name = rd.PosStr()
55 rd.Done()
56 return state.DynamicGetVar(self.mem, name, scope_e.LocalOrGlobal)
57
58
59class ParseCommand(vm._Callable):
60
61 def __init__(self, parse_ctx, errfmt):
62 # type: (parse_lib.ParseContext, ui.ErrorFormatter) -> None
63 self.parse_ctx = parse_ctx
64 self.errfmt = errfmt
65
66 def Call(self, rd):
67 # type: (typed_args.Reader) -> value_t
68 code_str = rd.PosStr()
69 rd.Done()
70
71 line_reader = reader.StringLineReader(code_str, self.parse_ctx.arena)
72 c_parser = self.parse_ctx.MakeOshParser(line_reader)
73
74 # TODO: it would be nice to point to the location of the expression
75 # argument
76 src = source.Dynamic('parseCommand()', rd.LeftParenToken())
77 with alloc.ctx_SourceCode(self.parse_ctx.arena, src):
78 try:
79 cmd = main_loop.ParseWholeFile(c_parser)
80 except error.Parse as e:
81 # This prints the location
82 self.errfmt.PrettyPrintError(e)
83
84 # TODO: add inner location info to this structured error
85 raise error.Structured(3, "Syntax error in parseCommand()",
86 rd.LeftParenToken())
87
88 return value.Command(cmd)
89
90
91class ParseExpr(vm._Callable):
92
93 def __init__(self, parse_ctx, errfmt):
94 # type: (parse_lib.ParseContext, ui.ErrorFormatter) -> None
95 self.parse_ctx = parse_ctx
96 self.errfmt = errfmt
97
98 def Call(self, rd):
99 # type: (typed_args.Reader) -> value_t
100 code_str = rd.PosStr()
101 rd.Done()
102
103 return value.Null
104
105
106class EvalExpr(vm._Callable):
107
108 def __init__(self, expr_ev):
109 # type: (expr_eval.ExprEvaluator) -> None
110 self.expr_ev = expr_ev
111
112 def Call(self, rd):
113 # type: (typed_args.Reader) -> value_t
114 lazy = rd.PosExpr()
115 rd.Done()
116
117 result = self.expr_ev.EvalExpr(lazy, rd.LeftParenToken())
118
119 return result