diff --git a/lib/core/src/StaticBuffer.c.ri b/lib/core/src/StaticBuffer.c.ri index d99699ca0..27c71950e 100644 --- a/lib/core/src/StaticBuffer.c.ri +++ b/lib/core/src/StaticBuffer.c.ri @@ -5,7 +5,7 @@ import c/libc; struct StaticBuffer { - buf: [25]mut uint8; + mut buf: [25]mut uint8; mut len: uint; pub func push(mut self, byte: uint8) { @@ -16,22 +16,22 @@ struct StaticBuffer { self.len += 1; } - pub func as_uint64(&self) -> uint64 { + pub func as_uint64(mut self) -> uint64 { self.buf[self.len] = 0; return unsafe { libc.strtoul(&self.buf[0], none, 10) }; } - pub func as_uint(&self) -> uint { + pub func as_uint(mut self) -> uint { self.buf[self.len] = 0; return unsafe { @as(uint, libc.strtoul(&self.buf[0], none, 10)) }; } - pub func as_int(&self) -> int { + pub func as_int(mut self) -> int { self.buf[self.len] = 0; return unsafe { @as(int, libc.strtol(&self.buf[0], none, 10))}; } - pub func as_string(&self) -> string { + pub func as_string(mut self) -> string { self.buf[self.len] = 0; return unsafe { string.from_raw_with_len(&self.buf[0], self.len).clone() }; } diff --git a/lib/core/src/TestRunner.ri b/lib/core/src/TestRunner.ri index 19aaeed75..a983e376f 100644 --- a/lib/core/src/TestRunner.ri +++ b/lib/core/src/TestRunner.ri @@ -76,7 +76,7 @@ struct Test { } struct TestRunner { - tests: []mut Test; + mut tests: []mut Test; mut ok_tests: uint64; mut fail_tests: uint64; mut skip_tests: uint64; diff --git a/lib/core/src/backtrace.c.ri b/lib/core/src/backtrace.c.ri index a2415f8e7..a775ac0a7 100644 --- a/lib/core/src/backtrace.c.ri +++ b/lib/core/src/backtrace.c.ri @@ -62,7 +62,7 @@ func bt_print_callback( func bt_error_handler(data: rawptr, msg_ptr: ?[&]mut uint8, errnum: int32) { unsafe { - bdata := @as(&mut BacktraceData, data); + mut bdata := @as(&mut BacktraceData, data); if !bdata.has_error { bdata.has_error = true; console_ewrite(" libbacktrace error: "); diff --git a/lib/core/src/errors.ri b/lib/core/src/errors.ri index 5e156ad8b..5c809b9a3 100644 --- a/lib/core/src/errors.ri +++ b/lib/core/src/errors.ri @@ -33,7 +33,7 @@ struct CallTrace { const RETURN_TRACE_MAX_SIZE := 50; struct ReturnTrace { - traces: [RETURN_TRACE_MAX_SIZE]mut CallTrace; + mut traces: [RETURN_TRACE_MAX_SIZE]mut CallTrace; mut cur_idx: uint; #[inline] diff --git a/lib/core/src/rune.ri b/lib/core/src/rune.ri index bd8dfe0ed..c04c59e50 100644 --- a/lib/core/src/rune.ri +++ b/lib/core/src/rune.ri @@ -50,7 +50,7 @@ extend rune < Stringable { pub func as_bytes(self) -> []uint8 { res := []uint8(cap: 5); - res_v := @as(DynArray, res); + mut res_v := @as(DynArray, res); res_v.len = utf32_decode_to_buffer(self, unsafe { @as([&]mut uint8, res_v.ptr) }); return res; } diff --git a/lib/rivet/src/ast/CHeader.ri b/lib/rivet/src/ast/CHeader.ri index 7a81aabb4..0e4ef91c6 100644 --- a/lib/rivet/src/ast/CHeader.ri +++ b/lib/rivet/src/ast/CHeader.ri @@ -119,7 +119,7 @@ extend Table { "{} -x c -E -dM /dev/null".fmt(self.prefs.target_backend_compiler) ) { defines_ := result.output.split_into_lines(); - defines := CDefines(); + mut defines := CDefines(); for define in defines_ { mut tokens := define.tokenize(b' '); _ = tokens.next(); // skip '#define' diff --git a/lib/rivet/src/ast/Decl.ri b/lib/rivet/src/ast/Decl.ri index 8b166768d..a231e7643 100644 --- a/lib/rivet/src/ast/Decl.ri +++ b/lib/rivet/src/ast/Decl.ri @@ -23,7 +23,7 @@ pub enum Decl { docs: []Comment; attributes: Attributes; abi: ABI; - decls: []Decl; + mut decls: []Decl; pos: token.Pos; }, Alias { @@ -42,8 +42,8 @@ pub enum Decl { attributes: Attributes; is_public: bool; name: string; - bases: []mut Type; - decls: []Decl; + mut bases: []mut Type; + mut decls: []Decl; pos: token.Pos; mut sym: Sym; }, @@ -53,10 +53,10 @@ pub enum Decl { is_public: bool; name: string; mut underlying_type: Type; - bases: []mut Type; - variants: []EnumVariantDecl; + mut bases: []mut Type; + mut variants: []mut EnumVariantDecl; is_tagged: bool; - decls: []Decl; + mut decls: []Decl; pos: token.Pos; mut sym: Sym; }, @@ -65,8 +65,8 @@ pub enum Decl { attributes: Attributes; is_public: bool; name: string; - bases: []mut Type; - decls: []Decl; + mut bases: []mut Type; + mut decls: []Decl; is_opaque: bool; pos: token.Pos; mut sym: Sym; @@ -85,8 +85,8 @@ pub enum Decl { Extend { attributes: Attributes; mut type: Type; - bases: []mut Type; - decls: []Decl; + mut bases: []mut Type; + mut decls: []Decl; pos: token.Pos; }, Const { @@ -106,7 +106,7 @@ pub enum Decl { is_public: bool; is_extern: bool; abi: ABI; - lefts: []ObjectData; + mut lefts: []mut ObjectData; mut right: Expr; pos: token.Pos; mut sym: Sym; @@ -125,10 +125,10 @@ pub enum Decl { is_operator: bool; abi: ABI; name: string; - args: []Arg; + mut args: []mut Arg; has_named_args: bool; mut ret_type: Type; - stmts: []mut Stmt; + mut stmts: []mut Stmt; mut scope: Scope; has_body: bool; self_is_mut: bool; @@ -143,7 +143,7 @@ pub enum Decl { docs: []Comment; attributes: Attributes; name: string; - stmts: []mut Stmt; + mut stmts: []mut Stmt; scope: Scope; pos: token.Pos; mut defer_stmts: []Stmt.Defer; @@ -187,7 +187,7 @@ pub struct EnumVariantDecl { pub has_type: bool; pub has_value: bool; pub value: Expr; - pub decls: []Decl; + pub mut decls: []Decl; pub pos: token.Pos; } diff --git a/lib/rivet/src/ast/Expr.ri b/lib/rivet/src/ast/Expr.ri index 1dd3fdca4..57e320946 100644 --- a/lib/rivet/src/ast/Expr.ri +++ b/lib/rivet/src/ast/Expr.ri @@ -16,7 +16,7 @@ pub enum Expr < traits.Stringable { pos: token.Pos; mut type: Type; - pub func clean_paren(self) -> Expr { + pub func clean_paren(&self) -> Expr { mut res := self.expr; while res is .Paren(paren) { res = paren.expr; @@ -98,7 +98,7 @@ pub enum Expr < traits.Stringable { mut variant: EnumVariant; }, TupleLiteral { - values: []mut Expr; + mut values: []mut Expr; pos: token.Pos; mut type: Type; }, @@ -114,7 +114,7 @@ pub enum Expr < traits.Stringable { pos: token.Pos; }, ArrayLiteral { - values: []mut Expr; + mut values: []mut Expr; is_dyn: bool; pos: token.Pos; mut type: Type; @@ -170,7 +170,7 @@ pub enum Expr < traits.Stringable { }, Call { mut left: Expr; - mut args: []CallArg; + mut args: []mut CallArg; mut spread_expr: Expr; has_spread_expr: bool; mut err_handler: CallErrorHandler; @@ -184,7 +184,7 @@ pub enum Expr < traits.Stringable { mut is_enum_variant: bool; mut enum_variant_sym: TypeSym; - func has_named_args(self) -> bool { + func has_named_args(&self) -> bool { for arg in self.args { if arg.is_named { return true; @@ -193,7 +193,7 @@ pub enum Expr < traits.Stringable { return false; } - func get_named_arg(self, name: string) -> ?CallArg { + func get_named_arg(&self, name: string) -> ?CallArg { for arg in self.args { if arg.is_named && arg.name == name { return arg; @@ -204,7 +204,7 @@ pub enum Expr < traits.Stringable { /// Returns the number of pure arguments, that is, not named, that /// this call has. - func pure_args_count(self) -> uint { + func pure_args_count(&self) -> uint { mut l: uint := 0; for arg in self.args { if !arg.is_named { @@ -218,13 +218,13 @@ pub enum Expr < traits.Stringable { } #[inline] - func has_err_handler(self) -> bool { + func has_err_handler(&self) -> bool { return self.err_handler.has_expr || self.err_handler.is_propagate; } }, BuiltinCall { name: string; - args: []CallArg; + mut args: []mut CallArg; pos: token.Pos; mut builtin: Builtin := .Invalid; mut type: Type; @@ -266,7 +266,7 @@ pub enum Expr < traits.Stringable { mut defer_stmts: []Stmt.Defer; }, If { - branches: []IfBranch; + mut branches: []mut IfBranch; has_else: bool; pos: token.Pos; mut expected_type: Type; @@ -274,7 +274,7 @@ pub enum Expr < traits.Stringable { }, Match { mut expr: Expr; - branches: []MatchBranch; + mut branches: []mut MatchBranch; mut is_typematch: bool; has_else: bool; mut scope: Scope; @@ -286,8 +286,9 @@ pub enum Expr < traits.Stringable { // Examples: // - if x := optional_or_result_fn() { ... } // - while byte := reader.read() { ... } + // - match x := optional_or_result_fn(); x == some { ... } Guard { - vars: []ObjectData; + mut vars: []mut ObjectData; mut expr: Expr; has_cond: bool; mut cond: Expr; @@ -633,7 +634,7 @@ pub struct IfBranch { #[boxed] pub struct MatchBranch { - pub patterns: []mut Expr; + pub mut patterns: []mut Expr; pub has_var: bool; pub var_is_mut: bool; pub var_name: string; diff --git a/lib/rivet/src/ast/Scope.ri b/lib/rivet/src/ast/Scope.ri index 92fc6a3f6..2d0116559 100644 --- a/lib/rivet/src/ast/Scope.ri +++ b/lib/rivet/src/ast/Scope.ri @@ -11,8 +11,8 @@ pub struct Scope { pub mut owner: ?Sym; pub mut parent: ?Scope; pub mut detached_from_parent: bool; - pub mut childrens: []Scope; - pub mut syms: []Sym; + pub mut childrens: []mut Scope; + pub mut syms: []mut Sym; pub mut is_local: bool; pub func add(mut self, sym: Sym) -> ! { @@ -27,7 +27,7 @@ pub struct Scope { } pub func add_or_get(mut self, sym: Sym) -> !Sym { - if old_sym := self.find(sym.name) { + if mut old_sym := self.find(sym.name) { if sym is TypeSym(type_sym) && old_sym is TypeSym(mut old_type_sym) { if old_type_sym.update(type_sym)! { return old_sym; @@ -116,24 +116,24 @@ pub struct Scope { } pub func update_type(self, name: string, type: Type) { - if sym := self.lookup(name) { - if sym is Var(var_info) { + if mut sym := self.lookup(name) { + if sym is Var(mut var_info) { var_info.type = type; } } } pub func update_is_hidden_ref(self, name: string, is_hidden_ref: bool) { - if sym := self.lookup(name) { - if sym is Var(var_info) { + if mut sym := self.lookup(name) { + if sym is Var(mut var_info) { var_info.is_hidden_ref = is_hidden_ref; } } } pub func update_is_used(self, name: string, is_used: bool) { - if sym := self.lookup(name) { - if sym is Var(var_info) { + if mut sym := self.lookup(name) { + if sym is Var(mut var_info) { var_info.is_used = is_used; } } diff --git a/lib/rivet/src/ast/SourceFile.ri b/lib/rivet/src/ast/SourceFile.ri index aaeed8f07..c8f1911b6 100644 --- a/lib/rivet/src/ast/SourceFile.ri +++ b/lib/rivet/src/ast/SourceFile.ri @@ -7,7 +7,7 @@ import ../token; #[boxed] pub struct SourceFile { pub path: string; - pub decls: []Decl; + pub mut decls: []mut Decl; pub mut mod: Module; pub mut imported_symbols: ImportedSymbols; pub mut pos: token.Pos; diff --git a/lib/rivet/src/ast/Stmt.ri b/lib/rivet/src/ast/Stmt.ri index e28f0d26a..8d9098619 100644 --- a/lib/rivet/src/ast/Stmt.ri +++ b/lib/rivet/src/ast/Stmt.ri @@ -9,7 +9,7 @@ pub enum Stmt { Comment(Comment), Expr(Expr), VarDecl { - lefts: []ObjectData; + mut lefts: []mut ObjectData; mut right: Expr; mut scope: Scope; pos: token.Pos; @@ -27,7 +27,7 @@ pub enum Stmt { For { mut index: ObjectData; has_index: bool; - values: []ObjectData; + mut values: []mut ObjectData; mut iterable: Expr; mut stmt: Stmt; mut scope: Scope; @@ -39,6 +39,7 @@ pub enum Stmt { Error, Success } + mut expr: Expr; mode: Mode; pos: token.Pos; diff --git a/lib/rivet/src/ast/Sym.ri b/lib/rivet/src/ast/Sym.ri index cbe91dc0e..5f20e30ce 100644 --- a/lib/rivet/src/ast/Sym.ri +++ b/lib/rivet/src/ast/Sym.ri @@ -179,7 +179,7 @@ pub struct Module < Sym { if type_sym := self.scope.find(unique_name) { return @as(TypeSym, type_sym); } - type_sym := TypeSym( + mut type_sym := TypeSym( is_public: true, name: unique_name, info: .DynArray(elem_type, is_mut), diff --git a/lib/rivet/src/ast/Table.ri b/lib/rivet/src/ast/Table.ri index 44eb67580..0a23dfbf9 100644 --- a/lib/rivet/src/ast/Table.ri +++ b/lib/rivet/src/ast/Table.ri @@ -17,6 +17,7 @@ pub struct Table { /// compiled reside. pub mut universe: Module; pub mut prefs: prefs.Prefs; + pub mut source_files: []mut SourceFile; pub pointer_size: uint; @@ -70,8 +71,6 @@ pub struct Table { pub mut string_t: Type; pub mut throwable_t: Type; - pub mut source_files: []SourceFile; - #[inline] pub func new(prefs_: prefs.Prefs) -> Table { universe_ := universe(); @@ -361,7 +360,7 @@ pub struct Table { } (utils.round_up(total_size, max_alignment), max_alignment) }, - .Trait(trait_info) -> { + .Trait(mut trait_info) -> { (size, align) = ((type_sym.fields.len + 2) * self.pointer_size, self.pointer_size); for mut btype in trait_info.bases { (bsize, _balign) := self.type_symbol_size(btype, is_raw); diff --git a/lib/rivet/src/ast/Type.ri b/lib/rivet/src/ast/Type.ri index cd27c226b..80ad8fb87 100644 --- a/lib/rivet/src/ast/Type.ri +++ b/lib/rivet/src/ast/Type.ri @@ -10,7 +10,7 @@ import ../token; #[default_value(.Void)] pub enum Type < traits.Stringable { Basic { - mut sym: TypeSym; + mut sym: ?TypeSym; mut is_unresolved: bool; mut expr: Expr; pos: token.Pos; @@ -27,11 +27,11 @@ pub enum Type < traits.Stringable { pos: token.Pos; }, Tuple { - inners: []mut Type; + mut inners: []mut Type; mut sym: TypeSym; pos: token.Pos; - func ==(self, other: Self) -> bool { + func ==(&self, other: &Self) -> bool { if self.inners.len != other.inners.len { return false; } @@ -76,14 +76,14 @@ pub enum Type < traits.Stringable { is_method: bool; self_is_mut: bool; self_is_ptr: bool; - args: []Arg; + mut args: []mut Arg; mut ret_type: Type; pos: token.Pos; mut sym: TypeSym; mut has_sym: bool; #[inline] - func symbol(self) -> Func { + func symbol(&self) -> Func { return if self.has_sym && self.sym.info is .Func(func_sym) { func_sym } else { @@ -108,31 +108,31 @@ pub enum Type < traits.Stringable { }; } - pub func unalias(self) -> ?Self { + pub func unalias(mut self) -> ?Self { // NOTE: `.unalias()` returns an option, so we use the same type without // unaliasing instead. return match self { .Rawptr -> self, - .Result(result) -> .Result(result.inner.unalias() ?? result.inner), - .Option(option) -> .Option(option.inner.unalias() ?? option.inner), - .Tuple(tuple_data) -> { - unaliased_types := []mut Type(cap: tuple_data.inners.len); - for i, tuple_type in tuple_data.inners { + .Result(mut result) -> .Result(result.inner.unalias() ?? result.inner), + .Option(mut option) -> .Option(option.inner.unalias() ?? option.inner), + .Tuple(mut tuple_data) -> { + mut unaliased_types := []mut Type(cap: tuple_data.inners.len); + for i, mut tuple_type in tuple_data.inners { unaliased_types[i] = tuple_type.unalias() ?? tuple_type; } .Tuple(unaliased_types, tuple_data.sym) }, - .DynArray(dyn_array_data) -> .DynArray( + .DynArray(mut dyn_array_data) -> .DynArray( dyn_array_data.inner.unalias() ?? dyn_array_data.inner, dyn_array_data.is_mut ), - .Array(array_data) -> .Array( + .Array(mut array_data) -> .Array( array_data.inner.unalias() ?? array_data.inner, ...self ), - .Pointer(pointer_data) -> .Pointer( + .Pointer(mut pointer_data) -> .Pointer( pointer_data.inner.unalias() ?? pointer_data.inner, ...self ), - .Func(func_data) -> { - for arg in func_data.args { + .Func(mut func_data) -> { + for mut arg in func_data.args { arg.type = arg.type.unalias() ?? arg.type; } .Func( @@ -140,7 +140,7 @@ pub enum Type < traits.Stringable { ...self ) }, - .Basic(basic) if !basic.is_unresolved -> if basic.sym.info is .Alias(alias_info) { + .Basic(mut basic) if !basic.is_unresolved -> if basic.sym?.info is .Alias(mut alias_info) { alias_info.parent.unalias() ?? alias_info.parent } else { .Basic(basic.sym) @@ -299,7 +299,7 @@ pub enum Type < traits.Stringable { }, .Basic(basic_lhs) if rhs is .Basic(basic_rhs) -> !(basic_lhs.is_unresolved && basic_rhs.is_unresolved) - && basic_lhs.sym == basic_rhs.sym, + && basic_lhs.sym? == basic_rhs.sym?, else -> false }; } @@ -391,12 +391,14 @@ pub enum Type < traits.Stringable { } sb.to_string() }, - .Basic(basic) -> if basic.is_unresolved { - basic.expr.to_string() - } else if qualstr { - basic.sym.qualname() + .Basic(basic) -> if type_sym := basic.sym { + if qualstr { + type_sym.qualname() + } else { + type_sym.name + } } else { - basic.sym.name + basic.expr.to_string() } }; } diff --git a/lib/rivet/src/ast/TypeInfo.ri b/lib/rivet/src/ast/TypeInfo.ri index 94fc1adea..fe85cfefe 100644 --- a/lib/rivet/src/ast/TypeInfo.ri +++ b/lib/rivet/src/ast/TypeInfo.ri @@ -44,10 +44,10 @@ pub enum TypeInfo < traits.Stringable { }, Trait { mut bases: []mut TypeSym; - mut implements: []TypeSym; + mut implements: []mut TypeSym; mut has_objects: bool; - func index_of(self, type_sym: TypeSym) -> ?uint { + func index_of(&self, type_sym: TypeSym) -> ?uint { for i, ts in self.implements { if ts.id == type_sym.id { return i; @@ -59,7 +59,7 @@ pub enum TypeInfo < traits.Stringable { func implement(mut self, type_sym: TypeSym) { if type_sym !in self.implements { self.implements.push(type_sym); - for b in self.bases { + for mut b in self.bases { @as(TypeInfo.Trait, b.info).implement(type_sym); } } @@ -72,7 +72,7 @@ pub enum TypeInfo < traits.Stringable { }, Enum { underlying_type: Type; - mut variants: []EnumVariant; + mut variants: []mut EnumVariant; is_tagged: bool; mut traits: []mut TypeSym; @@ -81,11 +81,11 @@ pub enum TypeInfo < traits.Stringable { self.variants.push(variant); } - func has_variant(self, name: string) -> bool { + func has_variant(&self, name: string) -> bool { return self.get_variant(name) != none; } - func get_variant(self, name: string) -> ?EnumVariant { + func get_variant(&self, name: string) -> ?EnumVariant { for v in self.variants { if v.name == name { return v; @@ -94,7 +94,7 @@ pub enum TypeInfo < traits.Stringable { return none; } - func get_variant_by_type(self, type: Type) -> ?EnumVariant { + func get_variant_by_type(&self, type: Type) -> ?EnumVariant { for v in self.variants { if v.has_type && v.type == type { return v; @@ -103,7 +103,7 @@ pub enum TypeInfo < traits.Stringable { return none; } - func contains_trait(self, type_sym: TypeSym) -> bool { + func contains_trait(&self, type_sym: TypeSym) -> bool { for trait_ in self.traits { if trait_.id == type_sym.id { return true; @@ -120,7 +120,7 @@ pub enum TypeInfo < traits.Stringable { mut bases: []mut TypeSym; mut traits: []mut TypeSym; - func contains_trait(self, type_sym: TypeSym) -> bool { + func contains_trait(&self, type_sym: TypeSym) -> bool { for trait_ in self.traits { if trait_.id == type_sym.id { return true; diff --git a/lib/rivet/src/ast/TypeSym.ri b/lib/rivet/src/ast/TypeSym.ri index 7df113e17..7b354bc5b 100644 --- a/lib/rivet/src/ast/TypeSym.ri +++ b/lib/rivet/src/ast/TypeSym.ri @@ -132,13 +132,13 @@ pub struct TypeSym < Sym { return self.full_fields_; } mut fields := []Field(); - if self.info is .Trait(trait_info) { + if self.info is .Trait(mut trait_info) { for mut b in trait_info.bases { for bf in b.full_fields() { fields.push(bf); } } - } else if self.info is .Struct(struct_info) { + } else if self.info is .Struct(mut struct_info) { for mut t in struct_info.traits { for tf in t.full_fields() { fields.push(tf); diff --git a/lib/rivet/src/checker/builtin_call.ri b/lib/rivet/src/checker/builtin_call.ri index e69c634ba..0e10b665a 100644 --- a/lib/rivet/src/checker/builtin_call.ri +++ b/lib/rivet/src/checker/builtin_call.ri @@ -36,7 +36,7 @@ extend Checker { err.emit(); } } else { - for i, arg in builtin_call.args { + for i, mut arg in builtin_call.args { arg_info := b_func.args[i]; arg.type = self.check_expr(arg.expr); if arg_info.is_mut { @@ -124,7 +124,7 @@ extend Checker { ), builtin_call.pos ); } - } else if from_ts := from_type.symbol() { + } else if mut from_ts := from_type.symbol() { match from_ts.info { .Trait(mut trait_info) -> if to_ts := to_type.symbol() { if to_ts in trait_info.implements { diff --git a/lib/rivet/src/checker/call_expr.ri b/lib/rivet/src/checker/call_expr.ri index b94eafeb5..f843f9dbe 100644 --- a/lib/rivet/src/checker/call_expr.ri +++ b/lib/rivet/src/checker/call_expr.ri @@ -20,8 +20,8 @@ extend Checker { }; match left { - .SelfTy(self_ty) -> self.check_ctor_call(self_ty.sym, call_expr), - .Ident(ident) if (ident.is_sym || ident.is_obj) -> match ident.sym is { + .SelfTy(mut self_ty) -> self.check_ctor_call(self_ty.sym, call_expr), + .Ident(mut ident) if (ident.is_sym || ident.is_obj) -> match ident.sym is { ast.TypeSym(mut type_sym) if type_sym.info is .Trait || type_sym.info is .Struct || type_sym.info is .String || type_sym.info is .Enum -> self.check_ctor_call(type_sym, call_expr), @@ -47,7 +47,7 @@ extend Checker { } } }, - .Selector(selector) -> if selector.is_path { + .Selector(mut selector) -> if selector.is_path { match selector.sym is { ast.TypeSym(mut s_type_sym) if s_type_sym.info is .Trait || s_type_sym.info is .Struct || s_type_sym.info is .String @@ -131,7 +131,7 @@ extend Checker { ); } }, - .EnumLiteral(enum_lit) -> { + .EnumLiteral(mut enum_lit) -> { enum_lit.is_instance = true; _ = self.check_expr(left); self.check_ctor_call(enum_lit.sym, call_expr); @@ -222,7 +222,7 @@ extend Checker { } else if variant.has_type { old_expected_type := self.expected_type; self.expected_type = variant.type; - arg0 := call_expr.args[0]; + mut arg0 := call_expr.args[0]; self.check_types( self.check_expr(arg0.expr), variant.type ) catch |err| { @@ -255,7 +255,7 @@ extend Checker { "cannot use spread expression with trait constructor", call_expr.pos ); } else if call_expr.args.len == 1 { - arg0 := call_expr.args[0]; + mut arg0 := call_expr.args[0]; value_t := self.table.comptime_number_to_type(self.check_expr(arg0.expr)); if value_t.symbol()? in trait_info.implements { trait_info.mark_has_objects(); @@ -292,7 +292,7 @@ extend Checker { return; } } - for i, arg in call_expr.args { + for i, mut arg in call_expr.args { mut field := ast.Field(); if arg.is_named { if t_field := type_sym.lookup_field(arg.name) { @@ -462,7 +462,7 @@ extend Checker { } old_expected_type := self.expected_type; - for i, arg in call_expr.args { + for i, mut arg in call_expr.args { arg_fn := if func_.is_variadic && i >= func_.args.len - 1 { func_.args[func_.args.len - 1] } else { diff --git a/lib/rivet/src/checker/decls.ri b/lib/rivet/src/checker/decls.ri index 46d9f0cbc..af8eefe57 100644 --- a/lib/rivet/src/checker/decls.ri +++ b/lib/rivet/src/checker/decls.ri @@ -6,19 +6,19 @@ import ../ast; import ../report; extend Checker { - func check_global_vars(mut self, decls: []mut ast.Decl) { + func check_global_vars(mut self, mut decls: []mut ast.Decl) { for mut decl in decls { old_sym := self.sym; if decl is .Const || decl is .Var { self.check_decl(decl); - } else if decl_decls := decl.decls() { + } else if mut decl_decls := decl.decls() { self.check_global_vars(decl_decls); } self.sym = old_sym; } } - func check_decls(mut self, decls: []mut ast.Decl) { + func check_decls(mut self, mut decls: []mut ast.Decl) { for mut decl in decls { if !(decl is .Const || decl is .Var) { self.check_decl(decl); @@ -55,19 +55,19 @@ extend Checker { }, "alias", alias_decl.name, alias_decl.pos ); }, - .Extern(extern_decl) -> { + .Extern(mut extern_decl) -> { self.inside_extern = true; self.check_decls(extern_decl.decls); self.inside_extern = false; }, - .Var(var_decl) -> { + .Var(mut var_decl) -> { self.inside_var_decl = true; self.check_var_decl( var_decl.lefts, var_decl.right, var_decl.scope, var_decl.pos ); self.inside_var_decl = false; }, - .Const(const_decl) -> { + .Const(mut const_decl) -> { self.check_name_case(.Upper, "constant", const_decl.name, const_decl.pos); if const_decl.has_type { old_expected_type := self.expected_type; @@ -95,11 +95,11 @@ extend Checker { } } }, - .Trait(trait_decl) -> { + .Trait(mut trait_decl) -> { self.check_name_case(.Pascal, "trait", trait_decl.name, trait_decl.pos); self.check_decls(trait_decl.decls); }, - .Enum(enum_decl) -> { + .Enum(mut enum_decl) -> { self.check_name_case(.Pascal, "enum", enum_decl.name, enum_decl.pos); for base in enum_decl.bases { if sym := base.symbol() { @@ -110,13 +110,13 @@ extend Checker { } } } - for variant in enum_decl.variants { + for mut variant in enum_decl.variants { self.check_name_case(.Pascal, "enum variant", variant.name, variant.pos); self.check_decls(variant.decls); } self.check_decls(enum_decl.decls); }, - .Struct(struct_decl) -> { + .Struct(mut struct_decl) -> { self.check_name_case(.Pascal, "struct", struct_decl.name, struct_decl.pos); for base in struct_decl.bases { if sym := base.symbol() { @@ -129,7 +129,7 @@ extend Checker { } self.check_decls(struct_decl.decls); }, - .Field(field_decl) -> { + .Field(mut field_decl) -> { self.check_name_case(.Snake, "field", field_decl.name, field_decl.pos); if field_decl.has_def_expr { old_expected_type := self.expected_type; @@ -141,7 +141,7 @@ extend Checker { }; } }, - .Extend(extend_decl) -> { + .Extend(mut extend_decl) -> { type_sym := extend_decl.type.symbol()?; for base in extend_decl.bases { if sym := base.symbol() { @@ -153,7 +153,7 @@ extend Checker { self.check_decls(extend_decl.decls); }, .Func(mut func_decl) -> self.check_func(func_decl), - .Test(test_decl) -> { + .Test(mut test_decl) -> { old_cur_func := self.cur_func; self.cur_func = ast.Func(ret_type: .Void); self.inside_test = true; @@ -213,7 +213,7 @@ extend Checker { if func_decl.is_method && func_decl.self_is_ptr && func_decl.self_type.is_boxed() { report.error("cannot take the address of a boxed value as receiver", func_decl.self_pos); } - for arg in func_decl.args { + for mut arg in func_decl.args { self.check_name_case(.Snake, "argument", arg.name, arg.pos); if arg.has_def_expr { if func_decl.abi != .Rivet { diff --git a/lib/rivet/src/checker/exprs.ri b/lib/rivet/src/checker/exprs.ri index f3c6f6281..4883c31b4 100644 --- a/lib/rivet/src/checker/exprs.ri +++ b/lib/rivet/src/checker/exprs.ri @@ -14,10 +14,10 @@ extend Checker { self.scope_returns = true; .Never(branch.pos) }, - .Paren(paren) -> self.check_expr(paren.expr), + .Paren(mut paren) -> self.check_expr(paren.expr), .NoneLiteral -> .None, .BoolLiteral -> self.table.bool_t, - .CharLiteral(char_lit) -> { + .CharLiteral(mut char_lit) -> { char_lit.type = if char_lit.is_byte { self.table.uint8_t } else { @@ -25,15 +25,15 @@ extend Checker { }; char_lit.type }, - .IntegerLiteral(int_lit) -> { + .IntegerLiteral(mut int_lit) -> { int_lit.type = self.table.comptime_int_t; int_lit.type }, - .FloatLiteral(float_lit) -> { + .FloatLiteral(mut float_lit) -> { float_lit.type = self.table.comptime_float_t; float_lit.type }, - .StringLiteral(string_lit) -> { + .StringLiteral(mut string_lit) -> { string_lit.type = if string_lit.is_bytestr { .Basic(self.table.universe.add_or_get_array( self.table.uint8_t, string_lit.value.len, false @@ -45,12 +45,12 @@ extend Checker { }; string_lit.type }, - .SelfLiteral(self_lit) -> { + .SelfLiteral(mut self_lit) -> { self_lit.type = self_lit.obj.type; self_lit.type }, .SelfTy -> .Void, - .EnumLiteral(enum_lit) -> { + .EnumLiteral(mut enum_lit) -> { enum_lit.type = .Void; if sym := self.expected_type.symbol(); sym.info is .Enum(enum_info) { if variant := enum_info.get_variant(enum_lit.value) { @@ -86,7 +86,7 @@ extend Checker { enum_lit.type }, .TupleLiteral(mut tuple_lit) -> self.check_tuple_literal(tuple_lit), - .ArrayCtor(array_ctor) -> { + .ArrayCtor(mut array_ctor) -> { if mut init_value := array_ctor.init_value { init_t := self.check_expr(init_value); if !self.check_compatible_types(init_t, array_ctor.elem_type) { @@ -137,7 +137,7 @@ extend Checker { array_ctor.type }, .ArrayLiteral(mut array_lit) -> self.check_array_literal(array_lit), - .Ident(ident) -> { + .Ident(mut ident) -> { ident.type = if ident.name == "_" { .Void } else if ident.is_comptime { @@ -164,7 +164,7 @@ extend Checker { ident.type }, .Selector(mut selector) -> self.check_selector(selector), - .Indirect(indirect) -> { + .Indirect(mut indirect) -> { indirect.left_type = self.check_expr(indirect.left); indirect.type = if indirect.left_type.is_pointer() || (indirect.left_type is .Pointer(ptr) && !ptr.is_indexable) @@ -187,7 +187,7 @@ extend Checker { }; indirect.type }, - .OptionCheck(option_check) -> { + .OptionCheck(mut option_check) -> { option_check.left_type = self.check_expr(option_check.left); option_check.type = if option_check.left_type is .Option(opt) { opt.inner @@ -197,7 +197,7 @@ extend Checker { }; option_check.type }, - .Range(range) -> { + .Range(mut range) -> { range.type = if range.has_start { self.check_expr(range.start) } else { @@ -216,7 +216,7 @@ extend Checker { .Index(mut index) -> self.check_index(index), .Call(mut call_expr) -> self.check_call(call_expr), .BuiltinCall(mut builtin_call) -> self.check_builtin_call(builtin_call), - .Block(block) -> { + .Block(mut block) -> { self.defer_stmts_start = self.defer_stmts.len; if block.is_unsafe { if self.inside_unsafe_block { @@ -255,7 +255,7 @@ extend Checker { .Binary(mut binary) -> self.check_binary(binary), .If(mut if_expr) -> self.check_if(if_expr), .Match(mut match_expr) -> self.check_match(match_expr), - .Guard(guard) -> { + .Guard(mut guard) -> { old_inside_guard_expr := self.inside_guard_expr; self.inside_guard_expr = true; self.check_var_decl(guard.vars, guard.expr, guard.scope, guard.pos); @@ -573,8 +573,8 @@ extend Checker { expected_pointer = true; indexable_pointer = opt_ptr.is_indexable; } - right := unary.right.clean_paren(); - if right is .Index(index) { + mut right := unary.right.clean_paren(); + if right is .Index(mut index) { if index.left_type is .Pointer && !expected_pointer { report.error("cannot take the address of a pointer indexing", unary.pos); } @@ -743,6 +743,7 @@ extend Checker { binary.var_obj.sym.type = right_type; } if binary.var_obj.is_mut { + self.check_expr_is_mut(binary.left); binary.var_obj.sym.is_hidden_ref = true; } } @@ -824,7 +825,7 @@ extend Checker { func check_if(mut self, mut if_expr: ast.Expr.If) -> ast.Type { if_expr.expected_type = self.expected_type; - for i, branch in if_expr.branches { + for i, mut branch in if_expr.branches { if !branch.is_else { bcond_t := self.check_expr(branch.cond); if branch.cond !is .Guard && bcond_t != self.table.bool_t { diff --git a/lib/rivet/src/checker/match_expr.ri b/lib/rivet/src/checker/match_expr.ri index 7d3d85c2d..12c2d222b 100644 --- a/lib/rivet/src/checker/match_expr.ri +++ b/lib/rivet/src/checker/match_expr.ri @@ -65,7 +65,7 @@ extend Checker { mut branch_exprs := maps.MapStringUint(); match_expr.expected_type = self.expected_type; - for ib, branch in match_expr.branches { + for ib, mut branch in match_expr.branches { if !branch.is_else { self.expected_type = expr_type; for i, mut pattern in branch.patterns { diff --git a/lib/rivet/src/checker/mod.ri b/lib/rivet/src/checker/mod.ri index d98e415e6..d6e7fc558 100644 --- a/lib/rivet/src/checker/mod.ri +++ b/lib/rivet/src/checker/mod.ri @@ -32,16 +32,16 @@ pub struct Checker { mut defer_stmts_start: uint; mut defer_stmts: []ast.Stmt.Defer; - pub func check_files(mut self, source_files: []ast.SourceFile) { + pub func check_files(mut self, mut source_files: []mut ast.SourceFile) { // check global variables - for source_file in source_files { + for mut source_file in source_files { self.sym = source_file.mod; self.source_file = source_file; self.expected_type = .Void; self.check_global_vars(source_file.decls); } // check the source code - for source_file in source_files { + for mut source_file in source_files { self.sym = source_file.mod; self.source_file = source_file; self.expected_type = .Void; @@ -78,12 +78,12 @@ pub struct Checker { } func check_var_decl( - mut self, lefts: []ast.ObjectData, mut right: ast.Expr, scope: ast.Scope, + mut self, mut lefts: []mut ast.ObjectData, mut right: ast.Expr, scope: ast.Scope, pos: token.Pos ) { if lefts.len == 1 { old_expected_type := self.expected_type; - left0 := lefts[0]; + mut left0 := lefts[0]; if !left0.is_extern { if left0.name == "_" && left0.is_mut { report.error("cannot use `mut` on `_`", left0.pos); @@ -146,7 +146,7 @@ pub struct Checker { right_sym := right_type.symbol()?; if right_sym.info is .Tuple(tuple_info) { if tuple_info.types.len == lefts.len { - for i, vd in lefts { + for i, mut vd in lefts { if vd.name == "_" && vd.is_mut { report.error("cannot use `mut` on `_`", vd.pos); } @@ -249,13 +249,10 @@ pub struct Checker { } } - func check_expr_is_mut( - self, expr: ast.Expr, from_assign: bool := false, - from_selector: bool := false - ) { + func check_expr_is_mut(self, mut expr: ast.Expr, from_assign: bool := false) { match expr { - .Paren(paren) -> self.check_expr_is_mut(paren.expr), - .SelfLiteral(self_lit) -> if self_lit.obj.is_mut { + .Paren(mut paren) -> self.check_expr_is_mut(paren.expr), + .SelfLiteral(mut self_lit) -> if self_lit.obj.is_mut { self_lit.obj.is_changed = true; } else { mut err := report.error_builder( @@ -264,7 +261,7 @@ pub struct Checker { err.add_help("consider making `self` as mutable: `mut self`"); err.emit(); }, - .Ident(ident) -> if ident.is_comptime { + .Ident(mut ident) -> if ident.is_comptime { report.error( "cannot use constant `@{}` as mutable value".fmt(ident.name), ident.pos @@ -272,31 +269,12 @@ pub struct Checker { } else if ident.name == "_" { return; } else if ident.found && (ident.is_sym || ident.is_obj) { - self.check_sym_is_mut(ident.sym, ident.pos, from_selector); + self.check_sym_is_mut(ident.sym, ident.pos); }, - .Selector(selector) -> if selector.is_path { - self.check_sym_is_mut(selector.sym, selector.pos, true); + .Selector(mut selector) -> if selector.is_path { + self.check_sym_is_mut(selector.sym, selector.pos); } else { - match selector.left { - .Ident(ident2) if ident2.found -> if ident2.is_sym { - self.check_sym_is_mut(ident2.sym, ident2.pos, true) - } else if ident2.sym is ast.Var(i_var) && i_var.level == .Argument { - if i_var.is_mut { - i_var.is_changed = true; - } else { - mut err := report.error_builder( - "cannot use `{}` as mutable argument".fmt(ident2.name), - ident.pos - ); - err.add_help( - "consider making this argument mutable: `mut {}`", - ident2.name - ); - err.emit(); - } - }, - else -> self.check_expr_is_mut(selector.left, from_assign, true) - } + self.check_expr_is_mut(selector.left); if selector.found && !selector.field_is_mut { report.error( "field `{}` of type `{}` is immutable".fmt( @@ -308,13 +286,13 @@ pub struct Checker { .Indirect(indirect) -> if !indirect.is_mut { report.error("cannot use a immutable pointer as mutable value", selector.pos); }, - .OptionCheck(option_check) -> self.check_expr_is_mut(option_check.left), + .OptionCheck(mut option_check) -> self.check_expr_is_mut(option_check.left), .NoneLiteral -> report.error("`none` cannot be modified", expr.position()), .StringLiteral -> report.error( "string literals cannot be modified", expr.position() ), - .TupleLiteral(tuple_lit) -> if from_assign { - for value in tuple_lit.values { + .TupleLiteral(mut tuple_lit) -> if from_assign { + for mut value in tuple_lit.values { self.check_expr_is_mut(value); } } else { @@ -323,13 +301,13 @@ pub struct Checker { .EnumLiteral(enum_lit) if !enum_lit.is_instance -> report.error( "enum literals cannot be modified", enum_lit.pos ), - .BuiltinCall(builtin_call) -> { - for arg in builtin_call.args { + .BuiltinCall(mut builtin_call) -> { + for mut arg in builtin_call.args { self.check_expr_is_mut(arg.expr); } }, - .Block(block) if block.is_expr -> self.check_expr_is_mut(block.expr), - .Index(index) -> { + .Block(mut block) if block.is_expr -> self.check_expr_is_mut(block.expr), + .Index(mut index) -> { if index.left_type is .Pointer(ptr) { if !ptr.is_mut { report.error( @@ -338,6 +316,7 @@ pub struct Checker { } return; } + self.check_expr_is_mut(index.left); expr_sym := index.left_type.symbol()?; if !expr_sym.info.is_mut_arr_or_dyn_array() { report.error( @@ -346,18 +325,18 @@ pub struct Checker { ); } }, - .Unary(unary) -> self.check_expr_is_mut(unary.right), - .Binary(binary) -> { + .Unary(mut unary) -> self.check_expr_is_mut(unary.right), + .Binary(mut binary) -> { self.check_expr_is_mut(binary.left); self.check_expr_is_mut(binary.right); }, - .If(if_expr) -> { - for branch in if_expr.branches { + .If(mut if_expr) -> { + for mut branch in if_expr.branches { self.check_expr_is_mut(branch.expr); } }, - .Match(match_expr) -> { - for branch in match_expr.branches { + .Match(mut match_expr) -> { + for mut branch in match_expr.branches { self.check_expr_is_mut(branch.expr); } }, @@ -365,13 +344,13 @@ pub struct Checker { } } - func check_sym_is_mut(self, sym: ast.Sym, pos: token.Pos, from_selector: bool) { + func check_sym_is_mut(self, mut sym: ast.Sym, pos: token.Pos) { _ = self; match sym is { ast.Const -> report.error( "cannot use constant `{}` as mutable value".fmt(sym.name), pos ), - ast.Var(var_info) if !(from_selector && var_info.level == .Local) -> { + ast.Var(mut var_info) -> { if var_info.is_mut { var_info.is_changed = true; } else { diff --git a/lib/rivet/src/checker/stmts.ri b/lib/rivet/src/checker/stmts.ri index 9156e8514..4887274fe 100644 --- a/lib/rivet/src/checker/stmts.ri +++ b/lib/rivet/src/checker/stmts.ri @@ -7,7 +7,7 @@ import ../token; import ../report; extend Checker { - func check_stmts(mut self, stmts: []mut ast.Stmt) { + func check_stmts(mut self, mut stmts: []mut ast.Stmt) { mut unreachable_pos := token.noPos; for mut stmt in stmts { if self.scope_returns && unreachable_pos.pos == 0 { @@ -23,11 +23,11 @@ extend Checker { func check_stmt(mut self, mut stmt: ast.Stmt) { match stmt { - .VarDecl(var_decl) -> self.check_var_decl( + .VarDecl(mut var_decl) -> self.check_var_decl( var_decl.lefts, var_decl.right, var_decl.scope, var_decl.pos ), .For(mut for_stmt) -> self.check_for(for_stmt), - .While(while_stmt) -> { + .While(mut while_stmt) -> { if !while_stmt.is_inf && self.check_expr( while_stmt.cond ) != self.table.bool_t { @@ -46,7 +46,7 @@ extend Checker { self.check_stmt(while_stmt.else_stmt); } }, - .Defer(defer_stmt) -> { + .Defer(mut defer_stmt) -> { if self.cur_func.ret_type is .Never { report.error("`never` functions cannot use `defer` statements", defer_stmt.pos); } @@ -74,11 +74,15 @@ extend Checker { elem_sym := elem_type.symbol()?; if for_stmt.values.len == 1 { value0 := for_stmt.values[0]; - if value0.is_mut && !iterable_sym.info.is_mut_arr_or_dyn_array() { - report.error( - "cannot modify immutable {}".fmt(iterable_sym.info), - for_stmt.iterable.position() - ); + if value0.is_mut { + if !iterable_sym.info.is_mut_arr_or_dyn_array() { + report.error( + "cannot modify immutable {}".fmt(iterable_sym.info), + for_stmt.iterable.position() + ); + } else { + self.check_expr_is_mut(for_stmt.iterable); + } } else if value0.is_ref { if elem_sym.is_boxed() { report.error("cannot take the address of a boxed value", value0.pos); @@ -93,13 +97,13 @@ extend Checker { for_stmt.index.sym.type = self.table.uint_t; } if for_stmt.values.len == 1 { - value0 := for_stmt.values[0]; + mut value0 := for_stmt.values[0]; self.check_name_case(.Snake, "variable", value0.name, value0.pos); value0.sym.type = elem_type; value0.sym.is_hidden_ref = value0.is_mut; } else { types := @as(ast.TypeInfo.Tuple, elem_type.symbol()?.info).types; - for i, value in for_stmt.values { + for i, mut value in for_stmt.values { self.check_name_case(.Snake, "variable", value.name, value.pos); if value.is_ref && elem_sym.is_boxed() { report.error("cannot take the address of a boxed value", value.pos); diff --git a/lib/rivet/src/checker/types.ri b/lib/rivet/src/checker/types.ri index 3785b7eba..3bed5e0e0 100644 --- a/lib/rivet/src/checker/types.ri +++ b/lib/rivet/src/checker/types.ri @@ -20,7 +20,7 @@ extend Checker { self, got: ast.Type, expected: ast.Type, pos: token.Pos, arg_name: string, func_kind: string, func_name: string ) { - if expected_sym := expected.symbol(); expected_sym.info is .Trait(mut trait_info) + if mut expected_sym := expected.symbol(); expected_sym.info is .Trait(mut trait_info) && expected != got { got_t := self.table.comptime_number_to_type(got); if got_t.symbol()? in trait_info.implements { @@ -114,7 +114,7 @@ extend Checker { return false; } - expected_sym := expected.symbol() ?? return false; + mut expected_sym := expected.symbol() ?? return false; got_sym := got.symbol() ?? return false; if expected is .Variadic { diff --git a/lib/rivet/src/codegen/decls.ri b/lib/rivet/src/codegen/decls.ri index 8d7100a65..b1de8f57c 100644 --- a/lib/rivet/src/codegen/decls.ri +++ b/lib/rivet/src/codegen/decls.ri @@ -6,7 +6,7 @@ import ./mir; import ../ast; extend Codegen { - func gen_decls(mut self, decls: []mut ast.Decl) { + func gen_decls(mut self, mut decls: []mut ast.Decl) { for mut decl in decls { self.gen_decl(decl); } @@ -14,7 +14,7 @@ extend Codegen { func gen_decl(mut self, mut decl: ast.Decl) { match decl { - .Extern(extern_decl) -> self.gen_decls(extern_decl.decls), + .Extern(mut extern_decl) -> self.gen_decls(extern_decl.decls), .Var(var_decl) -> { for left in var_decl.lefts { self.mir.globals.push(mir.Global( @@ -24,10 +24,10 @@ extend Codegen { )); } }, - .Trait(trait_decl) -> self.gen_decls(trait_decl.decls), - .Enum(enum_decl) -> self.gen_decls(enum_decl.decls), - .Struct(struct_decl) -> self.gen_decls(struct_decl.decls), - .Extend(extend_decl) -> self.gen_decls(extend_decl.decls), + .Trait(mut trait_decl) -> self.gen_decls(trait_decl.decls), + .Enum(mut enum_decl) -> self.gen_decls(enum_decl.decls), + .Struct(mut struct_decl) -> self.gen_decls(struct_decl.decls), + .Extend(mut extend_decl) -> self.gen_decls(extend_decl.decls), .Func(mut func_decl) -> self.gen_func(func_decl), else -> {} } diff --git a/lib/rivet/src/codegen/mir/mod.ri b/lib/rivet/src/codegen/mir/mod.ri index 8cec061ff..adc19057a 100644 --- a/lib/rivet/src/codegen/mir/mod.ri +++ b/lib/rivet/src/codegen/mir/mod.ri @@ -208,10 +208,10 @@ pub struct Var { pub mut is_moved: bool; pub mut is_dropped: bool; pub mut is_initialized: bool; - pub fields: []Var; + pub mut fields: []mut Var; - pub func set_field(self, name: string, value: Expr) { - for field in self.fields { + pub func set_field(mut self, name: string, value: Expr) { + for mut field in self.fields { if field.dbg_name == name { field.value = value; break; diff --git a/lib/rivet/src/codegen/mod.ri b/lib/rivet/src/codegen/mod.ri index 268000a75..658159335 100644 --- a/lib/rivet/src/codegen/mod.ri +++ b/lib/rivet/src/codegen/mod.ri @@ -37,10 +37,10 @@ pub struct Codegen { mut loop_exit_label: string; mut while_continue_expr: ?mir.Expr; - pub func generate_mirs(mut self, source_files: []ast.SourceFile) { + pub func generate_mirs(mut self, mut source_files: []mut ast.SourceFile) { self.init_types(); self.rivet_internal = self.get_or_create_mir("rivetc.compiler.internal"); - for source_file in source_files { + for mut source_file in source_files { self.generate_mir(source_file); } if self.prefs.emit_mir { @@ -53,7 +53,7 @@ pub struct Codegen { } } - pub func generate_mir(mut self, source_file: ast.SourceFile) { + pub func generate_mir(mut self, mut source_file: ast.SourceFile) { self.source_file = source_file; self.mir = self.get_or_create_mir(source_file.mod.name); self.gen_decls(source_file.decls); @@ -205,9 +205,9 @@ pub struct Codegen { return sym.mangled_name; } - func add_locals(mut self, scope: ast.Scope) { - for sym in scope.syms { - if sym is ast.Var(local) { + func add_locals(mut self, mut scope: ast.Scope) { + for mut sym in scope.syms { + if sym is ast.Var(mut local) { local.mir_name = if self.cur_func.has_local(local.name) { "{}_{}".fmt(local.name, self.cur_func.locals.len) } else { @@ -220,7 +220,7 @@ pub struct Codegen { )); } } - for children in scope.childrens { + for mut children in scope.childrens { self.add_locals(children); } } diff --git a/lib/rivet/src/lib.ri b/lib/rivet/src/lib.ri index 42e203584..4abc5928f 100644 --- a/lib/rivet/src/lib.ri +++ b/lib/rivet/src/lib.ri @@ -121,9 +121,9 @@ pub struct Compiler { } func import_modules(mut self) -> ! { - for sf in self.table.source_files { - for d in sf.decls { - if d is .Import(import_decl) { + for mut sf in self.table.source_files { + for mut d in sf.decls { + if d is .Import(mut import_decl) { if self.table.universe.scope.exists(import_decl.info.full_name) { continue; } @@ -145,7 +145,7 @@ pub struct Compiler { func load_module( mut self, pathx: string, alias_name: string, file_path: string, pos: token.Pos ) -> !ast.ImportedMod { - mod := self.load_module_files(pathx, alias_name, file_path, pos)!; + mut mod := self.load_module_files(pathx, alias_name, file_path, pos)!; if mod.found { mod.mod = if mod_mod_ := self.table.universe.scope.find(mod.full_name) { @as(ast.Module, mod_mod_) @@ -288,7 +288,7 @@ pub struct Compiler { } self.vlog("-----------------------------------------"); source_files := self.table.source_files; - self.table.source_files = []ast.SourceFile(cap: source_files.len); + self.table.source_files = []mut ast.SourceFile(cap: source_files.len); for node in g_resolved.nodes { for pf in source_files { if pf.mod.name == node.name { diff --git a/lib/rivet/src/parser/decls.ri b/lib/rivet/src/parser/decls.ri index a35461bb2..d6b4e0bdf 100644 --- a/lib/rivet/src/parser/decls.ri +++ b/lib/rivet/src/parser/decls.ri @@ -276,7 +276,7 @@ extend Parser { }, self.accept(.KwVar) -> { // variable declarations - mut lefts := []ast.ObjectData(); + mut lefts := []mut ast.ObjectData(); if self.accept(.Lparen) { // multiple variables while { @@ -389,7 +389,7 @@ extend Parser { } self.expect(.Lbrace); mut is_tagged := false; - mut variants := []ast.EnumVariantDecl(); + mut variants := []mut ast.EnumVariantDecl(); while { v_pos := self.tok.pos; v_name := self.parse_name(); @@ -505,7 +505,7 @@ extend Parser { self.expect(.String); self.inside_func = true; self.open_scope(); - sc := self.scope; + mut sc := self.scope; sc.detached_from_parent = true; mut stmts := []mut ast.Stmt(); self.expect(.Lbrace); @@ -570,13 +570,13 @@ extend Parser { mut self_is_mut := false; mut self_is_ptr := false; mut self_pos := token.noPos; - mut args := []ast.Arg(); + mut args := []mut ast.Arg(); mut has_named_args := false; mut is_variadic := false; self.inside_func = true; self.open_scope(); - sc := self.scope; + mut sc := self.scope; sc.detached_from_parent = true; self.expect(.Lparen); if self.tok.kind != .Rparen { diff --git a/lib/rivet/src/parser/exprs.ri b/lib/rivet/src/parser/exprs.ri index d83cb27fd..2e6759b52 100644 --- a/lib/rivet/src/parser/exprs.ri +++ b/lib/rivet/src/parser/exprs.ri @@ -226,7 +226,7 @@ extend Parser { } else { self.parse_name() }; - mut args := []ast.CallArg(); + mut args := []mut ast.CallArg(); self.expect(.Lparen); if name in ["as", "size_of", "align_of"] { arg_pos := self.tok.pos; @@ -423,7 +423,7 @@ extend Parser { && (expr is .Ident || expr is .Selector || expr is .Paren || expr is .SelfTy || expr is .EnumLiteral) -> { self.next(); - mut args := []ast.CallArg(); + mut args := []mut ast.CallArg(); mut spread_expr := ast.Expr.Empty(self.tok.pos); mut has_spread_expr := false; if self.tok.kind != .Rparen { @@ -558,7 +558,7 @@ extend Parser { } func parse_if_expr(mut self) -> ast.Expr { - mut branches := []ast.IfBranch(); + mut branches := []mut ast.IfBranch(); mut has_else := false; mut pos := self.tok.pos; while self.tok.kind in [.KwIf, .KwElse] { @@ -600,7 +600,7 @@ extend Parser { func parse_match_expr(mut self) -> ast.Expr { mut has_else := false; - mut branches := []ast.MatchBranch(); + mut branches := []mut ast.MatchBranch(); pos := self.prev_tok.pos; old_inside_match_header := self.inside_match_header; self.inside_match_header = true; @@ -734,7 +734,7 @@ extend Parser { func parse_guard_expr(mut self) -> ast.Expr { pos := self.tok.pos; - mut vars := []ast.ObjectData(); + mut vars := []mut ast.ObjectData(); if self.accept(.Lparen) { while { vars.push(self.parse_var_decl(support_type: false)); diff --git a/lib/rivet/src/parser/mod.ri b/lib/rivet/src/parser/mod.ri index 405c615ae..a69b74824 100644 --- a/lib/rivet/src/parser/mod.ri +++ b/lib/rivet/src/parser/mod.ri @@ -117,7 +117,7 @@ pub struct Parser { func close_scope(mut self) { self.scope.end = self.tok.pos.pos; - if parent := self.scope.parent { + if mut parent := self.scope.parent { parent.childrens.push(self.scope); self.scope = parent; } diff --git a/lib/rivet/src/parser/stmts.ri b/lib/rivet/src/parser/stmts.ri index fda623b4f..ab56be2fe 100644 --- a/lib/rivet/src/parser/stmts.ri +++ b/lib/rivet/src/parser/stmts.ri @@ -59,7 +59,7 @@ extend Parser { index = self.parse_var_decl(support_mut: false, support_type: false); self.expect(.Comma); } - mut values := []ast.ObjectData(); + mut values := []mut ast.ObjectData(); if self.accept(.Lparen) { while { values.push( @@ -113,7 +113,7 @@ extend Parser { && self.decl_operator_is_used() -> { // variable declarations mut pos := self.tok.pos; - mut lefts := []ast.ObjectData(); + mut lefts := []mut ast.ObjectData(); if self.accept(.Lparen) { // multiple variables while { diff --git a/lib/rivet/src/parser/types.ri b/lib/rivet/src/parser/types.ri index 5c9e8766e..ddab907b4 100644 --- a/lib/rivet/src/parser/types.ri +++ b/lib/rivet/src/parser/types.ri @@ -16,7 +16,7 @@ extend Parser { // function types self.expect(.KwFunc); self.expect(.Lparen); - mut args := []ast.Arg(); + mut args := []mut ast.Arg(); if self.tok.kind != .Rparen { while { arg_pos := self.tok.pos; diff --git a/lib/rivet/src/resolver/Register.ri b/lib/rivet/src/resolver/Register.ri index 6db0a625b..c058921c0 100644 --- a/lib/rivet/src/resolver/Register.ri +++ b/lib/rivet/src/resolver/Register.ri @@ -33,18 +33,18 @@ pub struct Register { self.table.throwable_t = .Basic(self.table.throwable_sym); } - func walk_decls(mut self, decls: []mut ast.Decl) { - for decl in decls { + func walk_decls(mut self, mut decls: []mut ast.Decl) { + for mut decl in decls { old_abi := self.abi; old_sym := self.sym; self.sym.scope.owner = self.sym; match decl { .Import(import_decl) -> self.import_decl(import_decl), - .Extern(extern_decl) -> { + .Extern(mut extern_decl) -> { self.abi = extern_decl.abi; self.walk_decls(extern_decl.decls); }, - .Alias(alias_decl) -> alias_decl.sym = self.add_sym( + .Alias(mut alias_decl) -> alias_decl.sym = self.add_sym( if alias_decl.is_typealias { ast.TypeSym( parent: self.sym, @@ -62,7 +62,7 @@ pub struct Register { ) }, alias_decl.pos ), - .Trait(trait_decl) -> { + .Trait(mut trait_decl) -> { trait_decl.sym = self.add_sym( ast.TypeSym( parent: self.sym, @@ -78,7 +78,7 @@ pub struct Register { self.sym = trait_decl.sym; self.walk_decls(trait_decl.decls); }, - .Struct(struct_decl) -> { + .Struct(mut struct_decl) -> { struct_decl.sym = if self.is_core_mod && struct_decl.name == "string" { @as(ast.Type.Basic, self.table.string_t).sym } else { @@ -98,7 +98,7 @@ pub struct Register { self.sym = struct_decl.sym; self.walk_decls(struct_decl.decls); }, - .Enum(enum_decl) -> { + .Enum(mut enum_decl) -> { info := ast.TypeInfo.Enum( underlying_type: enum_decl.underlying_type, is_tagged: enum_decl.is_tagged @@ -112,7 +112,7 @@ pub struct Register { ), enum_decl.pos ); mut enum_info := @as(ast.TypeInfo.Enum, info); - for variant in enum_decl.variants { + for mut variant in enum_decl.variants { if enum_info.has_variant(variant.name) { report.error("enum `{}` has duplicate variant `{}`".fmt( enum_decl.name, variant.name @@ -153,7 +153,7 @@ pub struct Register { self.walk_decls(enum_decl.decls); }, .Field(field_decl) -> { - type_sym := @as(ast.TypeSym, self.sym); + mut type_sym := @as(ast.TypeSym, self.sym); if type_sym.has_field(field_decl.name) { report.error( "{} `{}` has duplicate field `{}`".fmt( @@ -172,7 +172,7 @@ pub struct Register { is_required: field_decl.attributes.has("required") )); }, - .Const(const_decl) -> const_decl.sym = self.add_sym(ast.Const( + .Const(mut const_decl) -> const_decl.sym = self.add_sym(ast.Const( parent: self.sym, is_public: const_decl.is_public, abi: self.abi, @@ -180,8 +180,8 @@ pub struct Register { expr: const_decl.expr, type: const_decl.type ), const_decl.pos), - .Var(var_decl) -> { - for left in var_decl.lefts { + .Var(mut var_decl) -> { + for mut left in var_decl.lefts { left.sym = ast.Var( parent: self.sym, is_public: var_decl.is_public, @@ -197,9 +197,15 @@ pub struct Register { }; } }, - .Extend(extend_decl) -> if extend_decl.type is .Basic(basic_type) { - if basic_type.is_unresolved { - if basic_type.expr is .Ident(ident) { + .Extend(mut extend_decl) -> if extend_decl.type is .Basic(mut basic_type) { + if type_sym := basic_type.sym { + self.sym = type_sym; + if type_sym.is_primitive() + && !self.source_file.mod.is_core() { + report.error("cannot extend primitive types", extend_decl.pos); + } + } else { + if basic_type.expr is .Ident(mut ident) { self.sym = if type_sym := self.sym.scope.find(ident.name) { type_sym } else { @@ -220,15 +226,6 @@ pub struct Register { ); continue; } - } else { - self.sym = basic_type.sym; - if basic_type.sym.is_primitive() - && !self.source_file.mod.is_core() { - report.error( - "cannot extend primitive types", - extend_decl.pos - ); - } } self.walk_decls(extend_decl.decls); } else { @@ -237,7 +234,7 @@ pub struct Register { extend_decl.pos ); }, - .Func(func_decl) -> func_decl.sym = self.add_sym(ast.Func( + .Func(mut func_decl) -> func_decl.sym = self.add_sym(ast.Func( parent: self.sym, abi: func_decl.abi, is_public: func_decl.is_public, @@ -295,7 +292,7 @@ pub struct Register { } } } else { - // `import module/path.{ A, B }` + // `import module/path.A` || `import module/path.{ A, B }` for import_info in import_decl.import_list { if import_info.name == "self" { if import_decl.is_public { diff --git a/lib/rivet/src/resolver/decls.ri b/lib/rivet/src/resolver/decls.ri index 14cb9edd2..20facfc9f 100644 --- a/lib/rivet/src/resolver/decls.ri +++ b/lib/rivet/src/resolver/decls.ri @@ -6,18 +6,18 @@ import ../ast; import ../report; extend Resolver { - func resolve_decls(mut self, decls: []ast.Decl) { - for decl in decls { + func resolve_decls(mut self, mut decls: []mut ast.Decl) { + for mut decl in decls { old_sym := self.sym; old_self_sym := self.self_sym; old_self_sym_is_set := self.self_sym_is_set; match decl { .Empty(empty_pos) -> report.error("BUG: empty declaration found", empty_pos), - .Extern(extern_decl) -> self.resolve_decls(extern_decl.decls), - .Alias(alias_decl) -> if alias_decl.is_typealias { + .Extern(mut extern_decl) -> self.resolve_decls(extern_decl.decls), + .Alias(mut alias_decl) -> if alias_decl.is_typealias { _ = self.resolve_type(alias_decl.parent_type); } else { - sym_ref := @as(ast.SymRef, alias_decl.sym); + mut sym_ref := @as(ast.SymRef, alias_decl.sym); self.resolve_expr(sym_ref.ref_expr); if sym_ref.ref_expr is .Ident(ident) && ident.found && ident.is_sym { sym_ref.ref = ident.sym; @@ -27,11 +27,11 @@ extend Resolver { sym_ref.ref_resolved = true; } }, - .Const(const_decl) -> if self.resolve_type(const_decl.type) { + .Const(mut const_decl) -> if self.resolve_type(const_decl.type) { self.resolve_expr(const_decl.expr); }, - .Var(var_decl) -> { - for left in var_decl.lefts { + .Var(mut var_decl) -> { + for mut left in var_decl.lefts { self.check_variable_shadowing(left.name, left.pos); _ = self.resolve_type(left.type); } @@ -39,17 +39,17 @@ extend Resolver { self.resolve_expr(var_decl.right); } }, - .Trait(trait_decl) -> { + .Trait(mut trait_decl) -> { self.self_sym = @as(ast.TypeSym, trait_decl.sym); self.self_sym_is_set = true; - trait_info := @as(ast.TypeInfo.Trait, self.self_sym.info); + mut trait_info := @as(ast.TypeInfo.Trait, self.self_sym.info); for mut base in trait_decl.bases { if self.resolve_type(base) { - base_sym := base.symbol()?; + mut base_sym := base.symbol()?; if base_sym.info is .Trait(mut base_trait_info) { trait_info.bases.push(base_sym); - for impl in base_trait_info.implements { - if impl.info is .Struct(struct_info) { + for mut impl in base_trait_info.implements { + if impl.info is .Struct(mut struct_info) { if !struct_info.contains_trait(base_sym) { base_trait_info.implement(impl); struct_info.traits.push(base_sym); @@ -70,19 +70,19 @@ extend Resolver { } self.resolve_decls(trait_decl.decls); }, - .Enum(enum_decl) -> { + .Enum(mut enum_decl) -> { if enum_decl.is_tagged || self.resolve_type(enum_decl.underlying_type) { self.self_sym = @as(ast.TypeSym, enum_decl.sym); self.self_sym_is_set = true; - enum_info := @as(ast.TypeInfo.Enum, self.self_sym.info); - for variant in enum_info.variants { + mut enum_info := @as(ast.TypeInfo.Enum, self.self_sym.info); + for mut variant in enum_info.variants { if !self.resolve_type(variant.type) { continue; } } for mut base in enum_decl.bases { if self.resolve_type(base) { - base_sym := base.symbol()?; + mut base_sym := base.symbol()?; if base_sym.info is .Trait(mut trait_info) { enum_info.traits.push(base_sym); trait_info.implement(self.self_sym); @@ -96,7 +96,7 @@ extend Resolver { } } } - for variant in enum_decl.variants { + for mut variant in enum_decl.variants { if !variant.decls.is_empty() { old_self_sym2 := self.self_sym; self.self_sym = variant.type.symbol() ?? self.self_sym; @@ -110,19 +110,19 @@ extend Resolver { } self.resolve_decls(enum_decl.decls); }, - .Struct(struct_decl) -> { + .Struct(mut struct_decl) -> { self.self_sym = @as(ast.TypeSym, struct_decl.sym); self.self_sym_is_set = true; for mut base in struct_decl.bases { if self.resolve_type(base) { - struct_info := @as(ast.TypeInfo.Struct, self.self_sym.info); - base_sym := base.symbol()?; + mut struct_info := @as(ast.TypeInfo.Struct, self.self_sym.info); + mut base_sym := base.symbol()?; if base_sym.info is .Trait(mut trait_info) { struct_info.traits.push(base_sym); trait_info.implement(self.self_sym); - } else if base_sym.info is .Struct(struct_info2) { + } else if base_sym.info is .Struct(mut struct_info2) { struct_info.bases.push(base_sym); - for b_trait in struct_info2.traits { + for mut b_trait in struct_info2.traits { @as(ast.TypeInfo.Trait, b_trait.info).implement( self.self_sym ); @@ -138,15 +138,15 @@ extend Resolver { } self.resolve_decls(struct_decl.decls); }, - .Extend(extend_decl) -> if self.resolve_type(extend_decl.type) { + .Extend(mut extend_decl) -> if self.resolve_type(extend_decl.type) { self.self_sym = extend_decl.type.symbol()?; self.self_sym_is_set = true; for mut base in extend_decl.bases { if self.resolve_type(base) { - base_sym := base.symbol()?; + mut base_sym := base.symbol()?; if base_sym.info is .Trait(mut trait_info) { trait_info.implement(self.self_sym); - } else if self.self_sym.info is .Struct(struct_info) + } else if self.self_sym.info is .Struct(mut struct_info) && base_sym.info is .Struct { struct_info.bases.push(base_sym); } else { @@ -160,11 +160,11 @@ extend Resolver { } self.resolve_decls(extend_decl.decls); }, - .Field(field_decl) -> if self.resolve_type(field_decl.type) + .Field(mut field_decl) -> if self.resolve_type(field_decl.type) && field_decl.has_def_expr { self.resolve_expr(field_decl.def_expr); }, - .Func(func_decl) -> { + .Func(mut func_decl) -> { if func_decl.is_method { mut self_type := ast.Type.Basic(self.self_sym); if func_decl.self_is_ptr { @@ -185,7 +185,7 @@ extend Resolver { func_decl.self_type = self_type; @as(ast.Func, func_decl.sym).self_type = self_type; } - for arg in func_decl.args { + for mut arg in func_decl.args { if self.resolve_type(arg.type) { self.check_variable_shadowing(arg.name, arg.pos); is_used := self.self_sym_is_set && self.self_sym.info is .Trait @@ -211,7 +211,7 @@ extend Resolver { self.resolve_stmt(stmt); } }, - .Test(test_decl) -> { + .Test(mut test_decl) -> { for mut stmt in test_decl.stmts { self.resolve_stmt(stmt); } diff --git a/lib/rivet/src/resolver/exprs.ri b/lib/rivet/src/resolver/exprs.ri index 25c4b1b96..104686fbe 100644 --- a/lib/rivet/src/resolver/exprs.ri +++ b/lib/rivet/src/resolver/exprs.ri @@ -9,20 +9,20 @@ import ../report; extend Resolver { func resolve_expr(mut self, mut expr: ast.Expr) { match expr { - .Empty(empty_pos) -> report.error("BUG: empty expression found", empty_pos), - .Paren(paren) -> self.resolve_expr(paren.expr), + .Empty(empty_pos) -> report.error("bug: unexpected empty expression found", empty_pos), + .Paren(mut paren) -> self.resolve_expr(paren.expr), .Type(mut type) -> _ = self.resolve_type(type), .Ident(mut ident) -> self.resolve_ident(ident), .Selector(mut selector) -> self.resolve_selector(selector), - .Indirect(indirect) -> self.resolve_expr(indirect.left), - .OptionCheck(option_check) -> self.resolve_expr(option_check.left), - .SelfTy(self_ty) -> if self.self_sym_is_set { + .Indirect(mut indirect) -> self.resolve_expr(indirect.left), + .OptionCheck(mut option_check) -> self.resolve_expr(option_check.left), + .SelfTy(mut self_ty) -> if self.self_sym_is_set { self_ty.sym = self.self_sym; self_ty.found = true; } else { report.error("cannot resolve `Self` expression", self_ty.pos); }, - .SelfLiteral(self_lit) -> if self.self_sym_is_set { + .SelfLiteral(mut self_lit) -> if self.self_sym_is_set { self_lit.sym = self.self_sym; self_lit.found = true; self_lit.obj = @as(ast.Var, self_lit.scope.lookup("self")?); @@ -30,12 +30,12 @@ extend Resolver { } else { report.error("cannot resolve `self` expression", self_ty.pos); }, - .TupleLiteral(tuple_lit) -> { + .TupleLiteral(mut tuple_lit) -> { for mut value in tuple_lit.values { self.resolve_expr(value); } }, - .ArrayCtor(array_ctor) -> { + .ArrayCtor(mut array_ctor) -> { _ = self.resolve_type(array_ctor.elem_type); if mut init_value := array_ctor.init_value { self.resolve_expr(init_value); @@ -61,16 +61,16 @@ extend Resolver { self.resolve_expr(cap_value); } }, - .ArrayLiteral(array_lit) -> { + .ArrayLiteral(mut array_lit) -> { for mut value in array_lit.values { self.resolve_expr(value); } }, - .BuiltinCall(builtin_call) -> { + .BuiltinCall(mut builtin_call) -> { if builtin := self.table.find_builtin(builtin_call.name) { if builtin is .Func { builtin_call.builtin = builtin; - for arg in builtin_call.args { + for mut arg in builtin_call.args { self.resolve_expr(arg.expr); } } else { @@ -86,9 +86,9 @@ extend Resolver { ); } }, - .Call(call) -> { + .Call(mut call) -> { self.resolve_expr(call.left); - for arg in call.args { + for mut arg in call.args { self.resolve_expr(arg.expr); } if call.has_spread_expr { @@ -112,8 +112,8 @@ extend Resolver { self.resolve_expr(call.err_handler.expr); } }, - .Unary(unary) -> self.resolve_expr(unary.right), - .Binary(binary) -> { + .Unary(mut unary) -> self.resolve_expr(unary.right), + .Binary(mut binary) -> { self.resolve_expr(binary.left); self.resolve_expr(binary.right); if binary.has_var_obj { @@ -130,7 +130,7 @@ extend Resolver { ); } }, - .Range(range) -> { + .Range(mut range) -> { if range.has_start { self.resolve_expr(range.start); } @@ -138,11 +138,11 @@ extend Resolver { self.resolve_expr(range.end); } }, - .Index(index) -> { + .Index(mut index) -> { self.resolve_expr(index.left); self.resolve_expr(index.index); }, - .Block(block) -> { + .Block(mut block) -> { for mut stmt in block.stmts { self.resolve_stmt(stmt); } @@ -150,12 +150,12 @@ extend Resolver { self.resolve_expr(block.expr); } }, - .Return(return_expr) -> if return_expr.has_expr { + .Return(mut return_expr) -> if return_expr.has_expr { self.resolve_expr(return_expr.expr); }, - .Throw(throw_expr) -> self.resolve_expr(throw_expr.expr), - .Guard(guard) -> { - for var_ in guard.vars { + .Throw(mut throw_expr) -> self.resolve_expr(throw_expr.expr), + .Guard(mut guard) -> { + for mut var_ in guard.vars { self.check_variable_shadowing(var_.name, var_.pos); var_.sym = ast.Var( is_mut: var_.is_mut, @@ -173,17 +173,17 @@ extend Resolver { self.resolve_expr(guard.cond); } }, - .If(if_expr) -> { - for branch in if_expr.branches { + .If(mut if_expr) -> { + for mut branch in if_expr.branches { if !branch.is_else { self.resolve_expr(branch.cond); } self.resolve_expr(branch.expr); } }, - .Match(match_expr) -> { + .Match(mut match_expr) -> { self.resolve_expr(match_expr.expr); - for branch in match_expr.branches { + for mut branch in match_expr.branches { if !branch.is_else { for mut pattern in branch.patterns { self.resolve_expr(pattern); @@ -207,7 +207,7 @@ extend Resolver { self.resolve_expr(branch.expr); } }, - .Assign(assign_expr) -> { + .Assign(mut assign_expr) -> { self.resolve_expr(assign_expr.left); self.resolve_expr(assign_expr.right); }, @@ -238,7 +238,7 @@ extend Resolver { ident.is_obj = true; ident.sym = obj; @as(ast.Var, obj).is_used = true; - } else if imported := self.source_file.imported_symbols.find(ident.name) { + } else if mut imported := self.source_file.imported_symbols.find(ident.name) { if !(imported.sym is ast.TypeSym(type_sym) && type_sym.info is .Placeholder) { imported.is_used = true; ident.found = true; @@ -329,12 +329,12 @@ extend Resolver { } } - func find_symbol(mut self, sym: ast.Sym, name: string, pos: token.Pos) -> ?ast.Sym { + func find_symbol(mut self, mut sym: ast.Sym, name: string, pos: token.Pos) -> ?ast.Sym { mut sym_ := sym; if sym is ast.SymRef(mut sym_ref) { sym_ = self.clean_symbol_reference(sym_ref); } - if s := sym_.scope.find(name) { + if mut s := sym_.scope.find(name) { self.check_vis(s, pos); return if s is ast.SymRef(mut sym_ref2) { self.clean_symbol_reference(sym_ref2) diff --git a/lib/rivet/src/resolver/mod.ri b/lib/rivet/src/resolver/mod.ri index 17708e0d7..d889d9c59 100644 --- a/lib/rivet/src/resolver/mod.ri +++ b/lib/rivet/src/resolver/mod.ri @@ -66,7 +66,7 @@ pub struct Resolver { func eval_size(mut self, mut expr: ast.Expr) -> ?int { return match expr { - .Paren(paren) -> self.eval_size(paren.expr), + .Paren(mut paren) -> self.eval_size(paren.expr), .IntegerLiteral(int_lit) -> int_lit.value.to_int() catch return none, .Ident(mut ident) -> { self.resolve_ident(ident); @@ -84,7 +84,7 @@ pub struct Resolver { none } }, - .Binary(binary) -> if left := self.eval_size(binary.left) { + .Binary(mut binary) -> if left := self.eval_size(binary.left) { if right := self.eval_size(binary.right) { match binary.op { .Plus -> left + right, @@ -105,7 +105,7 @@ pub struct Resolver { } else { none }, - .BuiltinCall(builtin_call) if builtin_call.name in ["size_of", "align_of"] -> { + .BuiltinCall(mut builtin_call) if builtin_call.name in ["size_of", "align_of"] -> { if builtin_call.args[0].expr is .Type(mut type) && self.resolve_type(type) { (size, align) := self.table.type_size(type); if builtin_call.name == "size_of" { @@ -121,8 +121,8 @@ pub struct Resolver { }; } - func eval_sym(mut self, sym: ast.Sym, pos: token.Pos) -> ?int { - if sym is ast.Const(const_) { + func eval_sym(mut self, mut sym: ast.Sym, pos: token.Pos) -> ?int { + if sym is ast.Const(mut const_) { if !const_.has_evaled_size { const_.evaled_size = self.eval_size(const_.expr)?; } diff --git a/lib/rivet/src/resolver/stmts.ri b/lib/rivet/src/resolver/stmts.ri index a13a33084..962cda81b 100644 --- a/lib/rivet/src/resolver/stmts.ri +++ b/lib/rivet/src/resolver/stmts.ri @@ -9,10 +9,10 @@ extend Resolver { func resolve_stmt(mut self, mut stmt: ast.Stmt) { match stmt { .Comment -> {}, - .Empty(empty_pos) -> report.error("BUG: empty statement found", empty_pos), + .Empty(empty_pos) -> report.error("bug: unexpected empty statement found", empty_pos), .Expr(mut expr) -> self.resolve_expr(expr), - .VarDecl(var_stmt) -> { - for left in var_stmt.lefts { + .VarDecl(mut var_stmt) -> { + for mut left in var_stmt.lefts { self.check_variable_shadowing(left.name, left.pos); _ = self.resolve_type(left.type); left.sym = ast.Var( @@ -28,7 +28,7 @@ extend Resolver { } self.resolve_expr(var_stmt.right); }, - .While(while_stmt) -> { + .While(mut while_stmt) -> { if !while_stmt.is_inf { self.resolve_expr(while_stmt.cond); } @@ -40,7 +40,7 @@ extend Resolver { self.resolve_stmt(while_stmt.else_stmt); } }, - .For(for_stmt) -> { + .For(mut for_stmt) -> { if for_stmt.has_index { self.check_variable_shadowing(for_stmt.index.name, for_stmt.index.pos); for_stmt.index.sym = ast.Var( @@ -54,7 +54,7 @@ extend Resolver { err.to_string(), for_stmt.index.pos ); } - for value in for_stmt.values { + for mut value in for_stmt.values { self.check_variable_shadowing(value.name, value.pos); value.sym = ast.Var( is_mut: value.is_mut, @@ -70,7 +70,7 @@ extend Resolver { self.resolve_expr(for_stmt.iterable); self.resolve_stmt(for_stmt.stmt); }, - .Defer(defer_stmt) -> self.resolve_expr(defer_stmt.expr) + .Defer(mut defer_stmt) -> self.resolve_expr(defer_stmt.expr) } } } diff --git a/lib/rivet/src/resolver/types.ri b/lib/rivet/src/resolver/types.ri index a3a207738..f9389d183 100644 --- a/lib/rivet/src/resolver/types.ri +++ b/lib/rivet/src/resolver/types.ri @@ -9,11 +9,11 @@ extend Resolver { func resolve_type(mut self, mut type: ast.Type) -> bool { return match type { .Void, .Never, .Rawptr -> true, - .Option(opt) -> self.resolve_type(opt.inner), - .Result(res) -> self.resolve_type(res.inner), - .Variadic(variadic) -> if self.resolve_type(variadic.inner) { - elem_sym := variadic.inner.symbol()?; - if elem_sym.info is .Trait(trait_info) { + .Option(mut opt) -> self.resolve_type(opt.inner), + .Result(mut res) -> self.resolve_type(res.inner), + .Variadic(mut variadic) -> if self.resolve_type(variadic.inner) { + mut elem_sym := variadic.inner.symbol()?; + if elem_sym.info is .Trait(mut trait_info) { trait_info.has_objects = true; } variadic.sym = self.table.universe.add_or_get_dyn_array(variadic.inner, false); @@ -21,13 +21,13 @@ extend Resolver { } else { false }, - .DynArray(vec) -> if self.resolve_type(vec.inner) { - vec.sym = self.table.universe.add_or_get_dyn_array(vec.inner, vec.is_mut); + .DynArray(mut dyn_arr) -> if self.resolve_type(dyn_arr.inner) { + dyn_arr.sym = self.table.universe.add_or_get_dyn_array(dyn_arr.inner, dyn_arr.is_mut); true } else { false }, - .Array(arr) -> if self.resolve_type(arr.inner) { + .Array(mut arr) -> if self.resolve_type(arr.inner) { if arr_size := self.eval_size(arr.size) { if arr_size <= 0 { mut err := report.error_builder( @@ -52,8 +52,8 @@ extend Resolver { } else { false }, - .Pointer(ptr) -> self.resolve_type(ptr.inner), - .Tuple(tuple) -> { + .Pointer(mut ptr) -> self.resolve_type(ptr.inner), + .Tuple(mut tuple) -> { mut resolved := false; for mut inner in tuple.inners { resolved = self.resolve_type(inner); @@ -63,9 +63,9 @@ extend Resolver { } resolved }, - .Func(func_t) -> { + .Func(mut func_t) -> { mut res1 := false; - for arg in func_t.args { + for mut arg in func_t.args { res1 = self.resolve_type(arg.type); } res1 = self.resolve_type(func_t.ret_type); @@ -73,7 +73,7 @@ extend Resolver { func_t.has_sym = true; res1 }, - .Basic(basic) -> if basic.is_unresolved { + .Basic(mut basic) -> if basic.is_unresolved { match basic.expr { .SelfTy -> if self.self_sym_is_set { basic.is_unresolved = false; @@ -85,10 +85,10 @@ extend Resolver { .Ident(mut ident) -> { self.resolve_ident(ident); if ident.found { - if ident.sym is ast.TypeSym(type_sym) { + if ident.sym is ast.TypeSym(mut type_sym) { basic.is_unresolved = false; basic.sym = type_sym; - if type_sym.info is .Alias(alias_info) { + if type_sym.info is .Alias(mut alias_info) { if self.resolve_type(alias_info.parent) { type.unalias_in_place(); } @@ -105,7 +105,7 @@ extend Resolver { .Selector(mut selector) -> { self.resolve_selector(selector); if selector.found { - if selector.sym is ast.TypeSym(type_sym) { + if selector.sym is ast.TypeSym(mut type_sym) { if type_sym.info is .Placeholder { report.error( "cannot find type `{}` in {} `{}`".fmt( @@ -118,7 +118,7 @@ extend Resolver { } else { basic.is_unresolved = false; basic.sym = type_sym; - if type_sym.info is .Alias(alias_info) { + if type_sym.info is .Alias(mut alias_info) { if self.resolve_type(alias_info.parent) { type.unalias_in_place(); } diff --git a/lib/rivet/src/tokenizer/preprocessor.ri b/lib/rivet/src/tokenizer/preprocessor.ri index 4669fdbdf..55600b771 100644 --- a/lib/rivet/src/tokenizer/preprocessor.ri +++ b/lib/rivet/src/tokenizer/preprocessor.ri @@ -12,7 +12,7 @@ extend Tokenizer { } func pp_directive(mut self) { - pos := self.current_pos(); + mut pos := self.current_pos(); self.pos += 1; // skip '#' self.skip_whitespace(); pp_dir := self.read_name(); @@ -192,7 +192,7 @@ extend Tokenizer { func pp_symbol(mut self) -> bool { self.pos -= 1; - pos := self.current_pos(); + mut pos := self.current_pos(); self.pos += 1; name := self.read_name(); self.pos += 1; diff --git a/lib/rivet/src/utils/file.ri b/lib/rivet/src/utils/file.ri index cb7192b93..7891a5b9e 100644 --- a/lib/rivet/src/utils/file.ri +++ b/lib/rivet/src/utils/file.ri @@ -49,7 +49,7 @@ struct SourceCache { return none; } - pub func find_line(self, path_: string, line: uint) -> ?string { + pub func find_line(mut self, path_: string, line: uint) -> ?string { return if lines := self.find_lines(path_) { lines[line] } else { @@ -57,7 +57,7 @@ struct SourceCache { }; } - pub func find_lines_between(self, path_: string, line: uint, end_line: uint) -> ?[]string { + pub func find_lines_between(mut self, path_: string, line: uint, end_line: uint) -> ?[]string { return if lines := self.find_lines(path_) { if lines.len > 0 && lines.len >= end_line { lines[line..end_line] @@ -69,10 +69,8 @@ struct SourceCache { }; } - pub func find_lines(self, path_: string) -> ?[]string { - // TODO: fix "variable does not need to be mutable" - // for mut cached in self.sources { - for &cached in self.sources { + pub func find_lines(mut self, path_: string) -> ?[]string { + for mut cached in self.sources { if cached.path == path_ { if cached.lines.is_empty() { cached.lines = cached.content.split_into_lines(); diff --git a/lib/rivet/src/utils/maps/mod.ri b/lib/rivet/src/utils/maps/mod.ri index b0a278269..e154667bd 100644 --- a/lib/rivet/src/utils/maps/mod.ri +++ b/lib/rivet/src/utils/maps/mod.ri @@ -15,7 +15,7 @@ pub struct MapStringUint { mut pairs: []mut StringUint; pub func set(mut self, key: string, value: uint) { - for pair in self.pairs { + for mut pair in self.pairs { if pair.key == key { pair.value = value; return; // found @@ -86,7 +86,7 @@ pub struct MapStringArrayOfStrings { } pub func set(mut self, key: string, value: []string) { - for pair in self.pairs { + for mut pair in self.pairs { if pair.key == key { pair.value = value; return; // found @@ -136,7 +136,7 @@ pub struct MapStringBool { mut pairs: []mut StringBool; pub func set(mut self, key: string, value: bool) { - for pair in self.pairs { + for mut pair in self.pairs { if pair.key == key { pair.value = value; return; // found diff --git a/lib/std/src/semver/parse.ri b/lib/std/src/semver/parse.ri index 9538b51f6..6f00a24c0 100644 --- a/lib/std/src/semver/parse.ri +++ b/lib/std/src/semver/parse.ri @@ -10,7 +10,7 @@ var versions := [VER_MAJOR, VER_MINOR, VER_PATCH]; struct RawVersion { prerelease: string; metadata: string; - raw_ints: []mut string; + mut raw_ints: []mut string; // TODO: Rewrite using regex: // /(\d+)\.(\d+)\.(\d+)(?:\-([0-9A-Za-z-.]+))?(?:\+([0-9A-Za-z-]+))?/ diff --git a/lib/std/src/semver/range.ri b/lib/std/src/semver/range.ri index 456b97e92..3df3018c0 100644 --- a/lib/std/src/semver/range.ri +++ b/lib/std/src/semver/range.ri @@ -128,7 +128,7 @@ struct Range { } func parse_x(input: string) -> ?Version { - raw_ver := RawVersion.parse(input).complete(); + mut raw_ver := RawVersion.parse(input).complete(); for typ in versions { if raw_ver.raw_ints[typ].index_of_any(xRangeSymbols) == none { continue; diff --git a/lib/std/src/strings/mod.ri b/lib/std/src/strings/mod.ri index a9bff9c01..3b4c2cd83 100644 --- a/lib/std/src/strings/mod.ri +++ b/lib/std/src/strings/mod.ri @@ -9,7 +9,7 @@ pub alias Builder := core.StringBuilder; /// Uses levenshtein distance algorithm to calculate the distance between /// two strings (lower is closer). pub func levenshtein_distance(a: string, b: string) -> int32 { - f := []mut int32(init: 0, len: b.len + 1); + mut f := []mut int32(init: 0, len: b.len + 1); for ca in a.as_bytes() { mut j: uint := 1; mut fj1 := f[0]; diff --git a/rivetc/src/checker.py b/rivetc/src/checker.py index 2afab9a91..8cd7c6294 100644 --- a/rivetc/src/checker.py +++ b/rivetc/src/checker.py @@ -280,11 +280,14 @@ def check_stmt(self, stmt): elem_typ = self.comp.comptime_number_to_type( iterable_sym.info.elem_typ ) - if stmt.value.is_mut and not iterable_sym.info.is_mut: - report.error( - f"cannot modify immutable {iterable_sym.kind}", - stmt.iterable.pos - ) + if stmt.value.is_mut: + if not iterable_sym.info.is_mut: + report.error( + f"cannot modify immutable {iterable_sym.kind}", + stmt.iterable.pos + ) + else: + self.check_expr_is_mut(stmt.iterable) elif stmt.value.is_ref: elem_typ = type.Ptr(elem_typ) if stmt.index != None: @@ -771,6 +774,7 @@ def check_expr(self, expr): expr.scope.update_type(expr.var.name, rtyp) expr.var.typ = rtyp if expr.var.is_mut: + self.check_expr_is_mut(expr.left) expr.scope.update_is_hidden_ref(expr.var.name, True) if lsym.kind == TypeKind.Enum: if lsym.info.is_tagged and expr.op not in ( @@ -1911,22 +1915,8 @@ def check_expr_is_mut(self, expr, from_assign = False): elif isinstance(expr, ast.SelectorExpr): if expr.is_path: self.check_sym_is_mut(expr.field_sym, expr.pos) - return - elif isinstance(expr.left, ast.Ident): - if expr.left.sym: - self.check_sym_is_mut(expr.left.sym, expr.pos) - elif expr.left.obj.level == sym.ObjLevel.Arg: - if not expr.left.obj.is_mut: - report.error( - f"cannot use `{expr.left.name}` as mutable argument", - expr.pos - ) - report.help( - f"consider making this argument mutable: `mut {expr.left.name}`" - ) - expr.left.obj.is_changed = True - else: - self.check_expr_is_mut(expr.left, from_assign) + return + self.check_expr_is_mut(expr.left, from_assign) if expr.is_indirect and isinstance(expr.left_typ, type.Ptr): if not expr.left_typ.is_mut: report.error( @@ -1963,6 +1953,7 @@ def check_expr_is_mut(self, expr, from_assign = False): expr.pos ) return + self.check_expr_is_mut(expr.left, from_assign) expr_sym = expr.left.typ.symbol() if not expr_sym.info.is_mut: report.error( diff --git a/rivetc/src/codegen/__init__.py b/rivetc/src/codegen/__init__.py index f8c84c1cd..844709299 100644 --- a/rivetc/src/codegen/__init__.py +++ b/rivetc/src/codegen/__init__.py @@ -981,10 +981,10 @@ def gen_expr(self, expr, custom_tmp = None): ) elif typ_sym.kind == TypeKind.Enum: if expr.is_enum_variant: - tmp = self.boxed_instance( - cg_utils.mangle_symbol(expr.enum_variant_sym), - expr.enum_variant_sym.id + tmp = ir.Ident( + ir.Type(cg_utils.mangle_symbol(expr.enum_variant_sym)), self.cur_func.local_name() ) + self.cur_func.alloca(tmp) initted_fields = [] type_fields = expr.enum_variant_sym.full_fields() for i, f in enumerate(expr.args): @@ -1860,8 +1860,9 @@ def gen_expr(self, expr, custom_tmp = None): val = ir.Selector( ir.Type(self.ir_type(expr.typ)), obj_val, ir.Name(f"v{expr.right.variant_info.value}") ) - if expr.var.is_mut and not isinstance(var_t2, ir.Pointer): + if expr.var.is_mut and not isinstance(var_t, ir.Pointer): val = ir.Inst(ir.InstKind.GetPtr, [val], var_t2) + var_t = var_t.ptr() else: val = ir.Inst( ir.InstKind.Cast, [ @@ -3153,18 +3154,17 @@ def sort_type_symbols(self, tss): field_deps.append(dep) elif ts.kind == TypeKind.Tuple: for f in ts.info.types: - dep = cg_utils.mangle_symbol(f.symbol()) + fsym = f.symbol() + dep = cg_utils.mangle_symbol(fsym) if dep not in typ_names or dep in field_deps or isinstance( f, type.Option - ): + ) or fsym.is_boxed(): continue field_deps.append(dep) elif ts.kind == TypeKind.Enum and ts.info.is_tagged: for variant in ts.info.variants: if variant.has_typ: variant_sym = variant.typ.symbol() - if variant_sym.kind != TypeKind.Struct: - continue if variant_sym.is_boxed() or isinstance(variant.typ, type.Option): continue dep = cg_utils.mangle_symbol(variant_sym) @@ -3178,23 +3178,25 @@ def sort_type_symbols(self, tss): continue field_deps.append(dep) for f in ts.fields: - dep = cg_utils.mangle_symbol(f.typ.symbol()) + fsym = f.typ.symbol() + dep = cg_utils.mangle_symbol(fsym) if dep not in typ_names or dep in field_deps or isinstance( f.typ, type.Option - ): + ) or fsym.is_boxed(): continue field_deps.append(dep) elif ts.kind == TypeKind.Struct: for base in ts.info.bases: dep = cg_utils.mangle_symbol(base) - if dep not in typ_names or dep in field_deps: + if dep not in typ_names or dep in field_deps or base.is_boxed(): continue field_deps.append(dep) for f in ts.fields: - dep = cg_utils.mangle_symbol(f.typ.symbol()) + fsym = f.typ.symbol() + dep = cg_utils.mangle_symbol(fsym) if dep not in typ_names or dep in field_deps or isinstance( f.typ, type.Option - ): + ) or fsym.is_boxed(): continue field_deps.append(dep) dg.add(ts.mangled_name, field_deps) diff --git a/rivetc/src/register.py b/rivetc/src/register.py index 8efa0c7d6..0aae94202 100644 --- a/rivetc/src/register.py +++ b/rivetc/src/register.py @@ -156,7 +156,7 @@ def walk_decls(self, decls): sym.Type( decl.is_public, variant.name, TypeKind.Struct, - info = sym.StructInfo(False, True, True) + info = sym.StructInfo(False, False, True) ) ) old_v_sym = self.sym diff --git a/tests/valid/src/enums.ri b/tests/valid/src/enums.ri index 00299bae2..38dcfda61 100644 --- a/tests/valid/src/enums.ri +++ b/tests/valid/src/enums.ri @@ -86,7 +86,7 @@ test "enums: tagged enum with fields" { } user_os = .Linux(kernel_version: 5_16_0, distro_name: "CentOS"); - if user_os is .Linux(linux) { + if user_os is .Linux(mut linux) { @assert(linux.kernel_version == 5_16_0); @assert(linux.distro_name == "CentOS"); linux.kernel_version = 5_12_0; diff --git a/tests/valid/src/for_stmt.ri b/tests/valid/src/for_stmt.ri index 3dab226a0..adf6ef590 100644 --- a/tests/valid/src/for_stmt.ri +++ b/tests/valid/src/for_stmt.ri @@ -32,7 +32,7 @@ test "`for` statement with referenced value" { } test "`for` statement with mutable value" { - arr: []mut int32 := +[1, 2, 3]; + mut arr: []mut int32 := +[1, 2, 3]; for mut elem in arr { elem = elem * 2; }