all: make comptime templates usable outside of vweb via $tmpl
parent
c6a8c3cad5
commit
5efd393af2
|
@ -333,7 +333,7 @@ fn (g &Game) draw_tetro() {
|
|||
fn (g &Game) draw_next_tetro() {
|
||||
if g.state != .gameover {
|
||||
idx := g.next_tetro_idx * tetro_size * tetro_size
|
||||
next_tetro := g.tetros_cache[idx..idx + tetro_size]
|
||||
next_tetro := g.tetros_cache[idx..idx + tetro_size].clone()
|
||||
pos_y := 0
|
||||
pos_x := field_width / 2 - tetro_size / 2
|
||||
for i in 0 .. tetro_size {
|
||||
|
|
|
@ -1823,20 +1823,20 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T
|
|||
// TODO: non deferred
|
||||
pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
||||
c.expected_type = c.cur_fn.return_type
|
||||
if return_stmt.exprs.len > 0 && c.expected_type == table.void_type {
|
||||
expected_type := c.unwrap_generic(c.expected_type)
|
||||
expected_type_sym := c.table.get_type_symbol(expected_type)
|
||||
if return_stmt.exprs.len > 0 && c.cur_fn.return_type == table.void_type {
|
||||
c.error('too many arguments to return, current function does not return anything',
|
||||
return_stmt.pos)
|
||||
return
|
||||
} else if return_stmt.exprs.len == 0 && !(c.expected_type == table.void_type ||
|
||||
c.table.get_type_symbol(c.expected_type).kind == .void) {
|
||||
expected_type_sym.kind == .void) {
|
||||
c.error('too few arguments to return', return_stmt.pos)
|
||||
return
|
||||
}
|
||||
if return_stmt.exprs.len == 0 {
|
||||
return
|
||||
}
|
||||
expected_type := c.unwrap_generic(c.expected_type)
|
||||
expected_type_sym := c.table.get_type_symbol(expected_type)
|
||||
exp_is_optional := expected_type.has_flag(.optional)
|
||||
mut expected_types := [expected_type]
|
||||
if expected_type_sym.kind == .multi_return {
|
||||
|
@ -2879,7 +2879,11 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
|||
c.nr_warnings += c2.nr_warnings
|
||||
c.nr_errors += c2.nr_errors
|
||||
}
|
||||
return c.table.find_type_idx('vweb.Result')
|
||||
if node.method_name == 'html' {
|
||||
return c.table.find_type_idx('vweb.Result')
|
||||
} else {
|
||||
return table.string_type
|
||||
}
|
||||
// return table.void_type
|
||||
}
|
||||
ast.ConcatExpr {
|
||||
|
|
|
@ -9,18 +9,28 @@ import v.util
|
|||
|
||||
fn (mut g Gen) comptime_call(node ast.ComptimeCall) {
|
||||
if node.is_vweb {
|
||||
is_html := node.method_name == 'html'
|
||||
for stmt in node.vweb_tmpl.stmts {
|
||||
if stmt is ast.FnDecl {
|
||||
// insert stmts from vweb_tmpl fn
|
||||
if stmt.name.starts_with('main.vweb_tmpl') {
|
||||
g.inside_vweb_tmpl = true
|
||||
if is_html {
|
||||
g.inside_vweb_tmpl = true
|
||||
}
|
||||
g.stmts(stmt.stmts)
|
||||
g.inside_vweb_tmpl = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
g.writeln('vweb__Context_html(&app->vweb, _tmpl_res_$g.fn_decl.name); strings__Builder_free(&sb); string_free(&_tmpl_res_$g.fn_decl.name);')
|
||||
if is_html {
|
||||
// return vweb html template
|
||||
g.writeln('vweb__Context_html(&app->vweb, _tmpl_res_$g.fn_decl.name); strings__Builder_free(&sb); string_free(&_tmpl_res_$g.fn_decl.name);')
|
||||
} else {
|
||||
// return $tmpl string
|
||||
fn_name := g.fn_decl.name.replace('.', '__')
|
||||
g.writeln('return _tmpl_res_$fn_name;')
|
||||
}
|
||||
return
|
||||
}
|
||||
g.writeln('// $' + 'method call. sym="$node.sym.name"')
|
||||
|
|
|
@ -46,32 +46,58 @@ fn (mut p Parser) hash() ast.HashStmt {
|
|||
|
||||
fn (mut p Parser) vweb() ast.ComptimeCall {
|
||||
p.check(.dollar)
|
||||
p.check(.name) // skip `vweb.html()` TODO
|
||||
p.check(.dot)
|
||||
p.check(.name)
|
||||
error_msg := 'only `\$tmpl()` and `\$vweb.html()` comptime functions are supported right now'
|
||||
if p.peek_tok.kind == .dot {
|
||||
n := p.check_name() // skip `vweb.html()` TODO
|
||||
if n != 'vweb' {
|
||||
p.error(error_msg)
|
||||
}
|
||||
p.check(.dot)
|
||||
}
|
||||
n := p.check_name() // (.name)
|
||||
if n != 'html' && n != 'tmpl' {
|
||||
p.error(error_msg)
|
||||
}
|
||||
is_html := n == 'html'
|
||||
p.check(.lpar)
|
||||
s := if is_html { '' } else { p.tok.lit }
|
||||
if !is_html {
|
||||
p.check(.string)
|
||||
}
|
||||
println('SSSS "$s"')
|
||||
p.check(.rpar)
|
||||
// Compile vweb html template to V code, parse that V code and embed the resulting V function
|
||||
// that returns an html string.
|
||||
fn_path := p.cur_fn_name.split('_')
|
||||
html_name := '${fn_path.last()}.html'
|
||||
tmpl_path := if is_html { '${fn_path.last()}.html' } else { s }
|
||||
// Looking next to the vweb program
|
||||
dir := os.dir(p.scanner.file_path)
|
||||
mut path := os.join_path(dir, fn_path.join('/'))
|
||||
path += '.html'
|
||||
if !is_html {
|
||||
path = tmpl_path
|
||||
}
|
||||
if !os.exists(path) {
|
||||
// can be in `templates/`
|
||||
path = os.join_path(dir, 'templates', fn_path.join('/'))
|
||||
path += '.html'
|
||||
if is_html {
|
||||
path = os.join_path(dir, 'templates', fn_path.join('/'))
|
||||
path += '.html'
|
||||
}
|
||||
if !os.exists(path) {
|
||||
p.error('vweb HTML template "$path" not found')
|
||||
if is_html {
|
||||
p.error('vweb HTML template "$path" not found')
|
||||
} else {
|
||||
p.error('template file "$path" not found')
|
||||
}
|
||||
}
|
||||
// println('path is now "$path"')
|
||||
}
|
||||
if p.pref.is_verbose {
|
||||
println('>>> compiling vweb HTML template "$path"')
|
||||
if true || p.pref.is_verbose {
|
||||
println('>>> compiling comptime template file "$path"')
|
||||
}
|
||||
v_code := tmpl.compile_file(path, p.cur_fn_name)
|
||||
tmp_fn_name := p.cur_fn_name.replace('.', '__')
|
||||
v_code := tmpl.compile_file(path, tmp_fn_name)
|
||||
println('done')
|
||||
$if print_vweb_template_expansions ? {
|
||||
lines := v_code.split('\n')
|
||||
for i, line in lines {
|
||||
|
@ -82,22 +108,22 @@ fn (mut p Parser) vweb() ast.ComptimeCall {
|
|||
start_pos: 0
|
||||
parent: p.global_scope
|
||||
}
|
||||
mut file := parse_text(v_code, p.table, p.pref, scope, p.global_scope)
|
||||
if p.pref.is_verbose {
|
||||
if true || p.pref.is_verbose {
|
||||
println('\n\n')
|
||||
println('>>> vweb template for $path:')
|
||||
println(v_code)
|
||||
println('>>> end of vweb template END')
|
||||
println('\n\n')
|
||||
}
|
||||
mut file := parse_text(v_code, p.table, p.pref, scope, p.global_scope)
|
||||
file = {
|
||||
file |
|
||||
path: html_name
|
||||
path: tmpl_path
|
||||
}
|
||||
// copy vars from current fn scope into vweb_tmpl scope
|
||||
for stmt in file.stmts {
|
||||
if stmt is ast.FnDecl {
|
||||
if stmt.name == 'main.vweb_tmpl_$p.cur_fn_name' {
|
||||
if stmt.name == 'main.vweb_tmpl_$tmp_fn_name' {
|
||||
mut tmpl_scope := file.scope.innermost(stmt.body_pos.pos)
|
||||
for _, obj in p.scope.objects {
|
||||
if obj is ast.Var {
|
||||
|
@ -105,7 +131,7 @@ fn (mut p Parser) vweb() ast.ComptimeCall {
|
|||
v.pos = stmt.body_pos
|
||||
tmpl_scope.register(v.name, v)
|
||||
// set the controller action var to used
|
||||
// if its unused in the template it will warn
|
||||
// if it's unused in the template it will warn
|
||||
v.is_used = true
|
||||
}
|
||||
}
|
||||
|
@ -116,6 +142,7 @@ fn (mut p Parser) vweb() ast.ComptimeCall {
|
|||
return ast.ComptimeCall{
|
||||
is_vweb: true
|
||||
vweb_tmpl: file
|
||||
method_name: n
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,23 +5,24 @@ import benchmark
|
|||
|
||||
fn test_all_v_prod_files() {
|
||||
// TODO: Fix running this test on Windows:
|
||||
$if !windows {
|
||||
options := runner.new_prod_options()
|
||||
mut bmark := benchmark.new_benchmark()
|
||||
for file in options.files {
|
||||
// println('file:$file')
|
||||
bmark.step()
|
||||
fres := runner.run_prod_file(options.wd, options.vexec, file) or {
|
||||
bmark.fail()
|
||||
eprintln(bmark.step_message_fail(err))
|
||||
assert false
|
||||
continue
|
||||
}
|
||||
bmark.ok()
|
||||
println(bmark.step_message_ok(fres))
|
||||
assert true
|
||||
}
|
||||
bmark.stop()
|
||||
println(bmark.total_message('total time spent running PROD files'))
|
||||
$if windows {
|
||||
return
|
||||
}
|
||||
options := runner.new_prod_options()
|
||||
mut bmark := benchmark.new_benchmark()
|
||||
for file in options.files {
|
||||
// println('file:$file')
|
||||
bmark.step()
|
||||
fres := runner.run_prod_file(options.wd, options.vexec, file) or {
|
||||
bmark.fail()
|
||||
eprintln(bmark.step_message_fail(err))
|
||||
assert false
|
||||
continue
|
||||
}
|
||||
bmark.ok()
|
||||
println(bmark.step_message_ok(fres))
|
||||
assert true
|
||||
}
|
||||
bmark.stop()
|
||||
println(bmark.total_message('total time spent running PROD files'))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
name: @name
|
||||
|
||||
age: @age
|
||||
|
||||
numbers: @numbers
|
||||
|
||||
@for number in numbers
|
||||
@number
|
||||
@end
|
|
@ -0,0 +1,21 @@
|
|||
fn one() string {
|
||||
name := 'Peter'
|
||||
age := 25
|
||||
numbers := [1, 2, 3]
|
||||
return $tmpl('tmpl/1.txt')
|
||||
}
|
||||
|
||||
fn test_tmpl() {
|
||||
assert one().trim_space() == 'name: Peter
|
||||
|
||||
age: 25
|
||||
|
||||
numbers: [1, 2, 3]
|
||||
|
||||
|
||||
1
|
||||
|
||||
2
|
||||
|
||||
3'
|
||||
}
|
Loading…
Reference in New Issue