.. | ||
ast | ||
builder | ||
callgraph | ||
cflag | ||
checker | ||
depgraph | ||
doc | ||
dotgraph | ||
embed_file | ||
errors | ||
eval | ||
fmt | ||
gen | ||
help | ||
live | ||
markused | ||
mathutil | ||
parser | ||
pkgconfig | ||
pref | ||
preludes | ||
preludes_js | ||
profile | ||
reflection | ||
scanner | ||
slow_tests | ||
tests | ||
token | ||
trace_calls | ||
transformer | ||
util | ||
vcache | ||
vet | ||
vmod | ||
compiler_errors_test.v | ||
README.md | ||
TEMPLATES.md |
Description
v
is a namespace for all of the V compiler modules.
The V compiler modules can be used by V programs that want to
process V source code in different ways, in fact, that is how
various V tools are implemented: v fmt
, v doc
, v ast
, vls
,
as well as the V compiler itself.
Compiler pipeline
A simple high level explanation
how the compiler pipeline (parser
-> checker
-> generator
) works.
Reading files
Getting builtin files
To load all builtin files,
a preference Preferences.lookup_path
for the path where to look for exists.
See Builder.get_builtin_files
as example.
If the file is a .vsh
file and the backend is C, vlib/os
will also be loaded as builtin.
Getting project files
Either there is a specific file: my_file.v
or a directory containing V files.
In the last case it scans that directory for all files.
See Builder.v_files_from_dir
as the helper method.
This list of files needs to be filtered so that only *.v
files exist.
Skips the following file types:
*_test.v
- either
*.c.v
or*.c.js
depending on the backend - all files that doesn't end with
.v
- Files that are not defined in
Preferences.compile_defines
orPreferences.compile_defines_all
if any file is defined.
Parsing files
To parse something a new template is created as the first step:
import v.ast
table := ast.new_table()
a new preference is created:
import v.pref
pref := &pref.Preferences{}
and a new scope is created:
import v.ast
scope := ast.Scope{
parent: 0
}
after that, you can parse your files.
Parse text
If you want to parse only text which isn't saved on the disk you can use this function.
import v.parser
code := ''
// table, pref and scope needs to be passed as reference
parsed_file := parser.parse_text(code, table, .parse_comments, &pref, &scope)
Parse a single file
For parsing files on disk, a path needs to be provided. The paths are collected one step earlier.
import v.parser
path := ''
// table, pref and scope needs to be passed as reference
parsed_file := parser.parse_file(path, table, .parse_comments, &pref, &scope)
Parse a set of files
If you have a batch of paths available which should be parsed, there is also a function which does all the work.
import v.parser
paths := ['']
// table, pref and scope needs to be passed as reference
parsed_files := parser.parse_files(paths, table, &pref, &scope)
Parse imports
A file often contains imports. These imports might need to be parsed as well.
The builder contains a method which does this: Builder.parse_imports
.
If the module which is imported isn't parsed already,
you have to collect it relatively from the main file.
For this the ast.File
contains a list of imports.
Those imports needs to be found on disk.
.
is just replaced with separators in the relative location of the main file.
Then all files from that directory are collected and parsed again like the previous steps explained.
Checking AST
A new checker is created:
import v.checker
mut checker := checker.new_checker(table, &pref)
After checking your files in checker.errors
and checker.warnings
you can see the results.
Check ast.File
checker.check(parsed_file)
Check a list of ast.File
checker.check_files(parsed_files)
Generate target from AST
Generating C code works just as this:
import v.gen.c
res := c.gen(parsed_files, table, &pref)