parser, cgen: fix multiple comptime tmpl in one function (#12757)

pull/12762/head
yuyi 2021-12-08 16:12:02 +08:00 committed by GitHub
parent 2fbf7fea75
commit e433badcb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 31 additions and 20 deletions

View File

@ -62,12 +62,12 @@ fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
}
}
fn_name := g.fn_decl.name.replace('.', '__') + node.pos.pos.str()
if is_html {
// return vweb html template
g.writeln('vweb__Context_html(&app->Context, _tmpl_res_$g.fn_decl.name); strings__Builder_free(&sb); string_free(&_tmpl_res_$g.fn_decl.name);')
g.writeln('vweb__Context_html(&app->Context, _tmpl_res_$fn_name); strings__Builder_free(&sb_$fn_name); string_free(&_tmpl_res_$fn_name);')
} else {
// return $tmpl string
fn_name := g.fn_decl.name.replace('.', '__')
g.write(cur_line)
if g.inside_return {
g.write('return ')

View File

@ -192,7 +192,7 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
}
// println('path is now "$path"')
}
tmp_fn_name := p.cur_fn_name.replace('.', '__')
tmp_fn_name := p.cur_fn_name.replace('.', '__') + start_pos.pos.str()
$if trace_comptime ? {
println('>>> compiling comptime template file "$path" for $tmp_fn_name')
}

View File

@ -8,10 +8,6 @@ import v.errors
import os
import strings
const tmpl_str_start = "sb.write_string('"
const tmpl_str_end = "')\n"
enum State {
html
css // <style>
@ -63,15 +59,17 @@ pub fn (mut p Parser) compile_template_file(template_file string, fn_name string
}
basepath := os.dir(template_file)
lstartlength := lines.len * 30
tmpl_str_start := "sb_${fn_name}.write_string('"
tmpl_str_end := "')\n"
mut source := strings.new_builder(1000)
source.writeln('
import strings
// === vweb html template ===
fn vweb_tmpl_${fn_name}() string {
mut sb := strings.new_builder($lstartlength)\n
mut sb_$fn_name := strings.new_builder($lstartlength)\n
')
source.write_string(parser.tmpl_str_start)
source.write_string(tmpl_str_start)
mut state := State.html
mut in_span := false
mut end_of_line_pos := 0
@ -172,27 +170,27 @@ mut sb := strings.new_builder($lstartlength)\n
source.write_string(line[pos + 6..line.len - 1])
source.writeln('" rel="stylesheet" type="text/css">')
} else if line.contains('@if ') {
source.writeln(parser.tmpl_str_end)
source.writeln(tmpl_str_end)
pos := line.index('@if') or { continue }
source.writeln('if ' + line[pos + 4..] + '{')
source.writeln(parser.tmpl_str_start)
source.writeln(tmpl_str_start)
} else if line.contains('@end') {
// Remove new line byte
source.go_back(1)
source.writeln(parser.tmpl_str_end)
source.writeln(tmpl_str_end)
source.writeln('}')
source.writeln(parser.tmpl_str_start)
source.writeln(tmpl_str_start)
} else if line.contains('@else') {
// Remove new line byte
source.go_back(1)
source.writeln(parser.tmpl_str_end)
source.writeln(tmpl_str_end)
source.writeln(' } else { ')
source.writeln(parser.tmpl_str_start)
source.writeln(tmpl_str_start)
} else if line.contains('@for') {
source.writeln(parser.tmpl_str_end)
source.writeln(tmpl_str_end)
pos := line.index('@for') or { continue }
source.writeln('for ' + line[pos + 4..] + '{')
source.writeln(parser.tmpl_str_start)
source.writeln(tmpl_str_start)
} else if state == .html && line.starts_with('span.') && line.ends_with('{') {
// `span.header {` => `<span class='header'>`
class := line.find_between('span.', '{').trim_space()
@ -228,7 +226,7 @@ mut sb := strings.new_builder($lstartlength)\n
} else {
// HTML, may include `@var`
// escaped by cgen, unless it's a `vweb.RawHtml` string
trailing_bs := parser.tmpl_str_end + 'sb.write_b(92)\n' + parser.tmpl_str_start
trailing_bs := tmpl_str_end + 'sb_${fn_name}.write_b(92)\n' + tmpl_str_start
round1 := ['\\', '\\\\', r"'", "\\'", r'@', r'$']
round2 := [r'$$', r'\@', r'.$', r'.@']
rline := line.replace_each(round1).replace_each(round2)
@ -239,8 +237,8 @@ mut sb := strings.new_builder($lstartlength)\n
}
}
}
source.writeln(parser.tmpl_str_end)
source.writeln('_tmpl_res_$fn_name := sb.str() ')
source.writeln(tmpl_str_end)
source.writeln('_tmpl_res_$fn_name := sb_${fn_name}.str() ')
source.writeln('return _tmpl_res_$fn_name')
source.writeln('}')
source.writeln('// === end of vweb html template ===')

View File

@ -0,0 +1,11 @@
fn test_multi_comptime_tmpl_in_one_fn() {
a := 'A'
at := $tmpl('tmpl/a.txt')
println(at)
assert at.contains('A')
b := 'B'
bt := $tmpl('tmpl/b.txt')
println(bt)
assert bt.contains('B')
}

View File

@ -0,0 +1 @@
@a

View File

@ -0,0 +1 @@
@b