1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
package eval
// NativeParseExpr parses a Nix expression using the native Go parser and
// returns a finalized AST ready for evaluation.
//
// Parameters:
// - src: the Nix source code
// - basePath: directory for resolving relative path literals (e.g. "/home/user/project/")
// - filePath: absolute path of the source file (for error messages)
// - symbols: the shared SymbolTable
// - builtinNames: ordered list of builtin names (for variable resolution)
func NativeParseExpr(src []byte, basePath string, filePath string, symbols *SymbolTable, builtinNames []string) (Expr, error) {
return nativeParseExprInto(src, basePath, filePath, OriginPath, symbols, builtinNames, nil)
}
// nativeParseExprInto parses and finalizes, optionally registering the file
// in state's PosTable so that positions can be resolved on demand.
func nativeParseExprInto(src []byte, basePath string, filePath string, origin PosOrigin, symbols *SymbolTable, builtinNames []string, state *EvalState) (Expr, error) {
// Without a state there is no table to register with, so synthesise the
// span this source would have been given as the first one — see NixParse
// for why that is preferable to leaving it positionless.
span := PosSpan{size: uint32(len(src)), ok: true}
if state != nil {
span = state.Pos.AddFile(filePath, origin, len(src))
}
ast, lex, err := nixParseInternal(src, basePath, filePath, symbols, span)
if err != nil {
return nil, err
}
if state != nil {
state.Pos.SetLineOffsets(span, lex.LineOffsets())
}
if err := Finalize(ast, symbols, builtinNames); err != nil {
return nil, err
}
return ast, nil
}
// NativeParseExprIntoState is like NativeParseExpr but also registers the
// file in state's PosTable for lazy position resolution. Use this when the
// parsed expression will be evaluated by state (so error positions work).
//
// filePath is taken to be a real source file. For source that is not a file —
// an --expr argument, stdin, or evaluator-internal code — use
// NativeParseExprWithOrigin instead, so that builtins.unsafeGetAttrPos reports
// no location for it, as C++ Nix does.
func NativeParseExprIntoState(state *EvalState, src []byte, basePath, filePath string) (Expr, error) {
return NativeParseExprWithOrigin(state, src, basePath, filePath, OriginPath)
}
// NativeParseExprWithOrigin is NativeParseExprIntoState with an explicit
// origin for the source text. The origin decides whether positions within it
// are visible to Nix code via builtins.unsafeGetAttrPos; see PosOrigin.
//
// filePath is still used for error messages, so non-file origins should pass
// a descriptive placeholder such as "<cmdline>" or "<stdin>", matching how
// C++ prints those origins (lix/libutil/position.cc:79-90).
func NativeParseExprWithOrigin(state *EvalState, src []byte, basePath, filePath string, origin PosOrigin) (Expr, error) {
return nativeParseExprInto(src, basePath, filePath, origin, state.Symbols, DefaultBuiltinNames, state)
}
|