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() {
|
fn (g &Game) draw_next_tetro() {
|
||||||
if g.state != .gameover {
|
if g.state != .gameover {
|
||||||
idx := g.next_tetro_idx * tetro_size * tetro_size
|
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_y := 0
|
||||||
pos_x := field_width / 2 - tetro_size / 2
|
pos_x := field_width / 2 - tetro_size / 2
|
||||||
for i in 0 .. tetro_size {
|
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
|
// TODO: non deferred
|
||||||
pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
||||||
c.expected_type = c.cur_fn.return_type
|
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',
|
c.error('too many arguments to return, current function does not return anything',
|
||||||
return_stmt.pos)
|
return_stmt.pos)
|
||||||
return
|
return
|
||||||
} else if return_stmt.exprs.len == 0 && !(c.expected_type == table.void_type ||
|
} 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)
|
c.error('too few arguments to return', return_stmt.pos)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if return_stmt.exprs.len == 0 {
|
if return_stmt.exprs.len == 0 {
|
||||||
return
|
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)
|
exp_is_optional := expected_type.has_flag(.optional)
|
||||||
mut expected_types := [expected_type]
|
mut expected_types := [expected_type]
|
||||||
if expected_type_sym.kind == .multi_return {
|
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_warnings += c2.nr_warnings
|
||||||
c.nr_errors += c2.nr_errors
|
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
|
// return table.void_type
|
||||||
}
|
}
|
||||||
ast.ConcatExpr {
|
ast.ConcatExpr {
|
||||||
|
|
|
@ -9,18 +9,28 @@ import v.util
|
||||||
|
|
||||||
fn (mut g Gen) comptime_call(node ast.ComptimeCall) {
|
fn (mut g Gen) comptime_call(node ast.ComptimeCall) {
|
||||||
if node.is_vweb {
|
if node.is_vweb {
|
||||||
|
is_html := node.method_name == 'html'
|
||||||
for stmt in node.vweb_tmpl.stmts {
|
for stmt in node.vweb_tmpl.stmts {
|
||||||
if stmt is ast.FnDecl {
|
if stmt is ast.FnDecl {
|
||||||
// insert stmts from vweb_tmpl fn
|
// insert stmts from vweb_tmpl fn
|
||||||
if stmt.name.starts_with('main.vweb_tmpl') {
|
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.stmts(stmt.stmts)
|
||||||
g.inside_vweb_tmpl = false
|
g.inside_vweb_tmpl = false
|
||||||
break
|
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
|
return
|
||||||
}
|
}
|
||||||
g.writeln('// $' + 'method call. sym="$node.sym.name"')
|
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 {
|
fn (mut p Parser) vweb() ast.ComptimeCall {
|
||||||
p.check(.dollar)
|
p.check(.dollar)
|
||||||
p.check(.name) // skip `vweb.html()` TODO
|
error_msg := 'only `\$tmpl()` and `\$vweb.html()` comptime functions are supported right now'
|
||||||
p.check(.dot)
|
if p.peek_tok.kind == .dot {
|
||||||
p.check(.name)
|
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)
|
p.check(.lpar)
|
||||||
|
s := if is_html { '' } else { p.tok.lit }
|
||||||
|
if !is_html {
|
||||||
|
p.check(.string)
|
||||||
|
}
|
||||||
|
println('SSSS "$s"')
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
// 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.
|
||||||
fn_path := p.cur_fn_name.split('_')
|
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
|
// Looking next to the vweb program
|
||||||
dir := os.dir(p.scanner.file_path)
|
dir := os.dir(p.scanner.file_path)
|
||||||
mut path := os.join_path(dir, fn_path.join('/'))
|
mut path := os.join_path(dir, fn_path.join('/'))
|
||||||
path += '.html'
|
path += '.html'
|
||||||
|
if !is_html {
|
||||||
|
path = tmpl_path
|
||||||
|
}
|
||||||
if !os.exists(path) {
|
if !os.exists(path) {
|
||||||
// can be in `templates/`
|
// can be in `templates/`
|
||||||
path = os.join_path(dir, 'templates', fn_path.join('/'))
|
if is_html {
|
||||||
path += '.html'
|
path = os.join_path(dir, 'templates', fn_path.join('/'))
|
||||||
|
path += '.html'
|
||||||
|
}
|
||||||
if !os.exists(path) {
|
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"')
|
// println('path is now "$path"')
|
||||||
}
|
}
|
||||||
if p.pref.is_verbose {
|
if true || p.pref.is_verbose {
|
||||||
println('>>> compiling vweb HTML template "$path"')
|
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 ? {
|
$if print_vweb_template_expansions ? {
|
||||||
lines := v_code.split('\n')
|
lines := v_code.split('\n')
|
||||||
for i, line in lines {
|
for i, line in lines {
|
||||||
|
@ -82,22 +108,22 @@ fn (mut p Parser) vweb() ast.ComptimeCall {
|
||||||
start_pos: 0
|
start_pos: 0
|
||||||
parent: p.global_scope
|
parent: p.global_scope
|
||||||
}
|
}
|
||||||
mut file := parse_text(v_code, p.table, p.pref, scope, p.global_scope)
|
if true || 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')
|
||||||
}
|
}
|
||||||
|
mut file := parse_text(v_code, p.table, p.pref, scope, p.global_scope)
|
||||||
file = {
|
file = {
|
||||||
file |
|
file |
|
||||||
path: html_name
|
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 {
|
||||||
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)
|
mut tmpl_scope := file.scope.innermost(stmt.body_pos.pos)
|
||||||
for _, obj in p.scope.objects {
|
for _, obj in p.scope.objects {
|
||||||
if obj is ast.Var {
|
if obj is ast.Var {
|
||||||
|
@ -105,7 +131,7 @@ fn (mut p Parser) vweb() ast.ComptimeCall {
|
||||||
v.pos = stmt.body_pos
|
v.pos = stmt.body_pos
|
||||||
tmpl_scope.register(v.name, v)
|
tmpl_scope.register(v.name, v)
|
||||||
// set the controller action var to used
|
// 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
|
v.is_used = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,6 +142,7 @@ fn (mut p Parser) vweb() ast.ComptimeCall {
|
||||||
return ast.ComptimeCall{
|
return ast.ComptimeCall{
|
||||||
is_vweb: true
|
is_vweb: true
|
||||||
vweb_tmpl: file
|
vweb_tmpl: file
|
||||||
|
method_name: n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,23 +5,24 @@ import benchmark
|
||||||
|
|
||||||
fn test_all_v_prod_files() {
|
fn test_all_v_prod_files() {
|
||||||
// TODO: Fix running this test on Windows:
|
// TODO: Fix running this test on Windows:
|
||||||
$if !windows {
|
$if windows {
|
||||||
options := runner.new_prod_options()
|
return
|
||||||
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'))
|
|
||||||
}
|
}
|
||||||
|
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