parser: comp `for` attrs array (#5903)

pull/5958/head
Louis Schmieder 2020-07-23 17:19:37 +02:00 committed by GitHub
parent 7a4c27bd08
commit b537d8e23e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 102 additions and 53 deletions

View File

@ -43,9 +43,21 @@ fn (g &Gen) comptime_call(node ast.ComptimeCall) {
if m.args.len > 1 { if m.args.len > 1 {
g.write(', ') g.write(', ')
} }
for i in 0 .. m.args.len - 1 { for i in 1 .. m.args.len{
g.write('((string*)${node.args_var}.data) [$i] ') if node.left is ast.Ident {
if i < m.args.len - 2 { left_name := node.left as ast.Ident
if m.args[i].name == left_name.name {
continue
}
}
if m.args[i].typ.is_int() || m.args[i].typ.idx() == table.bool_type_idx {
// Gets the type name and cast the string to the type with the string_<type> function
type_name := g.table.types[int(m.args[i].typ)].str()
g.write('string_${type_name}(((string*)${node.args_var}.data) [${i-1}])')
} else {
g.write('((string*)${node.args_var}.data) [${i-1}] ')
}
if i < m.args.len - 1 {
g.write(', ') g.write(', ')
} }
} }
@ -131,12 +143,16 @@ fn (mut g Gen) comp_for(node ast.CompFor) {
} }
g.writeln('method = tos_lit("$method.name");') g.writeln('method = tos_lit("$method.name");')
if i == 0 { if i == 0 {
g.write('\tstring ') g.write('\tarray_string ')
} }
if method.attrs.len == 0 { if method.attrs.len == 0 {
g.writeln('attrs = tos_lit("");') g.writeln('attrs = new_array_from_c_array(0, 0, sizeof(string), _MOV((string[0]){}));')
} else { } else {
g.writeln('attrs = tos_lit("${method.attrs[0]}");') mut attrs := []string{}
for attrib in method.attrs {
attrs << 'tos_lit("$attrib")'
}
g.writeln('attrs = new_array_from_c_array($attrs.len, $attrs.len, sizeof(string), _MOV((string[$attrs.len]){' + attrs.join(', ') + '}));')
} }
g.stmts(node.stmts) g.stmts(node.stmts)
i++ i++

View File

@ -164,7 +164,7 @@ fn (mut p Parser) comp_for() ast.CompFor {
}) })
p.scope.register('attrs', ast.Var{ p.scope.register('attrs', ast.Var{
name: 'attrs' name: 'attrs'
typ: table.string_type typ: p.table.find_type_idx('array_string')
}) })
p.check(.key_in) p.check(.key_in)
// expr := p.expr(0) // expr := p.expr(0)

View File

@ -13,7 +13,7 @@ import time
pub const ( pub const (
methods_with_form = ['POST', 'PUT', 'PATCH'] methods_with_form = ['POST', 'PUT', 'PATCH']
method_all = ['GET','POST','PUT','PATCH','DELETE'] method_all = ['GET','POST','PUT','PATCH','DELETE', 'HEAD', 'OPTIONS']
header_server = 'Server: VWeb\r\n' header_server = 'Server: VWeb\r\n'
header_connection_close = 'Connection: close\r\n' header_connection_close = 'Connection: close\r\n'
headers_close = '${header_server}${header_connection_close}\r\n' headers_close = '${header_server}${header_connection_close}\r\n'
@ -340,7 +340,7 @@ fn handle_conn<T>(conn net.Socket, mut app T) {
println('route matching...') println('route matching...')
//t := time.ticks() //t := time.ticks()
//mut action := '' //mut action := ''
mut route_words := []string{} mut route_words_a := [][]string{}
mut url_words := vals[1][1..].split('/').filter(it != '') mut url_words := vals[1][1..].split('/').filter(it != '')
@ -360,10 +360,11 @@ fn handle_conn<T>(conn net.Socket, mut app T) {
} }
} }
mut vars := []string{cap: route_words.len} mut vars := []string{cap: route_words_a.len}
mut action := '' mut action := ''
$for method in T { $for method in T {
if attrs == '' { route_words_a = [][]string{}
if attrs.len == 0 {
// No routing for this method. If it matches, call it and finish matching // No routing for this method. If it matches, call it and finish matching
// since such methods have a priority. // since such methods have a priority.
// For example URL `/register` matches route `/:user`, but `fn register()` // For example URL `/register` matches route `/:user`, but `fn register()`
@ -374,7 +375,37 @@ fn handle_conn<T>(conn net.Socket, mut app T) {
return return
} }
} else { } else {
route_words = attrs[1..].split('/') // Get methods
// Get is default
if 'post' in attrs {
if req.method == 'POST' {
route_words_a = attrs.filter(it.to_lower() != 'post').map(it[1..].split('/'))
}
} else if 'put' in attrs {
if req.method == 'PUT' {
route_words_a = attrs.filter(it.to_lower() != 'put').map(it[1..].split('/'))
}
} else if 'patch' in attrs {
if req.method == 'PATCH' {
route_words_a = attrs.filter(it.to_lower() != 'patch').map(it[1..].split('/'))
}
} else if 'delete' in attrs {
if req.method == 'DELETE' {
route_words_a = attrs.filter(it.to_lower() != 'delete').map(it[1..].split('/'))
}
} else if 'head' in attrs {
if req.method == 'HEAD' {
route_words_a = attrs.filter(it.to_lower() != 'head').map(it[1..].split('/'))
}
} else if 'options' in attrs {
if req.method == 'OPTIONS' {
route_words_a = attrs.filter(it.to_lower() != 'options').map(it[1..].split('/'))
}
} else {
route_words_a = attrs.filter(it.to_lower() != 'get').map(it[1..].split('/'))
}
if route_words_a.len > 0 {
for route_words in route_words_a {
if url_words.len == route_words.len || (url_words.len >= route_words.len - 1 && route_words.last().ends_with('...')) { if url_words.len == route_words.len || (url_words.len >= route_words.len - 1 && route_words.last().ends_with('...')) {
// match `/:user/:repo/tree` to `/vlang/v/tree` // match `/:user/:repo/tree` to `/vlang/v/tree`
mut matching := false mut matching := false
@ -420,6 +451,8 @@ fn handle_conn<T>(conn net.Socket, mut app T) {
} }
} }
} }
}
}
if action == '' { if action == '' {
// site not found // site not found
conn.send_string(http_404) or {} conn.send_string(http_404) or {}
@ -432,7 +465,7 @@ fn send_action<T>(action string, vars []string, mut app T) {
// TODO remove this function // TODO remove this function
$for method in T { $for method in T {
// search again for method // search again for method
if action == method && attrs != '' { if action == method && attrs.len > 0 {
// call action method // call action method
app.$method(vars) app.$method(vars)
} }