checker: check mutating methods; generics fixes
							parent
							
								
									945439dab6
								
							
						
					
					
						commit
						3d83934caf
					
				| 
						 | 
					@ -621,7 +621,7 @@ pub fn is_writable_folder(folder string) ?bool {
 | 
				
			||||||
		return error('`folder` is not a folder')
 | 
							return error('`folder` is not a folder')
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	tmp_perm_check := os.join_path(folder, 'tmp_perm_check')
 | 
						tmp_perm_check := os.join_path(folder, 'tmp_perm_check')
 | 
				
			||||||
	f := os.open_file(tmp_perm_check, 'w+', 0o700) or {
 | 
						mut f := os.open_file(tmp_perm_check, 'w+', 0o700) or {
 | 
				
			||||||
		return error('cannot write to folder `$folder`: $err')
 | 
							return error('cannot write to folder `$folder`: $err')
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	f.close()
 | 
						f.close()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,10 +13,10 @@ import v.depgraph
 | 
				
			||||||
pub struct Builder {
 | 
					pub struct Builder {
 | 
				
			||||||
pub:
 | 
					pub:
 | 
				
			||||||
	table               &table.Table
 | 
						table               &table.Table
 | 
				
			||||||
	checker             checker.Checker
 | 
					 | 
				
			||||||
	compiled_dir        string // contains os.real_path() of the dir of the final file beeing compiled, or the dir itself when doing `v .`
 | 
						compiled_dir        string // contains os.real_path() of the dir of the final file beeing compiled, or the dir itself when doing `v .`
 | 
				
			||||||
	module_path         string
 | 
						module_path         string
 | 
				
			||||||
mut:
 | 
					mut:
 | 
				
			||||||
 | 
						checker             checker.Checker
 | 
				
			||||||
	pref                &pref.Preferences
 | 
						pref                &pref.Preferences
 | 
				
			||||||
	parsed_files        []ast.File
 | 
						parsed_files        []ast.File
 | 
				
			||||||
	global_scope        &ast.Scope
 | 
						global_scope        &ast.Scope
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,8 +15,8 @@ const (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct Checker {
 | 
					pub struct Checker {
 | 
				
			||||||
	table            &table.Table
 | 
					 | 
				
			||||||
pub mut:
 | 
					pub mut:
 | 
				
			||||||
 | 
						table            &table.Table
 | 
				
			||||||
	file             ast.File
 | 
						file             ast.File
 | 
				
			||||||
	nr_errors        int
 | 
						nr_errors        int
 | 
				
			||||||
	nr_warnings      int
 | 
						nr_warnings      int
 | 
				
			||||||
| 
						 | 
					@ -572,6 +572,10 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn (mut c Checker) fail_if_immutable(expr ast.Expr) {
 | 
					fn (mut c Checker) fail_if_immutable(expr ast.Expr) {
 | 
				
			||||||
	match expr {
 | 
						match expr {
 | 
				
			||||||
 | 
							ast.CastExpr {
 | 
				
			||||||
 | 
								// TODO
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		ast.Ident {
 | 
							ast.Ident {
 | 
				
			||||||
			scope := c.file.scope.innermost(it.pos.pos)
 | 
								scope := c.file.scope.innermost(it.pos.pos)
 | 
				
			||||||
			if v := scope.find_var(it.name) {
 | 
								if v := scope.find_var(it.name) {
 | 
				
			||||||
| 
						 | 
					@ -580,7 +584,10 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) {
 | 
				
			||||||
						it.pos)
 | 
											it.pos)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else if it.name in c.const_names {
 | 
								} else if it.name in c.const_names {
 | 
				
			||||||
				c.error('cannot assign to constant `$it.name`', it.pos)
 | 
									if it.name .contains('mod_file_cacher') {
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									c.error('cannot modify constant `$it.name`', it.pos)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ast.IndexExpr {
 | 
							ast.IndexExpr {
 | 
				
			||||||
| 
						 | 
					@ -766,6 +773,9 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
 | 
				
			||||||
			// println('warn $method_name lef.mod=$left_type_sym.mod c.mod=$c.mod')
 | 
								// println('warn $method_name lef.mod=$left_type_sym.mod c.mod=$c.mod')
 | 
				
			||||||
			c.error('method `${left_type_sym.name}.$method_name` is private', call_expr.pos)
 | 
								c.error('method `${left_type_sym.name}.$method_name` is private', call_expr.pos)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if method.args[0].is_mut {
 | 
				
			||||||
 | 
								c.fail_if_immutable(call_expr.left)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if method.return_type == table.void_type && method.ctdefine.len > 0 && method.ctdefine !in
 | 
							if method.return_type == table.void_type && method.ctdefine.len > 0 && method.ctdefine !in
 | 
				
			||||||
			c.pref.compile_defines {
 | 
								c.pref.compile_defines {
 | 
				
			||||||
			call_expr.should_be_skipped = true
 | 
								call_expr.should_be_skipped = true
 | 
				
			||||||
| 
						 | 
					@ -999,6 +1009,8 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
 | 
				
			||||||
		if arg.is_mut && !call_arg.is_mut {
 | 
							if arg.is_mut && !call_arg.is_mut {
 | 
				
			||||||
			c.error('`$arg.name` is a mutable argument, you need to provide `mut`: `${call_expr.name}(mut ...)`',
 | 
								c.error('`$arg.name` is a mutable argument, you need to provide `mut`: `${call_expr.name}(mut ...)`',
 | 
				
			||||||
				call_arg.expr.position())
 | 
									call_arg.expr.position())
 | 
				
			||||||
 | 
							} else if !arg.is_mut && call_arg.is_mut {
 | 
				
			||||||
 | 
								c.error('`$arg.name` argument is not mutable, `mut` is not needed`', call_arg.expr.position())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// Handle expected interface
 | 
							// Handle expected interface
 | 
				
			||||||
		if arg_typ_sym.kind == .interface_ {
 | 
							if arg_typ_sym.kind == .interface_ {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,10 +8,10 @@ import v.ast
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Doc {
 | 
					struct Doc {
 | 
				
			||||||
	out   strings.Builder
 | 
					 | 
				
			||||||
	table &table.Table
 | 
						table &table.Table
 | 
				
			||||||
	mod   string
 | 
						mod   string
 | 
				
			||||||
mut:
 | 
					mut:
 | 
				
			||||||
 | 
						out   strings.Builder
 | 
				
			||||||
	stmts []ast.Stmt // all module statements from all files
 | 
						stmts []ast.Stmt // all module statements from all files
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,6 +46,10 @@ const (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Gen {
 | 
					struct Gen {
 | 
				
			||||||
 | 
						table                &table.Table
 | 
				
			||||||
 | 
						pref                 &pref.Preferences
 | 
				
			||||||
 | 
						module_built         string
 | 
				
			||||||
 | 
					mut:
 | 
				
			||||||
	out                  strings.Builder
 | 
						out                  strings.Builder
 | 
				
			||||||
	cheaders             strings.Builder
 | 
						cheaders             strings.Builder
 | 
				
			||||||
	includes             strings.Builder // all C #includes required by V modules
 | 
						includes             strings.Builder // all C #includes required by V modules
 | 
				
			||||||
| 
						 | 
					@ -62,10 +66,6 @@ struct Gen {
 | 
				
			||||||
	pcs_declarations     strings.Builder // -prof profile counter declarations for each function
 | 
						pcs_declarations     strings.Builder // -prof profile counter declarations for each function
 | 
				
			||||||
	hotcode_definitions  strings.Builder // -live declarations & functions
 | 
						hotcode_definitions  strings.Builder // -live declarations & functions
 | 
				
			||||||
	options              strings.Builder // `Option_xxxx` types
 | 
						options              strings.Builder // `Option_xxxx` types
 | 
				
			||||||
	table                &table.Table
 | 
					 | 
				
			||||||
	pref                 &pref.Preferences
 | 
					 | 
				
			||||||
	module_built         string
 | 
					 | 
				
			||||||
mut:
 | 
					 | 
				
			||||||
	file                 ast.File
 | 
						file                 ast.File
 | 
				
			||||||
	fn_decl              &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0
 | 
						fn_decl              &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0
 | 
				
			||||||
	last_fn_c_name       string
 | 
						last_fn_c_name       string
 | 
				
			||||||
| 
						 | 
					@ -178,7 +178,7 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	g.finish()
 | 
						g.finish()
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	b := strings.new_builder(250000)
 | 
						mut b := strings.new_builder(250000)
 | 
				
			||||||
	b.writeln(g.hashes())
 | 
						b.writeln(g.hashes())
 | 
				
			||||||
	b.writeln(g.comptime_defines.str())
 | 
						b.writeln(g.comptime_defines.str())
 | 
				
			||||||
	b.writeln('\n// V typedefs:')
 | 
						b.writeln('\n// V typedefs:')
 | 
				
			||||||
| 
						 | 
					@ -311,7 +311,7 @@ pub fn (mut g Gen) write_typeof_functions() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// V type to C type
 | 
					// V type to C type
 | 
				
			||||||
fn (mut g Gen) typ(t table.Type) string {
 | 
					fn (g &Gen) typ(t table.Type) string {
 | 
				
			||||||
	mut styp := g.base_type(t)
 | 
						mut styp := g.base_type(t)
 | 
				
			||||||
	if styp.len == 1 && t == table.t_type && g.cur_generic_type != 0 {
 | 
						if styp.len == 1 && t == table.t_type && g.cur_generic_type != 0 {
 | 
				
			||||||
		// T => int etc
 | 
							// T => int etc
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,9 +23,9 @@ const (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct JsGen {
 | 
					struct JsGen {
 | 
				
			||||||
	table             &table.Table
 | 
						table             &table.Table
 | 
				
			||||||
	definitions       strings.Builder
 | 
					 | 
				
			||||||
	pref              &pref.Preferences
 | 
						pref              &pref.Preferences
 | 
				
			||||||
mut:
 | 
					mut:
 | 
				
			||||||
 | 
						definitions       strings.Builder
 | 
				
			||||||
	out               strings.Builder
 | 
						out               strings.Builder
 | 
				
			||||||
	namespaces        map[string]strings.Builder
 | 
						namespaces        map[string]strings.Builder
 | 
				
			||||||
	namespaces_pub    map[string][]string
 | 
						namespaces_pub    map[string][]string
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ module js
 | 
				
			||||||
import v.ast
 | 
					import v.ast
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct JsDoc {
 | 
					struct JsDoc {
 | 
				
			||||||
 | 
					mut:
 | 
				
			||||||
	gen        &JsGen
 | 
						gen        &JsGen
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -221,7 +221,8 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			sym := p.table.get_type_symbol(arg.typ)
 | 
								sym := p.table.get_type_symbol(arg.typ)
 | 
				
			||||||
			if sym.kind !in [.array, .struct_, .map, .placeholder] && !arg.typ.is_ptr() {
 | 
								if sym.kind !in [.array, .struct_, .map, .placeholder] && arg.typ != table.t_type &&
 | 
				
			||||||
 | 
									!arg.typ.is_ptr() {
 | 
				
			||||||
				p.error('mutable arguments are only allowed for arrays, maps, and structs\n' +
 | 
									p.error('mutable arguments are only allowed for arrays, maps, and structs\n' +
 | 
				
			||||||
					'return values instead: `fn foo(n mut int) {` => `fn foo(n int) int {`')
 | 
										'return values instead: `fn foo(n mut int) {` => `fn foo(n int) int {`')
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -359,6 +360,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// fn decl
 | 
				
			||||||
fn (mut p Parser) fn_args() ([]table.Arg, bool) {
 | 
					fn (mut p Parser) fn_args() ([]table.Arg, bool) {
 | 
				
			||||||
	p.check(.lpar)
 | 
						p.check(.lpar)
 | 
				
			||||||
	mut args := []table.Arg{}
 | 
						mut args := []table.Arg{}
 | 
				
			||||||
| 
						 | 
					@ -381,7 +383,7 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool) {
 | 
				
			||||||
				is_variadic = true
 | 
									is_variadic = true
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			mut arg_type := p.parse_type()
 | 
								mut arg_type := p.parse_type()
 | 
				
			||||||
			if is_mut {
 | 
								if is_mut && arg_type != table.t_type {
 | 
				
			||||||
				// if arg_type.is_ptr() {
 | 
									// if arg_type.is_ptr() {
 | 
				
			||||||
				// p.error('cannot mut')
 | 
									// p.error('cannot mut')
 | 
				
			||||||
				// }
 | 
									// }
 | 
				
			||||||
| 
						 | 
					@ -425,7 +427,7 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool) {
 | 
				
			||||||
				is_variadic = true
 | 
									is_variadic = true
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			mut typ := p.parse_type()
 | 
								mut typ := p.parse_type()
 | 
				
			||||||
			if is_mut {
 | 
								if is_mut && typ != table.t_type {
 | 
				
			||||||
				if typ.is_ptr() {
 | 
									if typ.is_ptr() {
 | 
				
			||||||
					// name := p.table.get_type_name(typ)
 | 
										// name := p.table.get_type_name(typ)
 | 
				
			||||||
					// p.warn('`$name` is already a reference, it cannot be marked as `mut`')
 | 
										// p.warn('`$name` is already a reference, it cannot be marked as `mut`')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,10 +16,10 @@ import runtime
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct Parser {
 | 
					pub struct Parser {
 | 
				
			||||||
	scanner           &scanner.Scanner
 | 
					 | 
				
			||||||
	file_name         string // "/home/user/hello.v"
 | 
						file_name         string // "/home/user/hello.v"
 | 
				
			||||||
	file_name_dir     string // "/home/user"
 | 
						file_name_dir     string // "/home/user"
 | 
				
			||||||
mut:
 | 
					mut:
 | 
				
			||||||
 | 
						scanner           &scanner.Scanner
 | 
				
			||||||
	tok               token.Token
 | 
						tok               token.Token
 | 
				
			||||||
	prev_tok          token.Token
 | 
						prev_tok          token.Token
 | 
				
			||||||
	peek_tok          token.Token
 | 
						peek_tok          token.Token
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,7 @@ fn mpath() string {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn new_preferences() Preferences {
 | 
					pub fn new_preferences() Preferences {
 | 
				
			||||||
	p := Preferences{}
 | 
						mut p := Preferences{}
 | 
				
			||||||
	p.fill_with_defaults()
 | 
						p.fill_with_defaults()
 | 
				
			||||||
	return p
 | 
						return p
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,8 +2,9 @@ module pref
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (prefs &Preferences) should_compile_filtered_files(dir string, files []string) []string {
 | 
					pub fn (prefs &Preferences) should_compile_filtered_files(dir string, files_ []string) []string {
 | 
				
			||||||
	mut res := []string{}
 | 
						mut res := []string{}
 | 
				
			||||||
 | 
						mut files := files_.clone()
 | 
				
			||||||
	files.sort()
 | 
						files.sort()
 | 
				
			||||||
	for file in files {
 | 
						for file in files {
 | 
				
			||||||
		if !file.ends_with('.v') && !file.ends_with('.vh') {
 | 
							if !file.ends_with('.v') && !file.ends_with('.vh') {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,6 +40,7 @@ pub enum TypeFlag {
 | 
				
			||||||
	unset
 | 
						unset
 | 
				
			||||||
	optional
 | 
						optional
 | 
				
			||||||
	variadic
 | 
						variadic
 | 
				
			||||||
 | 
						generic
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (types []Type) contains(typ Type) bool {
 | 
					pub fn (types []Type) contains(typ Type) bool {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,6 +40,7 @@ fn test_foo() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn create<T>() {
 | 
					fn create<T>() {
 | 
				
			||||||
	a := T{}
 | 
						a := T{}
 | 
				
			||||||
 | 
						println(a.foo)
 | 
				
			||||||
	mut xx := T{}
 | 
						mut xx := T{}
 | 
				
			||||||
	xx.foo = 'foo'
 | 
						xx.foo = 'foo'
 | 
				
			||||||
	println(xx.foo)
 | 
						println(xx.foo)
 | 
				
			||||||
| 
						 | 
					@ -63,10 +64,15 @@ fn (u User) init() {
 | 
				
			||||||
fn (c City) init() {
 | 
					fn (c City) init() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn gen_arg<T>(mut x T) {
 | 
				
			||||||
 | 
						println(x.foo) // = 'foo'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn test_create() {
 | 
					fn test_create() {
 | 
				
			||||||
	create<User>()
 | 
						create<User>()
 | 
				
			||||||
	create<City>()
 | 
						create<City>()
 | 
				
			||||||
	// create<User>()
 | 
						u := User{}
 | 
				
			||||||
 | 
						//gen_arg<User>(mut u)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -142,8 +142,8 @@ pub fn run<T>(port int) {
 | 
				
			||||||
	//app.reset()
 | 
						//app.reset()
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		conn := l.accept() or { panic('accept() failed') }
 | 
							conn := l.accept() or { panic('accept() failed') }
 | 
				
			||||||
		handle_conn<T>(conn, mut app)
 | 
							//handle_conn<T>(conn, mut app)
 | 
				
			||||||
		//foobar<T>()
 | 
							app = handle_conn<T>(conn, app)
 | 
				
			||||||
		// TODO move this to handle_conn<T>(conn, app)
 | 
							// TODO move this to handle_conn<T>(conn, app)
 | 
				
			||||||
		//message := readall(conn)
 | 
							//message := readall(conn)
 | 
				
			||||||
		//println(message)
 | 
							//println(message)
 | 
				
			||||||
| 
						 | 
					@ -169,7 +169,9 @@ pub fn run<T>(port int) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn handle_conn<T>(conn net.Socket, app mut T) {
 | 
					//fn handle_conn<T>(conn net.Socket, app mut T) {
 | 
				
			||||||
 | 
					fn handle_conn<T>(conn net.Socket, app_ T) T {
 | 
				
			||||||
 | 
						mut app := app_
 | 
				
			||||||
	//first_line := strip(lines[0])
 | 
						//first_line := strip(lines[0])
 | 
				
			||||||
	first_line := conn.read_line()
 | 
						first_line := conn.read_line()
 | 
				
			||||||
	println('firstline="$first_line"')
 | 
						println('firstline="$first_line"')
 | 
				
			||||||
| 
						 | 
					@ -182,7 +184,7 @@ fn handle_conn<T>(conn net.Socket, app mut T) {
 | 
				
			||||||
		println('no vals for http')
 | 
							println('no vals for http')
 | 
				
			||||||
		conn.send_string(http_500) or {}
 | 
							conn.send_string(http_500) or {}
 | 
				
			||||||
		conn.close() or {}
 | 
							conn.close() or {}
 | 
				
			||||||
		return
 | 
							return app
 | 
				
			||||||
		//continue
 | 
							//continue
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	mut headers := []string{}
 | 
						mut headers := []string{}
 | 
				
			||||||
| 
						 | 
					@ -263,7 +265,7 @@ fn handle_conn<T>(conn net.Socket, app mut T) {
 | 
				
			||||||
			println('no vals for http')
 | 
								println('no vals for http')
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		conn.close() or {}
 | 
							conn.close() or {}
 | 
				
			||||||
		return
 | 
							return app
 | 
				
			||||||
		//continue
 | 
							//continue
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -274,10 +276,10 @@ fn handle_conn<T>(conn net.Socket, app mut T) {
 | 
				
			||||||
	if static_file != '' && mime_type != '' {
 | 
						if static_file != '' && mime_type != '' {
 | 
				
			||||||
		data := os.read_file(static_file) or {
 | 
							data := os.read_file(static_file) or {
 | 
				
			||||||
			conn.send_string(http_404) or {}
 | 
								conn.send_string(http_404) or {}
 | 
				
			||||||
			return
 | 
								return app
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		app.vweb.send_response_to_client(mime_type, data)
 | 
							app.vweb.send_response_to_client(mime_type, data)
 | 
				
			||||||
		return
 | 
							return app
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Call the right action
 | 
						// Call the right action
 | 
				
			||||||
| 
						 | 
					@ -292,6 +294,7 @@ fn handle_conn<T>(conn net.Socket, app mut T) {
 | 
				
			||||||
	*/
 | 
						*/
 | 
				
			||||||
	conn.close() or {}
 | 
						conn.close() or {}
 | 
				
			||||||
	app.reset()
 | 
						app.reset()
 | 
				
			||||||
 | 
						return app
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn (mut ctx Context) parse_form(s string) {
 | 
					fn (mut ctx Context) parse_form(s string) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue