vweb: impl of comptime tmpl parsing (fix vweb_example)
parent
013bfc7ebc
commit
1c2bf7b244
|
@ -782,7 +782,8 @@ pub:
|
||||||
method_name string
|
method_name string
|
||||||
left Expr
|
left Expr
|
||||||
is_vweb bool
|
is_vweb bool
|
||||||
vweb_stmts []Stmt
|
// vweb_stmts []Stmt
|
||||||
|
vweb_tmpl File
|
||||||
pub mut:
|
pub mut:
|
||||||
sym table.TypeSymbol
|
sym table.TypeSymbol
|
||||||
}
|
}
|
||||||
|
|
|
@ -1829,6 +1829,10 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||||
}
|
}
|
||||||
ast.ComptimeCall {
|
ast.ComptimeCall {
|
||||||
it.sym = c.table.get_type_symbol(c.unwrap_generic(c.expr(it.left)))
|
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
|
return table.void_type
|
||||||
}
|
}
|
||||||
ast.ConcatExpr {
|
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) {
|
fn (g &Gen) comptime_call(node ast.ComptimeCall) {
|
||||||
if node.is_vweb {
|
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)')
|
g.writeln('vweb__Context_html(&app-> vweb, tmpl_res)')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import v.pref
|
||||||
import v.vmod
|
import v.vmod
|
||||||
import v.table
|
import v.table
|
||||||
import vweb.tmpl
|
import vweb.tmpl
|
||||||
import v.token
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
supported_platforms = ['windows', 'mac', 'macos', 'darwin', 'linux', 'freebsd', 'openbsd',
|
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 {
|
fn (mut p Parser) vweb() ast.ComptimeCall {
|
||||||
p.check(.dollar)
|
p.check(.dollar)
|
||||||
p.check(.name) // skip `vweb.html()` TODO
|
p.check(.name) // skip `vweb.html()` TODO
|
||||||
p.check(.dot)
|
p.check(.dot)
|
||||||
pos := p.scanner.pos
|
|
||||||
p.check(.name)
|
p.check(.name)
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
state := p.save_state()
|
|
||||||
// Compile vweb html template to V code, parse that V code and embed the resulting V function
|
// Compile vweb html template to V code, parse that V code and embed the resulting V function
|
||||||
// that returns an html string.
|
// that returns an html string.
|
||||||
mut path := p.cur_fn_name + '.html'
|
mut path := p.cur_fn_name + '.html'
|
||||||
// if p.pref.is_debug {
|
// if p.pref.is_debug {
|
||||||
println('>>> compiling vweb HTML template "$path"')
|
println('>>> compiling vweb HTML template "$path"')
|
||||||
v_code := tmpl.compile_file(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 {
|
if p.pref.is_verbose {
|
||||||
println('\n\n')
|
println('\n\n')
|
||||||
println('>>> vweb template for ${path}:')
|
println('>>> vweb template for ${path}:')
|
||||||
println(v_code)
|
println(v_code)
|
||||||
println('>>> end of vweb template END')
|
println('>>> end of vweb template END')
|
||||||
println('\n\n')
|
println('\n\n')
|
||||||
p.scanner.text = p.scanner.text[..pos] + v_code + p.scanner.text[pos..]
|
|
||||||
println(p.scanner.text)
|
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
/*
|
/*
|
||||||
if !os.exists(path) {
|
if !os.exists(path) {
|
||||||
// Can't find the template file in current directory,
|
// 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{
|
return ast.ComptimeCall{
|
||||||
is_vweb: true
|
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()
|
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 {
|
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,
|
// 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
|
||||||
|
@ -85,7 +99,6 @@ pub fn parse_file(path string, b_table &table.Table, comments_mode scanner.Comme
|
||||||
// text := os.read_file(path) or {
|
// text := os.read_file(path) or {
|
||||||
// panic(err)
|
// panic(err)
|
||||||
// }
|
// }
|
||||||
mut stmts := []ast.Stmt{}
|
|
||||||
mut p := Parser{
|
mut p := Parser{
|
||||||
scanner: scanner.new_scanner_file(path, comments_mode)
|
scanner: scanner.new_scanner_file(path, comments_mode)
|
||||||
comments_mode: 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{}
|
warnings: []errors.Warning{}
|
||||||
global_scope: global_scope
|
global_scope: global_scope
|
||||||
}
|
}
|
||||||
|
return p.parse()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut p Parser) parse() ast.File {
|
||||||
// comments_mode: comments_mode
|
// comments_mode: comments_mode
|
||||||
p.init_parse_fns()
|
p.init_parse_fns()
|
||||||
p.read_first_token()
|
p.read_first_token()
|
||||||
|
mut stmts := []ast.Stmt{}
|
||||||
for p.tok.kind == .comment {
|
for p.tok.kind == .comment {
|
||||||
stmts << p.comment()
|
stmts << p.comment()
|
||||||
}
|
}
|
||||||
// module
|
// module
|
||||||
mut mstmt := ast.Stmt{}
|
|
||||||
module_decl := p.module_decl()
|
module_decl := p.module_decl()
|
||||||
mstmt = module_decl
|
stmts << module_decl
|
||||||
stmts << mstmt
|
|
||||||
// imports
|
// imports
|
||||||
for p.tok.kind == .key_import {
|
for p.tok.kind == .key_import {
|
||||||
stmts << p.import_stmt()
|
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
|
p.scope.end_pos = p.tok.pos
|
||||||
//
|
//
|
||||||
return ast.File{
|
return ast.File{
|
||||||
path: path
|
path: p.file_name
|
||||||
mod: module_decl
|
mod: module_decl
|
||||||
imports: p.ast_imports
|
imports: p.ast_imports
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
|
|
|
@ -34,7 +34,9 @@ pub fn compile_template(content string) string {
|
||||||
mut s := strings.new_builder(1000)
|
mut s := strings.new_builder(1000)
|
||||||
// base := path.all_after_last('/').replace('.html', '')
|
// base := path.all_after_last('/').replace('.html', '')
|
||||||
s.writeln("
|
s.writeln("
|
||||||
|
import strings
|
||||||
// === vweb html template ===
|
// === vweb html template ===
|
||||||
|
fn vweb_tmpl() {
|
||||||
mut sb := strings.new_builder(${lines.len * 30})
|
mut sb := strings.new_builder(${lines.len * 30})
|
||||||
header := \' \' // TODO remove
|
header := \' \' // TODO remove
|
||||||
_ = header
|
_ = header
|
||||||
|
@ -90,6 +92,7 @@ pub fn compile_template(content string) string {
|
||||||
}
|
}
|
||||||
s.writeln(str_end)
|
s.writeln(str_end)
|
||||||
s.writeln('tmpl_res := sb.str() ')
|
s.writeln('tmpl_res := sb.str() ')
|
||||||
|
s.writeln('}')
|
||||||
s.writeln('// === end of vweb html template ===')
|
s.writeln('// === end of vweb html template ===')
|
||||||
return s.str()
|
return s.str()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue