vweb: impl of comptime tmpl parsing (fix vweb_example)
							parent
							
								
									013bfc7ebc
								
							
						
					
					
						commit
						1c2bf7b244
					
				|  | @ -782,7 +782,8 @@ pub: | |||
| 	method_name string | ||||
| 	left        Expr | ||||
| 	is_vweb     bool | ||||
| 	vweb_stmts  []Stmt | ||||
| 	// vweb_stmts  []Stmt
 | ||||
| 	vweb_tmpl   File | ||||
| pub mut: | ||||
| 	sym         table.TypeSymbol | ||||
| } | ||||
|  |  | |||
|  | @ -1829,6 +1829,10 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { | |||
| 		} | ||||
| 		ast.ComptimeCall { | ||||
| 			it.sym = c.table.get_type_symbol(c.unwrap_generic(c.expr(it.left))) | ||||
| 			if it.is_vweb { | ||||
| 				mut c2 := new_checker(c.table, c.pref) | ||||
| 				c2.check(it.vweb_tmpl) | ||||
| 			} | ||||
| 			return table.void_type | ||||
| 		} | ||||
| 		ast.ConcatExpr { | ||||
|  |  | |||
|  | @ -4351,6 +4351,16 @@ fn (mut g Gen) interface_call(typ, interface_type table.Type) { | |||
| 
 | ||||
| fn (g &Gen) comptime_call(node ast.ComptimeCall) { | ||||
| 	if node.is_vweb { | ||||
| 		for stmt in node.vweb_tmpl.stmts { | ||||
| 			if stmt is ast.FnDecl { | ||||
| 				fn_decl := stmt as ast.FnDecl | ||||
| 				// insert stmts from vweb_tmpl fn
 | ||||
| 				if fn_decl.name == 'vweb_tmpl' { | ||||
| 					g.stmts(fn_decl.stmts) | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		g.writeln('vweb__Context_html(&app-> vweb, tmpl_res)') | ||||
| 		return | ||||
| 	} | ||||
|  |  | |||
|  | @ -9,7 +9,6 @@ import v.pref | |||
| import v.vmod | ||||
| import v.table | ||||
| import vweb.tmpl | ||||
| import v.token | ||||
| 
 | ||||
| const ( | ||||
| 	supported_platforms = ['windows', 'mac', 'macos', 'darwin', 'linux', 'freebsd', 'openbsd', | ||||
|  | @ -78,60 +77,31 @@ fn (mut p Parser) hash() ast.HashStmt { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| struct ParserState { | ||||
| 	scanner_pos int | ||||
| 	tok         token.Token | ||||
| 	prev_tok    token.Token | ||||
| 	peek_tok    token.Token | ||||
| 	peek_tok2   token.Token | ||||
| 	peek_tok3   token.Token | ||||
| } | ||||
| 
 | ||||
| pub fn (p &Parser) save_state() ParserState { | ||||
| 	return ParserState{ | ||||
| 		scanner_pos: p.scanner.pos | ||||
| 		tok: p.tok | ||||
| 		prev_tok: p.prev_tok | ||||
| 		peek_tok: p.peek_tok | ||||
| 		peek_tok2: p.peek_tok2 | ||||
| 		peek_tok3: p.peek_tok3 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub fn (mut p Parser) restore_state(state ParserState) { | ||||
| 	p.scanner.pos = state.scanner_pos | ||||
| 	p.tok = state.tok | ||||
| 	p.prev_tok = state.prev_tok | ||||
| 	p.peek_tok = state.peek_tok | ||||
| 	p.peek_tok2 = state.peek_tok2 | ||||
| 	p.peek_tok3 = state.peek_tok3 | ||||
| } | ||||
| 
 | ||||
| fn (mut p Parser) vweb() ast.ComptimeCall { | ||||
| 	p.check(.dollar) | ||||
| 	p.check(.name) // skip `vweb.html()` TODO
 | ||||
| 	p.check(.dot) | ||||
| 	pos := p.scanner.pos | ||||
| 	p.check(.name) | ||||
| 	p.check(.lpar) | ||||
| 	p.check(.rpar) | ||||
| 	state := p.save_state() | ||||
| 	// Compile vweb html template to V code, parse that V code and embed the resulting V function
 | ||||
| 	// that returns an html string.
 | ||||
| 	mut path := p.cur_fn_name + '.html' | ||||
| 	// if p.pref.is_debug {
 | ||||
| 	println('>>> compiling vweb HTML template "$path"') | ||||
| 	v_code := tmpl.compile_file(path) | ||||
| 	mut scope := &ast.Scope{ | ||||
| 		start_pos: 0 | ||||
| 		parent: 0 | ||||
| 	} | ||||
| 	file := parse_text(v_code, p.table, scope, p.global_scope) | ||||
| 	if p.pref.is_verbose { | ||||
| 		println('\n\n') | ||||
| 		println('>>> vweb template for ${path}:') | ||||
| 		println(v_code) | ||||
| 		println('>>> end of vweb template END') | ||||
| 		println('\n\n') | ||||
| 		p.scanner.text = p.scanner.text[..pos] + v_code + p.scanner.text[pos..] | ||||
| 		println(p.scanner.text) | ||||
| 	} | ||||
| 	// }
 | ||||
| 	/* | ||||
| 	if !os.exists(path) { | ||||
| 		// Can't find the template file in current directory,
 | ||||
|  | @ -143,15 +113,9 @@ fn (mut p Parser) vweb() ast.ComptimeCall { | |||
| 		} | ||||
| 	} | ||||
| 	*/ | ||||
| 	p.restore_state(state) | ||||
| 	p.scanner.pos = pos + v_code.len + 1 | ||||
| 	/* | ||||
| 	println('restored:') | ||||
| 	println(p.scanner.text[p.scanner.pos..]) | ||||
| 	println('=============') | ||||
| 	*/ | ||||
| 	return ast.ComptimeCall{ | ||||
| 		is_vweb: true | ||||
| 		vweb_tmpl: file | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -75,6 +75,20 @@ pub fn parse_stmt(text string, table &table.Table, scope &ast.Scope) ast.Stmt { | |||
| 	return p.stmt() | ||||
| } | ||||
| 
 | ||||
| pub fn parse_text(text string, b_table &table.Table, scope &ast.Scope, global_scope &ast.Scope) ast.File { | ||||
| 	s := scanner.new_scanner(text, .skip_comments) | ||||
| 	mut p := Parser{ | ||||
| 		scanner: s | ||||
| 		table: b_table | ||||
| 		pref: &pref.Preferences{} | ||||
| 		scope: scope | ||||
| 		errors: []errors.Error{} | ||||
| 		warnings: []errors.Warning{} | ||||
| 		global_scope: global_scope | ||||
| 	} | ||||
| 	return p.parse() | ||||
| } | ||||
| 
 | ||||
| pub fn parse_file(path string, b_table &table.Table, comments_mode scanner.CommentsMode, pref &pref.Preferences, global_scope &ast.Scope) ast.File { | ||||
| 	// NB: when comments_mode == .toplevel_comments,
 | ||||
| 	// the parser gives feedback to the scanner about toplevel statements, so that the scanner can skip
 | ||||
|  | @ -85,7 +99,6 @@ pub fn parse_file(path string, b_table &table.Table, comments_mode scanner.Comme | |||
| 	// text := os.read_file(path) or {
 | ||||
| 	// panic(err)
 | ||||
| 	// }
 | ||||
| 	mut stmts := []ast.Stmt{} | ||||
| 	mut p := Parser{ | ||||
| 		scanner: scanner.new_scanner_file(path, comments_mode) | ||||
| 		comments_mode: comments_mode | ||||
|  | @ -101,17 +114,20 @@ pub fn parse_file(path string, b_table &table.Table, comments_mode scanner.Comme | |||
| 		warnings: []errors.Warning{} | ||||
| 		global_scope: global_scope | ||||
| 	} | ||||
| 	return p.parse() | ||||
| } | ||||
| 
 | ||||
| fn (mut p Parser) parse() ast.File { | ||||
| 	// comments_mode: comments_mode
 | ||||
| 	p.init_parse_fns() | ||||
| 	p.read_first_token() | ||||
| 	mut stmts := []ast.Stmt{} | ||||
| 	for p.tok.kind == .comment { | ||||
| 		stmts << p.comment() | ||||
| 	} | ||||
| 	// module
 | ||||
| 	mut mstmt := ast.Stmt{} | ||||
| 	module_decl := p.module_decl() | ||||
| 	mstmt = module_decl | ||||
| 	stmts << mstmt | ||||
| 	stmts << module_decl | ||||
| 	// imports
 | ||||
| 	for p.tok.kind == .key_import { | ||||
| 		stmts << p.import_stmt() | ||||
|  | @ -137,7 +153,7 @@ pub fn parse_file(path string, b_table &table.Table, comments_mode scanner.Comme | |||
| 	p.scope.end_pos = p.tok.pos | ||||
| 	//
 | ||||
| 	return ast.File{ | ||||
| 		path: path | ||||
| 		path: p.file_name | ||||
| 		mod: module_decl | ||||
| 		imports: p.ast_imports | ||||
| 		stmts: stmts | ||||
|  |  | |||
|  | @ -34,7 +34,9 @@ pub fn compile_template(content string) string { | |||
| 	mut s := strings.new_builder(1000) | ||||
| 	// base := path.all_after_last('/').replace('.html', '')
 | ||||
| 	s.writeln(" | ||||
| 	import strings | ||||
| 	// === vweb html template ===
 | ||||
| 	fn vweb_tmpl() { | ||||
| 	mut sb := strings.new_builder(${lines.len * 30}) | ||||
| 	header := \' \' // TODO remove | ||||
| 	_ = header | ||||
|  | @ -90,6 +92,7 @@ pub fn compile_template(content string) string { | |||
| 	} | ||||
| 	s.writeln(str_end) | ||||
| 	s.writeln('tmpl_res := sb.str() ') | ||||
| 	s.writeln('}') | ||||
| 	s.writeln('// === end of vweb html template ===') | ||||
| 	return s.str() | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue