I made an attempt to do this with macros
import strformat, macros, macrocache
const varCache = CacheTable"vars"
macro getVar(varId: static string): untyped =
let v = varCache[varId][1]
result = quote do:
when not declared(`v`):
{.error: "Don't mark variable as immutable in nested scope".}
else:
`v`
macro mutable*(id, typ, val: untyped): untyped =
let varId = &"mutable::{id}::{id.lineInfo}"
let varName = ident varId
varCache[varId] = newStmtList(id, varName)
let typ =
if typ.kind == nnkNilLit: newEmptyNode()
else: typ
let templDefn = newProc(id, params = [ident "untyped"], procType =
nnkTemplateDef,
body = newStmtList(newCall(bindSym "getVar",
newLit varId)))
result = newStmtList(nnkVarSection.newTree(newIdentDefs(varName, typ,
val)), templDefn)
macro immutable*(id: typed): untyped =
if id.symKind == nskLet:
error(&"identifier is already immutable", result)
let varId = $id
let varName = $varCache[varId][0]
let newName = ident (&":{varName} is now immutable:")
result = newLetStmt(newName, id)
varCache[varId][1] = newName
type
Baz = object
x: int
y: string
proc test() =
let foo {.mutable.} = @["A"]
foo.add "B"
foo.add "C"
immutable foo
#foo.add "D" # Compiler error
echo foo
let bar {.mutable.} = [1, 2, 3]
bar[0] = 10
bar[1] = 20
immutable bar
#bar[2] = 30 # Compiler error
echo bar
let baz {.mutable.} = Baz(x: 1, y: "Hello")
baz.x = 5
echo baz
immutable baz
#baz.y = "World" # Compiler error
test()
Run
- Small improvement discussion: Use `let` to lock variable previ... dxb
- Small improvement discussion: Use `let` to lock variable previ... dwin
- Small improvement discussion: Use `let` to lock variable previ... xigoi
- Small improvement discussion: Use `let` to lock variable previ... cmc
- Small improvement discussion: Use `let` to lock variable previ... cmc
- Small improvement discussion: Use `let` to lock variable previ... cmc
- Small improvement discussion: Use `let` to lock variable previ... dxb
- Small improvement discussion: Use `let` to lock variable previ... planetis
- Small improvement discussion: Use `let` to lock variable previ... SolitudeSF
- Small improvement discussion: Use `let` to lock variable previ... cmc
- Small improvement discussion: Use `let` to lock variable previ... dwin
- Small improvement discussion: Use `let` to lock variable previ... federico3
- Small improvement discussion: Use `let` to lock variable previ... cmc
- Small improvement discussion: Use `let` to lock variable previ... exelotl
- Small improvement discussion: Use `let` to lock variable previ... ElegantBeef
- Small improvement discussion: Use `let` to lock variable previ... cmc
- Small improvement discussion: Use `let` to lock variable previ... ElegantBeef
- Small improvement discussion: Use `let` to lock variable previ... geekrelief
- Small improvement discussion: Use `let` to lock variable previ... ElegantBeef
- Small improvement discussion: Use `let` to lock variable previ... geekrelief
- Small improvement discussion: Use `let` to lock variable previ... ElegantBeef
