ast: mark ast.File{} with `[heap]`, and use []&ast.File consistently
parent
e512caf8f5
commit
bc01de2181
|
@ -552,16 +552,17 @@ pub:
|
||||||
// Each V source file is represented by one File structure.
|
// Each V source file is represented by one File structure.
|
||||||
// When the V compiler runs, the parser will fill an []File.
|
// When the V compiler runs, the parser will fill an []File.
|
||||||
// That array is then passed to V's checker.
|
// That array is then passed to V's checker.
|
||||||
|
[heap]
|
||||||
pub struct File {
|
pub struct File {
|
||||||
pub:
|
pub:
|
||||||
path string // absolute path of the source file - '/projects/v/file.v'
|
|
||||||
path_base string // file name - 'file.v' (useful for tracing)
|
|
||||||
nr_lines int // number of source code lines in the file (including newlines and comments)
|
nr_lines int // number of source code lines in the file (including newlines and comments)
|
||||||
nr_bytes int // number of processed source code bytes
|
nr_bytes int // number of processed source code bytes
|
||||||
mod Module // the module of the source file (from `module xyz` at the top)
|
mod Module // the module of the source file (from `module xyz` at the top)
|
||||||
global_scope &Scope
|
global_scope &Scope
|
||||||
is_test bool // true for _test.v files
|
is_test bool // true for _test.v files
|
||||||
pub mut:
|
pub mut:
|
||||||
|
path string // absolute path of the source file - '/projects/v/file.v'
|
||||||
|
path_base string // file name - 'file.v' (useful for tracing)
|
||||||
scope &Scope
|
scope &Scope
|
||||||
stmts []Stmt // all the statements in the source file
|
stmts []Stmt // all the statements in the source file
|
||||||
imports []Import // all the imports
|
imports []Import // all the imports
|
||||||
|
|
|
@ -3,7 +3,7 @@ import v.ast.walker
|
||||||
import v.parser
|
import v.parser
|
||||||
import v.pref
|
import v.pref
|
||||||
|
|
||||||
fn parse_text(text string) ast.File {
|
fn parse_text(text string) &ast.File {
|
||||||
tbl := ast.new_table()
|
tbl := ast.new_table()
|
||||||
prefs := pref.new_preferences()
|
prefs := pref.new_preferences()
|
||||||
scope := &ast.Scope{
|
scope := &ast.Scope{
|
||||||
|
@ -49,7 +49,7 @@ fn test_inspect() {
|
||||||
module main
|
module main
|
||||||
'
|
'
|
||||||
file := parse_text(source)
|
file := parse_text(source)
|
||||||
walker.inspect(&file, voidptr(0), fn (node ast.Node, data voidptr) bool {
|
walker.inspect(file, voidptr(0), fn (node ast.Node, data voidptr) bool {
|
||||||
// Second visit must be ast.Stmt
|
// Second visit must be ast.Stmt
|
||||||
if node is ast.Stmt {
|
if node is ast.Stmt {
|
||||||
if node !is ast.Module {
|
if node !is ast.Module {
|
||||||
|
@ -61,7 +61,6 @@ module main
|
||||||
assert mod.name == 'main'
|
assert mod.name == 'main'
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// First visit must be ast.File
|
|
||||||
assert node is ast.File
|
assert node is ast.File
|
||||||
// True means that the inspector must now
|
// True means that the inspector must now
|
||||||
// inspect the ast.File's children
|
// inspect the ast.File's children
|
||||||
|
|
|
@ -17,7 +17,7 @@ pub:
|
||||||
module_path string
|
module_path string
|
||||||
mut:
|
mut:
|
||||||
pref &pref.Preferences
|
pref &pref.Preferences
|
||||||
checker checker.Checker
|
checker &checker.Checker
|
||||||
global_scope &ast.Scope
|
global_scope &ast.Scope
|
||||||
out_name_c string
|
out_name_c string
|
||||||
out_name_js string
|
out_name_js string
|
||||||
|
@ -26,7 +26,7 @@ mut:
|
||||||
stats_bytes int // size of backend generated source code in bytes
|
stats_bytes int // size of backend generated source code in bytes
|
||||||
pub mut:
|
pub mut:
|
||||||
module_search_paths []string
|
module_search_paths []string
|
||||||
parsed_files []ast.File
|
parsed_files []&ast.File
|
||||||
cached_msvc MsvcResult
|
cached_msvc MsvcResult
|
||||||
table &ast.Table
|
table &ast.Table
|
||||||
ccoptions CcompilerOptions
|
ccoptions CcompilerOptions
|
||||||
|
@ -192,7 +192,7 @@ pub fn (mut b Builder) resolve_deps() {
|
||||||
eprintln(mods.str())
|
eprintln(mods.str())
|
||||||
eprintln('-------------------------------')
|
eprintln('-------------------------------')
|
||||||
}
|
}
|
||||||
mut reordered_parsed_files := []ast.File{}
|
mut reordered_parsed_files := []&ast.File{}
|
||||||
for m in mods {
|
for m in mods {
|
||||||
for pf in b.parsed_files {
|
for pf in b.parsed_files {
|
||||||
if m == pf.mod.name {
|
if m == pf.mod.name {
|
||||||
|
|
|
@ -48,7 +48,7 @@ pub fn compile(command string, pref &pref.Preferences) {
|
||||||
compilation_time_micros := 1 + sw.elapsed().microseconds()
|
compilation_time_micros := 1 + sw.elapsed().microseconds()
|
||||||
scompilation_time_ms := util.bold('${f64(compilation_time_micros) / 1000.0:6.3f}')
|
scompilation_time_ms := util.bold('${f64(compilation_time_micros) / 1000.0:6.3f}')
|
||||||
mut all_v_source_lines, mut all_v_source_bytes := 0, 0
|
mut all_v_source_lines, mut all_v_source_bytes := 0, 0
|
||||||
for mut pf in b.parsed_files {
|
for pf in b.parsed_files {
|
||||||
all_v_source_lines += pf.nr_lines
|
all_v_source_lines += pf.nr_lines
|
||||||
all_v_source_bytes += pf.nr_bytes
|
all_v_source_bytes += pf.nr_bytes
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ const (
|
||||||
vroot_is_deprecated_message = '@VROOT is deprecated, use @VMODROOT or @VEXEROOT instead'
|
vroot_is_deprecated_message = '@VROOT is deprecated, use @VMODROOT or @VEXEROOT instead'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
[heap]
|
||||||
pub struct Checker {
|
pub struct Checker {
|
||||||
pref &pref.Preferences // Preferences shared from V struct
|
pref &pref.Preferences // Preferences shared from V struct
|
||||||
pub mut:
|
pub mut:
|
||||||
|
@ -92,12 +93,12 @@ mut:
|
||||||
is_c_call bool // remove once C.c_call("string") deprecation is removed
|
is_c_call bool // remove once C.c_call("string") deprecation is removed
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_checker(table &ast.Table, pref &pref.Preferences) Checker {
|
pub fn new_checker(table &ast.Table, pref &pref.Preferences) &Checker {
|
||||||
mut timers_should_print := false
|
mut timers_should_print := false
|
||||||
$if time_checking ? {
|
$if time_checking ? {
|
||||||
timers_should_print = true
|
timers_should_print = true
|
||||||
}
|
}
|
||||||
return Checker{
|
return &Checker{
|
||||||
table: table
|
table: table
|
||||||
pref: pref
|
pref: pref
|
||||||
timers: util.new_timers(timers_should_print)
|
timers: util.new_timers(timers_should_print)
|
||||||
|
@ -160,13 +161,13 @@ pub fn (mut c Checker) change_current_file(file &ast.File) {
|
||||||
c.mod = file.mod.name
|
c.mod = file.mod.name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
pub fn (mut c Checker) check_files(ast_files []&ast.File) {
|
||||||
// c.files = ast_files
|
// c.files = ast_files
|
||||||
mut has_main_mod_file := false
|
mut has_main_mod_file := false
|
||||||
mut has_main_fn := false
|
mut has_main_fn := false
|
||||||
mut files_from_main_module := []&ast.File{}
|
mut files_from_main_module := []&ast.File{}
|
||||||
for i in 0 .. ast_files.len {
|
for i in 0 .. ast_files.len {
|
||||||
file := unsafe { &ast_files[i] }
|
file := unsafe { ast_files[i] }
|
||||||
c.timers.start('checker_check $file.path')
|
c.timers.start('checker_check $file.path')
|
||||||
c.check(file)
|
c.check(file)
|
||||||
if file.mod.name == 'main' {
|
if file.mod.name == 'main' {
|
||||||
|
@ -204,7 +205,7 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
||||||
for {
|
for {
|
||||||
for file in ast_files {
|
for file in ast_files {
|
||||||
if file.generic_fns.len > 0 {
|
if file.generic_fns.len > 0 {
|
||||||
c.change_current_file(&file)
|
c.change_current_file(file)
|
||||||
c.post_process_generic_fns()
|
c.post_process_generic_fns()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ mut:
|
||||||
json_forward_decls strings.Builder // json type forward decls
|
json_forward_decls strings.Builder // json type forward decls
|
||||||
enum_typedefs strings.Builder // enum types
|
enum_typedefs strings.Builder // enum types
|
||||||
sql_buf strings.Builder // for writing exprs to args via `sqlite3_bind_int()` etc
|
sql_buf strings.Builder // for writing exprs to args via `sqlite3_bind_int()` etc
|
||||||
file ast.File
|
file &ast.File
|
||||||
fn_decl &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0
|
fn_decl &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0
|
||||||
last_fn_c_name string
|
last_fn_c_name string
|
||||||
tmp_count int // counter for unique tmp vars (_tmp1, tmp2 etc)
|
tmp_count int // counter for unique tmp vars (_tmp1, tmp2 etc)
|
||||||
|
@ -175,7 +175,7 @@ mut:
|
||||||
// main_fn_decl_node ast.FnDecl
|
// main_fn_decl_node ast.FnDecl
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen(files []ast.File, table &ast.Table, pref &pref.Preferences) string {
|
pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
||||||
// println('start cgen2')
|
// println('start cgen2')
|
||||||
mut module_built := ''
|
mut module_built := ''
|
||||||
if pref.build_mode == .build_module {
|
if pref.build_mode == .build_module {
|
||||||
|
@ -192,6 +192,7 @@ pub fn gen(files []ast.File, table &ast.Table, pref &pref.Preferences) string {
|
||||||
timers_should_print = true
|
timers_should_print = true
|
||||||
}
|
}
|
||||||
mut g := Gen{
|
mut g := Gen{
|
||||||
|
file: 0
|
||||||
out: strings.new_builder(512000)
|
out: strings.new_builder(512000)
|
||||||
cheaders: strings.new_builder(15000)
|
cheaders: strings.new_builder(15000)
|
||||||
includes: strings.new_builder(100)
|
includes: strings.new_builder(100)
|
||||||
|
|
|
@ -42,7 +42,7 @@ mut:
|
||||||
namespaces map[string]&Namespace
|
namespaces map[string]&Namespace
|
||||||
doc &JsDoc
|
doc &JsDoc
|
||||||
enable_doc bool
|
enable_doc bool
|
||||||
file ast.File
|
file &ast.File
|
||||||
tmp_count int
|
tmp_count int
|
||||||
inside_ternary bool
|
inside_ternary bool
|
||||||
inside_loop bool
|
inside_loop bool
|
||||||
|
@ -62,7 +62,7 @@ mut:
|
||||||
call_stack []ast.CallExpr
|
call_stack []ast.CallExpr
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen(files []ast.File, table &ast.Table, pref &pref.Preferences) string {
|
pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
||||||
mut g := &JsGen{
|
mut g := &JsGen{
|
||||||
definitions: strings.new_builder(100)
|
definitions: strings.new_builder(100)
|
||||||
table: table
|
table: table
|
||||||
|
@ -72,6 +72,7 @@ pub fn gen(files []ast.File, table &ast.Table, pref &pref.Preferences) string {
|
||||||
doc: 0
|
doc: 0
|
||||||
ns: 0
|
ns: 0
|
||||||
enable_doc: true
|
enable_doc: true
|
||||||
|
file: 0
|
||||||
}
|
}
|
||||||
g.doc = new_jsdoc(g)
|
g.doc = new_jsdoc(g)
|
||||||
// TODO: Add '[-no]-jsdoc' flag
|
// TODO: Add '[-no]-jsdoc' flag
|
||||||
|
|
|
@ -67,7 +67,7 @@ fn (g &Gen) get_backend() ?CodeGen {
|
||||||
return error('unsupported architecture')
|
return error('unsupported architecture')
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen(files []ast.File, table &ast.Table, out_name string, pref &pref.Preferences) (int, int) {
|
pub fn gen(files []&ast.File, table &ast.Table, out_name string, pref &pref.Preferences) (int, int) {
|
||||||
mut g := &Gen{
|
mut g := &Gen{
|
||||||
table: table
|
table: table
|
||||||
sect_header_name_pos: 0
|
sect_header_name_pos: 0
|
||||||
|
|
|
@ -7,7 +7,7 @@ import v.util
|
||||||
import v.pref
|
import v.pref
|
||||||
|
|
||||||
// mark_used walks the AST, starting at main() and marks all used fns transitively
|
// mark_used walks the AST, starting at main() and marks all used fns transitively
|
||||||
pub fn mark_used(mut table ast.Table, pref &pref.Preferences, ast_files []ast.File) {
|
pub fn mark_used(mut table ast.Table, pref &pref.Preferences, ast_files []&ast.File) {
|
||||||
mut all_fns, all_consts := all_fn_and_const(ast_files)
|
mut all_fns, all_consts := all_fn_and_const(ast_files)
|
||||||
util.timing_start(@METHOD)
|
util.timing_start(@METHOD)
|
||||||
defer {
|
defer {
|
||||||
|
@ -267,7 +267,7 @@ pub fn mark_used(mut table ast.Table, pref &pref.Preferences, ast_files []ast.Fi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn all_fn_and_const(ast_files []ast.File) (map[string]ast.FnDecl, map[string]ast.ConstField) {
|
fn all_fn_and_const(ast_files []&ast.File) (map[string]ast.FnDecl, map[string]ast.ConstField) {
|
||||||
util.timing_start(@METHOD)
|
util.timing_start(@METHOD)
|
||||||
defer {
|
defer {
|
||||||
util.timing_measure(@METHOD)
|
util.timing_measure(@METHOD)
|
||||||
|
@ -275,7 +275,7 @@ fn all_fn_and_const(ast_files []ast.File) (map[string]ast.FnDecl, map[string]ast
|
||||||
mut all_fns := map[string]ast.FnDecl{}
|
mut all_fns := map[string]ast.FnDecl{}
|
||||||
mut all_consts := map[string]ast.ConstField{}
|
mut all_consts := map[string]ast.ConstField{}
|
||||||
for i in 0 .. ast_files.len {
|
for i in 0 .. ast_files.len {
|
||||||
file := unsafe { &ast_files[i] }
|
file := ast_files[i]
|
||||||
for node in file.stmts {
|
for node in file.stmts {
|
||||||
match node {
|
match node {
|
||||||
ast.FnDecl {
|
ast.FnDecl {
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub mut:
|
||||||
n_maps int
|
n_maps int
|
||||||
n_asserts int
|
n_asserts int
|
||||||
mut:
|
mut:
|
||||||
files []ast.File
|
files []&ast.File
|
||||||
all_fns map[string]ast.FnDecl
|
all_fns map[string]ast.FnDecl
|
||||||
all_consts map[string]ast.ConstField
|
all_consts map[string]ast.ConstField
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,10 +187,7 @@ fn (mut p Parser) comp_call() ast.ComptimeCall {
|
||||||
println('')
|
println('')
|
||||||
}
|
}
|
||||||
mut file := parse_comptime(v_code, p.table, p.pref, scope, p.global_scope)
|
mut file := parse_comptime(v_code, p.table, p.pref, scope, p.global_scope)
|
||||||
file = ast.File{
|
file.path = tmpl_path
|
||||||
...file
|
|
||||||
path: tmpl_path
|
|
||||||
}
|
|
||||||
// copy vars from current fn scope into vweb_tmpl scope
|
// copy vars from current fn scope into vweb_tmpl scope
|
||||||
for stmt in file.stmts {
|
for stmt in file.stmts {
|
||||||
if stmt is ast.FnDecl {
|
if stmt is ast.FnDecl {
|
||||||
|
|
|
@ -101,7 +101,7 @@ pub fn parse_stmt(text string, table &ast.Table, scope &ast.Scope) ast.Stmt {
|
||||||
return p.stmt(false)
|
return p.stmt(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_comptime(text string, table &ast.Table, pref &pref.Preferences, scope &ast.Scope, global_scope &ast.Scope) ast.File {
|
pub fn parse_comptime(text string, table &ast.Table, pref &pref.Preferences, scope &ast.Scope, global_scope &ast.Scope) &ast.File {
|
||||||
mut p := Parser{
|
mut p := Parser{
|
||||||
scanner: scanner.new_scanner(text, .skip_comments, pref)
|
scanner: scanner.new_scanner(text, .skip_comments, pref)
|
||||||
table: table
|
table: table
|
||||||
|
@ -114,7 +114,7 @@ pub fn parse_comptime(text string, table &ast.Table, pref &pref.Preferences, sco
|
||||||
return p.parse()
|
return p.parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_text(text string, path string, table &ast.Table, comments_mode scanner.CommentsMode, pref &pref.Preferences, global_scope &ast.Scope) ast.File {
|
pub fn parse_text(text string, path string, table &ast.Table, comments_mode scanner.CommentsMode, pref &pref.Preferences, global_scope &ast.Scope) &ast.File {
|
||||||
mut p := Parser{
|
mut p := Parser{
|
||||||
scanner: scanner.new_scanner(text, comments_mode, pref)
|
scanner: scanner.new_scanner(text, comments_mode, pref)
|
||||||
comments_mode: comments_mode
|
comments_mode: comments_mode
|
||||||
|
@ -173,7 +173,7 @@ pub fn (mut p Parser) set_path(path string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_file(path string, table &ast.Table, comments_mode scanner.CommentsMode, pref &pref.Preferences, global_scope &ast.Scope) ast.File {
|
pub fn parse_file(path string, table &ast.Table, comments_mode scanner.CommentsMode, pref &pref.Preferences, global_scope &ast.Scope) &ast.File {
|
||||||
// NB: when comments_mode == .toplevel_comments,
|
// NB: when comments_mode == .toplevel_comments,
|
||||||
// the parser gives feedback to the scanner about toplevel statements, so that the scanner can skip
|
// the parser gives feedback to the scanner about toplevel statements, so that the scanner can skip
|
||||||
// all the tricky inner comments. This is needed because we do not have a good general solution
|
// all the tricky inner comments. This is needed because we do not have a good general solution
|
||||||
|
@ -199,7 +199,7 @@ pub fn parse_file(path string, table &ast.Table, comments_mode scanner.CommentsM
|
||||||
return p.parse()
|
return p.parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_vet_file(path string, table_ &ast.Table, pref &pref.Preferences) (ast.File, []vet.Error) {
|
pub fn parse_vet_file(path string, table_ &ast.Table, pref &pref.Preferences) (&ast.File, []vet.Error) {
|
||||||
global_scope := &ast.Scope{
|
global_scope := &ast.Scope{
|
||||||
parent: 0
|
parent: 0
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,7 @@ pub fn parse_vet_file(path string, table_ &ast.Table, pref &pref.Preferences) (a
|
||||||
return file, p.vet_errors
|
return file, p.vet_errors
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut p Parser) parse() ast.File {
|
pub fn (mut p Parser) parse() &ast.File {
|
||||||
util.timing_start('PARSE')
|
util.timing_start('PARSE')
|
||||||
defer {
|
defer {
|
||||||
util.timing_measure_cumulative('PARSE')
|
util.timing_measure_cumulative('PARSE')
|
||||||
|
@ -283,7 +283,7 @@ pub fn (mut p Parser) parse() ast.File {
|
||||||
// println(stmts[0])
|
// println(stmts[0])
|
||||||
p.scope.end_pos = p.tok.pos
|
p.scope.end_pos = p.tok.pos
|
||||||
//
|
//
|
||||||
return ast.File{
|
return &ast.File{
|
||||||
path: p.file_name
|
path: p.file_name
|
||||||
path_base: p.file_base
|
path_base: p.file_base
|
||||||
is_test: p.inside_test_file
|
is_test: p.inside_test_file
|
||||||
|
@ -310,7 +310,7 @@ mut:
|
||||||
mu2 &sync.Mutex
|
mu2 &sync.Mutex
|
||||||
paths []string
|
paths []string
|
||||||
table &ast.Table
|
table &ast.Table
|
||||||
parsed_ast_files []ast.File
|
parsed_ast_files []&ast.File
|
||||||
pref &pref.Preferences
|
pref &pref.Preferences
|
||||||
global_scope &ast.Scope
|
global_scope &ast.Scope
|
||||||
}
|
}
|
||||||
|
@ -335,7 +335,7 @@ fn (mut q Queue) run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
pub fn parse_files(paths []string, table &ast.Table, pref &pref.Preferences, global_scope &ast.Scope) []ast.File {
|
pub fn parse_files(paths []string, table &ast.Table, pref &pref.Preferences, global_scope &ast.Scope) []&ast.File {
|
||||||
mut timers := util.new_timers(false)
|
mut timers := util.new_timers(false)
|
||||||
$if time_parsing ? {
|
$if time_parsing ? {
|
||||||
timers.should_print = true
|
timers.should_print = true
|
||||||
|
@ -365,7 +365,7 @@ pub fn parse_files(paths []string, table &ast.Table, pref &pref.Preferences, glo
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
// ///////////////
|
// ///////////////
|
||||||
mut files := []ast.File{}
|
mut files := []&ast.File{}
|
||||||
for path in paths {
|
for path in paths {
|
||||||
// println('parse_files $path')
|
// println('parse_files $path')
|
||||||
timers.start('parse_file $path')
|
timers.start('parse_file $path')
|
||||||
|
|
|
@ -43,7 +43,7 @@ fn test_eval() {
|
||||||
for input in inputs {
|
for input in inputs {
|
||||||
stmts << parse_stmt(input, table, scope)
|
stmts << parse_stmt(input, table, scope)
|
||||||
}
|
}
|
||||||
file := ast.File{
|
file := &ast.File{
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
scope: scope
|
scope: scope
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ fn test_one() {
|
||||||
for line in input {
|
for line in input {
|
||||||
e << parse_stmt(line, table, scope)
|
e << parse_stmt(line, table, scope)
|
||||||
}
|
}
|
||||||
program := ast.File{
|
program := &ast.File{
|
||||||
stmts: e
|
stmts: e
|
||||||
scope: scope
|
scope: scope
|
||||||
global_scope: scope
|
global_scope: scope
|
||||||
|
@ -147,7 +147,7 @@ fn test_parse_expr() {
|
||||||
println('\n\nst="$s"')
|
println('\n\nst="$s"')
|
||||||
e << parse_stmt(s, table, scope)
|
e << parse_stmt(s, table, scope)
|
||||||
}
|
}
|
||||||
program := ast.File{
|
program := &ast.File{
|
||||||
stmts: e
|
stmts: e
|
||||||
scope: scope
|
scope: scope
|
||||||
global_scope: scope
|
global_scope: scope
|
||||||
|
|
Loading…
Reference in New Issue