v icon indicating copy to clipboard operation
v copied to clipboard

Use of $tmpl cannot be used as a function parameter

Open chrisdavies opened this issue 2 years ago • 1 comments

V 0.3.0 3bdf2f0

What did you do?

Attempted to return an HTML template by explicitly referring to it by name from a web handler:

return app.html($tmpl('index.html'))

What did you expect to see?

The rendered template.

What did you see instead?

The program fails to compile:

/tmp/v_1000/vvv.6869482243414842251.tmp.c:31972: error: identifier expected

Workaround

	s := $tmpl('index.html')
	return app.html(s)

Here's the generated line 31999 (the issue is the return _tmpl_res_login733 part):

		vweb__Result _t2 = vweb__Context_html(&app->Context, return _tmpl_res_login733);

This should just be something like this (the return is removed):

		vweb__Result _t2 = vweb__Context_html(&app->Context, _tmpl_res_login733);

It looks like the $tmpl function / pragma / whatever that is is being blindly replaced with a return {template} in the generated C, rather than taking its context into account.

V doctor

OS: linux, Linux version 5.18.7-200.fc36.x86_64 ([email protected]) (gcc (GCC) 12.1.1 20220507 (Red Hat 12.1.1-1), GNU ld version 2.37-27.fc36) #1 SMP PREEMPT_DYNAMIC Sat Jun 25 20:06:14 UTC 2022 Processor: 12 cpus, 64bit, little endian, Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz CC version: cc (GCC) 12.1.1 20220507 (Red Hat 12.1.1-1)

getwd: /home/chip vmodules: /home/chip/.vmodules vroot: /home/chip/bin vexe: /home/chip/bin/v vexe mtime: 2022-07-04 14:53:19 is vroot writable: true is vmodules writable: true V full version: V 0.3.0 eb10cc9.3bdf2f0

Git version: git version 2.36.1 Git vroot status: 0.3-28-g3bdf2f05 .git/config present: true thirdparty/tcc status: thirdparty-linux-amd64 827f7452

Full source

<!-- index.html -->
<html>
  <head>
    <title>V Test</title>
  </head>
  <body>
    <form method="POST" action="/login">
      <h1>Login</h1>
      <input placeholder="email" type="email" name="email" />
      <input placeholder="password" type="password" name="password" />
      <button>Login</button>
    </form>
  </body>
</html>
// main.v
import vweb

struct App {
	vweb.Context
}

fn main() {
	vweb.run(&App{}, 3003)
}

[post]
fn (mut app App) login(email string, password string) vweb.Result {
	if email == '[email protected]' && password == 'password' {
		name := email.split('@')[0]
		return app.redirect('/hello/$name')
	}
	// This is the offending line
	return app.html($tmpl('index.html'))
}

['/']
fn (mut app App) index() vweb.Result {
	return $vweb.html()
}

['/hello/:name']
fn (mut app App) hello_name(name string) vweb.Result {
	return app.text('Hello, $name!')
}

chrisdavies avatar Jul 04 '22 15:07 chrisdavies

$tmpl is being replaced with other code at compile time so I don't think this is a bug. The $tmpl function isn't executed at compile time so it is not replaced with a string value as you might think.

It seems to me that the workaround you found is the intended behaviour, as it also passes a string to app.html. I think this should be more clarified in the docs.

Casper64 avatar Sep 07 '22 18:09 Casper64

at least, proper checker error message is needed.

kahsa avatar Oct 23 '22 01:10 kahsa

Fixed by #16229.

yuyi98 avatar Oct 28 '22 13:10 yuyi98