Skip to content

Instantly share code, notes, and snippets.

@spytheman
Created May 30, 2021 13:13
Show Gist options
  • Select an option

  • Save spytheman/8e130adcac6736c380b432c7a60fdb5d to your computer and use it in GitHub Desktop.

Select an option

Save spytheman/8e130adcac6736c380b432c7a60fdb5d to your computer and use it in GitHub Desktop.
import term
fn show(a []int, b []int) {
padding := ' '.repeat(26)
eprintln(padding +
'a.cap: $a.cap | a.len: $a.len ${a:-20} | b.cap: $b.cap | .len: $b.len ${b:-20}\n')
}
fn explain(code string, msg string) {
padding := ' '.repeat(25 - code.len)
eprintln(term.yellow(term.bold(code)) + '$padding // ' + term.gray(msg))
}
explain('mut a := [1, 2, 3, 4, 5]', '')
explain('mut b := a[1..3]', '> `a` and `b` both use the same memory block; `a` can access all elements in the block, `b` - only some.')
mut a := [1, 2, 3, 4, 5]
mut b := a[1..3]
show(a, b)
explain('b[0] = 100', 'Since both `a` and `b` use both the same memory block, this changes what is in a[1] too.')
b[0] = 100
show(a, b)
explain('a.trim(1)', 'After trimming, the memory block still exists, and the elements are not changed. What is changed, is *only* a.len .')
a.trim(1)
show(a, b)
// a = a[..1]
explain('a[0] = 200', 'This still modifies a shared element, that is visible to *both* `a` and `b`.')
a[0] = 200
show(a, b)
explain('a << 300', 'A new element is added to `a`. `a` still has enough capacity => no reallocation, but `a.len` changes.')
a << 300
show(a, b)
explain('a[1] = 400', 'Change an element of `a`, but `b` still shares it (because there was no reallocation) => `b[0]` is now also 400.')
a[1] = 400
show(a, b)
explain('b[0] = 500', 'Change an element of `b`, so likewise, `a[1]` is now too 500.')
b[0] = 500
show(a, b)
explain('b << 600', 'Append 600 to `b` => b was at its capacity, so it needs to allocate new space.')
explain(' ', 'NB: ==> `b` is now *independent*, and no longer shares elements with `a`.')
b << 600
show(a, b)
explain('a[1] = 700', 'change an element of a, but does nothing to `b` now.')
a[1] = 700
show(a, b)
explain('a << 800', 'Add an element to `a`, does not change `b`.')
a << 800
show(a, b)
@spytheman
Copy link
Author

Something similar can be achieved with this program (the first part makes it possible for the second part to use a kind of DSL), with less repetitions in the code to be executed/commented/traced:

import os
import term
import arrays
const commentsign = '//'
const used = term.bold('')
fn source_line(code string, msg string, showcode string, mlen int) {
	if code == '' && msg.starts_with('/') { return }
	println(code)
	msg_lines := msg.split('\n')
	for i, mline in msg_lines {
		mcode := if i == 0 { code } else { '' }
		padding := ' '.repeat(mlen - mcode.len)
		println('println(term.white(term.bold("$mcode")) + "$padding " + term.green("// $mline"))')
	}
	if code.trim_space() != '' {
		println(showcode)
	}		
}
fn simulate(sourcefile string) {
	slines := os.read_file(sourcefile) or { '' }.all_after('\nsimulate(@FILE)\n').trim_space().split('\n')
	mlen := arrays.max<int>(slines.map(it.split(commentsign)[0].len)) + 2
	println(r"import term
	fn show(a []int, b []int, mlen int) {
		padding := ' '.repeat(mlen + 1)
		what := 'a.cap: $a.cap | a.len: $a.len ${a:-20} | b.cap: $b.cap | .len: $b.len ${b:-20}'
		println(padding + term.blue(what))
	}
	")
	for s in slines {
		mut parts := s.split(commentsign)
		parts << ''
		source_line(parts[0], parts[1], 'show(a, b, $mlen)', mlen)
	}
	exit(0)
}
simulate(@FILE)
mut a, mut b := [1, 2, 3, 4, 5], a[1..3] // `a` and `b` both use the same memory block.
// `a` can access all elements in the block, `b` - only some.
b[0] = 100 // Since both `a` and `b` use both the same memory block, this changes what is in `a[1]` too.
a.trim(1) // After trimming, the memory block still exists, and the elements are not changed.
// What is changed, is *only* `a.len`:
/// a = a[..1]
a[0] = 200 // This still modifies a shared element, that is visible to *both* `a` and `b`.
a << 300 // A new element is added to `a`, but `a` still has enough capacity.
// => no reallocation, but `a.len` changes.
a[1] = 400 // Change an element of `a`, but `b` still shares it (because there was no reallocation).
// => `b[0]` is now also 400.
b[0] = 500 // Change an element of `b`, so likewise, `a[1]` is now too 500.
b << 600 // Append 600 to `b` => `b` was at its capacity, so it needs to allocate new space.
// NB: ==> `b` is now *independent*, and no longer shares elements with `a`.
a[1] = 700 // change an element of `a`, but does nothing to `b` now.
a << 800 // Add an element to `a`, does not change `b`.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment