vweb: ['/:arg1/:arg2/action'] attribute
parent
f03688e443
commit
b7175b54eb
|
@ -249,3 +249,9 @@ fn __print_assert_failure(i &VAssertMetaInfo) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MethodAttr {
|
||||
pub:
|
||||
value string
|
||||
method string
|
||||
}
|
||||
|
|
|
@ -15,10 +15,10 @@ pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CallExpr | C
|
|||
ParExpr | PostfixExpr | PrefixExpr | RangeExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral |
|
||||
StringLiteral | StructInit | Type | TypeOf
|
||||
|
||||
pub type Stmt = AssertStmt | AssignStmt | Attr | Block | BranchStmt | Comment | CompIf |
|
||||
ConstDecl | DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt |
|
||||
GlobalDecl | GoStmt | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module |
|
||||
Return | SqlStmt | StructDecl | TypeDecl | UnsafeStmt
|
||||
pub type Stmt = AssertStmt | AssignStmt | Attr | Block | BranchStmt | Comment | CompFor |
|
||||
CompIf | ConstDecl | DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt |
|
||||
ForStmt | GlobalDecl | GoStmt | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl |
|
||||
Module | Return | SqlStmt | StructDecl | TypeDecl | UnsafeStmt
|
||||
|
||||
pub type ScopeObject = ConstField | GlobalDecl | Var
|
||||
|
||||
|
@ -457,11 +457,11 @@ pub mut:
|
|||
|
||||
pub struct MatchBranch {
|
||||
pub:
|
||||
exprs []Expr // left side
|
||||
stmts []Stmt // right side
|
||||
pos token.Position
|
||||
comment Comment // comment above `xxx {`
|
||||
is_else bool
|
||||
exprs []Expr // left side
|
||||
stmts []Stmt // right side
|
||||
pos token.Position
|
||||
comment Comment // comment above `xxx {`
|
||||
is_else bool
|
||||
post_comments []Comment
|
||||
}
|
||||
|
||||
|
@ -486,6 +486,15 @@ pub mut:
|
|||
else_stmts []Stmt
|
||||
}
|
||||
|
||||
pub struct CompFor {
|
||||
pub:
|
||||
val_var string
|
||||
stmts []Stmt
|
||||
pub mut:
|
||||
// expr Expr
|
||||
typ table.Type
|
||||
}
|
||||
|
||||
pub struct ForStmt {
|
||||
pub:
|
||||
cond Expr
|
||||
|
@ -594,12 +603,12 @@ pub:
|
|||
|
||||
pub struct EnumDecl {
|
||||
pub:
|
||||
name string
|
||||
is_pub bool
|
||||
is_flag bool // true when the enum has [flag] tag
|
||||
name string
|
||||
is_pub bool
|
||||
is_flag bool // true when the enum has [flag] tag
|
||||
comments []Comment // enum Abc { /* comments */ ... }
|
||||
fields []EnumField
|
||||
pos token.Position
|
||||
fields []EnumField
|
||||
pos token.Position
|
||||
}
|
||||
|
||||
pub struct AliasTypeDecl {
|
||||
|
@ -799,6 +808,7 @@ pub:
|
|||
left Expr
|
||||
is_vweb bool
|
||||
vweb_tmpl File
|
||||
args_var string
|
||||
pub mut:
|
||||
sym table.TypeSymbol
|
||||
}
|
||||
|
@ -876,7 +886,7 @@ pub fn (expr Expr) position() token.Position {
|
|||
AsCast {
|
||||
return expr.pos
|
||||
}
|
||||
// ast.Ident { }
|
||||
// ast.Ident { }
|
||||
CastExpr {
|
||||
return expr.pos
|
||||
}
|
||||
|
@ -904,7 +914,7 @@ pub fn (expr Expr) position() token.Position {
|
|||
IfExpr {
|
||||
return expr.pos
|
||||
}
|
||||
// ast.IfGuardExpr { }
|
||||
// ast.IfGuardExpr { }
|
||||
IndexExpr {
|
||||
return expr.pos
|
||||
}
|
||||
|
@ -935,12 +945,11 @@ pub fn (expr Expr) position() token.Position {
|
|||
PostfixExpr {
|
||||
return expr.pos
|
||||
}
|
||||
// ast.None { }
|
||||
// ast.None { }
|
||||
PrefixExpr {
|
||||
|
||||
return expr.pos
|
||||
}
|
||||
// ast.ParExpr { }
|
||||
// ast.ParExpr { }
|
||||
SelectorExpr {
|
||||
return expr.pos
|
||||
}
|
||||
|
@ -953,14 +962,14 @@ pub fn (expr Expr) position() token.Position {
|
|||
StringInterLiteral {
|
||||
return expr.pos
|
||||
}
|
||||
// ast.Type { }
|
||||
// ast.Type { }
|
||||
StructInit {
|
||||
return expr.pos
|
||||
}
|
||||
Likely {
|
||||
return expr.pos
|
||||
}
|
||||
// ast.TypeOf { }
|
||||
// ast.TypeOf { }
|
||||
else {
|
||||
return token.Position{}
|
||||
}
|
||||
|
@ -971,29 +980,29 @@ pub fn (stmt Stmt) position() token.Position {
|
|||
match stmt {
|
||||
AssertStmt { return stmt.pos }
|
||||
AssignStmt { return stmt.pos }
|
||||
/*
|
||||
// Attr {
|
||||
/*
|
||||
// Attr {
|
||||
// }
|
||||
// Block {
|
||||
// }
|
||||
// BranchStmt {
|
||||
// }
|
||||
*/
|
||||
*/
|
||||
Comment { return stmt.pos }
|
||||
CompIf { return stmt.pos }
|
||||
ConstDecl { return stmt.pos }
|
||||
/*
|
||||
// DeferStmt {
|
||||
/*
|
||||
// DeferStmt {
|
||||
// }
|
||||
*/
|
||||
*/
|
||||
EnumDecl { return stmt.pos }
|
||||
ExprStmt { return stmt.pos }
|
||||
FnDecl { return stmt.pos }
|
||||
ForCStmt { return stmt.pos }
|
||||
ForInStmt { return stmt.pos }
|
||||
ForStmt { return stmt.pos }
|
||||
/*
|
||||
// GlobalDecl {
|
||||
/*
|
||||
// GlobalDecl {
|
||||
// }
|
||||
// GoStmt {
|
||||
// }
|
||||
|
@ -1003,23 +1012,23 @@ pub fn (stmt Stmt) position() token.Position {
|
|||
// }
|
||||
// HashStmt {
|
||||
// }
|
||||
*/
|
||||
*/
|
||||
Import { return stmt.pos }
|
||||
/*
|
||||
// InterfaceDecl {
|
||||
/*
|
||||
// InterfaceDecl {
|
||||
// }
|
||||
// Module {
|
||||
// }
|
||||
*/
|
||||
*/
|
||||
Return { return stmt.pos }
|
||||
StructDecl { return stmt.pos }
|
||||
/*
|
||||
// TypeDecl {
|
||||
/*
|
||||
// TypeDecl {
|
||||
// }
|
||||
// UnsafeStmt {
|
||||
// }
|
||||
*/
|
||||
//
|
||||
*/
|
||||
//
|
||||
else { return token.Position{} }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,9 +105,8 @@ pub fn (mut c Checker) check2(ast_file ast.File) []errors.Error {
|
|||
pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
||||
mut has_main_mod_file := false
|
||||
mut has_main_fn := false
|
||||
|
||||
mut files_from_main_module := []&ast.File{}
|
||||
for i in 0..ast_files.len {
|
||||
for i in 0 .. ast_files.len {
|
||||
file := &ast_files[i]
|
||||
c.check(file)
|
||||
if file.mod.name == 'main' {
|
||||
|
@ -118,7 +117,6 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if has_main_mod_file && !has_main_fn && files_from_main_module.len > 0 {
|
||||
if c.pref.is_script && !c.pref.is_test {
|
||||
first_main_file := files_from_main_module[0]
|
||||
|
@ -131,7 +129,6 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
|||
has_main_fn = true
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure fn main is defined in non lib builds
|
||||
if c.pref.build_mode == .build_module || c.pref.is_test {
|
||||
return
|
||||
|
@ -163,14 +160,14 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
|
|||
c.warn('const $no_pub_in_main_warning', stmt.pos)
|
||||
}
|
||||
}
|
||||
/*
|
||||
// TODO not a Stmt
|
||||
/*
|
||||
// TODO not a Stmt
|
||||
ast.ConstField {
|
||||
if stmt.is_pub {
|
||||
c.warn('const field `$stmt.name` $no_pub_in_main_warning', stmt.pos)
|
||||
}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
ast.EnumDecl {
|
||||
if stmt.is_pub {
|
||||
c.warn('enum `$stmt.name` $no_pub_in_main_warning', stmt.pos)
|
||||
|
@ -232,7 +229,7 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
|
|||
}
|
||||
|
||||
fn (mut c Checker) check_valid_snake_case(name, identifier string, pos token.Position) {
|
||||
if !c.pref.is_vweb && ( name[0] == `_` || name.contains('._') ) {
|
||||
if !c.pref.is_vweb && (name[0] == `_` || name.contains('._')) {
|
||||
c.error('$identifier `$name` cannot start with `_`', pos)
|
||||
}
|
||||
if util.contains_capital(name) {
|
||||
|
@ -378,7 +375,7 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
|
|||
.placeholder {
|
||||
c.error('unknown struct: $type_sym.name', struct_init.pos)
|
||||
}
|
||||
// string & array are also structs but .kind of string/array
|
||||
// string & array are also structs but .kind of string/array
|
||||
.struct_, .string, .array, .alias {
|
||||
mut info := table.Struct{}
|
||||
if type_sym.kind == .alias {
|
||||
|
@ -1044,10 +1041,10 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
|||
if rts_info.generic_types.len > 0 {
|
||||
// TODO: multiple generic types
|
||||
// for gt in rts_info.generic_types {
|
||||
// gtss := c.table.get_type_symbol(gt)
|
||||
// gtss := c.table.get_type_symbol(gt)
|
||||
// }
|
||||
gts := c.table.get_type_symbol(call_expr.generic_type)
|
||||
nrt := '${rts.name}<$gts.name>'
|
||||
nrt := '$rts.name<$gts.name>'
|
||||
idx := c.table.type_idxs[nrt]
|
||||
if idx == 0 {
|
||||
c.error('unknown type: $nrt', call_expr.pos)
|
||||
|
@ -1055,8 +1052,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
|||
call_expr.return_type = table.new_type(idx).derive(f.return_type)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
call_expr.return_type = f.return_type
|
||||
}
|
||||
if f.return_type == table.void_type &&
|
||||
|
@ -1509,8 +1505,7 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
|||
right_sym := c.table.get_type_symbol(right_type_unwrapped)
|
||||
if (left_type.is_ptr() || left_sym.is_pointer()) &&
|
||||
assign_stmt.op !in [.assign, .decl_assign] && !c.inside_unsafe {
|
||||
c.error('pointer arithmetic is only allowed in `unsafe` blocks',
|
||||
assign_stmt.pos)
|
||||
c.error('pointer arithmetic is only allowed in `unsafe` blocks', assign_stmt.pos)
|
||||
}
|
||||
// Single side check
|
||||
match assign_stmt.op {
|
||||
|
@ -1732,7 +1727,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
|||
node.pos)
|
||||
}
|
||||
}
|
||||
// ast.Attr {}
|
||||
// ast.Attr {}
|
||||
ast.AssignStmt {
|
||||
c.assign_stmt(mut node)
|
||||
}
|
||||
|
@ -1744,6 +1739,10 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
|||
c.error('$node.tok.lit statement not within a loop', node.tok.position())
|
||||
}
|
||||
}
|
||||
ast.CompFor {
|
||||
// node.typ = c.expr(node.expr)
|
||||
c.stmts(node.stmts)
|
||||
}
|
||||
ast.CompIf {
|
||||
// c.expr(it.cond)
|
||||
c.stmts(node.stmts)
|
||||
|
@ -1897,7 +1896,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
|||
}
|
||||
}
|
||||
}
|
||||
// ast.HashStmt {}
|
||||
// ast.HashStmt {}
|
||||
ast.Import {}
|
||||
ast.InterfaceDecl {
|
||||
c.interface_decl(it)
|
||||
|
@ -2317,7 +2316,7 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
|||
// main.compare_f32 may actually be builtin.compare_f32
|
||||
saved_mod := ident.mod
|
||||
ident.mod = 'builtin'
|
||||
builtin_type := c.ident( ident )
|
||||
builtin_type := c.ident(ident)
|
||||
if builtin_type != table.void_type {
|
||||
return builtin_type
|
||||
}
|
||||
|
@ -2446,7 +2445,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
|
|||
unhandled << '`$v_str`'
|
||||
}
|
||||
} }
|
||||
//
|
||||
//
|
||||
table.Enum { for v in it.vals {
|
||||
if v !in branch_exprs {
|
||||
is_exhaustive = false
|
||||
|
@ -2580,8 +2579,7 @@ pub fn (mut c Checker) postfix_expr(node ast.PostfixExpr) table.Type {
|
|||
c.fail_if_immutable(node.expr)
|
||||
}
|
||||
if (typ.is_ptr() || typ_sym.is_pointer()) && !c.inside_unsafe {
|
||||
c.error('pointer arithmetic is only allowed in `unsafe` blocks',
|
||||
node.pos)
|
||||
c.error('pointer arithmetic is only allowed in `unsafe` blocks', node.pos)
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
|
|
@ -290,6 +290,7 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) {
|
|||
ast.Comment {
|
||||
f.comment(it)
|
||||
}
|
||||
ast.CompFor {}
|
||||
ast.CompIf {
|
||||
inversion := if it.is_not { '!' } else { '' }
|
||||
is_opt := if it.is_opt { ' ?' } else { '' }
|
||||
|
|
|
@ -94,6 +94,7 @@ mut:
|
|||
inside_call bool
|
||||
has_main bool
|
||||
inside_const bool
|
||||
comp_for_method string // $for method in T {
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -625,6 +626,9 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
|||
// }
|
||||
}
|
||||
ast.Comment {}
|
||||
ast.CompFor {
|
||||
g.comp_for(node)
|
||||
}
|
||||
ast.CompIf {
|
||||
g.comp_if(node)
|
||||
}
|
||||
|
@ -1160,7 +1164,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
|||
is_call = true
|
||||
return_type = val.return_type
|
||||
}
|
||||
// TODO: no buffer fiddling
|
||||
// TODO: no buffer fiddling
|
||||
ast.AnonFn {
|
||||
if blank_assign {
|
||||
g.write('{')
|
||||
|
@ -3044,7 +3048,7 @@ fn (g Gen) sort_structs(typesa []table.TypeSymbol) []table.TypeSymbol {
|
|||
field_deps << dep
|
||||
}
|
||||
}
|
||||
// table.Interface {}
|
||||
// table.Interface {}
|
||||
else {}
|
||||
}
|
||||
// add type and dependant types to graph
|
||||
|
@ -3504,11 +3508,11 @@ fn (mut g Gen) comp_if_to_ifdef(name string, is_comptime_optional bool) string {
|
|||
'linux_or_macos' {
|
||||
return ''
|
||||
}
|
||||
//
|
||||
//
|
||||
'js' {
|
||||
return '_VJS'
|
||||
}
|
||||
// compilers:
|
||||
// compilers:
|
||||
'tinyc' {
|
||||
return '__TINYC__'
|
||||
}
|
||||
|
@ -3524,7 +3528,7 @@ fn (mut g Gen) comp_if_to_ifdef(name string, is_comptime_optional bool) string {
|
|||
'cplusplus' {
|
||||
return '__cplusplus'
|
||||
}
|
||||
// other:
|
||||
// other:
|
||||
'debug' {
|
||||
return '_VDEBUG'
|
||||
}
|
||||
|
|
|
@ -27,11 +27,40 @@ fn (g &Gen) comptime_call(node ast.ComptimeCall) {
|
|||
g.writeln('// $' + 'method call. sym="$node.sym.name"')
|
||||
mut j := 0
|
||||
result_type := g.table.find_type_idx('vweb.Result') // TODO not just vweb
|
||||
if node.method_name == 'method' {
|
||||
// `app.$method()`
|
||||
m := node.sym.find_method(g.comp_for_method) or {
|
||||
return
|
||||
}
|
||||
/*
|
||||
vals := m.attrs[0].split('/')
|
||||
args := vals.filter(it.starts_with(':')).map(it[1..])
|
||||
println(vals)
|
||||
for val in vals {
|
||||
}
|
||||
*/
|
||||
g.write('${util.no_dots(node.sym.name)}_${g.comp_for_method}(')
|
||||
g.expr(node.left)
|
||||
if m.args.len > 1 {
|
||||
g.write(', ')
|
||||
}
|
||||
for i in 0 .. m.args.len - 1 {
|
||||
g.write('((string*)${node.args_var}.data) [$i] ')
|
||||
if i < m.args.len - 2 {
|
||||
g.write(', ')
|
||||
}
|
||||
}
|
||||
g.write(' ); // vweb action call with args')
|
||||
return
|
||||
}
|
||||
for method in node.sym.methods {
|
||||
// if method.return_type != table.void_type {
|
||||
if method.return_type != result_type {
|
||||
continue
|
||||
}
|
||||
if method.args.len != 1 {
|
||||
continue
|
||||
}
|
||||
// receiver := method.args[0]
|
||||
// if !p.expr_var.ptr {
|
||||
// p.error('`$p.expr_var.name` needs to be a reference')
|
||||
|
@ -69,3 +98,29 @@ fn (mut g Gen) comp_if(it ast.CompIf) {
|
|||
}
|
||||
g.writeln('\n#endif\n// } $it.val\n')
|
||||
}
|
||||
|
||||
fn (mut g Gen) comp_for(node ast.CompFor) {
|
||||
g.writeln('// comptime $' + 'for {')
|
||||
sym := g.table.get_type_symbol(g.unwrap_generic(node.typ))
|
||||
mut i := 0
|
||||
// g.writeln('string method = tos_lit("");')
|
||||
for method in sym.methods {
|
||||
if method.attrs.len == 0 {
|
||||
continue
|
||||
}
|
||||
g.comp_for_method = method.name
|
||||
g.writeln('\t// method $i')
|
||||
if i == 0 {
|
||||
g.write('\tstring ')
|
||||
}
|
||||
g.writeln('method = tos_lit("$method.name");')
|
||||
if i == 0 {
|
||||
g.write('\tstring ')
|
||||
}
|
||||
g.writeln('attrs = tos_lit("${method.attrs[0]}");')
|
||||
g.stmts(node.stmts)
|
||||
i++
|
||||
g.writeln('')
|
||||
}
|
||||
g.writeln('// } comptime for')
|
||||
}
|
||||
|
|
|
@ -422,6 +422,8 @@ fn (mut g JsGen) stmt(node ast.Stmt) {
|
|||
ast.Comment {
|
||||
// Skip: don't generate comments
|
||||
}
|
||||
ast.CompFor {
|
||||
}
|
||||
ast.CompIf {
|
||||
// skip: JS has no compile time if
|
||||
}
|
||||
|
|
|
@ -116,12 +116,15 @@ fn (mut p Parser) vweb() ast.ComptimeCall {
|
|||
println('>>> end of vweb template END')
|
||||
println('\n\n')
|
||||
}
|
||||
file = {file| path:html_name}
|
||||
file = {
|
||||
file |
|
||||
path: html_name
|
||||
}
|
||||
// copy vars from current fn scope into vweb_tmpl scope
|
||||
for stmt in file.stmts {
|
||||
if stmt is ast.FnDecl {
|
||||
fn_decl := stmt as ast.FnDecl
|
||||
if fn_decl.name == 'main.vweb_tmpl_${p.cur_fn_name}' {
|
||||
if fn_decl.name == 'main.vweb_tmpl_$p.cur_fn_name' {
|
||||
tmpl_scope := file.scope.innermost(fn_decl.body_pos.pos)
|
||||
for _, obj in p.scope.objects {
|
||||
if obj is ast.Var {
|
||||
|
@ -143,6 +146,32 @@ fn (mut p Parser) vweb() ast.ComptimeCall {
|
|||
}
|
||||
}
|
||||
|
||||
fn (mut p Parser) comp_for() ast.CompFor {
|
||||
println('COMP FOR')
|
||||
p.next()
|
||||
p.check(.key_for)
|
||||
val_var := p.check_name()
|
||||
p.scope.register(val_var, ast.Var{
|
||||
name: val_var
|
||||
typ: table.string_type
|
||||
})
|
||||
p.scope.register('attrs', ast.Var{
|
||||
name: 'attrs'
|
||||
typ: table.string_type
|
||||
})
|
||||
p.check(.key_in)
|
||||
// expr := p.expr(0)
|
||||
typ := p.parse_type()
|
||||
// p.check(.dot)
|
||||
// p.check_name()
|
||||
stmts := p.parse_block()
|
||||
return ast.CompFor{
|
||||
val_var: val_var
|
||||
stmts: stmts
|
||||
typ: typ
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut p Parser) comp_if() ast.Stmt {
|
||||
pos := p.tok.position()
|
||||
p.next()
|
||||
|
@ -159,15 +188,13 @@ fn (mut p Parser) comp_if() ast.Stmt {
|
|||
mut skip := false
|
||||
if val in supported_platforms {
|
||||
os := os_from_string(val)
|
||||
if (!is_not && os != p.pref.os) ||
|
||||
(is_not && os == p.pref.os) {
|
||||
if (!is_not && os != p.pref.os) || (is_not && os == p.pref.os) {
|
||||
skip = true
|
||||
}
|
||||
} else if val in supported_ccompilers {
|
||||
cc := cc_from_string(val)
|
||||
user_cc := cc_from_string(p.pref.ccompiler)
|
||||
if (!is_not && cc != user_cc) ||
|
||||
(is_not && cc == user_cc) {
|
||||
if (!is_not && cc != user_cc) || (is_not && cc == user_cc) {
|
||||
skip = true
|
||||
}
|
||||
}
|
||||
|
@ -215,8 +242,7 @@ fn (mut p Parser) comp_if() ast.Stmt {
|
|||
val: val
|
||||
stmts: stmts
|
||||
}
|
||||
if p.tok.kind == .dollar &&
|
||||
p.peek_tok.kind == .key_else {
|
||||
if p.tok.kind == .dollar && p.peek_tok.kind == .key_else {
|
||||
p.next()
|
||||
p.next()
|
||||
node.has_else = true
|
||||
|
@ -339,6 +365,11 @@ fn (mut p Parser) comptime_method_call(left ast.Expr) ast.ComptimeCall {
|
|||
}
|
||||
*/
|
||||
p.check(.lpar)
|
||||
mut args_var := ''
|
||||
if p.tok.kind == .name {
|
||||
args_var = p.tok.lit
|
||||
p.next()
|
||||
}
|
||||
p.check(.rpar)
|
||||
if p.tok.kind == .key_orelse {
|
||||
p.check(.key_orelse)
|
||||
|
@ -349,5 +380,6 @@ fn (mut p Parser) comptime_method_call(left ast.Expr) ast.ComptimeCall {
|
|||
return ast.ComptimeCall{
|
||||
left: left
|
||||
method_name: method_name
|
||||
args_var: args_var
|
||||
}
|
||||
}
|
||||
|
|
|
@ -240,6 +240,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||
is_deprecated: is_deprecated
|
||||
ctdefine: ctdefine
|
||||
mod: p.mod
|
||||
attrs: p.attrs
|
||||
})
|
||||
} else {
|
||||
if language == .c {
|
||||
|
|
|
@ -536,6 +536,8 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
|
|||
.dollar {
|
||||
if p.peek_tok.kind == .key_if {
|
||||
return p.comp_if()
|
||||
} else if p.peek_tok.kind == .key_for {
|
||||
return p.comp_for()
|
||||
} else if p.peek_tok.kind == .name {
|
||||
return ast.ExprStmt{
|
||||
expr: p.vweb()
|
||||
|
@ -592,7 +594,7 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
|
|||
p.error_with_pos('const can only be defined at the top level (outside of functions)',
|
||||
p.tok.position())
|
||||
}
|
||||
// literals, 'if', etc. in here
|
||||
// literals, 'if', etc. in here
|
||||
else {
|
||||
return p.parse_multi_expr(is_top_level)
|
||||
}
|
||||
|
@ -647,15 +649,21 @@ fn (mut p Parser) parse_attr() ast.Attr {
|
|||
p.next()
|
||||
is_if_attr = true
|
||||
}
|
||||
mut name := p.check_name()
|
||||
if p.tok.kind == .colon {
|
||||
name += ':'
|
||||
mut name := ''
|
||||
if p.tok.kind == .string {
|
||||
name = p.tok.lit
|
||||
p.next()
|
||||
if p.tok.kind == .name {
|
||||
name += p.check_name()
|
||||
} else if p.tok.kind == .string {
|
||||
name += p.tok.lit
|
||||
} else {
|
||||
mut name = p.check_name()
|
||||
if p.tok.kind == .colon {
|
||||
name += ':'
|
||||
p.next()
|
||||
if p.tok.kind == .name {
|
||||
name += p.check_name()
|
||||
} else if p.tok.kind == .string {
|
||||
name += p.tok.lit
|
||||
p.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
if is_if_attr {
|
||||
|
@ -847,11 +855,10 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
|||
if p.tok.lit in ['r', 'c', 'js'] && p.peek_tok.kind == .string && !p.inside_str_interp {
|
||||
return p.string_expr()
|
||||
}
|
||||
known_var := p.mark_var_as_used( p.tok.lit )
|
||||
known_var := p.mark_var_as_used(p.tok.lit)
|
||||
mut is_mod_cast := false
|
||||
if p.peek_tok.kind == .dot && !known_var &&
|
||||
(language != .v || p.known_import(p.tok.lit) ||
|
||||
p.mod.all_after_last('.') == p.tok.lit) {
|
||||
(language != .v || p.known_import(p.tok.lit) || p.mod.all_after_last('.') == p.tok.lit) {
|
||||
if language == .c {
|
||||
mod = 'C'
|
||||
} else if language == .js {
|
||||
|
@ -874,8 +881,7 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
|||
// p.warn('name expr $p.tok.lit $p.peek_tok.str()')
|
||||
// fn call or type cast
|
||||
if p.peek_tok.kind == .lpar ||
|
||||
(p.peek_tok.kind == .lt && !lit0_is_capital && p.peek_tok2.kind == .name &&
|
||||
p.peek_tok3.kind == .gt) {
|
||||
(p.peek_tok.kind == .lt && !lit0_is_capital && p.peek_tok2.kind == .name && p.peek_tok3.kind == .gt) {
|
||||
// foo() or foo<int>()
|
||||
mut name := p.tok.lit
|
||||
if mod.len > 0 {
|
||||
|
@ -884,7 +890,8 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
|||
name_w_mod := p.prepend_mod(name)
|
||||
// type cast. TODO: finish
|
||||
// if name in table.builtin_type_names {
|
||||
if (!known_var && (name in p.table.type_idxs || name_w_mod in p.table.type_idxs) &&
|
||||
if (!known_var && (name in p.table.type_idxs ||
|
||||
name_w_mod in p.table.type_idxs) &&
|
||||
name !in ['C.stat', 'C.sigaction']) || is_mod_cast {
|
||||
// TODO handle C.stat()
|
||||
mut to_typ := p.parse_type()
|
||||
|
@ -918,8 +925,9 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
|||
// println('calling $p.tok.lit')
|
||||
node = p.call_expr(language, mod)
|
||||
}
|
||||
} else if (p.peek_tok.kind == .lcbr || (p.peek_tok.kind == .lt && lit0_is_capital)) && !p.inside_match && !p.inside_match_case && !p.inside_if &&
|
||||
!p.inside_for { // && (p.tok.lit[0].is_capital() || p.builtin_mod) {
|
||||
} else if (p.peek_tok.kind == .lcbr ||
|
||||
(p.peek_tok.kind == .lt && lit0_is_capital)) && !p.inside_match && !p.inside_match_case &&
|
||||
!p.inside_if && !p.inside_for { // && (p.tok.lit[0].is_capital() || p.builtin_mod) {
|
||||
return p.struct_init(false) // short_syntax: false
|
||||
} else if p.peek_tok.kind == .dot && (lit0_is_capital && !known_var && language == .v) {
|
||||
// `Color.green`
|
||||
|
@ -1523,7 +1531,8 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
|
|||
decl_pos := start_pos.extend(end_pos)
|
||||
name := p.check_name()
|
||||
if name.len == 1 && name[0].is_capital() {
|
||||
p.error_with_pos('single letter capital names are reserved for generic template types.', decl_pos)
|
||||
p.error_with_pos('single letter capital names are reserved for generic template types.',
|
||||
decl_pos)
|
||||
}
|
||||
mut sum_variants := []table.Type{}
|
||||
if p.tok.kind == .assign {
|
||||
|
|
|
@ -30,6 +30,7 @@ pub:
|
|||
is_deprecated bool
|
||||
mod string
|
||||
ctdefine string // compile time define. myflag, when [if myflag] tag
|
||||
attrs []string
|
||||
pub mut:
|
||||
name string
|
||||
}
|
||||
|
@ -225,7 +226,9 @@ pub fn (mut t Table) register_builtin_type_symbol(typ TypeSymbol) int {
|
|||
typ |
|
||||
kind: existing_type.kind
|
||||
}
|
||||
} else {
|
||||
}
|
||||
//
|
||||
else {
|
||||
t.types[existing_idx] = typ
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
struct App {
|
||||
}
|
||||
|
||||
['foo/bar/three']
|
||||
fn (mut app App) run() {
|
||||
}
|
||||
|
||||
['attr2']
|
||||
fn (mut app App) method2() {
|
||||
}
|
||||
|
||||
fn test_comptime_for() {
|
||||
/*
|
||||
app := App{}
|
||||
|
||||
$for method in App { //.method_attrs {
|
||||
words := attrs.split('/')
|
||||
println(words)
|
||||
//println(method.value)
|
||||
}
|
||||
assert true
|
||||
println('DONE')
|
||||
*/
|
||||
if true {}
|
||||
//
|
||||
else{}
|
||||
}
|
|
@ -255,13 +255,6 @@ fn handle_conn<T>(conn net.Socket, mut app T) {
|
|||
}
|
||||
}
|
||||
|
||||
mut action := vals[1][1..].all_before('/')
|
||||
if action.contains('?') {
|
||||
action = action.all_before('?')
|
||||
}
|
||||
if action == '' {
|
||||
action = 'index'
|
||||
}
|
||||
req := http.Request{
|
||||
headers: http.parse_headers(headers) //s.split_into_lines())
|
||||
data: strip(body)
|
||||
|
@ -274,7 +267,7 @@ fn handle_conn<T>(conn net.Socket, mut app T) {
|
|||
println('req.headers = ')
|
||||
println(req.headers)
|
||||
println('req.data="$req.data"' )
|
||||
println('vweb action = "$action"')
|
||||
//println('vweb action = "$action"')
|
||||
}
|
||||
//mut app := T{
|
||||
app.vweb = Context{
|
||||
|
@ -316,19 +309,60 @@ fn handle_conn<T>(conn net.Socket, mut app T) {
|
|||
data.free()
|
||||
return
|
||||
}
|
||||
|
||||
app.init()
|
||||
// Call the right action
|
||||
mut action := ''
|
||||
mut route_words := []string{}
|
||||
mut ok := true
|
||||
url_words := vals[1][1..].split('/')
|
||||
mut vars := []string{cap: route_words.len}
|
||||
$for method in T {
|
||||
ok = true
|
||||
route_words = attrs[1..].split('/')
|
||||
//println('words:') println(route_words)
|
||||
//println('vals:') println(url_words)
|
||||
vars = []string{cap: route_words.len}
|
||||
if route_words.len == url_words.len {
|
||||
// match `/:user/:repo/tree` to `/vlang/v/tree`
|
||||
for i, word in route_words {
|
||||
if word.starts_with(':') {
|
||||
// remember and skip the var
|
||||
vars << url_words[i]
|
||||
continue
|
||||
}
|
||||
if word != url_words[i] {
|
||||
ok = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if ok {
|
||||
action = method
|
||||
app.$method(vars)
|
||||
conn.close() or {}
|
||||
return
|
||||
}
|
||||
}
|
||||
// No route matched, just do a simple `/home` => `action=home`
|
||||
if action == '' {
|
||||
action = vals[1][1..].all_before('/')
|
||||
if action.contains('?') {
|
||||
action = action.all_before('?')
|
||||
}
|
||||
if action == '' {
|
||||
action = 'index'
|
||||
}
|
||||
}
|
||||
$if debug {
|
||||
println('action=$action')
|
||||
}
|
||||
app.init()
|
||||
|
||||
app.$action()
|
||||
/*
|
||||
app.$action() or {
|
||||
conn.send_string(http_404) or {}
|
||||
}
|
||||
*/
|
||||
|
||||
conn.close() or {}
|
||||
//app.reset()
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue