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')
|
||||
}
|
||||
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')
|
||||
}
|
||||
f.close()
|
||||
|
|
|
@ -13,10 +13,10 @@ import v.depgraph
|
|||
pub struct Builder {
|
||||
pub:
|
||||
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 .`
|
||||
module_path string
|
||||
mut:
|
||||
checker checker.Checker
|
||||
pref &pref.Preferences
|
||||
parsed_files []ast.File
|
||||
global_scope &ast.Scope
|
||||
|
|
|
@ -15,8 +15,8 @@ const (
|
|||
)
|
||||
|
||||
pub struct Checker {
|
||||
table &table.Table
|
||||
pub mut:
|
||||
table &table.Table
|
||||
file ast.File
|
||||
nr_errors 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) {
|
||||
match expr {
|
||||
ast.CastExpr {
|
||||
// TODO
|
||||
return
|
||||
}
|
||||
ast.Ident {
|
||||
scope := c.file.scope.innermost(it.pos.pos)
|
||||
if v := scope.find_var(it.name) {
|
||||
|
@ -580,7 +584,10 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) {
|
|||
it.pos)
|
||||
}
|
||||
} 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 {
|
||||
|
@ -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')
|
||||
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
|
||||
c.pref.compile_defines {
|
||||
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 {
|
||||
c.error('`$arg.name` is a mutable argument, you need to provide `mut`: `${call_expr.name}(mut ...)`',
|
||||
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
|
||||
if arg_typ_sym.kind == .interface_ {
|
||||
|
|
|
@ -8,10 +8,10 @@ import v.ast
|
|||
import os
|
||||
|
||||
struct Doc {
|
||||
out strings.Builder
|
||||
table &table.Table
|
||||
mod string
|
||||
mut:
|
||||
out strings.Builder
|
||||
stmts []ast.Stmt // all module statements from all files
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,10 @@ const (
|
|||
)
|
||||
|
||||
struct Gen {
|
||||
table &table.Table
|
||||
pref &pref.Preferences
|
||||
module_built string
|
||||
mut:
|
||||
out strings.Builder
|
||||
cheaders strings.Builder
|
||||
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
|
||||
hotcode_definitions strings.Builder // -live declarations & functions
|
||||
options strings.Builder // `Option_xxxx` types
|
||||
table &table.Table
|
||||
pref &pref.Preferences
|
||||
module_built string
|
||||
mut:
|
||||
file ast.File
|
||||
fn_decl &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0
|
||||
last_fn_c_name string
|
||||
|
@ -178,7 +178,7 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
|||
//
|
||||
g.finish()
|
||||
//
|
||||
b := strings.new_builder(250000)
|
||||
mut b := strings.new_builder(250000)
|
||||
b.writeln(g.hashes())
|
||||
b.writeln(g.comptime_defines.str())
|
||||
b.writeln('\n// V typedefs:')
|
||||
|
@ -311,7 +311,7 @@ pub fn (mut g Gen) write_typeof_functions() {
|
|||
}
|
||||
|
||||
// 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)
|
||||
if styp.len == 1 && t == table.t_type && g.cur_generic_type != 0 {
|
||||
// T => int etc
|
||||
|
@ -339,7 +339,7 @@ fn (g &Gen) base_type(t table.Type) string {
|
|||
}
|
||||
|
||||
// TODO this really shouldnt be seperate from typ
|
||||
// but I(emily) would rather have this generation
|
||||
// but I(emily) would rather have this generation
|
||||
// all unified in one place so that it doesnt break
|
||||
// if one location changes
|
||||
fn (g &Gen) optional_type_name(t table.Type) (string, string) {
|
||||
|
@ -2796,7 +2796,7 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) {
|
|||
for field in info.fields {
|
||||
// Some of these structs may want to contain
|
||||
// optionals that may not be defined at this point
|
||||
// if this is the case then we are going to
|
||||
// if this is the case then we are going to
|
||||
// buffer manip out in front of the struct
|
||||
// write the optional in and then continue
|
||||
if field.typ.flag_is(.optional) {
|
||||
|
|
|
@ -23,9 +23,9 @@ const (
|
|||
|
||||
struct JsGen {
|
||||
table &table.Table
|
||||
definitions strings.Builder
|
||||
pref &pref.Preferences
|
||||
mut:
|
||||
definitions strings.Builder
|
||||
out strings.Builder
|
||||
namespaces map[string]strings.Builder
|
||||
namespaces_pub map[string][]string
|
||||
|
|
|
@ -3,6 +3,7 @@ module js
|
|||
import v.ast
|
||||
|
||||
struct JsDoc {
|
||||
mut:
|
||||
gen &JsGen
|
||||
}
|
||||
|
||||
|
|
|
@ -221,7 +221,8 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||
continue
|
||||
}
|
||||
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' +
|
||||
'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) {
|
||||
p.check(.lpar)
|
||||
mut args := []table.Arg{}
|
||||
|
@ -381,7 +383,7 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool) {
|
|||
is_variadic = true
|
||||
}
|
||||
mut arg_type := p.parse_type()
|
||||
if is_mut {
|
||||
if is_mut && arg_type != table.t_type {
|
||||
// if arg_type.is_ptr() {
|
||||
// p.error('cannot mut')
|
||||
// }
|
||||
|
@ -425,7 +427,7 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool) {
|
|||
is_variadic = true
|
||||
}
|
||||
mut typ := p.parse_type()
|
||||
if is_mut {
|
||||
if is_mut && typ != table.t_type {
|
||||
if typ.is_ptr() {
|
||||
// name := p.table.get_type_name(typ)
|
||||
// p.warn('`$name` is already a reference, it cannot be marked as `mut`')
|
||||
|
|
|
@ -16,10 +16,10 @@ import runtime
|
|||
import time
|
||||
|
||||
pub struct Parser {
|
||||
scanner &scanner.Scanner
|
||||
file_name string // "/home/user/hello.v"
|
||||
file_name_dir string // "/home/user"
|
||||
mut:
|
||||
scanner &scanner.Scanner
|
||||
tok token.Token
|
||||
prev_tok token.Token
|
||||
peek_tok token.Token
|
||||
|
|
|
@ -14,7 +14,7 @@ fn mpath() string {
|
|||
}
|
||||
|
||||
pub fn new_preferences() Preferences {
|
||||
p := Preferences{}
|
||||
mut p := Preferences{}
|
||||
p.fill_with_defaults()
|
||||
return p
|
||||
}
|
||||
|
|
|
@ -2,8 +2,9 @@ module pref
|
|||
|
||||
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 files := files_.clone()
|
||||
files.sort()
|
||||
for file in files {
|
||||
if !file.ends_with('.v') && !file.ends_with('.vh') {
|
||||
|
|
|
@ -40,6 +40,7 @@ pub enum TypeFlag {
|
|||
unset
|
||||
optional
|
||||
variadic
|
||||
generic
|
||||
}
|
||||
|
||||
pub fn (types []Type) contains(typ Type) bool {
|
||||
|
|
|
@ -40,6 +40,7 @@ fn test_foo() {
|
|||
|
||||
fn create<T>() {
|
||||
a := T{}
|
||||
println(a.foo)
|
||||
mut xx := T{}
|
||||
xx.foo = 'foo'
|
||||
println(xx.foo)
|
||||
|
@ -63,10 +64,15 @@ fn (u User) init() {
|
|||
fn (c City) init() {
|
||||
}
|
||||
|
||||
fn gen_arg<T>(mut x T) {
|
||||
println(x.foo) // = 'foo'
|
||||
}
|
||||
|
||||
fn test_create() {
|
||||
create<User>()
|
||||
create<City>()
|
||||
// create<User>()
|
||||
u := User{}
|
||||
//gen_arg<User>(mut u)
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -142,8 +142,8 @@ pub fn run<T>(port int) {
|
|||
//app.reset()
|
||||
for {
|
||||
conn := l.accept() or { panic('accept() failed') }
|
||||
handle_conn<T>(conn, mut app)
|
||||
//foobar<T>()
|
||||
//handle_conn<T>(conn, mut app)
|
||||
app = handle_conn<T>(conn, app)
|
||||
// TODO move this to handle_conn<T>(conn, app)
|
||||
//message := readall(conn)
|
||||
//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 := conn.read_line()
|
||||
println('firstline="$first_line"')
|
||||
|
@ -182,7 +184,7 @@ fn handle_conn<T>(conn net.Socket, app mut T) {
|
|||
println('no vals for http')
|
||||
conn.send_string(http_500) or {}
|
||||
conn.close() or {}
|
||||
return
|
||||
return app
|
||||
//continue
|
||||
}
|
||||
mut headers := []string{}
|
||||
|
@ -263,7 +265,7 @@ fn handle_conn<T>(conn net.Socket, app mut T) {
|
|||
println('no vals for http')
|
||||
}
|
||||
conn.close() or {}
|
||||
return
|
||||
return app
|
||||
//continue
|
||||
}
|
||||
|
||||
|
@ -274,10 +276,10 @@ fn handle_conn<T>(conn net.Socket, app mut T) {
|
|||
if static_file != '' && mime_type != '' {
|
||||
data := os.read_file(static_file) or {
|
||||
conn.send_string(http_404) or {}
|
||||
return
|
||||
return app
|
||||
}
|
||||
app.vweb.send_response_to_client(mime_type, data)
|
||||
return
|
||||
return app
|
||||
}
|
||||
|
||||
// Call the right action
|
||||
|
@ -292,6 +294,7 @@ fn handle_conn<T>(conn net.Socket, app mut T) {
|
|||
*/
|
||||
conn.close() or {}
|
||||
app.reset()
|
||||
return app
|
||||
}
|
||||
|
||||
fn (mut ctx Context) parse_form(s string) {
|
||||
|
|
Loading…
Reference in New Issue