parser: comp `for` attrs array (#5903)
							parent
							
								
									7a4c27bd08
								
							
						
					
					
						commit
						b537d8e23e
					
				| 
						 | 
					@ -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++
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										125
									
								
								vlib/vweb/vweb.v
								
								
								
								
							
							
						
						
									
										125
									
								
								vlib/vweb/vweb.v
								
								
								
								
							| 
						 | 
					@ -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,48 +375,80 @@ fn handle_conn<T>(conn net.Socket, mut app T) {
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			route_words = attrs[1..].split('/')
 | 
								// Get methods
 | 
				
			||||||
			if url_words.len == route_words.len || (url_words.len >= route_words.len - 1 && route_words.last().ends_with('...')) {
 | 
								// Get is default
 | 
				
			||||||
				// match `/:user/:repo/tree` to `/vlang/v/tree`
 | 
								if 'post' in attrs {
 | 
				
			||||||
				mut matching := false
 | 
									if req.method == 'POST' {
 | 
				
			||||||
				mut unknown := false
 | 
										route_words_a = attrs.filter(it.to_lower() != 'post').map(it[1..].split('/'))
 | 
				
			||||||
				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 {
 | 
								} else if 'put' in attrs {
 | 
				
			||||||
					// absolute router words like `/test/site`
 | 
									if req.method == 'PUT' {
 | 
				
			||||||
					app.$method(vars)
 | 
										route_words_a = attrs.filter(it.to_lower() != 'put').map(it[1..].split('/'))
 | 
				
			||||||
					return
 | 
									}
 | 
				
			||||||
				} else if matching && unknown {
 | 
								} else if 'patch' in attrs {
 | 
				
			||||||
					// router words with paramter like `/:test/site`
 | 
									if req.method == 'PATCH' {
 | 
				
			||||||
					action = method
 | 
										route_words_a = attrs.filter(it.to_lower() != 'patch').map(it[1..].split('/'))
 | 
				
			||||||
					vars = variables
 | 
									}
 | 
				
			||||||
 | 
								} 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<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)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue