From b537d8e23e58b213b48c16273371fad6845cc88a Mon Sep 17 00:00:00 2001 From: Louis Schmieder Date: Thu, 23 Jul 2020 17:19:37 +0200 Subject: [PATCH] parser: comp `for` attrs array (#5903) --- vlib/v/gen/comptime.v | 28 +++++++-- vlib/v/parser/comptime.v | 2 +- vlib/vweb/vweb.v | 125 +++++++++++++++++++++++++-------------- 3 files changed, 102 insertions(+), 53 deletions(-) diff --git a/vlib/v/gen/comptime.v b/vlib/v/gen/comptime.v index 931320153c..0353b71abe 100644 --- a/vlib/v/gen/comptime.v +++ b/vlib/v/gen/comptime.v @@ -43,9 +43,21 @@ fn (g &Gen) comptime_call(node ast.ComptimeCall) { 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 { + for i in 1 .. m.args.len{ + if node.left is ast.Ident { + 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_ 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(', ') } } @@ -131,12 +143,16 @@ fn (mut g Gen) comp_for(node ast.CompFor) { } g.writeln('method = tos_lit("$method.name");') if i == 0 { - g.write('\tstring ') + g.write('\tarray_string ') } 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 { - 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) i++ diff --git a/vlib/v/parser/comptime.v b/vlib/v/parser/comptime.v index a2d7770275..89d13e4935 100644 --- a/vlib/v/parser/comptime.v +++ b/vlib/v/parser/comptime.v @@ -164,7 +164,7 @@ fn (mut p Parser) comp_for() ast.CompFor { }) p.scope.register('attrs', ast.Var{ name: 'attrs' - typ: table.string_type + typ: p.table.find_type_idx('array_string') }) p.check(.key_in) // expr := p.expr(0) diff --git a/vlib/vweb/vweb.v b/vlib/vweb/vweb.v index 0092e01103..32506861af 100644 --- a/vlib/vweb/vweb.v +++ b/vlib/vweb/vweb.v @@ -13,7 +13,7 @@ import time pub const ( 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_connection_close = 'Connection: close\r\n' headers_close = '${header_server}${header_connection_close}\r\n' @@ -340,7 +340,7 @@ fn handle_conn(conn net.Socket, mut app T) { println('route matching...') //t := time.ticks() //mut action := '' - mut route_words := []string{} + mut route_words_a := [][]string{} mut url_words := vals[1][1..].split('/').filter(it != '') @@ -360,10 +360,11 @@ fn handle_conn(conn net.Socket, mut app T) { } } - mut vars := []string{cap: route_words.len} + mut vars := []string{cap: route_words_a.len} mut action := '' $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 // since such methods have a priority. // For example URL `/register` matches route `/:user`, but `fn register()` @@ -374,48 +375,80 @@ fn handle_conn(conn net.Socket, mut app T) { return } } else { - route_words = attrs[1..].split('/') - 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` - mut matching := false - mut unknown := false - mut variables := []string{cap: route_words.len} - for i in 0..route_words.len { - if url_words.len == i { - variables << '' - matching = true - unknown = true - break - } - if url_words[i] == route_words[i] { - // no parameter - matching = true - continue - } else if route_words[i].starts_with(':') { - // is parameter - if i < route_words.len && !route_words[i].ends_with('...') { - // normal parameter - variables << url_words[i] - } else { - // array parameter only in the end - variables << url_words[i..].join('/') - } - matching = true - unknown = true - continue - } else { - matching = false - break - } + // 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('/')) } - if matching && !unknown { - // absolute router words like `/test/site` - app.$method(vars) - return - } else if matching && unknown { - // router words with paramter like `/:test/site` - action = method - vars = variables + } 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('...')) { + // match `/:user/:repo/tree` to `/vlang/v/tree` + mut matching := false + mut unknown := false + mut variables := []string{cap: route_words.len} + for i in 0..route_words.len { + if url_words.len == i { + variables << '' + matching = true + unknown = true + break + } + if url_words[i] == route_words[i] { + // no parameter + matching = true + continue + } else if route_words[i].starts_with(':') { + // is parameter + if i < route_words.len && !route_words[i].ends_with('...') { + // normal parameter + variables << url_words[i] + } else { + // array parameter only in the end + variables << url_words[i..].join('/') + } + matching = true + unknown = true + continue + } else { + matching = false + break + } + } + if matching && !unknown { + // absolute router words like `/test/site` + app.$method(vars) + return + } else if matching && unknown { + // router words with paramter like `/:test/site` + action = method + vars = variables + } + } } } } @@ -432,7 +465,7 @@ fn send_action(action string, vars []string, mut app T) { // TODO remove this function $for method in T { // search again for method - if action == method && attrs != '' { + if action == method && attrs.len > 0 { // call action method app.$method(vars) }